bytes_cast/
unaligned.rs

1//! Integer and float types without alignment requirement, for each endianness.
2//!
3//! They implement `BytesCast` as well as standard convertion traits
4//! to and from the corresponding primitive integer type.
5//!
6//! # The `u8` type
7//!
8//! There is no need for types such as `U8Be`
9//! since `u8` already does not have endianness or alignement requirements.
10//! Use `u8` directly.
11
12use super::BytesCast;
13
14macro_rules! unaligned {
15    ($Int: ident $BeStruct: ident $LeStruct: ident $NeStruct: ident) => {
16        unaligned!(@doc $Int $BeStruct from_be_bytes to_be_bytes "Big", "");
17        unaligned!(@doc $Int $LeStruct from_le_bytes to_le_bytes "Little", "");
18        unaligned!(@doc $Int $NeStruct from_ne_bytes to_ne_bytes "CPU-native",
19                   "\n\nThe byte order depends on the target CPU architecture.");
20    };
21
22    // This is a separate macro invocation to work around
23    // https://github.com/rust-lang/rust/issues/52607
24    (
25            @doc $Int: ident $Struct: ident
26            $from_bytes: ident $to_bytes: ident
27            $endian: expr, $extra_doc: expr
28    ) => {
29        unaligned!(
30            @def $Int $Struct $from_bytes $to_bytes concat!(
31                $endian, "-endian `", stringify!($Int), "`, \
32                without alignment requirement.\n\
33                \n\
34                Implements the [`BytesCast`] trait to reinterpret `&[u8]` byte slices, \
35                and the [`From`] and [`Into`] traits to convert to and from \
36                `", stringify!($Int), "`.",
37                $extra_doc
38            )
39        );
40    };
41
42    (
43        @def $Int: ident $Struct: ident
44        $from_bytes: ident $to_bytes: ident
45        $doc: expr
46    ) => {
47        #[derive(BytesCast)]
48        #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
49        #[doc = $doc]
50        #[repr(transparent)]
51        pub struct $Struct([u8; ::core::mem::size_of::<$Int>()]);
52
53        /// Converts to native-endian. Same as `.into()`, but `.into()` may need a type annotation.
54        impl $Struct {
55            #[inline]
56            pub fn get(self) -> $Int {
57                self.into()
58            }
59        }
60
61        /// Converts to native-endian
62        impl From<$Struct> for $Int {
63            #[inline]
64            fn from(value: $Struct) -> Self {
65                $Int::$from_bytes(value.0)
66            }
67        }
68
69        /// Converts from native-endian
70        impl From<$Int> for $Struct {
71            #[inline]
72            fn from(value: $Int) -> Self {
73                Self(value.$to_bytes())
74            }
75        }
76    };
77}
78
79unaligned!(u16 U16Be U16Le U16Ne);
80unaligned!(u32 U32Be U32Le U32Ne);
81unaligned!(u64 U64Be U64Le U64Ne);
82unaligned!(u128 U128Be U128Le U128Ne);
83
84unaligned!(i16 I16Be I16Le I16Ne);
85unaligned!(i32 I32Be I32Le I32Ne);
86unaligned!(i64 I64Be I64Le I64Ne);
87unaligned!(i128 I128Be I128Le I128Ne);
88
89unaligned!(f32 F32Be F32Le F32Ne);
90unaligned!(f64 F64Be F64Le F64Ne);