1 | /// The endian of the data. |
2 | #[derive (Debug, Clone, Copy, PartialEq, Eq, Hash)] |
3 | pub enum Endian { |
4 | /// Little endian. |
5 | Little, |
6 | /// Big endian. |
7 | Big, |
8 | } |
9 | |
10 | /// Alias for [`Endian::Little`]. |
11 | pub const LE: Endian = Endian::Little; |
12 | /// Alias for [`Endian::Big`]. |
13 | pub const BE: Endian = Endian::Big; |
14 | /// Same as the return value of [`Endian::native`]. |
15 | pub const NATIVE_ENDIAN: Endian = Endian::native(); |
16 | /// Alias for [`Endian::Big`]. |
17 | pub const NETWORK_ENDIAN: Endian = Endian::Big; |
18 | |
19 | macro_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 | |
32 | macro_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 | |
45 | impl 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)] |
101 | mod 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 | } |
257 | |