vmm/utils/
byte_order.rs

1// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4macro_rules! generate_read_fn {
5    ($fn_name: ident, $data_type: ty, $byte_type: ty, $type_size: expr, $endian_type: ident) => {
6        /// Read bytes from the slice
7        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        /// Write bytes to the slice
19        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                    // test write
85                    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                    // test read
91                    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}