1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3pub enum Endian {
4 Little,
6 Big,
8}
9
10pub const LE: Endian = Endian::Little;
12pub const BE: Endian = Endian::Big;
14pub const NATIVE_ENDIAN: Endian = Endian::native();
16pub 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 #[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 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 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 impl_read_method!(f32, read_f32, 4);
77 impl_read_method!(f64, read_f64, 8);
78
79 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 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 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}