endian_num/
lib.rs

1//! Byte-order-aware numeric types.
2//!
3//! This crate provides the [`Be`] (big-endian) and [`Le`] (little-endian) byte-order-aware numeric types.
4//!
5//! Unlike the popular [`byteorder`] crate, which focuses on the action of encoding and decoding numbers to and from byte streams, this crate focuses on the state of numbers.
6//! This is useful to create structs that contain fields of a specific endianness for interoperability, such as in virtio.
7//! In comparison to other crates that focus on state, this crate closely follows naming conventions from [`core::num`], has rich functionality, and extensive documentation of each method.
8//!
9//! [`byteorder`]: https://docs.rs/byteorder
10//!
11//! The core API looks _roughly_ like this (correspondingly for `Be`):
12//!
13//! ```ignore
14//! #[repr(transparent)]
15//! pub struct<T> Le(pub T);
16//!
17//! impl Le<T: Integer> {
18//!     pub const fn from_ne(n: T) -> Self;
19//!     pub const fn from_be(n: Be<T>) -> Self;
20//!
21//!     pub const fn to_ne(self) -> T;
22//!     pub const fn to_be(self) -> Be<T>;
23//!
24//!     pub const fn to_be_bytes(self) -> [u8; mem::size_of::<Self>()];
25//!     pub const fn to_le_bytes(self) -> [u8; mem::size_of::<Self>()];
26//!     pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()];
27//!
28//!     pub const fn from_be_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self;
29//!     pub const fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self;
30//!     pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self;
31//! }
32//! ```
33//!
34//! The types also implement appropriate traits from [`core::cmp`], [`core::convert`], [`core::fmt`], and [`core::ops`] and provide additional helper methods for computations.
35//!
36//! In addition to widening and byte-reordering [`From`] implementations, the endian number types implement conversions to and from arrays of smaller number types of the same ordering.
37//! This is useful in situations, where a larger field has to be treated as multiple smaller field.
38//!
39//! # Examples
40//!
41//! ```
42//! use endian_num::Le;
43//!
44//! let a = Le::<u32>::from_ne(0x1A);
45//! let b = Le::<u32>::from_ne(0x2B00);
46//!
47//! assert_eq!((a + b).to_le_bytes(), [0x1A, 0x2B, 0x00, 0x00]);
48//! ```
49//!
50//! # Optional features
51//!
52//! This crate has the following optional features:
53//!
54//! - [`bitflags`] — `Be` and `Le` implement [`Bits`], [`ParseHex`], and [`WriteHex`].
55//! - [`bytemuck`] — `Be` and `Le` implement [`Zeroable`] and [`Pod`].
56//! - `linux-types` — Type aliases like in [`linux/types.h`], such as [`le32`].
57//! - [`zerocopy`] — `Be` and `Le` implement [`KnownLayout`], [`Immutable`], [`FromBytes`], and [`IntoBytes`].
58//!
59//! [`Bits`]: bitflags::Bits
60//! [`ParseHex`]: bitflags::parser::ParseHex
61//! [`WriteHex`]: bitflags::parser::WriteHex
62//! [`Zeroable`]: bytemuck::Zeroable
63//! [`Pod`]: bytemuck::Pod
64//! [`linux/types.h`]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/types.h?h=v6.9#n36
65//! [`KnownLayout`]: zerocopy::KnownLayout
66//! [`Immutable`]: zerocopy::Immutable
67//! [`FromBytes`]: zerocopy::FromBytes
68//! [`IntoBytes`]: zerocopy::IntoBytes
69//!
70//! # Related crates
71//!
72//! Several crates provide alternative approaches to byte-order-aware numeric types:
73//!
74//! - [endian-type](https://docs.rs/endian-type)
75//! - [endian-type-rs](https://docs.rs/endian-type-rs) — Depends on `num`.
76//! - [endiantype](https://docs.rs/endiantype)
77//! - [nora_endian](https://docs.rs/nora_endian)
78//! - [simple_endian](https://docs.rs/simple_endian) — Also provides `f32`, `f64`, and `bool` types.
79//! - [`zerocopy::byteorder`] — These types are [`Unaligned`](zerocopy::Unaligned), which makes them unsuitable for volatile memory operations.
80//!
81//! [`zerocopy::byteorder`]: https://docs.rs/zerocopy/0.7/zerocopy/byteorder/index.html
82
83#![no_std]
84#![cfg_attr(docsrs, feature(doc_auto_cfg))]
85#![warn(missing_docs)]
86#![warn(rust_2018_idioms)]
87
88#[macro_use]
89mod internal_macros;
90
91use core::cmp::Ordering;
92use core::iter::{Product, Sum};
93use core::num::TryFromIntError;
94use core::ops::{
95    Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
96    Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
97};
98use core::{fmt, mem};
99
100/// An integer stored in big-endian byte order.
101///
102/// # Examples
103///
104/// ```
105/// use endian_num::Be;
106///
107/// let n = 0x1Au32;
108///
109/// if cfg!(target_endian = "big") {
110///     assert_eq!(Be::<u32>::from_ne(n).0, n);
111/// } else {
112///     assert_eq!(Be::<u32>::from_ne(n).0, n.swap_bytes());
113/// }
114/// ```
115#[cfg_attr(
116    feature = "bytemuck",
117    derive(bytemuck_derive::Zeroable, bytemuck_derive::Pod)
118)]
119#[cfg_attr(
120    feature = "zerocopy",
121    derive(
122        zerocopy_derive::KnownLayout,
123        zerocopy_derive::Immutable,
124        zerocopy_derive::FromBytes,
125        zerocopy_derive::IntoBytes,
126    )
127)]
128#[derive(Default, Hash, PartialEq, Eq, Clone, Copy)]
129#[repr(transparent)]
130pub struct Be<T>(pub T);
131
132/// An integer stored in little-endian byte order.
133///
134/// # Examples
135///
136/// ```
137/// use endian_num::Le;
138///
139/// let n = 0x1Au32;
140///
141/// if cfg!(target_endian = "little") {
142///     assert_eq!(Le::<u32>::from_ne(n).0, n);
143/// } else {
144///     assert_eq!(Le::<u32>::from_ne(n).0, n.swap_bytes());
145/// }
146/// ```
147#[cfg_attr(
148    feature = "bytemuck",
149    derive(bytemuck_derive::Zeroable, bytemuck_derive::Pod)
150)]
151#[cfg_attr(
152    feature = "zerocopy",
153    derive(
154        zerocopy_derive::KnownLayout,
155        zerocopy_derive::Immutable,
156        zerocopy_derive::FromBytes,
157        zerocopy_derive::IntoBytes,
158    )
159)]
160#[derive(Default, Hash, PartialEq, Eq, Clone, Copy)]
161#[repr(transparent)]
162pub struct Le<T>(pub T);
163
164macro_rules! impl_fmt {
165    (impl<T> $Trait:ident for Xe<T>) => {
166        impl_fmt!(impl<T> $Trait for Be<T>);
167        impl_fmt!(impl<T> $Trait for Le<T>);
168    };
169    (impl<T> $Trait:ident for $SelfT:ident<T>) => {
170        impl<T> fmt::$Trait for $SelfT<T>
171        where
172            Self: Copy + Into<T>,
173            T: fmt::$Trait,
174        {
175            #[inline]
176            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
177                (*self).into().fmt(f)
178            }
179        }
180    };
181}
182
183impl_fmt! { impl<T> Debug for Xe<T> }
184impl_fmt! { impl<T> Display for Xe<T> }
185impl_fmt! { impl<T> Binary for Xe<T> }
186impl_fmt! { impl<T> Octal for Xe<T> }
187impl_fmt! { impl<T> LowerHex for Xe<T> }
188impl_fmt! { impl<T> UpperHex for Xe<T> }
189impl_fmt! { impl<T> LowerExp for Xe<T> }
190impl_fmt! { impl<T> UpperExp for Xe<T> }
191
192macro_rules! unop_impl {
193    (impl $Trait:ident, $method:ident for $T:ty) => {
194        impl $Trait for $T {
195            type Output = Self;
196
197            #[inline]
198            #[track_caller]
199            fn $method(self) -> Self::Output {
200                Self::Output::from_ne($Trait::$method(self.to_ne()))
201            }
202        }
203    };
204}
205
206macro_rules! binop_impl {
207    (impl $Trait:ident<Self>, $method:ident for $T:ty) => {
208        impl $Trait<Self> for $T {
209            type Output = Self;
210
211            #[inline]
212            #[track_caller]
213            fn $method(self, rhs: Self) -> Self::Output {
214                Self::Output::from_ne($Trait::$method(self.to_ne(), rhs.to_ne()))
215            }
216        }
217    };
218    (impl $Trait:ident<$Rhs:ty>, $method:ident for $T:ty) => {
219        impl $Trait<$Rhs> for $T {
220            type Output = Self;
221
222            #[inline]
223            #[track_caller]
224            fn $method(self, rhs: $Rhs) -> Self::Output {
225                Self::Output::from_ne($Trait::$method(self.to_ne(), rhs))
226            }
227        }
228    };
229}
230
231macro_rules! op_assign_impl {
232    (impl $Trait:ident<$Rhs:ty>, $method:ident for $T:ty, $binop:path) => {
233        impl $Trait<$Rhs> for $T {
234            #[inline]
235            #[track_caller]
236            fn $method(&mut self, rhs: $Rhs) {
237                *self = $binop(*self, rhs);
238            }
239        }
240    };
241}
242
243macro_rules! endian_impl {
244    ($(Xe<$T:ty>)*) => {$(
245        endian_impl! { Be<$T> }
246        endian_impl! { Le<$T> }
247    )*};
248    ($($Xe:ident<$T:ty>)*) => {$(
249        impl PartialOrd for $Xe<$T> {
250            #[inline]
251            fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
252                Some(self.cmp(rhs))
253            }
254        }
255
256        impl Ord for $Xe<$T> {
257            #[inline]
258            fn cmp(&self, rhs: &Self) -> Ordering {
259                Ord::cmp(&self.to_ne(), &rhs.to_ne())
260            }
261        }
262
263        unop_impl! { impl Not, not for $Xe<$T> }
264
265        forward_ref_unop! { impl Not, not for $Xe<$T> }
266
267        binop_impl! { impl Add<Self>, add for $Xe<$T> }
268        binop_impl! { impl BitAnd<Self>, bitand for $Xe<$T> }
269        binop_impl! { impl BitOr<Self>, bitor for $Xe<$T> }
270        binop_impl! { impl BitXor<Self>, bitxor for $Xe<$T> }
271        binop_impl! { impl Div<Self>, div for $Xe<$T> }
272        binop_impl! { impl Mul<Self>, mul for $Xe<$T> }
273        binop_impl! { impl Rem<Self>, rem for $Xe<$T> }
274        binop_impl! { impl Sub<Self>, sub for $Xe<$T> }
275
276        forward_ref_binop! { impl Add<$Xe<$T>>, add for $Xe<$T> }
277        forward_ref_binop! { impl BitAnd<$Xe<$T>>, bitand for $Xe<$T> }
278        forward_ref_binop! { impl BitOr<$Xe<$T>>, bitor for $Xe<$T> }
279        forward_ref_binop! { impl BitXor<$Xe<$T>>, bitxor for $Xe<$T> }
280        forward_ref_binop! { impl Div<$Xe<$T>>, div for $Xe<$T> }
281        forward_ref_binop! { impl Mul<$Xe<$T>>, mul for $Xe<$T> }
282        forward_ref_binop! { impl Rem<$Xe<$T>>, rem for $Xe<$T> }
283        forward_ref_binop! { impl Sub<$Xe<$T>>, sub for $Xe<$T> }
284
285        op_assign_impl! { impl AddAssign<Self>, add_assign for $Xe<$T>, Add::add }
286        op_assign_impl! { impl BitAndAssign<Self>, bitand_assign for $Xe<$T>, BitAnd::bitand }
287        op_assign_impl! { impl BitOrAssign<Self>, bitor_assign for $Xe<$T>, BitOr::bitor }
288        op_assign_impl! { impl BitXorAssign<Self>, bitxor_assign for $Xe<$T>, BitXor::bitxor }
289        op_assign_impl! { impl DivAssign<Self>, div_assign for $Xe<$T>, Div::div }
290        op_assign_impl! { impl MulAssign<Self>, mul_assign for $Xe<$T>, Mul::mul }
291        op_assign_impl! { impl RemAssign<Self>, rem_assign for $Xe<$T>, Rem::rem }
292        op_assign_impl! { impl SubAssign<Self>, sub_assign for $Xe<$T>, Sub::sub }
293
294        forward_ref_op_assign! { impl AddAssign<$Xe<$T>>, add_assign for $Xe<$T> }
295        forward_ref_op_assign! { impl BitAndAssign<$Xe<$T>>, bitand_assign for $Xe<$T> }
296        forward_ref_op_assign! { impl BitOrAssign<$Xe<$T>>, bitor_assign for $Xe<$T> }
297        forward_ref_op_assign! { impl BitXorAssign<$Xe<$T>>, bitxor_assign for $Xe<$T> }
298        forward_ref_op_assign! { impl DivAssign<$Xe<$T>>, div_assign for $Xe<$T> }
299        forward_ref_op_assign! { impl MulAssign<$Xe<$T>>, mul_assign for $Xe<$T> }
300        forward_ref_op_assign! { impl RemAssign<$Xe<$T>>, rem_assign for $Xe<$T> }
301        forward_ref_op_assign! { impl SubAssign<$Xe<$T>>, sub_assign for $Xe<$T> }
302
303        binop_impl! { impl Shl<u8>, shl for $Xe<$T> }
304        binop_impl! { impl Shl<u16>, shl for $Xe<$T> }
305        binop_impl! { impl Shl<u32>, shl for $Xe<$T> }
306        binop_impl! { impl Shl<u64>, shl for $Xe<$T> }
307        binop_impl! { impl Shl<u128>, shl for $Xe<$T> }
308        binop_impl! { impl Shl<usize>, shl for $Xe<$T> }
309        binop_impl! { impl Shl<i8>, shl for $Xe<$T> }
310        binop_impl! { impl Shl<i16>, shl for $Xe<$T> }
311        binop_impl! { impl Shl<i32>, shl for $Xe<$T> }
312        binop_impl! { impl Shl<i64>, shl for $Xe<$T> }
313        binop_impl! { impl Shl<i128>, shl for $Xe<$T> }
314        binop_impl! { impl Shl<isize>, shl for $Xe<$T> }
315
316        binop_impl! { impl Shr<u8>, shr for $Xe<$T> }
317        binop_impl! { impl Shr<u16>, shr for $Xe<$T> }
318        binop_impl! { impl Shr<u32>, shr for $Xe<$T> }
319        binop_impl! { impl Shr<u64>, shr for $Xe<$T> }
320        binop_impl! { impl Shr<u128>, shr for $Xe<$T> }
321        binop_impl! { impl Shr<usize>, shr for $Xe<$T> }
322        binop_impl! { impl Shr<i8>, shr for $Xe<$T> }
323        binop_impl! { impl Shr<i16>, shr for $Xe<$T> }
324        binop_impl! { impl Shr<i32>, shr for $Xe<$T> }
325        binop_impl! { impl Shr<i64>, shr for $Xe<$T> }
326        binop_impl! { impl Shr<i128>, shr for $Xe<$T> }
327        binop_impl! { impl Shr<isize>, shr for $Xe<$T> }
328
329        forward_ref_binop! { impl Shl<u8>, shl for $Xe<$T> }
330        forward_ref_binop! { impl Shl<u16>, shl for $Xe<$T> }
331        forward_ref_binop! { impl Shl<u32>, shl for $Xe<$T> }
332        forward_ref_binop! { impl Shl<u64>, shl for $Xe<$T> }
333        forward_ref_binop! { impl Shl<u128>, shl for $Xe<$T> }
334        forward_ref_binop! { impl Shl<usize>, shl for $Xe<$T> }
335        forward_ref_binop! { impl Shl<i8>, shl for $Xe<$T> }
336        forward_ref_binop! { impl Shl<i16>, shl for $Xe<$T> }
337        forward_ref_binop! { impl Shl<i32>, shl for $Xe<$T> }
338        forward_ref_binop! { impl Shl<i64>, shl for $Xe<$T> }
339        forward_ref_binop! { impl Shl<i128>, shl for $Xe<$T> }
340        forward_ref_binop! { impl Shl<isize>, shl for $Xe<$T> }
341
342        forward_ref_binop! { impl Shr<u8>, shr for $Xe<$T> }
343        forward_ref_binop! { impl Shr<u16>, shr for $Xe<$T> }
344        forward_ref_binop! { impl Shr<u32>, shr for $Xe<$T> }
345        forward_ref_binop! { impl Shr<u64>, shr for $Xe<$T> }
346        forward_ref_binop! { impl Shr<u128>, shr for $Xe<$T> }
347        forward_ref_binop! { impl Shr<usize>, shr for $Xe<$T> }
348        forward_ref_binop! { impl Shr<i8>, shr for $Xe<$T> }
349        forward_ref_binop! { impl Shr<i16>, shr for $Xe<$T> }
350        forward_ref_binop! { impl Shr<i32>, shr for $Xe<$T> }
351        forward_ref_binop! { impl Shr<i64>, shr for $Xe<$T> }
352        forward_ref_binop! { impl Shr<i128>, shr for $Xe<$T> }
353        forward_ref_binop! { impl Shr<isize>, shr for $Xe<$T> }
354
355        op_assign_impl! { impl ShlAssign<u8>, shl_assign for $Xe<$T>, Shl::shl }
356        op_assign_impl! { impl ShlAssign<u16>, shl_assign for $Xe<$T>, Shl::shl }
357        op_assign_impl! { impl ShlAssign<u32>, shl_assign for $Xe<$T>, Shl::shl }
358        op_assign_impl! { impl ShlAssign<u64>, shl_assign for $Xe<$T>, Shl::shl }
359        op_assign_impl! { impl ShlAssign<u128>, shl_assign for $Xe<$T>, Shl::shl }
360        op_assign_impl! { impl ShlAssign<usize>, shl_assign for $Xe<$T>, Shl::shl }
361        op_assign_impl! { impl ShlAssign<i8>, shl_assign for $Xe<$T>, Shl::shl }
362        op_assign_impl! { impl ShlAssign<i16>, shl_assign for $Xe<$T>, Shl::shl }
363        op_assign_impl! { impl ShlAssign<i32>, shl_assign for $Xe<$T>, Shl::shl }
364        op_assign_impl! { impl ShlAssign<i64>, shl_assign for $Xe<$T>, Shl::shl }
365        op_assign_impl! { impl ShlAssign<i128>, shl_assign for $Xe<$T>, Shl::shl }
366        op_assign_impl! { impl ShlAssign<isize>, shl_assign for $Xe<$T>, Shl::shl }
367
368        op_assign_impl! { impl ShrAssign<u8>, shr_assign for $Xe<$T>, Shr::shr }
369        op_assign_impl! { impl ShrAssign<u16>, shr_assign for $Xe<$T>, Shr::shr }
370        op_assign_impl! { impl ShrAssign<u32>, shr_assign for $Xe<$T>, Shr::shr }
371        op_assign_impl! { impl ShrAssign<u64>, shr_assign for $Xe<$T>, Shr::shr }
372        op_assign_impl! { impl ShrAssign<u128>, shr_assign for $Xe<$T>, Shr::shr }
373        op_assign_impl! { impl ShrAssign<usize>, shr_assign for $Xe<$T>, Shr::shr }
374        op_assign_impl! { impl ShrAssign<i8>, shr_assign for $Xe<$T>, Shr::shr }
375        op_assign_impl! { impl ShrAssign<i16>, shr_assign for $Xe<$T>, Shr::shr }
376        op_assign_impl! { impl ShrAssign<i32>, shr_assign for $Xe<$T>, Shr::shr }
377        op_assign_impl! { impl ShrAssign<i64>, shr_assign for $Xe<$T>, Shr::shr }
378        op_assign_impl! { impl ShrAssign<i128>, shr_assign for $Xe<$T>, Shr::shr }
379        op_assign_impl! { impl ShrAssign<isize>, shr_assign for $Xe<$T>, Shr::shr }
380
381        forward_ref_op_assign! { impl ShlAssign<u8>, shl_assign for $Xe<$T> }
382        forward_ref_op_assign! { impl ShlAssign<u16>, shl_assign for $Xe<$T> }
383        forward_ref_op_assign! { impl ShlAssign<u32>, shl_assign for $Xe<$T> }
384        forward_ref_op_assign! { impl ShlAssign<u64>, shl_assign for $Xe<$T> }
385        forward_ref_op_assign! { impl ShlAssign<u128>, shl_assign for $Xe<$T> }
386        forward_ref_op_assign! { impl ShlAssign<usize>, shl_assign for $Xe<$T> }
387        forward_ref_op_assign! { impl ShlAssign<i8>, shl_assign for $Xe<$T> }
388        forward_ref_op_assign! { impl ShlAssign<i16>, shl_assign for $Xe<$T> }
389        forward_ref_op_assign! { impl ShlAssign<i32>, shl_assign for $Xe<$T> }
390        forward_ref_op_assign! { impl ShlAssign<i64>, shl_assign for $Xe<$T> }
391        forward_ref_op_assign! { impl ShlAssign<i128>, shl_assign for $Xe<$T> }
392        forward_ref_op_assign! { impl ShlAssign<isize>, shl_assign for $Xe<$T> }
393
394        forward_ref_op_assign! { impl ShrAssign<u8>, shr_assign for $Xe<$T> }
395        forward_ref_op_assign! { impl ShrAssign<u16>, shr_assign for $Xe<$T> }
396        forward_ref_op_assign! { impl ShrAssign<u32>, shr_assign for $Xe<$T> }
397        forward_ref_op_assign! { impl ShrAssign<u64>, shr_assign for $Xe<$T> }
398        forward_ref_op_assign! { impl ShrAssign<u128>, shr_assign for $Xe<$T> }
399        forward_ref_op_assign! { impl ShrAssign<usize>, shr_assign for $Xe<$T> }
400        forward_ref_op_assign! { impl ShrAssign<i8>, shr_assign for $Xe<$T> }
401        forward_ref_op_assign! { impl ShrAssign<i16>, shr_assign for $Xe<$T> }
402        forward_ref_op_assign! { impl ShrAssign<i32>, shr_assign for $Xe<$T> }
403        forward_ref_op_assign! { impl ShrAssign<i64>, shr_assign for $Xe<$T> }
404        forward_ref_op_assign! { impl ShrAssign<i128>, shr_assign for $Xe<$T> }
405        forward_ref_op_assign! { impl ShrAssign<isize>, shr_assign for $Xe<$T> }
406    )*};
407}
408
409endian_impl! { Xe<u8> Xe<u16> Xe<u32> Xe<u64> Xe<u128> Xe<usize> Xe<i8> Xe<i16> Xe<i32> Xe<i64> Xe<i128> Xe<isize> }
410
411macro_rules! impl_from {
412    (Xe<$Small:ty> => Xe<$Large:ty>) => {
413        impl_from!(Be<$Small> => Be<$Large>);
414        impl_from!(Le<$Small> => Le<$Large>);
415    };
416    ($Small:ty => $Large:ty) => {
417        impl From<$Small> for $Large {
418            #[doc = concat!("Converts [`", stringify!($Small), "`] to [`", stringify!($Large), "`] losslessly.")]
419            #[inline]
420            fn from(small: $Small) -> Self {
421                Self::from_ne(small.to_ne().into())
422            }
423        }
424    };
425}
426
427// unsigned integer -> unsigned integer
428impl_from!(Xe<u8> => Xe<u16>);
429impl_from!(Xe<u8> => Xe<u32>);
430impl_from!(Xe<u8> => Xe<u64>);
431impl_from!(Xe<u8> => Xe<u128>);
432impl_from!(Xe<u8> => Xe<usize>);
433impl_from!(Xe<u16> => Xe<u32>);
434impl_from!(Xe<u16> => Xe<u64>);
435impl_from!(Xe<u16> => Xe<u128>);
436impl_from!(Xe<u32> => Xe<u64>);
437impl_from!(Xe<u32> => Xe<u128>);
438impl_from!(Xe<u64> => Xe<u128>);
439
440// signed integer -> signed integer
441impl_from!(Xe<i8> => Xe<i16>);
442impl_from!(Xe<i8> => Xe<i32>);
443impl_from!(Xe<i8> => Xe<i64>);
444impl_from!(Xe<i8> => Xe<i128>);
445impl_from!(Xe<i8> => Xe<isize>);
446impl_from!(Xe<i16> => Xe<i32>);
447impl_from!(Xe<i16> => Xe<i64>);
448impl_from!(Xe<i16> => Xe<i128>);
449impl_from!(Xe<i32> => Xe<i64>);
450impl_from!(Xe<i32> => Xe<i128>);
451impl_from!(Xe<i64> => Xe<i128>);
452
453// unsigned integer -> signed integer
454impl_from!(Xe<u8> => Xe<i16>);
455impl_from!(Xe<u8> => Xe<i32>);
456impl_from!(Xe<u8> => Xe<i64>);
457impl_from!(Xe<u8> => Xe<i128>);
458impl_from!(Xe<u16> => Xe<i32>);
459impl_from!(Xe<u16> => Xe<i64>);
460impl_from!(Xe<u16> => Xe<i128>);
461impl_from!(Xe<u32> => Xe<i64>);
462impl_from!(Xe<u32> => Xe<i128>);
463impl_from!(Xe<u64> => Xe<i128>);
464
465// The C99 standard defines bounds on INTPTR_MIN, INTPTR_MAX, and UINTPTR_MAX
466// which imply that pointer-sized integers must be at least 16 bits:
467// https://port70.net/~nsz/c/c99/n1256.html#7.18.2.4
468impl_from!(Xe<u16> => Xe<usize>);
469impl_from!(Xe<u8> => Xe<isize>);
470impl_from!(Xe<i16> => Xe<isize>);
471
472macro_rules! impl_try_from {
473    (Xe<$source:ty> => $(Xe<$target:ty>),+) => {$(
474        impl_try_from!(Be<$source> => Be<$target>);
475        impl_try_from!(Le<$source> => Le<$target>);
476    )*};
477    ($Xe:ident<$source:ty> => $Xe2:ident<$target:ty>) => {
478        impl TryFrom<$Xe<$source>> for $Xe<$target> {
479            type Error = TryFromIntError;
480
481            /// Try to create the target number type from a source
482            /// number type. This returns an error if the source value
483            /// is outside of the range of the target type.
484            #[inline]
485            fn try_from(u: $Xe<$source>) -> Result<Self, Self::Error> {
486                <$target>::try_from(u.to_ne()).map(Self::from_ne)
487            }
488        }
489    };
490}
491
492// unsigned integer -> unsigned integer
493impl_try_from!(Xe<u16> => Xe<u8>);
494impl_try_from!(Xe<u32> => Xe<u8>, Xe<u16>);
495impl_try_from!(Xe<u64> => Xe<u8>, Xe<u16>, Xe<u32>);
496impl_try_from!(Xe<u128> => Xe<u8>, Xe<u16>, Xe<u32>, Xe<u64>);
497
498// signed integer -> signed integer
499impl_try_from!(Xe<i16> => Xe<i8>);
500impl_try_from!(Xe<i32> => Xe<i8>, Xe<i16>);
501impl_try_from!(Xe<i64> => Xe<i8>, Xe<i16>, Xe<i32>);
502impl_try_from!(Xe<i128> => Xe<i8>, Xe<i16>, Xe<i32>, Xe<i64>);
503
504// unsigned integer -> signed integer
505impl_try_from!(Xe<u8> => Xe<i8>);
506impl_try_from!(Xe<u16> => Xe<i8>, Xe<i16>);
507impl_try_from!(Xe<u32> => Xe<i8>, Xe<i16>, Xe<i32>);
508impl_try_from!(Xe<u64> => Xe<i8>, Xe<i16>, Xe<i32>, Xe<i64>);
509impl_try_from!(Xe<u128> => Xe<i8>, Xe<i16>, Xe<i32>, Xe<i64>, Xe<i128>);
510
511// signed integer -> unsigned integer
512impl_try_from!(Xe<i8> => Xe<u8>, Xe<u16>, Xe<u32>, Xe<u64>, Xe<u128>);
513impl_try_from!(Xe<i16> => Xe<u8>);
514impl_try_from!(Xe<i16> => Xe<u16>, Xe<u32>, Xe<u64>, Xe<u128>);
515impl_try_from!(Xe<i32> => Xe<u8>, Xe<u16>);
516impl_try_from!(Xe<i32> => Xe<u32>, Xe<u64>, Xe<u128>);
517impl_try_from!(Xe<i64> => Xe<u8>, Xe<u16>, Xe<u32>);
518impl_try_from!(Xe<i64> => Xe<u64>, Xe<u128>);
519impl_try_from!(Xe<i128> => Xe<u8>, Xe<u16>, Xe<u32>, Xe<u64>);
520impl_try_from!(Xe<i128> => Xe<u128>);
521
522// usize/isize
523impl_try_from!(Xe<usize> => Xe<isize>);
524impl_try_from!(Xe<isize> => Xe<usize>);
525
526macro_rules! impl_sum_product {
527    ($(Xe<$T:ty>)*) => {$(
528        impl_sum_product!(Be<$T>);
529        impl_sum_product!(Le<$T>);
530    )*};
531    ($Xe:ty) => (
532        impl Sum for $Xe {
533            fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
534                iter.fold(<$Xe>::from_ne(0), |a, b| a + b)
535            }
536        }
537
538        impl Product for $Xe {
539            fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
540                iter.fold(<$Xe>::from_ne(1), |a, b| a * b)
541            }
542        }
543
544        impl<'a> Sum<&'a $Xe> for $Xe {
545            fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
546                iter.fold(<$Xe>::from_ne(0), |a, b| a + b)
547            }
548        }
549
550        impl<'a> Product<&'a $Xe> for $Xe {
551            fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
552                iter.fold(<$Xe>::from_ne(1), |a, b| a * b)
553            }
554        }
555    );
556}
557
558impl_sum_product! { Xe<i8> Xe<i16> Xe<i32> Xe<i64> Xe<i128> Xe<isize> Xe<u8> Xe<u16> Xe<u32> Xe<u64> Xe<u128> Xe<usize> }
559
560#[cfg(target_pointer_width = "16")]
561macro_rules! usize_macro {
562    ($macro:ident) => {
563        $macro!(u16)
564    };
565}
566
567#[cfg(target_pointer_width = "32")]
568macro_rules! usize_macro {
569    ($macro:ident) => {
570        $macro!(u32)
571    };
572}
573
574#[cfg(target_pointer_width = "64")]
575macro_rules! usize_macro {
576    ($macro:ident) => {
577        $macro!(u64)
578    };
579}
580
581#[rustfmt::skip]
582macro_rules! rot {
583    (u8) => { 2 };
584    (u16) => { 4 };
585    (u32) => { 8 };
586    (u64) => { 12 };
587    (u128) => { 16 };
588    (usize) => { usize_macro!(rot) };
589    (i8) => { rot!(u8) };
590    (i16) => { rot!(u16) };
591    (i32) => { rot!(u32) };
592    (i64) => { rot!(u64) };
593    (i128) => { rot!(u128) };
594    (isize) => { rot!(usize) };
595}
596
597#[rustfmt::skip]
598macro_rules! rot_op {
599    (u8) => { "0x82" };
600    (u16) => { "0xa003" };
601    (u32) => { "0x10000b3" };
602    (u64) => { "0xaa00000000006e1" };
603    (u128) => { "0x13f40000000000000000000000004f76" };
604    (usize) => { usize_macro!(rot_op) };
605    (i8) => { "-0x7e" };
606    (i16) => { "-0x5ffd" };
607    (i32) => { rot_op!(u32) };
608    (i64) => { rot_op!(u64) };
609    (i128) => { rot_op!(u128) };
610    (isize) => { rot_op!(usize) };
611}
612
613#[rustfmt::skip]
614macro_rules! rot_result {
615    (u8) => { "0xa" };
616    (u16) => { "0x3a" };
617    (u32) => { "0xb301" };
618    (u64) => { "0x6e10aa" };
619    (u128) => { "0x4f7613f4" };
620    (usize) => { usize_macro!(rot_result) };
621    (i8) => { rot_result!(u8) };
622    (i16) => { rot_result!(u16) };
623    (i32) => { rot_result!(u32) };
624    (i64) => { rot_result!(u64) };
625    (i128) => { rot_result!(u128) };
626    (isize) => { rot_result!(usize) };
627}
628
629#[rustfmt::skip]
630macro_rules! swap_op {
631    (u8) => { "0x12" };
632    (u16) => { "0x1234" };
633    (u32) => { "0x12345678" };
634    (u64) => { "0x1234567890123456" };
635    (u128) => { "0x12345678901234567890123456789012" };
636    (usize) => { usize_macro!(swap_op) };
637    (i8) => { swap_op!(u8) };
638    (i16) => { swap_op!(u16) };
639    (i32) => { swap_op!(u32) };
640    (i64) => { swap_op!(u64) };
641    (i128) => { swap_op!(u128) };
642    (isize) => { swap_op!(usize) };
643}
644
645#[rustfmt::skip]
646macro_rules! swapped {
647    (u8) => { "0x12" };
648    (u16) => { "0x3412" };
649    (u32) => { "0x78563412" };
650    (u64) => { "0x5634129078563412" };
651    (u128) => { "0x12907856341290785634129078563412" };
652    (usize) => { usize_macro!(swapped) };
653    (i8) => { swapped!(u8) };
654    (i16) => { swapped!(u16) };
655    (i32) => { swapped!(u32) };
656    (i64) => { swapped!(u64) };
657    (i128) => { swapped!(u128) };
658    (isize) => { swapped!(usize) };
659}
660
661#[rustfmt::skip]
662macro_rules! reversed {
663    (u8) => { "0x48" };
664    (u16) => { "0x2c48" };
665    (u32) => { "0x1e6a2c48" };
666    (u64) => { "0x6a2c48091e6a2c48" };
667    (u128) => { "0x48091e6a2c48091e6a2c48091e6a2c48" };
668    (usize) => { usize_macro!(reversed) };
669    (i8) => { reversed!(u8) };
670    (i16) => { reversed!(u16) };
671    (i32) => { reversed!(u32) };
672    (i64) => { reversed!(u64) };
673    (i128) => { reversed!(u128) };
674    (isize) => { reversed!(usize) };
675}
676
677macro_rules! be_bytes {
678    (u8) => { "[0x12]" };
679    (u16) => { "[0x12, 0x34]" };
680    (u32) => { "[0x12, 0x34, 0x56, 0x78]" };
681    (u64) => { "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]" };
682    (u128) => { "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]" };
683    (usize) => { usize_macro!(be_bytes) };
684    (i8) => { be_bytes!(u8) };
685    (i16) => { be_bytes!(u16) };
686    (i32) => { be_bytes!(u32) };
687    (i64) => { be_bytes!(u64) };
688    (i128) => { be_bytes!(u128) };
689    (isize) => { be_bytes!(usize) };
690}
691
692macro_rules! le_bytes {
693    (u8) => { "[0x12]" };
694    (u16) => { "[0x34, 0x12]" };
695    (u32) => { "[0x78, 0x56, 0x34, 0x12]" };
696    (u64) => { "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]" };
697    (u128) => { "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]" };
698    (usize) => { usize_macro!(le_bytes) };
699    (i8) => { le_bytes!(u8) };
700    (i16) => { le_bytes!(u16) };
701    (i32) => { le_bytes!(u32) };
702    (i64) => { le_bytes!(u64) };
703    (i128) => { le_bytes!(u128) };
704    (isize) => { le_bytes!(usize) };
705}
706
707macro_rules! endian_int_impl {
708    ($(Xe<$T:ident>)*) => {$(
709        endian_int_impl! { Be<$T>, from_be, to_be, "big", Le, from_le, to_le, "little" }
710        endian_int_impl! { Le<$T>, from_le, to_le, "little", Be, from_be, to_be, "big" }
711    )*};
712    ($Xe:ident<$T:ident>, $from_xe:ident, $to_xe:ident, $order:literal, $Other:ident, $from_other:ident, $to_other:ident, $order_other:literal) => {
713        impl $Xe<$T> {
714            /// The smallest value that can be represented by this integer type.
715            ///
716            /// # Examples
717            ///
718            /// Basic usage:
719            ///
720            /// ```
721            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
722            ///
723            #[doc = concat!("assert_eq!(", stringify!($Xe), "::<", stringify!($T), ">::MIN, ", stringify!($Xe), "::<", stringify!($T), ">::from_ne(", stringify!($T), "::MIN));")]
724            /// ```
725            pub const MIN: Self = Self::from_ne(<$T>::MIN);
726
727            /// The largest value that can be represented by this integer type.
728            ///
729            /// # Examples
730            ///
731            /// Basic usage:
732            ///
733            /// ```
734            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
735            ///
736            #[doc = concat!("assert_eq!(", stringify!($Xe), "::<", stringify!($T), ">::MAX, ", stringify!($Xe), "::<", stringify!($T), ">::from_ne(", stringify!($T), "::MAX));")]
737            /// ```
738            pub const MAX: Self = Self::from_ne(<$T>::MAX);
739
740            /// The size of this integer type in bits.
741            ///
742            /// # Examples
743            ///
744            /// Basic usage:
745            ///
746            /// ```
747            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
748            ///
749            #[doc = concat!("assert_eq!(", stringify!($Xe), "::<", stringify!($T), ">::BITS, ", stringify!($T), "::BITS);")]
750            /// ```
751            pub const BITS: u32 = <$T>::BITS;
752
753            #[doc = concat!("Creates a new ", $order, "-endian integer from a native-endian integer.")]
754            ///
755            #[doc = concat!("On ", $order, " endian, this is a no-op. On ", $order_other, " endian, the bytes are swapped.")]
756            ///
757            /// # Examples
758            ///
759            /// Basic usage:
760            ///
761            /// ```
762            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
763            ///
764            #[doc = concat!("let n = 0x1A", stringify!($T), ";")]
765            ///
766            #[doc = concat!("if cfg!(target_endian = \"", $order, "\") {")]
767            #[doc = concat!("    assert_eq!(", stringify!($Xe), "::<", stringify!($T), ">::from_ne(n).0, n);")]
768            /// } else {
769            #[doc = concat!("    assert_eq!(", stringify!($Xe), "::<", stringify!($T), ">::from_ne(n).0, n.swap_bytes());")]
770            /// }
771            /// ```
772            #[must_use]
773            #[inline]
774            pub const fn from_ne(n: $T) -> Self {
775                Self(n.$to_xe())
776            }
777
778            #[doc = concat!("Creates a new ", $order, "-endian integer from a ", $order_other, "-endian integer.")]
779            ///
780            /// This always swaps the bytes.
781            ///
782            /// # Examples
783            ///
784            /// ```
785            #[doc = concat!("use endian_num::{Be, Le};")]
786            ///
787            #[doc = concat!("let n = 0x1A", stringify!($T), ";")]
788            ///
789            #[doc = concat!("assert_eq!(", stringify!($Xe), "::<", stringify!($T), ">::", stringify!($from_other), "(", stringify!($Other), "(n)).0, n.swap_bytes());")]
790            /// ```
791            #[must_use]
792            #[inline]
793            pub const fn $from_other(n: $Other<$T>) -> Self {
794                Self(n.0.swap_bytes())
795            }
796
797            /// Returns the integer in native-endian byte order.
798            ///
799            #[doc = concat!("On ", $order, " endian, this is a no-op. On ", $order_other, " endian, the bytes are swapped.")]
800            ///
801            /// # Examples
802            ///
803            /// Basic usage:
804            ///
805            /// ```
806            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
807            ///
808            #[doc = concat!("let n = 0x1A", stringify!($T), ";")]
809            ///
810            #[doc = concat!("if cfg!(target_endian = \"", $order, "\") {")]
811            #[doc = concat!("    assert_eq!(", stringify!($Xe), "(n).to_ne(), n);")]
812            /// } else {
813            #[doc = concat!("    assert_eq!(", stringify!($Xe), "(n).to_ne(), n.swap_bytes());")]
814            /// }
815            /// ```
816            #[must_use = "this returns the result of the operation, \
817                          without modifying the original"]
818            #[inline]
819            pub const fn to_ne(self) -> $T {
820                <$T>::$from_xe(self.0)
821            }
822
823            #[doc = concat!("Returns the integer in ", $order_other, "-endian byte order.")]
824            ///
825            /// This always swaps the bytes.
826            ///
827            /// # Examples
828            ///
829            /// Basic usage:
830            ///
831            /// ```
832            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
833            ///
834            #[doc = concat!("let n = 0x1A", stringify!($T), ";")]
835            ///
836            #[doc = concat!("assert_eq!(", stringify!($Xe), "(n).", stringify!($to_other), "().0, n.swap_bytes());")]
837            /// ```
838            #[must_use = "this returns the result of the operation, \
839                          without modifying the original"]
840            #[inline]
841            pub const fn $to_other(self) -> $Other<$T> {
842                $Other(self.0.swap_bytes())
843            }
844
845            /// Return the memory representation of this integer as a byte array in big-endian (network) byte order.
846            ///
847            /// # Examples
848            ///
849            /// ```
850            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
851            ///
852            #[doc = concat!("let bytes = ", stringify!($Xe), "::<", stringify!($T), ">::from_ne(", swap_op!($T), ").to_be_bytes();")]
853            #[doc = concat!("assert_eq!(bytes, ", be_bytes!($T), ");")]
854            /// ```
855            #[must_use = "this returns the result of the operation, \
856                          without modifying the original"]
857            #[inline]
858            pub const fn to_be_bytes(self) -> [u8; mem::size_of::<Self>()] {
859                self.to_ne().to_be_bytes()
860            }
861
862            /// Return the memory representation of this integer as a byte array in little-endian byte order.
863            ///
864            /// # Examples
865            ///
866            /// ```
867            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
868            ///
869            #[doc = concat!("let bytes = ", stringify!($Xe), "::<", stringify!($T), ">::from_ne(", swap_op!($T), ").to_le_bytes();")]
870            #[doc = concat!("assert_eq!(bytes, ", le_bytes!($T), ");")]
871            /// ```
872            #[must_use = "this returns the result of the operation, \
873                          without modifying the original"]
874            #[inline]
875            pub const fn to_le_bytes(self) -> [u8; mem::size_of::<Self>()] {
876                self.to_ne().to_le_bytes()
877            }
878
879            /// Return the memory representation of this integer as a byte array in
880            /// native byte order.
881            ///
882            /// As the target platform's native endianness is used, portable code
883            /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate,
884            /// instead.
885            ///
886            /// [`to_be_bytes`]: Self::to_be_bytes
887            /// [`to_le_bytes`]: Self::to_le_bytes
888            ///
889            /// # Examples
890            ///
891            /// ```
892            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
893            ///
894            #[doc = concat!("let bytes = ", stringify!($Xe), "::<", stringify!($T), ">::from_ne(", swap_op!($T), ").to_ne_bytes();")]
895            /// assert_eq!(
896            ///     bytes,
897            ///     if cfg!(target_endian = "big") {
898            #[doc = concat!("        ", be_bytes!($T))]
899            ///     } else {
900            #[doc = concat!("        ", le_bytes!($T))]
901            ///     }
902            /// );
903            /// ```
904            #[must_use = "this returns the result of the operation, \
905                          without modifying the original"]
906            #[inline]
907            pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
908                self.to_ne().to_ne_bytes()
909            }
910
911            #[doc = concat!("Create a ", $order, " endian integer value from its representation as a byte array in ", $order, " endian.")]
912            ///
913            /// # Examples
914            ///
915            /// ```
916            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
917            ///
918            #[doc = concat!("let value = ", stringify!($Xe), "::<", stringify!($T), ">::from_be_bytes(", be_bytes!($T), ");")]
919            #[doc = concat!("assert_eq!(value.to_ne(), ", swap_op!($T), ");")]
920            /// ```
921            ///
922            /// When starting from a slice rather than an array, fallible conversion APIs can be used:
923            ///
924            /// ```
925            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
926            ///
927            #[doc = concat!("fn read_be_", stringify!($T), "(input: &mut &[u8]) -> ", stringify!($Xe), "<", stringify!($T), "> {")]
928            #[doc = concat!("    let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($Xe), "<", stringify!($T), ">>());")]
929            ///     *input = rest;
930            #[doc = concat!("    ", stringify!($Xe), "::<", stringify!($T), ">::from_be_bytes(int_bytes.try_into().unwrap())")]
931            /// }
932            /// ```
933            #[must_use]
934            #[inline]
935            pub const fn from_be_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
936                Self::from_ne(<$T>::from_be_bytes(bytes))
937            }
938
939            #[doc = concat!("Create a ", $order, " endian integer value from its representation as a byte array in ", $order_other, " endian.")]
940            ///
941            /// # Examples
942            ///
943            /// ```
944            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
945            ///
946            #[doc = concat!("let value = ", stringify!($Xe), "::<", stringify!($T), ">::from_le_bytes(", le_bytes!($T), ");")]
947            #[doc = concat!("assert_eq!(value.to_ne(), ", swap_op!($T), ");")]
948            /// ```
949            ///
950            /// When starting from a slice rather than an array, fallible conversion APIs can be used:
951            ///
952            /// ```
953            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
954            ///
955            #[doc = concat!("fn read_le_", stringify!($T), "(input: &mut &[u8]) -> ", stringify!($Xe), "<", stringify!($T), "> {")]
956            #[doc = concat!("    let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($Xe), "<", stringify!($T), ">>());")]
957            ///     *input = rest;
958            #[doc = concat!("    ", stringify!($Xe), "::<", stringify!($T), ">::from_le_bytes(int_bytes.try_into().unwrap())")]
959            /// }
960            /// ```
961            #[must_use]
962            #[inline]
963            pub const fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
964                Self::from_ne(<$T>::from_le_bytes(bytes))
965            }
966
967            #[doc = concat!("Create a ", $order, " endian integer value from its memory representation as a byte array in native endianness.")]
968            ///
969            /// As the target platform's native endianness is used, portable code
970            /// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as
971            /// appropriate instead.
972            ///
973            /// [`from_be_bytes`]: Self::from_be_bytes
974            /// [`from_le_bytes`]: Self::from_le_bytes
975            ///
976            /// # Examples
977            ///
978            /// ```
979            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
980            ///
981            #[doc = concat!("let value = ", stringify!($Xe), "::<", stringify!($T), ">::from_ne_bytes(if cfg!(target_endian = \"big\") {")]
982            #[doc = concat!("    ", be_bytes!($T))]
983            /// } else {
984            #[doc = concat!("    ", le_bytes!($T))]
985            /// });
986            #[doc = concat!("assert_eq!(value.to_ne(), ", swap_op!($T), ");")]
987            /// ```
988            ///
989            /// When starting from a slice rather than an array, fallible conversion APIs can be used:
990            ///
991            /// ```
992            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
993            ///
994            #[doc = concat!("fn read_ne_", stringify!($T), "(input: &mut &[u8]) -> ", stringify!($Xe), "<", stringify!($T), "> {")]
995            #[doc = concat!("    let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($Xe), "<", stringify!($T), ">>());")]
996            ///     *input = rest;
997            #[doc = concat!("    ", stringify!($Xe), "::<", stringify!($T), ">::from_ne_bytes(int_bytes.try_into().unwrap())")]
998            /// }
999            /// ```
1000            #[must_use]
1001            #[inline]
1002            pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
1003                Self::from_ne(<$T>::from_ne_bytes(bytes))
1004            }
1005
1006            /// Shifts the bits to the left by a specified amount, `n`,
1007            /// wrapping the truncated bits to the end of the resulting integer.
1008            ///
1009            /// Please note this isn't the same operation as the `<<` shifting operator!
1010            ///
1011            /// # Examples
1012            ///
1013            /// Basic usage:
1014            ///
1015            /// ```
1016            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
1017            ///
1018            #[doc = concat!("let n = ", stringify!($Xe), "::<", stringify!($T), ">::from_ne(", rot_op!($T), ");")]
1019            #[doc = concat!("let m = ", stringify!($Xe), "::<", stringify!($T), ">::from_ne(", rot_result!($T), ");")]
1020            ///
1021            #[doc = concat!("assert_eq!(n.rotate_left(", rot!($T), "), m);")]
1022            /// ```
1023            #[must_use = "this returns the result of the operation, \
1024                          without modifying the original"]
1025            #[inline]
1026            pub const fn rotate_left(self, n: u32) -> Self {
1027                Self::from_ne(self.to_ne().rotate_left(n))
1028            }
1029
1030            /// Shifts the bits to the right by a specified amount, `n`,
1031            /// wrapping the truncated bits to the beginning of the resulting
1032            /// integer.
1033            ///
1034            /// Please note this isn't the same operation as the `>>` shifting operator!
1035            ///
1036            /// # Examples
1037            ///
1038            /// Basic usage:
1039            ///
1040            /// ```
1041            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
1042            ///
1043            #[doc = concat!("let n = ", stringify!($Xe), "::<", stringify!($T), ">::from_ne(", rot_result!($T), ");")]
1044            #[doc = concat!("let m = ", stringify!($Xe), "::<", stringify!($T), ">::from_ne(", rot_op!($T), ");")]
1045            ///
1046            #[doc = concat!("assert_eq!(n.rotate_right(", rot!($T), "), m);")]
1047            /// ```
1048            #[must_use = "this returns the result of the operation, \
1049                          without modifying the original"]
1050            #[inline]
1051            pub const fn rotate_right(self, n: u32) -> Self {
1052                Self::from_ne(self.to_ne().rotate_right(n))
1053            }
1054
1055            /// Reverses the byte order of the integer.
1056            ///
1057            /// # Examples
1058            ///
1059            /// Basic usage:
1060            ///
1061            /// ```
1062            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
1063            ///
1064            #[doc = concat!("let n = ", stringify!($Xe), "(", swap_op!($T), stringify!($T), ");")]
1065            /// let m = n.swap_bytes();
1066            ///
1067            #[doc = concat!("assert_eq!(m, ", stringify!($Xe), "(", swapped!($T), "));")]
1068            /// ```
1069            #[must_use = "this returns the result of the operation, \
1070                          without modifying the original"]
1071            #[inline]
1072            pub const fn swap_bytes(self) -> Self {
1073                Self(self.0.swap_bytes())
1074            }
1075
1076            /// Reverses the order of bits in the integer.
1077            ///
1078            /// The least significant bit becomes the most significant bit,
1079            /// second least-significant bit becomes second most-significant bit, etc.
1080            ///
1081            /// # Examples
1082            ///
1083            /// Basic usage:
1084            ///
1085            /// ```
1086            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
1087            ///
1088            #[doc = concat!("let n = ", stringify!($Xe), "(", swap_op!($T), stringify!($T), ");")]
1089            /// let m = n.reverse_bits();
1090            ///
1091            #[doc = concat!("assert_eq!(m, ", stringify!($Xe), "(", reversed!($T), "));")]
1092            #[doc = concat!("assert_eq!(", stringify!($Xe), "(0), ", stringify!($Xe), "(0", stringify!($T), ").reverse_bits());")]
1093            /// ```
1094            #[must_use = "this returns the result of the operation, \
1095                          without modifying the original"]
1096            #[inline]
1097            pub const fn reverse_bits(self) -> Self {
1098                Self(self.0.reverse_bits())
1099            }
1100
1101            /// Raises self to the power of `exp`, using exponentiation by squaring.
1102            ///
1103            /// # Examples
1104            ///
1105            /// Basic usage:
1106            ///
1107            /// ```
1108            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
1109            ///
1110            #[doc = concat!("assert_eq!(", stringify!($Xe), "::<", stringify!($T), ">::from_ne(2).pow(5).to_ne(), 32);")]
1111            /// ```
1112            #[must_use = "this returns the result of the operation, \
1113                          without modifying the original"]
1114            #[inline]
1115            pub const fn pow(self, exp: u32) -> Self {
1116                Self::from_ne(self.to_ne().pow(exp))
1117            }
1118        }
1119
1120        impl From<$T> for $Xe<$T> {
1121            #[inline]
1122            fn from(value: $T) -> Self {
1123                Self::from_ne(value)
1124            }
1125        }
1126
1127        impl From<$Xe<$T>> for $T {
1128            #[inline]
1129            fn from(value: $Xe<$T>) -> Self {
1130                value.to_ne()
1131            }
1132        }
1133
1134        impl From<$Other<$T>> for $Xe<$T> {
1135            #[inline]
1136            fn from(value: $Other<$T>) -> Self {
1137                Self::$from_other(value)
1138            }
1139        }
1140
1141        #[cfg(feature = "bitflags")]
1142        impl bitflags::Bits for $Xe<$T> {
1143            const EMPTY: Self = Self::MIN;
1144
1145            const ALL: Self = Self::MAX;
1146        }
1147
1148        #[cfg(feature = "bitflags")]
1149        impl bitflags::parser::ParseHex for $Xe<$T>
1150        {
1151            fn parse_hex(input: &str) -> Result<Self, bitflags::parser::ParseError> {
1152                <$T>::parse_hex(input).map($Xe::<$T>::from_ne)
1153            }
1154        }
1155
1156        #[cfg(feature = "bitflags")]
1157        impl bitflags::parser::WriteHex for $Xe<$T>
1158        {
1159            fn write_hex<W: fmt::Write>(&self, writer: W) -> fmt::Result {
1160                self.to_ne().write_hex(writer)
1161            }
1162        }
1163    };
1164}
1165
1166endian_int_impl! { Xe<u8> Xe<u16> Xe<u32> Xe<u64> Xe<u128> Xe<usize> Xe<i8> Xe<i16> Xe<i32> Xe<i64> Xe<i128> Xe<isize> }
1167
1168macro_rules! endian_int_impl_signed {
1169    ($(Xe<$T:ty>)*) => {$(
1170        endian_int_impl_signed! { Be<$T> }
1171        endian_int_impl_signed! { Le<$T> }
1172    )*};
1173    ($Xe:ident<$T:ty>) => {
1174        unop_impl! { impl Neg, neg for $Xe<$T> }
1175        forward_ref_unop! { impl Neg, neg for $Xe<$T> }
1176
1177        impl $Xe<$T> {
1178            /// Computes the absolute value of self.
1179            ///
1180            #[doc = concat!("See [`", stringify!($T), "::abs`]")]
1181            /// for documentation on overflow behavior.
1182            ///
1183            /// # Examples
1184            ///
1185            /// Basic usage:
1186            ///
1187            /// ```
1188            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
1189            ///
1190            #[doc = concat!("assert_eq!(", stringify!($Xe), "::<", stringify!($T), ">::from_ne(10).abs(), ", stringify!($Xe), "::<", stringify!($T), ">::from_ne(10));")]
1191            #[doc = concat!("assert_eq!(", stringify!($Xe), "::<", stringify!($T), ">::from_ne(-10).abs(), ", stringify!($Xe), "::<", stringify!($T), ">::from_ne(10));")]
1192            /// ```
1193            #[must_use = "this returns the result of the operation, \
1194                          without modifying the original"]
1195            #[inline]
1196            pub const fn abs(self) -> Self {
1197                Self::from_ne(self.to_ne().abs())
1198            }
1199
1200            /// Returns a number representing sign of `self`.
1201            ///
1202            ///  - `0` if the number is zero
1203            ///  - `1` if the number is positive
1204            ///  - `-1` if the number is negative
1205            ///
1206            /// # Examples
1207            ///
1208            /// Basic usage:
1209            ///
1210            /// ```
1211            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
1212            ///
1213            #[doc = concat!("assert_eq!(", stringify!($Xe), "::<", stringify!($T), ">::from_ne(10).signum().to_ne(), 1);")]
1214            #[doc = concat!("assert_eq!(", stringify!($Xe), "::<", stringify!($T), ">::from_ne(0).signum().to_ne(), 0);")]
1215            #[doc = concat!("assert_eq!(", stringify!($Xe), "::<", stringify!($T), ">::from_ne(-10).signum().to_ne(), -1);")]
1216            /// ```
1217            #[must_use = "this returns the result of the operation, \
1218                          without modifying the original"]
1219            #[inline]
1220            pub const fn signum(self) -> Self {
1221                Self::from_ne(self.to_ne().signum())
1222            }
1223
1224            /// Returns `true` if `self` is positive and `false` if the number is zero or
1225            /// negative.
1226            ///
1227            /// # Examples
1228            ///
1229            /// Basic usage:
1230            ///
1231            /// ```
1232            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
1233            ///
1234            #[doc = concat!("assert!(", stringify!($Xe), "::<", stringify!($T), ">::from_ne(10).is_positive());")]
1235            #[doc = concat!("assert!(!", stringify!($Xe), "::<", stringify!($T), ">::from_ne(-10).is_positive());")]
1236            /// ```
1237            #[must_use]
1238            #[inline]
1239            pub const fn is_positive(self) -> bool {
1240                self.to_ne().is_positive()
1241            }
1242
1243            /// Returns `true` if `self` is negative and `false` if the number is zero or
1244            /// positive.
1245            ///
1246            /// # Examples
1247            ///
1248            /// Basic usage:
1249            ///
1250            /// ```
1251            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
1252            ///
1253            #[doc = concat!("assert!(", stringify!($Xe), "::<", stringify!($T), ">::from_ne(-10).is_negative());")]
1254            #[doc = concat!("assert!(!", stringify!($Xe), "::<", stringify!($T), ">::from_ne(10).is_negative());")]
1255            /// ```
1256            #[must_use]
1257            #[inline]
1258            pub const fn is_negative(self) -> bool {
1259                self.to_ne().is_negative()
1260            }
1261
1262            /// Returns the number of ones in the binary representation of `self`.
1263            ///
1264            /// # Examples
1265            ///
1266            /// Basic usage:
1267            ///
1268            /// ```
1269            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
1270            ///
1271            #[doc = concat!("let n = ", stringify!($Xe), "(0b100_0000", stringify!($T), ");")]
1272            ///
1273            /// assert_eq!(n.count_ones(), 1);
1274            /// ```
1275            #[doc(alias = "popcount")]
1276            #[doc(alias = "popcnt")]
1277            #[must_use = "this returns the result of the operation, \
1278                          without modifying the original"]
1279            #[inline]
1280            pub const fn count_ones(self) -> u32 {
1281                self.0.count_ones()
1282            }
1283
1284            /// Returns the number of zeros in the binary representation of `self`.
1285            ///
1286            /// # Examples
1287            ///
1288            /// Basic usage:
1289            ///
1290            /// ```
1291            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
1292            ///
1293            #[doc = concat!("assert_eq!(", stringify!($Xe), "::<", stringify!($T), ">::MAX.count_zeros(), 1);")]
1294            /// ```
1295            #[must_use = "this returns the result of the operation, \
1296                          without modifying the original"]
1297            #[inline]
1298            pub const fn count_zeros(self) -> u32 {
1299                self.0.count_zeros()
1300            }
1301
1302            /// Returns the number of leading zeros in the binary representation of `self`.
1303            ///
1304            /// # Examples
1305            ///
1306            /// Basic usage:
1307            ///
1308            /// ```
1309            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
1310            ///
1311            #[doc = concat!("let n = ", stringify!($Xe), "::<", stringify!($T), ">::from_ne(-1);")]
1312            ///
1313            /// assert_eq!(n.leading_zeros(), 0);
1314            /// ```
1315            #[must_use = "this returns the result of the operation, \
1316                          without modifying the original"]
1317            #[inline]
1318            pub const fn leading_zeros(self) -> u32 {
1319                self.to_ne().leading_zeros()
1320            }
1321
1322            /// Returns the number of trailing zeros in the binary representation of `self`.
1323            ///
1324            /// # Examples
1325            ///
1326            /// Basic usage:
1327            ///
1328            /// ```
1329            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
1330            ///
1331            #[doc = concat!("let n = ", stringify!($Xe), "::<", stringify!($T), ">::from_ne(-4);")]
1332            ///
1333            /// assert_eq!(n.trailing_zeros(), 2);
1334            /// ```
1335            #[must_use = "this returns the result of the operation, \
1336                          without modifying the original"]
1337            #[inline]
1338            pub const fn trailing_zeros(self) -> u32 {
1339                self.to_ne().trailing_zeros()
1340            }
1341        }
1342    };
1343}
1344
1345endian_int_impl_signed! { Xe<i8> Xe<i16> Xe<i32> Xe<i64> Xe<i128> Xe<isize> }
1346
1347macro_rules! endian_int_impl_unsigned {
1348    ($(Xe<$T:ty>)*) => {$(
1349        endian_int_impl_unsigned! { Be<$T> }
1350        endian_int_impl_unsigned! { Le<$T> }
1351    )*};
1352    ($Xe:ident<$T:ty>) => {
1353        impl $Xe<$T> {
1354            /// Returns the number of ones in the binary representation of `self`.
1355            ///
1356            /// # Examples
1357            ///
1358            /// Basic usage:
1359            ///
1360            /// ```
1361            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
1362            ///
1363            #[doc = concat!("let n = ", stringify!($Xe), "(0b01001100", stringify!($T), ");")]
1364            ///
1365            /// assert_eq!(n.count_ones(), 3);
1366            /// ```
1367            #[doc(alias = "popcount")]
1368            #[doc(alias = "popcnt")]
1369            #[must_use = "this returns the result of the operation, \
1370                          without modifying the original"]
1371            #[inline]
1372            pub const fn count_ones(self) -> u32 {
1373                self.0.count_ones()
1374            }
1375
1376            /// Returns the number of zeros in the binary representation of `self`.
1377            ///
1378            /// # Examples
1379            ///
1380            /// Basic usage:
1381            ///
1382            /// ```
1383            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
1384            ///
1385            #[doc = concat!("assert_eq!(", stringify!($Xe), "::<", stringify!($T), ">::MAX.count_zeros(), 0);")]
1386            /// ```
1387            #[must_use = "this returns the result of the operation, \
1388                          without modifying the original"]
1389            #[inline]
1390            pub const fn count_zeros(self) -> u32 {
1391                self.0.count_zeros()
1392            }
1393
1394            /// Returns the number of leading zeros in the binary representation of `self`.
1395            ///
1396            /// # Examples
1397            ///
1398            /// Basic usage:
1399            ///
1400            /// ```
1401            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
1402            ///
1403            #[doc = concat!("let n = ", stringify!($Xe), "::<", stringify!($T), ">::from_ne(", stringify!($T), "::MAX >> 2);")]
1404            ///
1405            /// assert_eq!(n.leading_zeros(), 2);
1406            /// ```
1407            #[must_use = "this returns the result of the operation, \
1408                          without modifying the original"]
1409            #[inline]
1410            pub const fn leading_zeros(self) -> u32 {
1411                self.to_ne().leading_zeros()
1412            }
1413
1414            /// Returns the number of trailing zeros in the binary representation of `self`.
1415            ///
1416            /// # Examples
1417            ///
1418            /// Basic usage:
1419            ///
1420            /// ```
1421            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
1422            ///
1423            #[doc = concat!("let n = ", stringify!($Xe), "::<", stringify!($T), ">::from_ne(0b0101000);")]
1424            ///
1425            /// assert_eq!(n.trailing_zeros(), 3);
1426            /// ```
1427            #[must_use = "this returns the result of the operation, \
1428                          without modifying the original"]
1429            #[inline]
1430            pub const fn trailing_zeros(self) -> u32 {
1431                self.to_ne().trailing_zeros()
1432            }
1433
1434            /// Returns `true` if and only if `self == 2^k` for some `k`.
1435            ///
1436            /// # Examples
1437            ///
1438            /// Basic usage:
1439            ///
1440            /// ```
1441            #[doc = concat!("use endian_num::", stringify!($Xe), ";")]
1442            ///
1443            #[doc = concat!("assert!(", stringify!($Xe), "::<", stringify!($T), ">::from_ne(16).is_power_of_two());")]
1444            #[doc = concat!("assert!(!", stringify!($Xe), "::<", stringify!($T), ">::from_ne(10).is_power_of_two());")]
1445            /// ```
1446            #[must_use = "this returns the result of the operation, \
1447                          without modifying the original"]
1448            #[inline]
1449            pub const fn is_power_of_two(self) -> bool {
1450                self.to_ne().is_power_of_two()
1451            }
1452        }
1453    };
1454}
1455
1456endian_int_impl_unsigned! { Xe<u8> Xe<u16> Xe<u32> Xe<u64> Xe<u128> Xe<usize> }
1457
1458macro_rules! impl_from_array {
1459    (Xe<$Large:ty>, [Xe<$Small:ty>; $i:literal]) => {
1460        impl_from_array!(Be<$Large>, [Be<$Small>; $i], "big");
1461        impl_from_array!(Le<$Large>, [Le<$Small>; $i], "little");
1462    };
1463    ($Large:ty, [$Small:ty; $i:literal], $order:literal) => {
1464        impl From<[$Small; $i]> for $Large {
1465            #[doc = concat!("Create an integer from its representation as a [`", stringify!($Small), "`] array in ", $order, " endian.")]
1466            #[inline]
1467            fn from(value: [$Small; $i]) -> Self {
1468                // SAFETY: integers are plain old datatypes so we can always transmute to them
1469                unsafe { mem::transmute(value) }
1470            }
1471        }
1472
1473        impl From<$Large> for [$Small; $i] {
1474            #[doc = concat!("Return the memory representation of this integer as a [`", stringify!($Small), "`] array in ", $order, "-endian byte order.")]
1475            #[inline]
1476            fn from(value: $Large) -> Self {
1477                // SAFETY: integers are plain old datatypes so we can always transmute them to
1478                // arrays of bytes
1479                unsafe { mem::transmute(value) }
1480            }
1481        }
1482    };
1483}
1484
1485impl_from_array!(Xe<u16>, [Xe<u8>; 2]);
1486impl_from_array!(Xe<u32>, [Xe<u8>; 4]);
1487impl_from_array!(Xe<u32>, [Xe<u16>; 2]);
1488impl_from_array!(Xe<u64>, [Xe<u8>; 8]);
1489impl_from_array!(Xe<u64>, [Xe<u16>; 4]);
1490impl_from_array!(Xe<u64>, [Xe<u32>; 2]);
1491impl_from_array!(Xe<u128>, [Xe<u8>; 16]);
1492impl_from_array!(Xe<u128>, [Xe<u16>; 8]);
1493impl_from_array!(Xe<u128>, [Xe<u32>; 4]);
1494impl_from_array!(Xe<u128>, [Xe<u64>; 2]);
1495
1496macro_rules! type_alias {
1497    (#[$cfg:meta], $alias:ident = $SelfT:ty, $bits:expr, $order:expr) => {
1498        #[doc = concat!("A ", stringify!($bits), "-bit unsigned integer stored in ", $order, "-endian byte order.")]
1499        ///
1500        /// # Examples
1501        ///
1502        /// Basic usage:
1503        ///
1504        /// ```
1505        #[doc = concat!("use endian_num::", stringify!($alias), ";")]
1506        ///
1507        #[doc = concat!("let n = 0x1A;")]
1508        ///
1509        #[doc = concat!("if cfg!(target_endian = \"", $order, "\") {")]
1510        #[doc = concat!("    assert_eq!(", stringify!($alias), "::from_ne(n).0, n);")]
1511        /// } else {
1512        #[doc = concat!("    assert_eq!(", stringify!($alias), "::from_ne(n).0, n.swap_bytes());")]
1513        /// }
1514        /// ```
1515        #[$cfg]
1516        #[allow(non_camel_case_types)]
1517        pub type $alias = $SelfT;
1518    };
1519}
1520
1521type_alias!(#[cfg(feature = "linux-types")], be16 = Be<u16>, 16, "big");
1522type_alias!(#[cfg(feature = "linux-types")], be32 = Be<u32>, 32, "big");
1523type_alias!(#[cfg(feature = "linux-types")], be64 = Be<u64>, 64, "big");
1524type_alias!(#[cfg(feature = "linux-types")], be128 = Be<u128>, 128, "big");
1525type_alias!(#[cfg(feature = "linux-types")], le16 = Le<u16>, 16, "little");
1526type_alias!(#[cfg(feature = "linux-types")], le32 = Le<u32>, 32, "little");
1527type_alias!(#[cfg(feature = "linux-types")], le64 = Le<u64>, 64, "little");
1528type_alias!(#[cfg(feature = "linux-types")], le128 = Le<u128>, 128, "little");