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