intx/
defs.rs

1macro_rules! unaligned_int {
2    (
3        $(
4            $( #[$docs:meta] )*
5            @[repr($repr:ty, $signedness:ident)]
6            $vis:vis struct $name:ident([u8; $num_bytes:literal])
7        );* $(;)?
8    ) => {
9        $(
10            $( #[$docs] )*
11            #[derive(
12                ::core::marker::Copy,
13                ::core::clone::Clone,
14                ::core::cmp::PartialEq,
15                ::core::cmp::Eq,
16            )]
17            $vis struct $name([::core::primitive::u8; $num_bytes]);
18
19            unaligned_int!(
20                @impl
21                $( #[$docs] )*
22                @[repr($repr, $signedness)]
23                $vis struct $name([u8; $num_bytes])
24            );
25
26            impl $name {
27                /// The amount of bits required by this integer type.
28                pub const BITS: ::core::primitive::u32 = $num_bytes * 8_u32;
29
30                /// Returns the index position of the most significant byte.
31                #[inline]
32                #[allow(dead_code)] // Note: not used by power-of-two sized ints atm
33                pub(crate) const fn msb_pos() -> ::core::primitive::usize {
34                    if ::core::cfg!(target_endian = "big") {
35                        0_usize
36                    } else {
37                        $num_bytes - 1_usize
38                    }
39                }
40            }
41
42            impl $name {
43                /// Returns the integer value as a byte array in native-endian order.
44                #[inline]
45                pub const fn to_ne_bytes(
46                    self,
47                ) -> [::core::primitive::u8; ::core::mem::size_of::<Self>()] {
48                    self.0
49                }
50
51                /// Returns the integer value as a byte array in little-endian order.
52                #[inline]
53                pub fn to_le_bytes(self) -> [::core::primitive::u8; ::core::mem::size_of::<Self>()] {
54                    $crate::utils::ne_bytes_to_le(self.to_ne_bytes())
55                }
56
57                /// Returns the integer value as a byte array in big-endian order.
58                #[inline]
59                pub fn to_be_bytes(self) -> [::core::primitive::u8; ::core::mem::size_of::<Self>()] {
60                    $crate::utils::ne_bytes_to_be(self.to_ne_bytes())
61                }
62
63                /// Creates an unaligned signed integer from the given bytes in native-endian order.
64                #[inline]
65                pub const fn from_ne_bytes(
66                    bytes: [::core::primitive::u8; ::core::mem::size_of::<Self>()],
67                ) -> Self {
68                    Self(bytes)
69                }
70
71                /// Creates an unaligned signed integer from the given bytes in little-endian order.
72                #[inline]
73                pub fn from_le_bytes(
74                    bytes: [::core::primitive::u8; ::core::mem::size_of::<Self>()],
75                ) -> Self {
76                    Self::from_ne_bytes($crate::utils::le_bytes_to_ne(bytes))
77                }
78
79                /// Creates an unaligned signed integer from the given bytes in big-endian order.
80                #[inline]
81                pub fn from_be_bytes(
82                    bytes: [::core::primitive::u8; ::core::mem::size_of::<Self>()],
83                ) -> Self {
84                    Self::from_ne_bytes($crate::utils::be_bytes_to_ne(bytes))
85                }
86            }
87
88            impl ::core::default::Default for $name {
89                #[inline]
90                fn default() -> Self {
91                    Self([0x00_u8; ::core::mem::size_of::<Self>()])
92                }
93            }
94
95            impl ::core::cmp::PartialOrd for $name {
96                #[inline]
97                fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> {
98                    <$repr as ::core::cmp::PartialOrd>::partial_cmp(
99                        &<$repr as ::core::convert::From<Self>>::from(*self),
100                        &<$repr as ::core::convert::From<Self>>::from(*other),
101                    )
102                }
103
104                #[inline]
105                fn lt(&self, other: &Self) -> ::core::primitive::bool {
106                    <$repr as ::core::cmp::PartialOrd>::lt(
107                        &<$repr as ::core::convert::From<Self>>::from(*self),
108                        &<$repr as ::core::convert::From<Self>>::from(*other),
109                    )
110                }
111
112                #[inline]
113                fn le(&self, other: &Self) -> ::core::primitive::bool {
114                    <$repr as ::core::cmp::PartialOrd>::le(
115                        &<$repr as ::core::convert::From<Self>>::from(*self),
116                        &<$repr as ::core::convert::From<Self>>::from(*other),
117                    )
118                }
119
120                #[inline]
121                fn gt(&self, other: &Self) -> ::core::primitive::bool {
122                    <$repr as ::core::cmp::PartialOrd>::gt(
123                        &<$repr as ::core::convert::From<Self>>::from(*self),
124                        &<$repr as ::core::convert::From<Self>>::from(*other),
125                    )
126                }
127
128                #[inline]
129                fn ge(&self, other: &Self) -> ::core::primitive::bool {
130                    <$repr as ::core::cmp::PartialOrd>::ge(
131                        &<$repr as ::core::convert::From<Self>>::from(*self),
132                        &<$repr as ::core::convert::From<Self>>::from(*other),
133                    )
134                }
135            }
136
137            impl ::core::cmp::Ord for $name {
138                #[inline]
139                fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
140                    <$repr as ::core::cmp::Ord>::cmp(
141                        &<$repr as ::core::convert::From<Self>>::from(*self),
142                        &<$repr as ::core::convert::From<Self>>::from(*other),
143                    )
144                }
145            }
146
147            impl ::core::hash::Hash for $name {
148                #[inline]
149                fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
150                    <$repr as ::core::hash::Hash>::hash(
151                        &<$repr as ::core::convert::From<Self>>::from(*self),
152                        state,
153                    )
154                }
155            }
156
157            impl ::core::fmt::Debug for $name {
158                fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
159                    <$repr as ::core::fmt::Debug>::fmt(
160                        &<$repr as ::core::convert::From<Self>>::from(*self),
161                        f,
162                    )
163                }
164            }
165
166            impl ::core::fmt::Display for $name {
167                fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
168                    <$repr as ::core::fmt::Display>::fmt(
169                        &<$repr as ::core::convert::From<Self>>::from(*self),
170                        f,
171                    )
172                }
173            }
174
175            impl ::core::fmt::Binary for $name {
176                fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
177                    <$repr as ::core::fmt::Binary>::fmt(
178                        &<$repr as ::core::convert::From<Self>>::from(*self),
179                        f,
180                    )
181                }
182            }
183
184            impl ::core::fmt::Octal for $name {
185                fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
186                    <$repr as ::core::fmt::Octal>::fmt(
187                        &<$repr as ::core::convert::From<Self>>::from(*self),
188                        f,
189                    )
190                }
191            }
192
193            impl ::core::fmt::LowerHex for $name {
194                fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
195                    <$repr as ::core::fmt::LowerHex>::fmt(
196                        &<$repr as ::core::convert::From<Self>>::from(*self),
197                        f,
198                    )
199                }
200            }
201
202            impl ::core::fmt::UpperHex for $name {
203                fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
204                    <$repr as ::core::fmt::UpperHex>::fmt(
205                        &<$repr as ::core::convert::From<Self>>::from(*self),
206                        f,
207                    )
208                }
209            }
210
211            impl ::core::fmt::LowerExp for $name {
212                fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
213                    <$repr as ::core::fmt::LowerExp>::fmt(
214                        &<$repr as ::core::convert::From<Self>>::from(*self),
215                        f,
216                    )
217                }
218            }
219
220            impl ::core::fmt::UpperExp for $name {
221                fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
222                    <$repr as ::core::fmt::UpperExp>::fmt(
223                        &<$repr as ::core::convert::From<Self>>::from(*self),
224                        f,
225                    )
226                }
227            }
228        )*
229    };
230    (
231        @impl
232        $( #[$docs:meta] )*
233        @[repr($repr:ty, unsigned)]
234        $vis:vis struct $name:ident([u8; $num_bytes:literal])
235    ) => {
236        impl $name {
237            /// The smallest value that can be represented by this integer type.
238            pub const MIN: Self = Self::from_ne_bytes([0x00_u8; $num_bytes]);
239
240            /// The largest value that can be represented by this integer type.
241            pub const MAX: Self = Self::from_ne_bytes([0xFF_u8; $num_bytes]);
242        }
243
244        impl $crate::UnalignedInteger for $name {
245            type Repr = $repr;
246
247            #[inline]
248            fn sign_ext_byte(self) -> ::core::primitive::u8 {
249                0x00_u8
250            }
251        }
252    };
253    (
254        @impl
255        $( #[$docs:meta] )*
256        @[repr($repr:ty, signed)]
257        $vis:vis struct $name:ident([u8; $num_bytes:literal])
258    ) => {
259        impl $name {
260            /// The smallest value that can be represented by this integer type.
261            pub const MIN: Self = {
262                let mut bytes = [0x00_u8; $num_bytes];
263                bytes[Self::msb_pos()] = 0x80_u8;
264                Self(bytes)
265            };
266
267            /// The largest value that can be represented by this integer type.
268            pub const MAX: Self = {
269                let mut bytes = [0xFF_u8; $num_bytes];
270                bytes[Self::msb_pos()] = 0x7F_u8;
271                Self(bytes)
272            };
273
274            /// Returns `true` if `self` is positive.
275            #[inline]
276            pub(crate) const fn is_positive(self) -> ::core::primitive::bool {
277                (self.0[Self::msb_pos()] & 0x80_u8) == 0x00_u8
278            }
279        }
280
281        impl $crate::UnalignedInteger for $name {
282            type Repr = $repr;
283
284            #[inline]
285            fn sign_ext_byte(self) -> ::core::primitive::u8 {
286                $crate::utils::sign_ext_byte(self.is_positive())
287            }
288        }
289    }
290}
291unaligned_int! {
292    /// 16-bit unsigned integer with alignment of 1.
293    @[repr(::core::primitive::u16, unsigned)]
294    pub struct U16([u8; 2]);
295
296    /// 16-bit signed integer with alignment of 1.
297    @[repr(::core::primitive::i16, signed)]
298    pub struct I16([u8; 2]);
299
300    /// 24-bit unsigned integer with alignment of 1.
301    @[repr(::core::primitive::u32, unsigned)]
302    pub struct U24([u8; 3]);
303
304    /// 24-bit signed integer with alignment of 1.
305    @[repr(::core::primitive::i32, signed)]
306    pub struct I24([u8; 3]);
307
308    /// 32-bit unsigned integer with alignment of 1.
309    @[repr(::core::primitive::u32, unsigned)]
310    pub struct U32([u8; 4]);
311
312    /// 32-bit signed integer with alignment of 1.
313    @[repr(::core::primitive::i32, signed)]
314    pub struct I32([u8; 4]);
315
316    /// 40-bit unsigned integer with alignment of 1.
317    @[repr(::core::primitive::u64, unsigned)]
318    pub struct U40([u8; 5]);
319
320    /// 40-bit signed integer with alignment of 1.
321    @[repr(::core::primitive::i64, signed)]
322    pub struct I40([u8; 5]);
323
324    /// 48-bit unsigned integer with alignment of 1.
325    @[repr(::core::primitive::u64, unsigned)]
326    pub struct U48([u8; 6]);
327
328    /// 48-bit signed integer with alignment of 1.
329    @[repr(::core::primitive::i64, signed)]
330    pub struct I48([u8; 6]);
331
332    /// 56-bit unsigned integer with alignment of 1.
333    @[repr(::core::primitive::u64, unsigned)]
334    pub struct U56([u8; 7]);
335
336    /// 56-bit signed integer with alignment of 1.
337    @[repr(::core::primitive::i64, signed)]
338    pub struct I56([u8; 7]);
339
340    /// 64-bit unsigned integer with alignment of 1.
341    @[repr(::core::primitive::u64, unsigned)]
342    pub struct U64([u8; 8]);
343
344    /// 64-bit signed integer with alignment of 1.
345    @[repr(::core::primitive::i64, signed)]
346    pub struct I64([u8; 8]);
347
348    /// 72-bit unsigned integer with alignment of 1.
349    @[repr(::core::primitive::u128, unsigned)]
350    pub struct U72([u8; 9]);
351
352    /// 72-bit signed integer with alignment of 1.
353    @[repr(::core::primitive::i128, signed)]
354    pub struct I72([u8; 9]);
355
356    /// 80-bit unsigned integer with alignment of 1.
357    @[repr(::core::primitive::u128, unsigned)]
358    pub struct U80([u8; 10]);
359
360    /// 80-bit signed integer with alignment of 1.
361    @[repr(::core::primitive::i128, signed)]
362    pub struct I80([u8; 10]);
363
364    /// 88-bit unsigned integer with alignment of 1.
365    @[repr(::core::primitive::u128, unsigned)]
366    pub struct U88([u8; 11]);
367
368    /// 88-bit signed integer with alignment of 1.
369    @[repr(::core::primitive::i128, signed)]
370    pub struct I88([u8; 11]);
371
372    /// 96-bit unsigned integer with alignment of 1.
373    @[repr(::core::primitive::u128, unsigned)]
374    pub struct U96([u8; 12]);
375
376    /// 96-bit signed integer with alignment of 1.
377    @[repr(::core::primitive::i128, signed)]
378    pub struct I96([u8; 12]);
379
380    /// 104-bit unsigned integer with alignment of 1.
381    @[repr(::core::primitive::u128, unsigned)]
382    pub struct U104([u8; 13]);
383
384    /// 104-bit signed integer with alignment of 1.
385    @[repr(::core::primitive::i128, signed)]
386    pub struct I104([u8; 13]);
387
388    /// 112-bit unsigned integer with alignment of 1.
389    @[repr(::core::primitive::u128, unsigned)]
390    pub struct U112([u8; 14]);
391
392    /// 112-bit signed integer with alignment of 1.
393    @[repr(::core::primitive::i128, signed)]
394    pub struct I112([u8; 14]);
395
396    /// 120-bit unsigned integer with alignment of 1.
397    @[repr(::core::primitive::u128, unsigned)]
398    pub struct U120([u8; 15]);
399
400    /// 120-bit signed integer with alignment of 1.
401    @[repr(::core::primitive::i128, signed)]
402    pub struct I120([u8; 15]);
403
404    /// 128-bit unsigned integer with alignment of 1.
405    @[repr(::core::primitive::u128, unsigned)]
406    pub struct U128([u8; 16]);
407
408    /// 128-bit signed integer with alignment of 1.
409    @[repr(::core::primitive::i128, signed)]
410    pub struct I128([u8; 16]);
411}