1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub enum ByteOrder {
8 LittleEndian = 1,
12 BigEndian = 0,
16}
17
18impl ByteOrder {
19 #[inline]
22 pub(crate) fn extract_bits(self, data: &[u8], start_bit: usize, length: usize) -> u64 {
23 match self {
24 ByteOrder::LittleEndian => {
25 let mut value: u64 = 0;
27 let mut bits_remaining = length;
28 let mut current_bit = start_bit;
29
30 while bits_remaining > 0 {
31 let byte_idx = current_bit / 8;
32 let bit_in_byte = current_bit % 8;
33 let bits_to_take = bits_remaining.min(8 - bit_in_byte);
34
35 let byte = data[byte_idx] as u64;
36 let mask = ((1u64 << bits_to_take) - 1) << bit_in_byte;
37 let extracted = (byte & mask) >> bit_in_byte;
38
39 value |= extracted << (length - bits_remaining);
40
41 bits_remaining -= bits_to_take;
42 current_bit += bits_to_take;
43 }
44
45 value
46 }
47 ByteOrder::BigEndian => {
48 let mut value: u64 = 0;
54 for i in 0..length {
55 let be_bit = start_bit + i;
57 let byte_num = be_bit / 8;
58 let bit_in_byte = be_bit % 8;
59 let physical_bit = byte_num * 8 + (7 - bit_in_byte);
60
61 let byte_idx = physical_bit / 8;
63 let bit_pos_in_byte = physical_bit % 8;
64 let bit_value = ((data[byte_idx] as u64) >> (7 - bit_pos_in_byte)) & 1;
65
66 value |= bit_value << (length - 1 - i);
68 }
69
70 value
71 }
72 }
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::ByteOrder;
79 use core::hash::Hash;
80
81 #[test]
83 fn test_byte_order_variants() {
84 assert_eq!(ByteOrder::LittleEndian as u8, 1);
85 assert_eq!(ByteOrder::BigEndian as u8, 0);
86 }
87
88 #[test]
89 fn test_byte_order_equality() {
90 assert_eq!(ByteOrder::LittleEndian, ByteOrder::LittleEndian);
91 assert_eq!(ByteOrder::BigEndian, ByteOrder::BigEndian);
92 assert_ne!(ByteOrder::LittleEndian, ByteOrder::BigEndian);
93 }
94
95 #[test]
96 fn test_byte_order_clone() {
97 let original = ByteOrder::LittleEndian;
98 let cloned = original;
99 assert_eq!(original, cloned);
100
101 let original2 = ByteOrder::BigEndian;
102 let cloned2 = original2;
103 assert_eq!(original2, cloned2);
104 }
105
106 #[test]
107 fn test_byte_order_copy() {
108 let order = ByteOrder::LittleEndian;
109 let copied = order; assert_eq!(order, copied); }
112
113 #[test]
114 fn test_byte_order_hash_trait() {
115 fn _assert_hash<T: Hash>() {}
117 _assert_hash::<ByteOrder>();
118 }
119
120 #[test]
121 fn test_extract_bits_little_endian() {
122 let data = [0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
124 let raw_value = ByteOrder::LittleEndian.extract_bits(&data, 0, 16);
125 assert_eq!(raw_value, 0x1234);
126 }
127
128 #[test]
129 fn test_extract_bits_big_endian() {
130 let data = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
133 let raw_value = ByteOrder::BigEndian.extract_bits(&data, 0, 16);
134 assert!(raw_value <= 65535);
136 }
137
138 #[test]
139 fn test_extract_bits_mixed_positions_little_endian() {
140 let data = [0x00, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00];
142 let raw_value = ByteOrder::LittleEndian.extract_bits(&data, 8, 16);
143 assert_eq!(raw_value, 0x1234);
144 }
145
146 #[test]
147 fn test_extract_bits_mixed_positions_big_endian() {
148 let data = [0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
151 let raw_value = ByteOrder::BigEndian.extract_bits(&data, 8, 16);
152 assert!(raw_value <= 65535);
154 }
155
156 #[test]
157 fn test_byte_order_difference() {
158 let data = [0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
161
162 let le_value = ByteOrder::LittleEndian.extract_bits(&data, 0, 16);
163 let be_value = ByteOrder::BigEndian.extract_bits(&data, 0, 16);
164
165 assert_eq!(le_value, 0x1234);
167
168 assert_ne!(
170 le_value, be_value,
171 "Big-endian and little-endian should produce different values"
172 );
173 assert!(be_value <= 65535);
174 }
175
176 #[cfg(feature = "std")]
178 mod tests_std {
179 use super::*;
180 use core::hash::{Hash, Hasher};
181 use std::collections::hash_map::DefaultHasher;
182
183 #[test]
184 fn test_byte_order_debug() {
185 let little = format!("{:?}", ByteOrder::LittleEndian);
186 assert!(little.contains("LittleEndian"));
187
188 let big = format!("{:?}", ByteOrder::BigEndian);
189 assert!(big.contains("BigEndian"));
190 }
191
192 #[test]
193 fn test_byte_order_hash() {
194 let mut hasher1 = DefaultHasher::new();
195 let mut hasher2 = DefaultHasher::new();
196
197 ByteOrder::LittleEndian.hash(&mut hasher1);
198 ByteOrder::LittleEndian.hash(&mut hasher2);
199 assert_eq!(hasher1.finish(), hasher2.finish());
200
201 let mut hasher3 = DefaultHasher::new();
202 ByteOrder::BigEndian.hash(&mut hasher3);
203 assert_ne!(hasher1.finish(), hasher3.finish());
204 }
205 }
206}