bits_io/buf/
byte_order.rs

1use bitvec::field::BitField;
2use funty::Integral;
3
4use crate::prelude::*;
5
6/// This trait defines operations to load and store integral values from a buffer, and enables
7/// implementing them in different ways for the different byte orders (Big Endian and Little
8/// Endian).
9pub trait ByteOrder {
10    fn load<O: BitStore, U: Integral>(src: &BitSlice<O>) -> U;
11    fn store<O: BitStore, U: Integral>(dest: &mut BitSlice<O>, value: U);
12}
13
14pub struct BigEndian {}
15
16pub struct LittleEndian {}
17
18pub type NetworkOrder = BigEndian;
19
20impl ByteOrder for BigEndian {
21    fn load<O: BitStore, U: Integral>(src: &BitSlice<O>) -> U {
22        src.load_be()
23    }
24
25    fn store<O: BitStore, U: Integral>(dest: &mut BitSlice<O>, value: U) {
26        dest.store_be(value);
27    }
28}
29
30impl ByteOrder for LittleEndian {
31    fn load<O: BitStore, U: Integral>(src: &BitSlice<O>) -> U {
32        src.load_le()
33    }
34
35    fn store<O: BitStore, U: Integral>(dest: &mut BitSlice<O>, value: U) {
36        dest.store_le(value)
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    // TODO: more test cases here (different data sizes)
45
46    #[test]
47    fn test_big_endian_write() {
48        let mut buf = [0u8; 2];
49        {
50            // Simulate writing 4 bits
51            let dest = &mut BitSlice::from_slice_mut(&mut buf);
52            BigEndian::store(&mut dest[..16], 0xABCDu16);
53            let value = u16::from_be_bytes(buf);
54            assert_eq!(value, 0xABCD);
55        }
56
57        // Now test that writing into a BitSlice<BitSafeU8> also works.
58        {
59            let dest = BitSlice::from_slice_mut(&mut buf);
60            let (_, dest) = unsafe { dest.split_at_unchecked_mut(0) };
61            BigEndian::store(&mut dest[..16], 0xABCDu16);
62            let value = u16::from_be_bytes(buf);
63            assert_eq!(value, 0xABCD);
64        }
65    }
66
67    #[test]
68    fn test_big_endian_read() {
69        let value = 0xABCDu16;
70        let value_bytes = value.to_be_bytes();
71        let src = BitSlice::from_slice(&value_bytes);
72        let read_value: u16 = BigEndian::load(src);
73        assert_eq!(value, read_value);
74    }
75
76    #[test]
77    fn test_little_endian_write() {
78        let mut buf = [0u8; 2];
79        {
80            // Simulate writing 4 bits
81            let dest = &mut BitSlice::from_slice_mut(&mut buf);
82            LittleEndian::store(&mut dest[..16], 0xABCDu16);
83            let value = u16::from_le_bytes(buf);
84            assert_eq!(value, 0xABCD);
85        }
86
87        // Now test that writing into a BitSlice<BitSafeU8> also works.
88        {
89            let dest = BitSlice::from_slice_mut(&mut buf);
90            let (_, dest) = unsafe { dest.split_at_unchecked_mut(0) };
91            LittleEndian::store(&mut dest[..16], 0xABCDu16);
92            let value = u16::from_le_bytes(buf);
93            assert_eq!(value, 0xABCD);
94        }
95    }
96
97    #[test]
98    fn test_little_endian_read() {
99        let value = 0xABCDu16;
100        let value_bytes = value.to_le_bytes();
101        let src = BitSlice::from_slice(&value_bytes);
102        let read_value: u16 = LittleEndian::load(src);
103        assert_eq!(value, read_value);
104    }
105}