network_types/
bitfield.rs1#[repr(C)]
7#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
8pub struct BitfieldUnit<Storage> {
9 storage: Storage,
10}
11
12impl<Storage> BitfieldUnit<Storage> {
13 #[inline]
14 pub const fn new(storage: Storage) -> Self {
15 Self { storage }
16 }
17}
18
19impl<Storage> BitfieldUnit<Storage>
20where
21 Storage: AsRef<[u8]> + AsMut<[u8]>,
22{
23 #[inline]
24 pub fn get_bit(&self, index: usize) -> bool {
25 debug_assert!(index / 8 < self.storage.as_ref().len());
26
27 let byte_index = index / 8;
28 let byte = self.storage.as_ref()[byte_index];
29
30 let bit_index = if cfg!(target_endian = "big") {
31 7 - (index % 8)
32 } else {
33 index % 8
34 };
35
36 let mask = 1 << bit_index;
37
38 byte & mask == mask
39 }
40
41 #[inline]
42 pub fn set_bit(&mut self, index: usize, val: bool) {
43 debug_assert!(index / 8 < self.storage.as_ref().len());
44
45 let byte_index = index / 8;
46 let byte = &mut self.storage.as_mut()[byte_index];
47
48 let bit_index = if cfg!(target_endian = "big") {
49 7 - (index % 8)
50 } else {
51 index % 8
52 };
53
54 let mask = 1 << bit_index;
55 if val {
56 *byte |= mask;
57 } else {
58 *byte &= !mask;
59 }
60 }
61
62 #[inline]
63 pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 {
64 debug_assert!(bit_width <= 64);
65 debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
66 debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len());
67
68 let mut val = 0;
69
70 for i in 0..(bit_width as usize) {
71 if self.get_bit(i + bit_offset) {
72 let index = if cfg!(target_endian = "big") {
73 bit_width as usize - 1 - i
74 } else {
75 i
76 };
77 val |= 1 << index;
78 }
79 }
80
81 val
82 }
83
84 #[inline]
85 pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) {
86 debug_assert!(bit_width <= 64);
87 debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
88 debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len());
89
90 for i in 0..(bit_width as usize) {
91 let mask = 1 << i;
92 let val_bit_is_set = val & mask == mask;
93 let index = if cfg!(target_endian = "big") {
94 bit_width as usize - 1 - i
95 } else {
96 i
97 };
98 self.set_bit(index + bit_offset, val_bit_is_set);
99 }
100 }
101}