1#![no_std]
2#![deny(
3 missing_docs,
4 unused_extern_crates,
5 unused_import_braces,
6 unused_qualifications
7)]
8pub use bitfield_macros::{bitfield_constructor, bitfield_debug, bitfield_fields};
15
16#[macro_export]
18macro_rules! check_msb_lsb_order {
19 ($msb:expr, $lsb:expr) => {
20 debug_assert!(
21 $msb >= $lsb,
22 "the MSB ({}) is smaller than the LSB ({}), you likely inverted them",
23 $msb,
24 $lsb
25 );
26 };
27}
28
29#[macro_export(local_inner_macros)]
45macro_rules! bitfield_impl {
46 (Debug for struct $name:ident([$t:ty]); $($rest:tt)*) => {
47 impl<T: AsRef<[$t]> + $crate::fmt::Debug> $crate::fmt::Debug for $name<T> {
48 bitfield_debug!{struct $name; $($rest)*}
49 }
50 };
51 (Debug for struct $name:ident($t:ty); $($rest:tt)*) => {
52 impl $crate::fmt::Debug for $name {
53 bitfield_debug!{struct $name; $($rest)*}
54 }
55 };
56 (BitAnd for struct $name:ident([$t:ty]); $($rest:tt)*) => {
57 bitfield_impl!{@bitwise BitAnd bitand BitAndAssign bitand_assign $name([$t]) &=}
58 };
59 (BitAnd for struct $name:ident($t:ty); $($rest:tt)*) => {
60 bitfield_impl!{@bitwise BitAnd bitand BitAndAssign bitand_assign $name($t) &=}
61 };
62 (BitOr for struct $name:ident([$t:ty]); $($rest:tt)*) => {
63 bitfield_impl!{@bitwise BitOr bitor BitOrAssign bitor_assign $name([$t]) |=}
64 };
65 (BitOr for struct $name:ident($t:ty); $($rest:tt)*) => {
66 bitfield_impl!{@bitwise BitOr bitor BitOrAssign bitor_assign $name($t) |=}
67 };
68 (BitXor for struct $name:ident([$t:ty]); $($rest:tt)*) => {
69 bitfield_impl!{@bitwise BitXor bitxor BitXorAssign bitxor_assign $name([$t]) ^=}
70 };
71 (BitXor for struct $name:ident($t:ty); $($rest:tt)*) => {
72 bitfield_impl!{@bitwise BitXor bitxor BitXorAssign bitxor_assign $name($t) ^=}
73 };
74 (@bitwise $bitwise:ident $func:ident $bitwise_assign:ident $func_assign:ident $name:ident([$t:ty]) $op:tt) => {
75 impl<T: AsMut<[$t]> + AsRef<[$t]>> $crate::ops::$bitwise for $name<T> {
76 type Output = Self;
77 fn $func(mut self, rhs: Self) -> Self {
78 bitfield_impl!(@mutate self rhs $op);
79 self
80 }
81 }
82 impl<T: AsMut<[$t]> + AsRef<[$t]>> $crate::ops::$bitwise_assign for $name<T> {
83 fn $func_assign(&mut self, rhs: Self) {
84 bitfield_impl!(@mutate self rhs $op);
85 }
86 }
87 };
88 (@bitwise $bitwise:ident $func:ident $bitwise_assign:ident $func_assign:ident $name:ident($t:ty) $op:tt) => {
89 impl $crate::ops::$bitwise for $name {
90 type Output = Self;
91 fn $func(mut self, rhs: Self) -> Self {
92 self.0 $op rhs.0;
93 self
94 }
95 }
96 impl $crate::ops::$bitwise_assign for $name {
97 fn $func_assign(&mut self, rhs: Self) {
98 self.0 $op rhs.0;
99 }
100 }
101 };
102 (@mutate $self:ident $rhs:ident $op:tt) => {{
103 let as_mut = AsMut::<[_]>::as_mut(&mut $self.0);
104 let rhs = AsRef::<[_]>::as_ref(&$rhs.0);
105 for i in 0..as_mut.len() {
106 as_mut[i] $op rhs[i];
107 }
108 }};
109 (new for struct $name:ident([$t:ty]); $($rest:tt)*) => {
110 impl<T: AsMut<[$t]> + Default> $name<T> {
111 bitfield_constructor!{$($rest)*}
112 }
113 };
114 (new for struct $name:ident($t:ty); $($rest:tt)*) => {
115 impl $name {
116 bitfield_constructor!{$($rest)*}
117 }
118 };
119 (new{$new:ident ($($setter_name:ident: $setter_type:ty),*$(,)?)} for struct $name:ident([$t:ty]); $($rest:tt)*) => {
120 impl<T: AsMut<[$t]> + Default> $name<T> {
121 pub fn $new($($setter_name: $setter_type),*) -> Self {
122 let mut value = Self(T::default());
123 $(
124 value.$setter_name($setter_name);
125 )*
126 value
127 }
128 }
129 };
130 (new{$new:ident ($($setter_name:ident: $setter_type:ty),*$(,)?)} for struct $name:ident($t:ty); $($rest:tt)*) => {
131 impl $name {
132 pub fn $new($($setter_name: $setter_type),*) -> Self {
133 let mut value = Self($t::default());
134 $(
135 value.$setter_name($setter_name);
136 )*
137 value
138 }
139 }
140 };
141 ($macro:ident for struct $name:ident $($rest:tt)*) => {
143 ::core::compile_error!(::core::stringify!(Unsupported impl $macro for struct $name));
144 };
145}
146
147#[macro_export(local_inner_macros)]
179macro_rules! bitfield_bitrange {
180 (@impl_bitrange_slice $name:ident, $slice_ty:ty, $bitrange_ty:ty) => {
181 impl<T: AsRef<[$slice_ty]>> $crate::BitRange<$bitrange_ty>
182 for $name<T> {
183 fn bit_range(&self, msb: usize, lsb: usize) -> $bitrange_ty {
184 check_msb_lsb_order!(msb, lsb);
185 let bit_len = $crate::size_of::<$slice_ty>()*8;
186 let value_bit_len = $crate::size_of::<$bitrange_ty>()*8;
187 let mut value = 0;
188 for i in (lsb..=msb).rev() {
189 value <<= 1;
190 value |= ((self.0.as_ref()[i/bit_len] >> (i%bit_len)) & 1) as $bitrange_ty;
191 }
192 value << (value_bit_len - (msb - lsb + 1)) >> (value_bit_len - (msb - lsb + 1))
193 }
194 }
195 impl<T: AsMut<[$slice_ty]>> $crate::BitRangeMut<$bitrange_ty>
196 for $name<T> {
197
198 fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $bitrange_ty) {
199 check_msb_lsb_order!(msb, lsb);
200 let bit_len = $crate::size_of::<$slice_ty>()*8;
201 let mut value = value;
202 for i in lsb..=msb {
203 self.0.as_mut()[i/bit_len] &= !(1 << (i%bit_len));
204 self.0.as_mut()[i/bit_len] |= (value & 1) as $slice_ty << (i%bit_len);
205 value >>= 1;
206 }
207 }
208 }
209 };
210 (@impl_bitrange_slice_msb0 $name:ident, $slice_ty:ty, $bitrange_ty:ty) => {
211 impl<T: AsRef<[$slice_ty]>> $crate::BitRange<$bitrange_ty>
212 for $name<T> {
213 fn bit_range(&self, msb: usize, lsb: usize) -> $bitrange_ty {
214 check_msb_lsb_order!(msb, lsb);
215 let bit_len = $crate::size_of::<$slice_ty>()*8;
216 let value_bit_len = $crate::size_of::<$bitrange_ty>()*8;
217 let mut value = 0;
218 for i in lsb..=msb {
219 value <<= 1;
220 value |= ((self.0.as_ref()[i/bit_len] >> (bit_len - i%bit_len - 1)) & 1)
221 as $bitrange_ty;
222 }
223 value << (value_bit_len - (msb - lsb + 1)) >> (value_bit_len - (msb - lsb + 1))
224 }
225 }
226 impl<T: AsMut<[$slice_ty]>> $crate::BitRangeMut<$bitrange_ty>
227 for $name<T> {
228 fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $bitrange_ty) {
229 check_msb_lsb_order!(msb, lsb);
230 let bit_len = $crate::size_of::<$slice_ty>()*8;
231 let mut value = value;
232 for i in (lsb..=msb).rev() {
233 self.0.as_mut()[i/bit_len] &= !(1 << (bit_len - i%bit_len - 1));
234 self.0.as_mut()[i/bit_len] |= (value & 1) as $slice_ty
235 << (bit_len - i%bit_len - 1);
236 value >>= 1;
237 }
238 }
239 }
240 };
241 (struct $name:ident([$t:ty])) => {
242 bitfield_bitrange!(@impl_bitrange_slice $name, $t, u8);
243 bitfield_bitrange!(@impl_bitrange_slice $name, $t, u16);
244 bitfield_bitrange!(@impl_bitrange_slice $name, $t, u32);
245 bitfield_bitrange!(@impl_bitrange_slice $name, $t, u64);
246 bitfield_bitrange!(@impl_bitrange_slice $name, $t, u128);
247 bitfield_bitrange!(@impl_bitrange_slice $name, $t, i8);
248 bitfield_bitrange!(@impl_bitrange_slice $name, $t, i16);
249 bitfield_bitrange!(@impl_bitrange_slice $name, $t, i32);
250 bitfield_bitrange!(@impl_bitrange_slice $name, $t, i64);
251 bitfield_bitrange!(@impl_bitrange_slice $name, $t, i128);
252 };
253 (struct $name:ident(MSB0 [$t:ty])) => {
254 bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, u8);
255 bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, u16);
256 bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, u32);
257 bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, u64);
258 bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, u128);
259 bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, i8);
260 bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, i16);
261 bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, i32);
262 bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, i64);
263 bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, i128);
264 };
265 (struct $name:ident($t:ty)) => {
266 impl<T> $crate::BitRange<T> for $name where $t: $crate::BitRange<T> {
267 fn bit_range(&self, msb: usize, lsb: usize) -> T {
268 self.0.bit_range(msb, lsb)
269 }
270 }
271 impl<T> $crate::BitRangeMut<T> for $name where $t: $crate::BitRangeMut<T> {
272 fn set_bit_range(&mut self, msb: usize, lsb: usize, value: T) {
273 self.0.set_bit_range(msb, lsb, value);
274 }
275 }
276 };
277}
278
279#[macro_export(local_inner_macros)]
340macro_rules! bitfield {
341 ($(#[$attribute:meta])* $vis:vis struct $name:ident($($type:tt)*); $(impl $trait:ident$({$($trait_arg:tt)*})?;)+ no default BitRange; $($rest:tt)*) => {
344 bitfield!{$(#[$attribute])* $vis struct $name($($type)*); no default BitRange; $(impl $trait$({$($trait_arg)*})?;)* $($rest)*}
345 };
346
347 ($(#[$attribute:meta])* $vis:vis struct $name:ident([$t:ty]); no default BitRange; impl $trait:ident$({$($trait_arg:tt)*})?; $($rest:tt)*) => {
350 bitfield_impl!{$trait$({$($trait_arg)*})? for struct $name([$t]); $($rest)*}
351
352 bitfield!{$(#[$attribute])* $vis struct $name([$t]); no default BitRange; $($rest)*}
353 };
354 ($(#[$attribute:meta])* $vis:vis struct $name:ident([$t:ty]); no default BitRange; $($rest:tt)*) => {
355 $(#[$attribute])*
356 $vis struct $name<T>(pub T);
357
358 impl<T: AsRef<[$t]>> $name<T> {
362 bitfield_fields!{only getter; $($rest)*}
363 }
364 impl<T: AsMut<[$t]>> $name<T> {
365 bitfield_fields!{only setter; $($rest)*}
366 }
367 };
368 ($(#[$attribute:meta])* $vis:vis struct $name:ident([$t:ty]); $($rest:tt)*) => {
369 bitfield_bitrange!(struct $name([$t]));
370 bitfield!{$(#[$attribute])* $vis struct $name([$t]); no default BitRange; $($rest)*}
371 };
372
373 ($(#[$attribute:meta])* $vis:vis struct $name:ident(MSB0 [$t:ty]); no default BitRange; $($rest:tt)*) => {
376 bitfield!{$(#[$attribute])* $vis struct $name([$t]); no default BitRange; $($rest)*}
377 };
378 ($(#[$attribute:meta])* $vis:vis struct $name:ident(MSB0 [$t:ty]); $($rest:tt)*) => {
379 bitfield_bitrange!(struct $name(MSB0 [$t]));
380 bitfield!{$(#[$attribute])* $vis struct $name([$t]); no default BitRange; $($rest)*}
381 };
382
383 ($(#[$attribute:meta])* $vis:vis struct $name:ident($t:ty); no default BitRange; impl $trait:ident$({$($trait_arg:tt)*})?; $($rest:tt)*) => {
384 bitfield_impl!{$trait$({$($trait_arg)*})? for struct $name($t); $($rest)*}
385
386 bitfield!{$(#[$attribute])* $vis struct $name($t); no default BitRange; $($rest)*}
387 };
388 ($(#[$attribute:meta])* $vis:vis struct $name:ident($t:ty); no default BitRange; $($rest:tt)*) => {
389 $(#[$attribute])*
390 $vis struct $name(pub $t);
391
392 impl $name {
393 bitfield_fields!{$t; $($rest)*}
394 }
395 };
396 ($(#[$attribute:meta])* $vis:vis struct $name:ident($t:ty); $($rest:tt)*) => {
397 bitfield_bitrange!(struct $name($t));
398 bitfield!{$(#[$attribute])* $vis struct $name($t); no default BitRange; $($rest)*}
399 };
400}
401
402#[doc(hidden)]
403pub use core::convert::Into;
404#[doc(hidden)]
405pub use core::convert::TryInto;
406#[doc(hidden)]
407pub use core::fmt;
408#[doc(hidden)]
409pub use core::mem::size_of;
410#[doc(hidden)]
411pub use core::ops;
412
413pub trait BitRange<T> {
415 fn bit_range(&self, msb: usize, lsb: usize) -> T;
417}
418
419pub trait BitRangeMut<T> {
421 fn set_bit_range(&mut self, msb: usize, lsb: usize, value: T);
423}
424
425pub trait Bit {
429 fn bit(&self, bit: usize) -> bool;
431}
432
433pub trait BitMut {
437 fn set_bit(&mut self, bit: usize, value: bool);
439}
440
441impl<T: BitRange<u8>> Bit for T {
442 fn bit(&self, bit: usize) -> bool {
443 self.bit_range(bit, bit) != 0
444 }
445}
446
447impl<T: BitRangeMut<u8>> BitMut for T {
448 fn set_bit(&mut self, bit: usize, value: bool) {
449 self.set_bit_range(bit, bit, value as u8);
450 }
451}
452
453#[doc(hidden)]
454trait ToUnsigned {
455 type Output;
456}
457
458macro_rules! impl_to_unsigned {
459 ($($t:ty => $u:ty),* $(,)?) => {
460 $(
461 impl ToUnsigned for $t {
462 type Output = $u;
463 }
464 )*
465 };
466}
467
468impl_to_unsigned! {
469 u8 => u8, u16 => u16, u32 => u32, u64 => u64, u128 => u128,
470 i8 => u8, i16 => u16, i32 => u32, i64 => u64, i128 => u128,
471}
472
473macro_rules! impl_bitrange_for_u {
474 ($t:ty, $bitrange_ty:ty) => {
475 impl BitRange<$bitrange_ty> for $t {
476 #[inline]
477 #[allow(clippy::cast_lossless)]
478 #[allow(clippy::manual_bits)]
479 fn bit_range(&self, msb: usize, lsb: usize) -> $bitrange_ty {
480 check_msb_lsb_order!(msb, lsb);
481 let bit_len = size_of::<$t>() * 8;
482 let result_bit_len = size_of::<$bitrange_ty>() * 8;
483 let result =
484 ((*self << (bit_len - msb - 1)) >> (bit_len - msb - 1 + lsb)) as $bitrange_ty;
485 result << (result_bit_len - (msb - lsb + 1)) >> (result_bit_len - (msb - lsb + 1))
486 }
487 }
488
489 impl BitRangeMut<$bitrange_ty> for $t {
490 #[inline]
491 #[allow(clippy::cast_lossless)]
492 #[allow(clippy::manual_bits)]
493 fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $bitrange_ty) {
494 check_msb_lsb_order!(msb, lsb);
495 let bit_len = size_of::<$t>() * 8;
496 let mask: <$t as ToUnsigned>::Output = !(0 as <$t as ToUnsigned>::Output)
497 << (bit_len - msb - 1)
498 >> (bit_len - msb - 1 + lsb)
499 << (lsb);
500 *self &= !mask as $t;
501 *self |= (((value as <$t as ToUnsigned>::Output) << lsb) & mask) as $t;
502 }
503 }
504 };
505}
506
507macro_rules! impl_bitrange_for_u_combinations {
508((),($($bitrange_ty:ty),*)) => {
509
510};
511(($t:ty),($($bitrange_ty:ty),*)) => {
512 $(impl_bitrange_for_u!{$t, $bitrange_ty})*
513};
514 (($t_head:ty, $($t_rest:ty),*),($($bitrange_ty:ty),*)) => {
515 impl_bitrange_for_u_combinations!{($t_head), ($($bitrange_ty),*)}
516 impl_bitrange_for_u_combinations!{($($t_rest),*), ($($bitrange_ty),*)}
517 };
518}
519
520impl_bitrange_for_u_combinations! {(u8, u16, u32, u64, u128), (u8, u16, u32, u64, u128)}
521impl_bitrange_for_u_combinations! {(u8, u16, u32, u64, u128), (i8, i16, i32, i64, i128)}
522impl_bitrange_for_u_combinations! {(i8, i16, i32, i64, i128), (u8, u16, u32, u64, u128)}
523impl_bitrange_for_u_combinations! {(i8, i16, i32, i64, i128), (i8, i16, i32, i64, i128)}