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 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 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}