bitfield/
lib.rs

1#![no_std]
2#![deny(
3    missing_docs,
4    unused_extern_crates,
5    unused_import_braces,
6    unused_qualifications
7)]
8//!  This crate provides macros to generate bitfield-like struct.
9//!
10//!  See the documentation of the macros for how to use them.
11//!
12//!  Examples and tests are also a great way to understand how to use these macros.
13
14pub use bitfield_macros::{bitfield_constructor, bitfield_debug, bitfield_fields};
15
16/// Internal use macro, that `debug_assert` than msb >= lsb and thus they are not inverted
17#[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/// Generates and dispatches trait implementations for a struct
30///
31/// This must be called outside of any `impl` block.
32///
33/// The syntax is `TheNameOfTheTrait for struct TheNameOfTheStruct(TheInnerType);` followed by the syntax of bitfield_fields.
34///
35/// Supported traits:
36/// * Debug
37/// * BitAnd
38/// * BitOr
39/// * BitXor
40///
41/// Additional derivations:
42/// * new
43///   * Creates a constructor, including parameters for all fields with a setter
44#[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    // display a more friendly error message when someone tries to use `impl <Trait>;` syntax when not supported
142    ($macro:ident for struct $name:ident $($rest:tt)*) => {
143        ::std::compile_error!(::std::stringify!(Unsupported impl $macro for struct $name));
144    };
145}
146
147/// Implements `BitRange` and `BitRangeMut` for a tuple struct (or "newtype").
148///
149/// This macro will generate an implementation of the `BitRange` trait for an existing single
150/// element tuple struct.
151///
152/// The syntax is more or less the same as declaring a "newtype", **without** the attributes,
153/// documentation comments and pub keyword.
154///
155/// The difference with a normal "newtype" is the type in parentheses. If the type is `[t]` (where
156/// `t` is any of the unsigned integer type), the "newtype" will be generic and implement
157/// `BitRange` for `T: AsRef<[t]>` and `BitRangeMut` for `T: AsMut<[t]>` (for example a slice, an array or a `Vec`). You can
158/// also use `MSB0 [t]`. The difference will be the positions of the bit. You can use the
159/// `bits_positions` example to see where each bits is. If the type is neither of this two, the
160/// "newtype" will wrap a value of the specified type and implements `BitRange` the same ways as
161/// the wrapped type.
162///
163/// # Examples
164///
165/// ```rust
166/// # use bitfield::bitfield_bitrange;
167/// # fn main() {}
168/// struct BitField1(u32);
169/// bitfield_bitrange!{struct BitField1(u32)}
170///
171/// struct BitField2<T>(T);
172/// bitfield_bitrange!{struct BitField2([u8])}
173///
174/// struct BitField3<T>(T);
175/// bitfield_bitrange!{struct BitField3(MSB0 [u8])}
176/// ```
177///
178#[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/// Combines `bitfield_bitrange` and `bitfield_fields`.
280///
281/// The syntax of this macro is the syntax of a tuple struct, including attributes and
282/// documentation comments, followed by a semicolon, some optional elements, and finally the fields
283/// as described in the `bitfield_fields` documentation.
284///
285/// The first optional element is `no default BitRange;`. With that, no implementation of
286/// `BitRange` will be generated.
287///
288/// The second optional element is a set of lines of the form `impl <Trait>;`. The following traits are supported:
289/// * `Debug`; This will generate an implementation of `fmt::Debug` with the `bitfield_debug` macro.
290/// * `BitAnd`, `BitOr`, `BitXor`; These will generate implementations of the relevant `ops::Bit___` and `ops::Bit___Assign` traits.
291/// * `new`; This will generate a constructor that calls all of the bitfield's setter methods with an argument of the appropriate type
292///
293/// The difference with calling those macros separately is that `bitfield_fields` is called
294/// from an appropriate `impl` block. If you use the non-slice form of `bitfield_bitrange`, the
295/// default type for `bitfield_fields` will be set to the wrapped fields.
296///
297/// See the documentation of these macros for more information on their respective syntax.
298///
299/// # Example
300///
301/// ```rust
302/// # use bitfield::bitfield;
303/// # fn main() {}
304/// bitfield!{
305///   pub struct BitField1(u16);
306///   impl Debug;
307///   // The fields default to u16
308///   field1, set_field1: 10, 0;
309///   pub field2, _ : 12, 3;
310/// }
311/// ```
312///
313/// or with a custom `BitRange` and `BitRangeMut` implementation :
314/// ```rust
315/// # use bitfield::{bitfield, BitRange, BitRangeMut};
316/// # fn main() {}
317/// bitfield!{
318///   pub struct BitField1(u16);
319///   no default BitRange;
320///   impl Debug;
321///   impl BitAnd;
322///   u8;
323///   field1, set_field1: 10, 0;
324///   pub field2, _ : 12, 3;
325/// }
326/// impl BitRange<u8> for BitField1 {
327///     fn bit_range(&self, msb: usize, lsb: usize) -> u8 {
328///         let width = msb - lsb + 1;
329///         let mask = (1 << width) - 1;
330///         ((self.0 >> lsb) & mask) as u8
331///     }
332/// }
333/// impl BitRangeMut<u8> for BitField1 {
334///     fn set_bit_range(&mut self, msb: usize, lsb: usize, value: u8) {
335///         self.0 = (value as u16) << lsb;
336///     }
337/// }
338/// ```
339#[macro_export(local_inner_macros)]
340macro_rules! bitfield {
341    // Force `impl <Trait>` to always be after `no default BitRange` it the two are present.
342    // This simplify the rest of the macro.
343    ($(#[$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    // If we have `impl <Trait>` without `no default BitRange`, we will still match, because when
348    // we call `bitfield_bitrange`, we add `no default BitRange`.
349    ($(#[$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: AsMut<[$t]> + AsRef<[$t]>> $name<T> {
359        //    bitfield_fields!{$($rest)*}
360        //}
361        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    // The only difference between the MSB0 version anf the non-MSB0 version, is the BitRange
374    // implementation. We delegate everything else to the non-MSB0 version of the macro.
375    ($(#[$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
411/// A trait to get ranges of bits.
412pub trait BitRange<T> {
413    /// Get a range of bits.
414    fn bit_range(&self, msb: usize, lsb: usize) -> T;
415}
416
417/// A trait to set ranges of bits.
418pub trait BitRangeMut<T> {
419    /// Set a range of bits.
420    fn set_bit_range(&mut self, msb: usize, lsb: usize, value: T);
421}
422
423/// A trait to get a single bit.
424///
425/// This trait is implemented for all type that implement `BitRange<u8>`.
426pub trait Bit {
427    /// Get a single bit.
428    fn bit(&self, bit: usize) -> bool;
429}
430
431/// A trait to set a single bit.
432///
433/// This trait is implemented for all type that implement `BitRangeMut<u8>`.
434pub trait BitMut {
435    /// Set a single bit.
436    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)}