endi/
endian.rs

1/// The endian of the data.
2#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3pub enum Endian {
4    /// Little endian.
5    Little,
6    /// Big endian.
7    Big,
8}
9
10/// Alias for [`Endian::Little`].
11pub const LE: Endian = Endian::Little;
12/// Alias for [`Endian::Big`].
13pub const BE: Endian = Endian::Big;
14/// Same as the return value of [`Endian::native`].
15pub const NATIVE_ENDIAN: Endian = Endian::native();
16/// Alias for [`Endian::Big`].
17pub const NETWORK_ENDIAN: Endian = Endian::Big;
18
19macro_rules! impl_read_method {
20    ($type:ty, $method:ident, $size:literal) => {
21        #[doc = concat!("Read a `", stringify!($type), "` from a byte slice.\n\n", "# Panics\n\n", "Panics if the slice is smaller than ", stringify!($size), " bytes.")]
22        #[inline]
23        pub fn $method(self, buf: &[u8]) -> $type {
24            match self {
25                Self::Little => <$type>::from_le_bytes(buf[..$size].try_into().unwrap()),
26                Self::Big => <$type>::from_be_bytes(buf[..$size].try_into().unwrap()),
27            }
28        }
29    };
30}
31
32macro_rules! impl_write_method {
33    ($type:ty, $method:ident, $size:literal) => {
34        #[doc = concat!("Write a `", stringify!($type), "` into a mutable byte slice.\n\n", "# Panics\n\n", "Panics if the slice is smaller than ", stringify!($size), " bytes.")]
35        #[inline]
36        pub fn $method(self, buf: &mut [u8], n: $type) {
37            match self {
38                Self::Little => buf[..$size].copy_from_slice(&n.to_le_bytes()),
39                Self::Big => buf[..$size].copy_from_slice(&n.to_be_bytes()),
40            }
41        }
42    };
43}
44
45impl Endian {
46    /// The native endian.
47    #[inline]
48    pub const fn native() -> Self {
49        #[cfg(target_endian = "little")]
50        {
51            Self::Little
52        }
53        #[cfg(target_endian = "big")]
54        {
55            Self::Big
56        }
57    }
58
59    // Reading.
60
61    // Unsigned integers
62    impl_read_method!(u8, read_u8, 1);
63    impl_read_method!(u16, read_u16, 2);
64    impl_read_method!(u32, read_u32, 4);
65    impl_read_method!(u64, read_u64, 8);
66    impl_read_method!(u128, read_u128, 16);
67
68    // Signed integers
69    impl_read_method!(i8, read_i8, 1);
70    impl_read_method!(i16, read_i16, 2);
71    impl_read_method!(i32, read_i32, 4);
72    impl_read_method!(i64, read_i64, 8);
73    impl_read_method!(i128, read_i128, 16);
74
75    // Floating point numbers
76    impl_read_method!(f32, read_f32, 4);
77    impl_read_method!(f64, read_f64, 8);
78
79    // Writing.
80
81    // Unsigned integers
82    impl_write_method!(u8, write_u8, 1);
83    impl_write_method!(u16, write_u16, 2);
84    impl_write_method!(u32, write_u32, 4);
85    impl_write_method!(u64, write_u64, 8);
86    impl_write_method!(u128, write_u128, 16);
87
88    // Signed integers
89    impl_write_method!(i8, write_i8, 1);
90    impl_write_method!(i16, write_i16, 2);
91    impl_write_method!(i32, write_i32, 4);
92    impl_write_method!(i64, write_i64, 8);
93    impl_write_method!(i128, write_i128, 16);
94
95    // Floating point numbers
96    impl_write_method!(f32, write_f32, 4);
97    impl_write_method!(f64, write_f64, 8);
98}
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103
104    #[test]
105    fn u8() {
106        let buf = [0x01];
107        assert_eq!(Endian::Little.read_u8(&buf), 0x01);
108        assert_eq!(Endian::Big.read_u8(&buf), 0x01);
109        let mut buf = [0x00];
110        Endian::Little.write_u8(&mut buf, 0x01);
111        assert_eq!(buf, [0x01]);
112        Endian::Big.write_u8(&mut buf, 0x01);
113        assert_eq!(buf, [0x01]);
114    }
115
116    #[test]
117    fn u16() {
118        let buf = [0x01, 0x02];
119        assert_eq!(Endian::Little.read_u16(&buf), 0x02_01);
120        assert_eq!(Endian::Big.read_u16(&buf), 0x01_02);
121        let mut buf = [0x00, 0x00];
122        Endian::Little.write_u16(&mut buf, 0x01_02);
123        assert_eq!(buf, [0x02, 0x01]);
124        Endian::Big.write_u16(&mut buf, 0x01_02);
125        assert_eq!(buf, [0x01, 0x02]);
126    }
127
128    #[test]
129    fn u32() {
130        let buf = [0x01, 0x02, 0x03, 0x04];
131        assert_eq!(Endian::Little.read_u32(&buf), 0x04_03_02_01);
132        assert_eq!(Endian::Big.read_u32(&buf), 0x01_02_03_04);
133        let mut buf = [0x00, 0x00, 0x00, 0x00];
134        Endian::Little.write_u32(&mut buf, 0x01_02_03_04);
135        assert_eq!(buf, [0x04, 0x03, 0x02, 0x01]);
136        Endian::Big.write_u32(&mut buf, 0x01_02_03_04);
137        assert_eq!(buf, [0x01, 0x02, 0x03, 0x04]);
138    }
139
140    #[test]
141    fn u64() {
142        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
143        assert_eq!(Endian::Little.read_u64(&buf), 0x08_07_06_05_04_03_02_01);
144        assert_eq!(Endian::Big.read_u64(&buf), 0x01_02_03_04_05_06_07_08);
145        let mut buf = [0x00; 8];
146        Endian::Little.write_u64(&mut buf, 0x01_02_03_04_05_06_07_08);
147        assert_eq!(buf, [0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01]);
148        Endian::Big.write_u64(&mut buf, 0x01_02_03_04_05_06_07_08);
149        assert_eq!(buf, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]);
150    }
151
152    #[test]
153    fn u128() {
154        let buf = [
155            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
156            0x0f, 0x10,
157        ];
158        assert_eq!(
159            Endian::Little.read_u128(&buf),
160            0x10_0f_0e_0d_0c_0b_0a_09_08_07_06_05_04_03_02_01
161        );
162        assert_eq!(
163            Endian::Big.read_u128(&buf),
164            0x01_02_03_04_05_06_07_08_09_0a_0b_0c_0d_0e_0f_10
165        );
166        let mut buf = [0x00; 16];
167        Endian::Little.write_u128(&mut buf, 0x01_02_03_04_05_06_07_08_09_0a_0b_0c_0d_0e_0f_10);
168        assert_eq!(
169            buf,
170            [
171                0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
172                0x02, 0x01
173            ]
174        );
175        Endian::Big.write_u128(&mut buf, 0x01_02_03_04_05_06_07_08_09_0a_0b_0c_0d_0e_0f_10);
176        assert_eq!(
177            buf,
178            [
179                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
180                0x0f, 0x10
181            ]
182        );
183    }
184
185    #[test]
186    fn i8() {
187        let buf = [0x01];
188        assert_eq!(Endian::Little.read_i8(&buf), 0x01);
189        assert_eq!(Endian::Big.read_i8(&buf), 0x01);
190        let mut buf = [0x00];
191        Endian::Little.write_i8(&mut buf, 0x01);
192        assert_eq!(buf, [0x01]);
193        Endian::Big.write_i8(&mut buf, 0x01);
194        assert_eq!(buf, [0x01]);
195    }
196
197    #[test]
198    fn i16() {
199        let buf = [0x01, 0x02];
200        assert_eq!(Endian::Little.read_i16(&buf), 0x02_01);
201        assert_eq!(Endian::Big.read_i16(&buf), 0x01_02);
202        let mut buf = [0x00, 0x00];
203        Endian::Little.write_i16(&mut buf, 0x01_02);
204        assert_eq!(buf, [0x02, 0x01]);
205        Endian::Big.write_i16(&mut buf, 0x01_02);
206        assert_eq!(buf, [0x01, 0x02]);
207    }
208
209    #[test]
210    fn i32() {
211        let buf = [0x01, 0x02, 0x03, 0x04];
212        assert_eq!(Endian::Little.read_i32(&buf), 0x04_03_02_01);
213        assert_eq!(Endian::Big.read_i32(&buf), 0x01_02_03_04);
214        let mut buf = [0x00, 0x00, 0x00, 0x00];
215        Endian::Little.write_i32(&mut buf, 0x01_02_03_04);
216        assert_eq!(buf, [0x04, 0x03, 0x02, 0x01]);
217        Endian::Big.write_i32(&mut buf, 0x01_02_03_04);
218        assert_eq!(buf, [0x01, 0x02, 0x03, 0x04]);
219    }
220
221    #[test]
222    fn i64() {
223        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
224        assert_eq!(Endian::Little.read_i64(&buf), 0x08_07_06_05_04_03_02_01);
225        assert_eq!(Endian::Big.read_i64(&buf), 0x01_02_03_04_05_06_07_08);
226        let mut buf = [0x00; 8];
227        Endian::Little.write_i64(&mut buf, 0x01_02_03_04_05_06_07_08);
228        assert_eq!(buf, [0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01]);
229        Endian::Big.write_i64(&mut buf, 0x01_02_03_04_05_06_07_08);
230        assert_eq!(buf, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]);
231    }
232
233    #[test]
234    fn f32() {
235        let buf = [0x00, 0x00, 0x80, 0x3f];
236        assert_eq!(Endian::Little.read_f32(&buf), 1.0);
237        assert_eq!(Endian::Big.read_f32(&buf), 4.6006e-41);
238        let mut buf = [0x00; 4];
239        Endian::Little.write_f32(&mut buf, 1.0);
240        assert_eq!(buf, [0x00, 0x00, 0x80, 0x3f]);
241        Endian::Big.write_f32(&mut buf, 1.0);
242        assert_eq!(buf, [0x3f, 0x80, 0x00, 0x00]);
243    }
244
245    #[test]
246    fn f64() {
247        let buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xbf, 0x3f];
248        assert_eq!(Endian::Little.read_f64(&buf), 0.124755859375);
249        assert_eq!(Endian::Big.read_f64(&buf), 7.7951696e-317);
250        let mut buf = [0x00; 8];
251        Endian::Little.write_f64(&mut buf, 0.124755859375);
252        assert_eq!(buf, [0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xbf, 0x3f]);
253        Endian::Big.write_f64(&mut buf, 1.0);
254        assert_eq!(buf, [0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
255    }
256}