bits_io/
byte_order.rs

1use crate::prelude::*;
2
3pub trait ByteOrder {
4    fn write_u32_to_bits<O: BitStore>(bits: &mut BitSlice<O>, value: u32);
5    fn read_u32_from_bits<O: BitStore>(bits: &BitSlice<O>) -> u32;
6}
7
8pub struct BigEndian {}
9
10pub struct LittleEndian {}
11
12pub type NetworkOrder = BigEndian;
13
14impl ByteOrder for BigEndian {
15    fn write_u32_to_bits<O: BitStore>(bits: &mut BitSlice<O>, value: u32) {
16        let n = bits.len();
17        assert!(n <= 32, "cannot write more than 32 bits");
18
19        for i in 0..n {
20            // Extract bit starting from MSB
21            let bit = (value >> (n - 1 - i)) & 1;
22            bits.set(i, bit != 0);
23        }
24    }
25
26    fn read_u32_from_bits<O: BitStore>(bits: &BitSlice<O>) -> u32 {
27        let n = bits.len();
28        assert!(n <= 32, "cannot read more than 32 bits into a u32");
29
30        bits.iter()
31            .fold(0u32, |acc, bit| (acc << 1) | (*bit as u32))
32    }
33}
34
35impl ByteOrder for LittleEndian {
36    fn write_u32_to_bits<O: BitStore>(bits: &mut BitSlice<O>, value: u32) {
37        let n = bits.len();
38        assert!(n <= 32, "cannot write more than 32 bits");
39
40        for i in 0..n {
41            // Extract bit starting from LSB
42            let bit = (value >> i) & 1;
43            bits.set(i, bit != 0);
44        }
45    }
46
47    fn read_u32_from_bits<O: BitStore>(bits: &BitSlice<O>) -> u32 {
48        let n = bits.len();
49        assert!(n <= 32, "cannot read more than 32 bits into a u32");
50
51        bits.iter()
52            .rev()
53            .fold(0u32, |acc, bit| (acc << 1) | (*bit as u32))
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use crate::{bit_read_exts::BitReadExts, bit_write_exts::BitWriteExts};
60
61    use super::*;
62    #[test]
63    fn test_big_endian_read_write() {
64        let test_cases = [
65            (0b1, 1),
66            (0b10, 2),
67            (0b10101010, 8),
68            (0b1010101010101010, 16),
69            (0xDEADBEEF, 32),
70        ];
71
72        for &(value, bits) in &test_cases {
73            let mut cursor = BitCursor::new(vec![0u8; 8]);
74
75            if bits <= 8 {
76                cursor.write_u8(value as u8).unwrap();
77            } else if bits <= 16 {
78                cursor.write_u16::<BigEndian>(value as u16).unwrap();
79            } else {
80                cursor.write_u32::<BigEndian>(value as u32).unwrap();
81            }
82
83            cursor.set_position(0);
84
85            let read_value = if bits <= 8 {
86                cursor.read_u8().unwrap() as u64
87            } else if bits <= 16 {
88                cursor.read_u16::<BigEndian>().unwrap() as u64
89            } else {
90                cursor.read_u32::<BigEndian>().unwrap() as u64
91            };
92
93            assert_eq!(value, read_value, "BigEndian failed for {} bits", bits);
94        }
95    }
96
97    #[test]
98    fn test_little_endian_read_write() {
99        let test_cases = [
100            (0b1, 1),
101            (0b10, 2),
102            (0b10101010, 8),
103            (0b1010101010101010, 16),
104            (0xDEADBEEF, 32),
105        ];
106
107        for &(value, bits) in &test_cases {
108            let mut cursor = BitCursor::new(vec![0u8; 8]);
109
110            if bits <= 8 {
111                cursor.write_u8(value as u8).unwrap();
112            } else if bits <= 16 {
113                cursor.write_u16::<LittleEndian>(value as u16).unwrap();
114            } else {
115                cursor.write_u32::<LittleEndian>(value as u32).unwrap();
116            }
117
118            cursor.set_position(0);
119
120            let read_value = if bits <= 8 {
121                cursor.read_u8().unwrap() as u64
122            } else if bits <= 16 {
123                cursor.read_u16::<LittleEndian>().unwrap() as u64
124            } else {
125                cursor.read_u32::<LittleEndian>().unwrap() as u64
126            };
127
128            assert_eq!(value, read_value, "LittleEndian failed for {} bits", bits);
129        }
130    }
131}