1#![allow(dead_code)]
2#![allow(non_snake_case)]
3#![allow(non_upper_case_globals)]
4
5pub trait Bit {
9 fn bit(&self, bit: usize) -> bool;
11
12 fn set_bit(&mut self, bit: usize, value: bool);
14}
15
16pub trait BitRange<T> {
18 fn bit_range(&self, msb: usize, lsb: usize) -> T;
20 fn set_bit_range(&mut self, msb: usize, lsb: usize, value: T);
22}
23
24pub struct Bits<T>(pub T);
26
27#[macro_export(local_inner_macros)]
28macro_rules! impl_bits {
29 () => {};
30 (@inner $T:tt => bool) => {
31 impl From<bool> for Bits<$T> {
32 fn from(value: bool) -> Self {
33 match value {
34 true => Self(1 as $T),
35 false => Self(0 as $T),
36 }
37 }
38 }
39 impl Into<bool> for Bits<$T> {
40 fn into(self) -> bool {
41 match self.0 {
42 0 => false,
43 _ => true,
44 }
45 }
46 }
47 impl Bit for Bits<$T> {
48 fn bit(&self, bit: usize) -> bool {
49 (self.0 & (1 << bit)) != 0
50 }
51
52 fn set_bit(&mut self, bit: usize, value: bool) {
53 match value {
54 true => self.0 |= 1 << bit,
55 false => self.0 &= !(1 << bit),
56 }
57 }
58 }
59 };
60 (@inner $T:tt => $U:tt) => {
61 impl From<$U> for Bits<$T> {
62 fn from(value: $U) -> Self {
63 Self(value as $T)
64 }
65 }
66 impl Into<$U> for Bits<$T> {
67 fn into(self) -> $U {
68 self.0 as $U
69 }
70 }
71 impl BitRange<$U> for Bits<$T> {
72 #[inline]
73 #[allow(unknown_lints)]
74 #[allow(cast_lossless)]
75 fn bit_range(&self, msb: usize, lsb: usize) -> $U {
76 let mask = ((1 << (msb - lsb + 1)) - 1) << lsb;
77 ((self.0 & mask) >> lsb) as $U
78 }
79
80 #[inline]
81 #[allow(unknown_lints)]
82 #[allow(cast_lossless)]
83 fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $U) {
84 let mask = ((1 << (msb - lsb + 1)) - 1) << lsb;
85 self.0 = (self.0 & !mask) | ((value as $T) << lsb);
86 }
87 }
88 };
89 ($T:tt => [$($U:tt),*]; $($rest:tt)*) => {
90 $(
91 impl_bits!{ @inner $T => $U }
92 )*
93 impl_bits!{ $($rest)* }
94 }
95}
96
97#[macro_export(local_inner_macros)]
98macro_rules! impl_bitrange {
99 () => {};
100 (@inner $T:ty => $U:ty) => {
101 impl From<$U> for Bits<$T> {
102 fn from(value: $U) -> Self {
103 Self(value as $T)
104 }
105 }
106 impl Into<$U> for Bits<$T> {
107 fn into(self) -> $U {
108 self.0 as $U
109 }
110 }
111 impl BitRange<$U> for Bits<$T> {
112 #[inline]
113 #[allow(unknown_lints)]
114 #[allow(cast_lossless)]
115 fn bit_range(&self, msb: usize, lsb: usize) -> $U {
116 let mask = ((1 << (msb - lsb + 1)) - 1) << lsb;
117 ((self.0 & mask) >> lsb) as $U
118 }
119
120 #[inline]
121 #[allow(unknown_lints)]
122 #[allow(cast_lossless)]
123 fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $U) {
124 let mask = ((1 << (msb - lsb + 1)) - 1) << lsb;
125 self.0 = (self.0 & !mask) | ((value as $T) << lsb);
126 }
127 }
128 };
129 ($T:ty => [$($U:ty),*]; $($rest:tt)*) => {
130 $(
131 impl_bitrange!{ @inner $T => $U }
132 )*
133 impl_bitrange!{ $($rest)* }
134 }
135}
136
137#[macro_export(local_inner_macros)]
138macro_rules! bitfield_fields {
139 () => {};
141 (@field ($(#[$attribute:meta])*) ($($vis:tt)*) _, _ : $sty:tt [] in $slot:tt) => {
143 };
144 (@field ($(#[$attribute:meta])*) ($($vis:tt)*) _, _ : $sty:tt [$msb:tt..$lsb:tt] in $slot:tt as $vty:tt) => {
145 };
146 (@field ($(#[$attribute:meta])*) ($($vis:tt)*) $getter:tt, _ : $sty:tt [] in $slot:tt) => {
148 $(#[$attribute])*
149 $($vis)* fn $getter(&self) -> $sty {
150 self.$slot
151 }
152 };
153 (@field ($(#[$attribute:meta])*) ($($vis:tt)*) $getter:tt, _ : $sty:tt [$msb:tt..$lsb:tt] in $slot:tt as bool) => {
155 $(#[$attribute])*
156 $($vis)* fn $getter(&self) -> bool {
157 Bits::<$sty>(self.$slot).bit($msb)
158 }
159 };
160 (@field ($(#[$attribute:meta])*) ($($vis:tt)*) $getter:tt, _ : $sty:tt [$msb:tt..$lsb:tt] in $slot:tt as $vty:tt) => {
162 $(#[$attribute])*
163 $($vis)* fn $getter(&self) -> $vty {
164 Bits::<$sty>(self.$slot).bit_range($msb, $lsb)
165 }
166 };
167 (@field ($(#[$attribute:meta])*) ($($vis:tt)*) _, $setter:tt : $sty:tt [] in $slot:tt) => {
169 $(#[$attribute])*
170 $($vis)* fn $setter(&mut self, value: $sty) -> &mut Self {
171 self.$slot = value;
172 self
173 }
174 };
175 (@field ($(#[$attribute:meta])*) ($($vis:tt)*) _, $setter:tt : $sty:tt [$msb:tt..$lsb:tt] in $slot:tt as bool) => {
177 $(#[$attribute])*
178 $($vis)* fn $setter(&mut self, value: bool) -> &mut Self {
179 let mut bits = Bits::<$sty>(self.$slot);
180 bits.set_bit($msb, value);
181 self.$slot = bits.into();
182 self
183 }
184 };
185 (@field ($(#[$attribute:meta])*) ($($vis:tt)*) _, $setter:tt : $sty:tt [$msb:tt..$lsb:tt] in $slot:tt as $vty:tt) => {
187 $(#[$attribute])*
188 $($vis)* fn $setter(&mut self, value: $vty) -> &mut Self {
189 let mut bits = Bits::<$sty>(self.$slot);
190 bits.set_bit_range($msb, $lsb, value);
191 self.$slot = bits.into();
192 self
193 }
194 };
195 (($(#[$attribute:meta])*) $getter:tt, $setter:tt : $sty:tt []; $($rest:tt)*) => {
197 bitfield_fields!{ @field ($(#[$attribute])*) () $getter, _ : $sty [] in 0 }
198 bitfield_fields!{ @field ($(#[$attribute])*) () _, $setter : $sty [] in 0 }
199 bitfield_fields!{ $($rest)* }
200 };
201 ($(#[$attribute:meta])* pub $getter:tt, $setter:tt : $sty:tt []; $($rest:tt)*) => {
202 bitfield_fields!{ @field ($(#[$attribute])*) (pub) $getter, _ : $sty [] in 0 }
203 bitfield_fields!{ @field ($(#[$attribute])*) (pub) _, $setter : $sty [] in 0 }
204 bitfield_fields!{ $($rest)* }
205 };
206 ($(#[$attribute:meta])* $getter:tt, $setter:tt : $sty:tt [] in $slot:tt; $($rest:tt)*) => {
208 bitfield_fields!{ @field ($(#[$attribute])*) () $getter, _ : $sty [] in $slot }
209 bitfield_fields!{ @field ($(#[$attribute])*) () _, $setter : $sty [] in $slot }
210 bitfield_fields!{ $($rest)* }
211 };
212 ($(#[$attribute:meta])* pub $getter:tt, $setter:tt : $sty:tt [] in $slot:tt; $($rest:tt)*) => {
213 bitfield_fields!{ @field ($(#[$attribute])*) (pub) $getter, _ : $sty [] in $slot }
214 bitfield_fields!{ @field ($(#[$attribute])*) (pub) _, $setter : $sty [] in $slot }
215 bitfield_fields!{ $($rest)* }
216 };
217 ($(#[$attribute:meta])* $getter:tt, $setter:tt : $sty:tt [$msb:tt]; $($rest:tt)*) => {
219 bitfield_fields!{ @field ($(#[$attribute])*) () $getter, _ : $sty [$msb..$msb] in 0 as $sty }
220 bitfield_fields!{ @field ($(#[$attribute])*) () _, $setter : $sty [$msb..$msb] in 0 as $sty }
221 bitfield_fields!{ $($rest)* }
222 };
223 ($(#[$attribute:meta])* pub $getter:tt, $setter:tt : $sty:tt [$msb:tt]; $($rest:tt)*) => {
224 bitfield_fields!{ @field ($(#[$attribute])*) (pub) $getter, _ : $sty [$msb..$msb] in 0 as $sty }
225 bitfield_fields!{ @field ($(#[$attribute])*) (pub) _, $setter : $sty [$msb..$msb] in 0 as $sty }
226 bitfield_fields!{ $($rest)* }
227 };
228 ($(#[$attribute:meta])* $getter:tt, $setter:tt : $sty:tt [$msb:tt] in $slot:tt; $($rest:tt)*) => {
230 bitfield_fields!{ @field ($(#[$attribute])*) () $getter, _ : $sty [$msb..$msb] in $slot as $sty }
231 bitfield_fields!{ @field ($(#[$attribute])*) () _, $setter : $sty [$msb..$msb] in $slot as $sty }
232 bitfield_fields!{ $($rest)* }
233 };
234 ($(#[$attribute:meta])* pub $getter:tt, $setter:tt : $sty:tt [$msb:tt] in $slot:tt; $($rest:tt)*) => {
235 bitfield_fields!{ @field ($(#[$attribute])*) (pub) $getter, _ : $sty [$msb..$msb] in $slot as $sty }
236 bitfield_fields!{ @field ($(#[$attribute])*) (pub) _, $setter : $sty [$msb..$msb] in $slot as $sty }
237 bitfield_fields!{ $($rest)* }
238 };
239 ($(#[$attribute:meta])* $getter:tt, $setter:tt : $sty:tt [$msb:tt] as $vty:tt; $($rest:tt)*) => {
241 bitfield_fields!{ @field ($(#[$attribute])*) () $getter, _ : $sty [$msb..$msb] in 0 as $vty }
242 bitfield_fields!{ @field ($(#[$attribute])*) () _, $setter : $sty [$msb..$msb] in 0 as $vty }
243 bitfield_fields!{ $($rest)* }
244 };
245 ($(#[$attribute:meta])* pub $getter:tt, $setter:tt : $sty:tt [$msb:tt] as $vty:tt; $($rest:tt)*) => {
246 bitfield_fields!{ @field ($(#[$attribute])*) (pub) $getter, _ : $sty [$msb..$msb] in 0 as $vty }
247 bitfield_fields!{ @field ($(#[$attribute])*) (pub) _, $setter : $sty [$msb..$msb] in 0 as $vty }
248 bitfield_fields!{ $($rest)* }
249 };
250 ($(#[$attribute:meta])* $getter:tt, $setter:tt : $sty:tt [$msb:tt] in $slot:tt as $vty:tt; $($rest:tt)*) => {
252 bitfield_fields!{ @field ($(#[$attribute])*) () $getter, _ : $sty [$msb..$msb] in $slot as $vty }
253 bitfield_fields!{ @field ($(#[$attribute])*) () _, $setter : $sty [$msb..$msb] in $slot as $vty }
254 bitfield_fields!{ $($rest)* }
255 };
256 ($(#[$attribute:meta])* pub $getter:tt, $setter:tt : $sty:tt [$msb:tt] in $slot:tt as $vty:tt; $($rest:tt)*) => {
257 bitfield_fields!{ @field ($(#[$attribute])*) (pub) $getter, _ : $sty [$msb..$msb] in $slot as $vty }
258 bitfield_fields!{ @field ($(#[$attribute])*) (pub) _, $setter : $sty [$msb..$msb] in $slot as $vty }
259 bitfield_fields!{ $($rest)* }
260 };
261 ($(#[$attribute:meta])* $getter:tt, $setter:tt : $sty:tt [$msb:tt..$lsb:tt]; $($rest:tt)*) => {
263 bitfield_fields!{ @field ($(#[$attribute])*) () $getter, _ : $sty [$msb..$lsb] in 0 as $sty }
264 bitfield_fields!{ @field ($(#[$attribute])*) () _, $setter : $sty [$msb..$lsb] in 0 as $sty }
265 bitfield_fields!{ $($rest)* }
266 };
267 ($(#[$attribute:meta])* pub $getter:tt, $setter:tt : $sty:tt [$msb:tt..$lsb:tt]; $($rest:tt)*) => {
268 bitfield_fields!{ @field ($(#[$attribute])*) (pub) $getter, _ : $sty [$msb..$lsb] in 0 as $sty }
269 bitfield_fields!{ @field ($(#[$attribute])*) (pub) _, $setter : $sty [$msb..$lsb] in 0 as $sty }
270 bitfield_fields!{ $($rest)* }
271 };
272 ($(#[$attribute:meta])* $getter:tt, $setter:tt : $sty:tt [$msb:tt..$lsb:tt] in $slot:tt; $($rest:tt)*) => {
274 bitfield_fields!{ @field ($(#[$attribute])*) () $getter, _ : $sty [$msb..$lsb] in $slot as $sty }
275 bitfield_fields!{ @field ($(#[$attribute])*) () _, $setter : $sty [$msb..$lsb] in $slot as $sty }
276 bitfield_fields!{ $($rest)* }
277 };
278 ($(#[$attribute:meta])* pub $getter:tt, $setter:tt : $sty:tt [$msb:tt..$lsb:tt] in $slot:tt; $($rest:tt)*) => {
279 bitfield_fields!{ @field ($(#[$attribute])*) (pub) $getter, _ : $sty [$msb..$lsb] in $slot as $sty }
280 bitfield_fields!{ @field ($(#[$attribute])*) (pub) _, $setter : $sty [$msb..$lsb] in $slot as $sty }
281 bitfield_fields!{ $($rest)* }
282 };
283 ($(#[$attribute:meta])* $getter:tt, $setter:tt : $sty:tt [$msb:tt..$lsb:tt] as $vty:tt; $($rest:tt)*) => {
285 bitfield_fields!{ @field ($(#[$attribute])*) () $getter, _ : $sty [$msb..$lsb] in 0 as $vty }
286 bitfield_fields!{ @field ($(#[$attribute])*) () _, $setter : $sty [$msb..$lsb] in 0 as $vty }
287 bitfield_fields!{ $($rest)* }
288 };
289 ($(#[$attribute:meta])* pub $getter:tt, $setter:tt : $sty:tt [$msb:tt..$lsb:tt] as $vty:tt; $($rest:tt)*) => {
290 bitfield_fields!{ @field ($(#[$attribute])*) (pub) $getter, _ : $sty [$msb..$lsb] in 0 as $vty }
291 bitfield_fields!{ @field ($(#[$attribute])*) (pub) _, $setter : $sty [$msb..$lsb] in 0 as $vty }
292 bitfield_fields!{ $($rest)* }
293 };
294 ($(#[$attribute:meta])* $getter:tt, $setter:tt : $sty:tt [$msb:tt..$lsb:tt] in $slot:tt as $vty:tt; $($rest:tt)*) => {
296 bitfield_fields!{ @field ($(#[$attribute])*) () $getter, _ : $sty [$msb..$lsb] in $slot as $vty }
297 bitfield_fields!{ @field ($(#[$attribute])*) () _, $setter : $sty [$msb..$lsb] in $slot as $vty }
298 bitfield_fields!{ $($rest)* }
299 };
300 ($(#[$attribute:meta])* pub $getter:tt, $setter:tt : $sty:tt [$msb:tt..$lsb:tt] in $slot:tt as $vty:tt; $($rest:tt)*) => {
301 bitfield_fields!{ @field ($(#[$attribute])*) (pub) $getter, _ : $sty [$msb..$lsb] in $slot as $vty }
302 bitfield_fields!{ @field ($(#[$attribute])*) (pub) _, $setter : $sty [$msb..$lsb] in $slot as $vty }
303 bitfield_fields!{ $($rest)* }
304 };
305}
306
307impl_bits! {
308 i8 => [bool, i8, i16, i32, i64, u8, u16, u32, u64];
309 i16 => [bool, i8, i16, i32, i64, u8, u16, u32, u64];
310 i32 => [bool, i8, i16, i32, i64, u8, u16, u32, u64];
311 i64 => [bool, i8, i16, i32, i64, u8, u16, u32, u64];
312 u8 => [bool, i8, i16, i32, i64, u8, u16, u32, u64];
313 u16 => [bool, i8, i16, i32, i64, u8, u16, u32, u64];
314 u32 => [bool, i8, i16, i32, i64, u8, u16, u32, u64];
315 u64 => [bool, i8, i16, i32, i64, u8, u16, u32, u64];
316}
317
318#[cfg(test)]
319mod tests {
320 use super::*;
321
322 #[derive(Copy, Clone, Default, Debug)]
323 struct FooBar(u8,u16,u32,u64);
324
325 impl FooBar {
326 bitfield_fields! {
327 f1a, set_f1a : u8 [0];
329 f1b, set_f1b : u8 [1] in 0;
330 f1c, set_f1c : u8 [2] as bool;
331 f1d, set_f1d : u8 [4..3] in 0 as u8;
332 f1e, set_f1e : u8 [7..5] in 0 as u16;
333 pub all1, _ : u8 [] in 0;
334 f2a, set_f2a : u16 [15] in 1 as bool;
336 f2b, set_f2b : u16 [14..0] in 1;
337 pub all2, _ : u16 [] in 1;
338 f3a, set_f3a : u32 [7..0] in 2 as u8;
340 f3b, set_f3b : u32 [15..8] in 2 as u8;
341 f3c, set_f3c : u32 [15..8] in 2 as u8;
342 pub all3, _ : u32 [] in 2;
343 rsv, _ : u64 [] in 3;
345 }
346 }
347
348 #[test]
349 fn test_foobar() {
350 let mut a = FooBar(0x77, 0x55AA, 0xFF77_AA55, 0x0000_FFFF_FF77_AA55);
351 assert_eq!(1, a.f1a());
352 assert_eq!(1, a.f1b());
353 assert_eq!(true, a.f1c());
354 assert_eq!(false, a.set_f1c(false).f1c());
355 assert_eq!(0x73, a.all1());
356 assert_eq!(2, a.f1d());
357 assert_eq!(0, a.set_f1d(0).f1d());
358 assert_eq!(0x63, a.all1());
359 assert_eq!(3, a.f1e());
360 assert_eq!(7, a.set_f1e(7).f1e());
361 assert_eq!(0xE3, a.all1());
362 assert_eq!(0x0000_FFFF_FF77_AA55, a.rsv());
363 }
364}