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 ::std::compile_error!(::std::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::fmt;
406#[doc(hidden)]
407pub use core::mem::size_of;
408#[doc(hidden)]
409pub use core::ops;
410
411pub trait BitRange<T> {
413 fn bit_range(&self, msb: usize, lsb: usize) -> T;
415}
416
417pub trait BitRangeMut<T> {
419 fn set_bit_range(&mut self, msb: usize, lsb: usize, value: T);
421}
422
423pub trait Bit {
427 fn bit(&self, bit: usize) -> bool;
429}
430
431pub trait BitMut {
435 fn set_bit(&mut self, bit: usize, value: bool);
437}
438
439impl<T: BitRange<u8>> Bit for T {
440 fn bit(&self, bit: usize) -> bool {
441 self.bit_range(bit, bit) != 0
442 }
443}
444
445impl<T: BitRangeMut<u8>> BitMut for T {
446 fn set_bit(&mut self, bit: usize, value: bool) {
447 self.set_bit_range(bit, bit, value as u8);
448 }
449}
450
451#[doc(hidden)]
452trait ToUnsigned {
453 type Output;
454}
455
456macro_rules! impl_to_unsigned {
457 ($($t:ty => $u:ty),* $(,)?) => {
458 $(
459 impl ToUnsigned for $t {
460 type Output = $u;
461 }
462 )*
463 };
464}
465
466impl_to_unsigned! {
467 u8 => u8, u16 => u16, u32 => u32, u64 => u64, u128 => u128,
468 i8 => u8, i16 => u16, i32 => u32, i64 => u64, i128 => u128,
469}
470
471macro_rules! impl_bitrange_for_u {
472 ($t:ty, $bitrange_ty:ty) => {
473 impl BitRange<$bitrange_ty> for $t {
474 #[inline]
475 #[allow(clippy::cast_lossless)]
476 #[allow(clippy::manual_bits)]
477 fn bit_range(&self, msb: usize, lsb: usize) -> $bitrange_ty {
478 check_msb_lsb_order!(msb, lsb);
479 let bit_len = size_of::<$t>() * 8;
480 let result_bit_len = size_of::<$bitrange_ty>() * 8;
481 let result =
482 ((*self << (bit_len - msb - 1)) >> (bit_len - msb - 1 + lsb)) as $bitrange_ty;
483 result << (result_bit_len - (msb - lsb + 1)) >> (result_bit_len - (msb - lsb + 1))
484 }
485 }
486
487 impl BitRangeMut<$bitrange_ty> for $t {
488 #[inline]
489 #[allow(clippy::cast_lossless)]
490 #[allow(clippy::manual_bits)]
491 fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $bitrange_ty) {
492 check_msb_lsb_order!(msb, lsb);
493 let bit_len = size_of::<$t>() * 8;
494 let mask: <$t as ToUnsigned>::Output = !(0 as <$t as ToUnsigned>::Output)
495 << (bit_len - msb - 1)
496 >> (bit_len - msb - 1 + lsb)
497 << (lsb);
498 *self &= !mask as $t;
499 *self |= (((value as <$t as ToUnsigned>::Output) << lsb) & mask) as $t;
500 }
501 }
502 };
503}
504
505macro_rules! impl_bitrange_for_u_combinations {
506((),($($bitrange_ty:ty),*)) => {
507
508};
509(($t:ty),($($bitrange_ty:ty),*)) => {
510 $(impl_bitrange_for_u!{$t, $bitrange_ty})*
511};
512 (($t_head:ty, $($t_rest:ty),*),($($bitrange_ty:ty),*)) => {
513 impl_bitrange_for_u_combinations!{($t_head), ($($bitrange_ty),*)}
514 impl_bitrange_for_u_combinations!{($($t_rest),*), ($($bitrange_ty),*)}
515 };
516}
517
518impl_bitrange_for_u_combinations! {(u8, u16, u32, u64, u128), (u8, u16, u32, u64, u128)}
519impl_bitrange_for_u_combinations! {(u8, u16, u32, u64, u128), (i8, i16, i32, i64, i128)}
520impl_bitrange_for_u_combinations! {(i8, i16, i32, i64, i128), (u8, u16, u32, u64, u128)}
521impl_bitrange_for_u_combinations! {(i8, i16, i32, i64, i128), (i8, i16, i32, i64, i128)}