1macro_rules! generate_read_fn {
5 ($fn_name: ident, $data_type: ty, $byte_type: ty, $type_size: expr, $endian_type: ident) => {
6 pub fn $fn_name(input: &[$byte_type]) -> $data_type {
8 let mut array = [0u8; std::mem::size_of::<$data_type>()];
9 let how_many = input.len().min(std::mem::size_of::<$data_type>());
10 array[..how_many].copy_from_slice(&input[..how_many]);
11 <$data_type>::$endian_type(array)
12 }
13 };
14}
15
16macro_rules! generate_write_fn {
17 ($fn_name: ident, $data_type: ty, $byte_type: ty, $endian_type: ident) => {
18 pub fn $fn_name(buf: &mut [$byte_type], n: $data_type) {
20 let bytes = n.$endian_type();
21 let how_much = buf.len().min(bytes.len());
22 buf[..how_much].copy_from_slice(&bytes[..how_much]);
23 }
24 };
25}
26
27generate_read_fn!(read_le_u32, u32, u8, 4, from_le_bytes);
28generate_read_fn!(read_le_u64, u64, u8, 8, from_le_bytes);
29
30generate_read_fn!(read_be_u16, u16, u8, 2, from_be_bytes);
31generate_read_fn!(read_be_u32, u32, u8, 4, from_be_bytes);
32
33generate_write_fn!(write_le_u32, u32, u8, to_le_bytes);
34generate_write_fn!(write_le_u64, u64, u8, to_le_bytes);
35
36generate_write_fn!(write_be_u16, u16, u8, to_be_bytes);
37generate_write_fn!(write_be_u32, u32, u8, to_be_bytes);
38
39#[cfg(test)]
40mod tests {
41 use super::*;
42 macro_rules! byte_order_test_read_write {
43 ($test_name: ident, $write_fn_name: ident, $read_fn_name: ident, $is_be: expr, $data_type: ty) => {
44 #[test]
45 fn $test_name() {
46 #[allow(overflowing_literals)]
47 let test_cases = [
48 (
49 0x0123_4567_89AB_CDEF as u64,
50 [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef],
51 ),
52 (
53 0x0000_0000_0000_0000 as u64,
54 [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
55 ),
56 (
57 0x1923_2345_ABF3_CCD4 as u64,
58 [0x19, 0x23, 0x23, 0x45, 0xAB, 0xF3, 0xCC, 0xD4],
59 ),
60 (
61 0x0FF0_0FF0_0FF0_0FF0 as u64,
62 [0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0],
63 ),
64 (
65 0xFFFF_FFFF_FFFF_FFFF as u64,
66 [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
67 ),
68 (
69 0x89AB_12D4_C2D2_09BB as u64,
70 [0x89, 0xAB, 0x12, 0xD4, 0xC2, 0xD2, 0x09, 0xBB],
71 ),
72 ];
73
74 let type_size = std::mem::size_of::<$data_type>();
75 #[allow(clippy::cast_possible_truncation)]
76 #[allow(clippy::cast_sign_loss)]
77 for (test_val, v_arr) in &test_cases {
78 let v = *test_val as $data_type;
79 let cmp_iter: Box<dyn Iterator<Item = _>> = if $is_be {
80 Box::new(v_arr[(8 - type_size)..].iter())
81 } else {
82 Box::new(v_arr.iter().rev())
83 };
84 let mut write_arr = vec![Default::default(); type_size];
86 $write_fn_name(&mut write_arr, v);
87 for (cmp, cur) in cmp_iter.zip(write_arr.iter()) {
88 assert_eq!(*cmp, *cur as u8)
89 }
90 let read_val = $read_fn_name(&write_arr);
92 assert_eq!(v, read_val);
93 }
94 }
95 };
96 }
97
98 byte_order_test_read_write!(test_le_u32, write_le_u32, read_le_u32, false, u32);
99 byte_order_test_read_write!(test_le_u64, write_le_u64, read_le_u64, false, u64);
100 byte_order_test_read_write!(test_be_u16, write_be_u16, read_be_u16, true, u16);
101 byte_order_test_read_write!(test_be_u32, write_be_u32, read_be_u32, true, u32);
102}