1#![cfg_attr(feature = "no_std", no_std)]
2
3pub use c2rust_bitfields_derive::BitfieldStruct;
4
5pub trait FieldType: Sized {
6 const IS_SIGNED: bool;
7
8 #[cfg(not(feature = "no_std"))]
9 const TOTAL_BIT_SIZE: usize = ::std::mem::size_of::<Self>() * 8;
10 #[cfg(feature = "no_std")]
11 const TOTAL_BIT_SIZE: usize = ::core::mem::size_of::<Self>() * 8;
12
13 fn get_bit(&self, bit: usize) -> bool;
14
15 fn set_field(&self, field: &mut [u8], bit_range: (usize, usize)) {
16 fn zero_bit(byte: &mut u8, n_bit: u64) {
17 let bit = 1 << n_bit;
18
19 *byte &= !bit as u8;
20 }
21
22 fn one_bit(byte: &mut u8, n_bit: u64) {
23 let bit = 1 << n_bit;
24
25 *byte |= bit as u8;
26 }
27
28 let (lhs_bit, rhs_bit) = bit_range;
29
30 for (i, bit_index) in (lhs_bit..=rhs_bit).enumerate() {
31 let byte_index = bit_index / 8;
32 let byte = &mut field[byte_index];
33
34 if self.get_bit(i) {
35 one_bit(byte, (bit_index % 8) as u64);
36 } else {
37 zero_bit(byte, (bit_index % 8) as u64);
38 }
39 }
40 }
41
42 fn get_field(field: &[u8], bit_range: (usize, usize)) -> Self;
43}
44
45macro_rules! impl_int {
46 ($($typ: ident),+) => {
47 $(
48 impl FieldType for $typ {
49 const IS_SIGNED: bool = $typ::MIN != 0;
50
51 fn get_bit(&self, bit: usize) -> bool {
52 ((*self >> bit) & 1) == 1
53 }
54
55 fn get_field(field: &[u8], bit_range: (usize, usize)) -> Self {
56 let (lhs_bit, rhs_bit) = bit_range;
57 let mut val = 0;
58
59 for (i, bit_index) in (lhs_bit..=rhs_bit).enumerate() {
60 let byte_index = bit_index / 8;
61 let byte = field[byte_index];
62 let bit = 1 << (bit_index % 8);
63 let read_bit = byte & bit;
64
65 if read_bit != 0 {
66 let write_bit = 1 << i;
67
68 val |= write_bit;
69 }
70 }
71
72 if Self::IS_SIGNED {
74 let bit_width = rhs_bit - lhs_bit + 1;
75 let unused_bits = Self::TOTAL_BIT_SIZE - bit_width;
76
77 val <<= unused_bits;
78 val >>= unused_bits;
79 }
80
81 val
82 }
83 }
84 )+
85 };
86}
87
88impl_int! {u8, u16, u32, u64, u128, i8, i16, i32, i64, i128}
89
90impl FieldType for bool {
91 const IS_SIGNED: bool = false;
92
93 fn get_bit(&self, _bit: usize) -> bool {
94 *self
95 }
96
97 fn get_field(field: &[u8], bit_range: (usize, usize)) -> Self {
98 let (lhs_bit, rhs_bit) = bit_range;
99 let mut val = false;
100
101 for bit_index in lhs_bit..=rhs_bit {
102 let byte_index = bit_index / 8;
103 let byte = field[byte_index];
104 let bit = 1 << (bit_index % 8);
105 let read_bit = byte & bit;
106
107 if read_bit != 0 {
108 val = true;
109 }
110 }
111
112 val
113 }
114}