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/// Generates and dispatches trait implementations for a struct
17///
18/// This must be called outside of any `impl` block.
19///
20/// The syntax is `TheNameOfTheTrait for struct TheNameOfTheStruct(TheInnerType);` followed by the syntax of bitfield_fields.
21///
22/// Supported traits:
23/// * Debug
24/// * BitAnd
25/// * BitOr
26/// * BitXor
27///
28/// Additional derivations:
29/// * new
30///   * Creates a constructor, including parameters for all fields with a setter
31#[macro_export(local_inner_macros)]
32macro_rules! bitfield_impl {
33    (Debug for struct $name:ident([$t:ty]); $($rest:tt)*) => {
34        impl<T: AsRef<[$t]> + $crate::fmt::Debug> $crate::fmt::Debug for $name<T> {
35            bitfield_debug!{struct $name; $($rest)*}
36        }
37    };
38    (Debug for struct $name:ident($t:ty); $($rest:tt)*) => {
39        impl $crate::fmt::Debug for $name {
40            bitfield_debug!{struct $name; $($rest)*}
41        }
42    };
43    (BitAnd for struct $name:ident([$t:ty]); $($rest:tt)*) => {
44        bitfield_impl!{@bitwise BitAnd bitand BitAndAssign bitand_assign $name([$t]) &=}
45    };
46    (BitAnd for struct $name:ident($t:ty); $($rest:tt)*) => {
47        bitfield_impl!{@bitwise BitAnd bitand BitAndAssign bitand_assign $name($t) &=}
48    };
49    (BitOr for struct $name:ident([$t:ty]); $($rest:tt)*) => {
50        bitfield_impl!{@bitwise BitOr bitor BitOrAssign bitor_assign $name([$t]) |=}
51    };
52    (BitOr for struct $name:ident($t:ty); $($rest:tt)*) => {
53        bitfield_impl!{@bitwise BitOr bitor BitOrAssign bitor_assign $name($t) |=}
54    };
55    (BitXor for struct $name:ident([$t:ty]); $($rest:tt)*) => {
56        bitfield_impl!{@bitwise BitXor bitxor BitXorAssign bitxor_assign $name([$t]) ^=}
57    };
58    (BitXor for struct $name:ident($t:ty); $($rest:tt)*) => {
59        bitfield_impl!{@bitwise BitXor bitxor BitXorAssign bitxor_assign $name($t) ^=}
60    };
61    (@bitwise $bitwise:ident $func:ident $bitwise_assign:ident $func_assign:ident $name:ident([$t:ty]) $op:tt) => {
62        impl<T: AsMut<[$t]> + AsRef<[$t]>> $crate::ops::$bitwise for $name<T> {
63            type Output = Self;
64            fn $func(mut self, rhs: Self) -> Self {
65                bitfield_impl!(@mutate self rhs $op);
66                self
67            }
68        }
69        impl<T: AsMut<[$t]> + AsRef<[$t]>> $crate::ops::$bitwise_assign for $name<T> {
70            fn $func_assign(&mut self, rhs: Self) {
71                bitfield_impl!(@mutate self rhs $op);
72            }
73        }
74    };
75    (@bitwise $bitwise:ident $func:ident $bitwise_assign:ident $func_assign:ident $name:ident($t:ty) $op:tt) => {
76        impl $crate::ops::$bitwise for $name {
77            type Output = Self;
78            fn $func(mut self, rhs: Self) -> Self {
79                self.0 $op rhs.0;
80                self
81            }
82        }
83        impl $crate::ops::$bitwise_assign for $name {
84            fn $func_assign(&mut self, rhs: Self) {
85                self.0 $op rhs.0;
86            }
87        }
88    };
89    (@mutate $self:ident $rhs:ident $op:tt) => {{
90        let as_mut = AsMut::<[_]>::as_mut(&mut $self.0);
91        let rhs = AsRef::<[_]>::as_ref(&$rhs.0);
92        for i in 0..as_mut.len() {
93            as_mut[i] $op rhs[i];
94        }
95    }};
96    (new for struct $name:ident([$t:ty]); $($rest:tt)*) => {
97        impl<T: AsMut<[$t]> + Default> $name<T> {
98            bitfield_constructor!{$($rest)*}
99        }
100    };
101    (new for struct $name:ident($t:ty); $($rest:tt)*) => {
102        impl $name {
103            bitfield_constructor!{$($rest)*}
104        }
105    };
106    (new{$new:ident ($($setter_name:ident: $setter_type:ty),*$(,)?)} for struct $name:ident([$t:ty]); $($rest:tt)*) => {
107        impl<T: AsMut<[$t]> + Default> $name<T> {
108            pub fn $new($($setter_name: $setter_type),*) -> Self {
109                let mut value = Self(T::default());
110                $(
111                    value.$setter_name($setter_name);
112                )*
113                value
114            }
115        }
116    };
117    (new{$new:ident ($($setter_name:ident: $setter_type:ty),*$(,)?)} for struct $name:ident($t:ty); $($rest:tt)*) => {
118        impl $name {
119            pub fn $new($($setter_name: $setter_type),*) -> Self {
120                let mut value = Self($t::default());
121                $(
122                    value.$setter_name($setter_name);
123                )*
124                value
125            }
126        }
127    };
128    // display a more friendly error message when someone tries to use `impl <Trait>;` syntax when not supported
129    ($macro:ident for struct $name:ident $($rest:tt)*) => {
130        ::std::compile_error!(::std::stringify!(Unsupported impl $macro for struct $name));
131    };
132}
133
134/// Implements `BitRange` and `BitRangeMut` for a tuple struct (or "newtype").
135///
136/// This macro will generate an implementation of the `BitRange` trait for an existing single
137/// element tuple struct.
138///
139/// The syntax is more or less the same as declaring a "newtype", **without** the attributes,
140/// documentation comments and pub keyword.
141///
142/// The difference with a normal "newtype" is the type in parentheses. If the type is `[t]` (where
143/// `t` is any of the unsigned integer type), the "newtype" will be generic and implement
144/// `BitRange` for `T: AsRef<[t]>` and `BitRangeMut` for `T: AsMut<[t]>` (for example a slice, an array or a `Vec`). You can
145/// also use `MSB0 [t]`. The difference will be the positions of the bit. You can use the
146/// `bits_positions` example to see where each bits is. If the type is neither of this two, the
147/// "newtype" will wrap a value of the specified type and implements `BitRange` the same ways as
148/// the wrapped type.
149///
150/// # Examples
151///
152/// ```rust
153/// # use bitfield::bitfield_bitrange;
154/// # fn main() {}
155/// struct BitField1(u32);
156/// bitfield_bitrange!{struct BitField1(u32)}
157///
158/// struct BitField2<T>(T);
159/// bitfield_bitrange!{struct BitField2([u8])}
160///
161/// struct BitField3<T>(T);
162/// bitfield_bitrange!{struct BitField3(MSB0 [u8])}
163/// ```
164///
165#[macro_export(local_inner_macros)]
166macro_rules! bitfield_bitrange {
167    (@impl_bitrange_slice $name:ident, $slice_ty:ty, $bitrange_ty:ty) => {
168        impl<T: AsRef<[$slice_ty]>> $crate::BitRange<$bitrange_ty>
169            for $name<T> {
170                fn bit_range(&self, msb: usize, lsb: usize) -> $bitrange_ty {
171                    let bit_len = $crate::size_of::<$slice_ty>()*8;
172                    let value_bit_len = $crate::size_of::<$bitrange_ty>()*8;
173                    let mut value = 0;
174                    for i in (lsb..=msb).rev() {
175                        value <<= 1;
176                        value |= ((self.0.as_ref()[i/bit_len] >> (i%bit_len)) & 1) as $bitrange_ty;
177                    }
178                    value << (value_bit_len - (msb - lsb + 1)) >> (value_bit_len - (msb - lsb + 1))
179                }
180        }
181        impl<T: AsMut<[$slice_ty]>> $crate::BitRangeMut<$bitrange_ty>
182            for $name<T> {
183
184                fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $bitrange_ty) {
185                    let bit_len = $crate::size_of::<$slice_ty>()*8;
186                    let mut value = value;
187                    for i in lsb..=msb {
188                        self.0.as_mut()[i/bit_len] &= !(1 << (i%bit_len));
189                        self.0.as_mut()[i/bit_len] |= (value & 1) as $slice_ty << (i%bit_len);
190                        value >>= 1;
191                    }
192                }
193            }
194    };
195    (@impl_bitrange_slice_msb0 $name:ident, $slice_ty:ty, $bitrange_ty:ty) => {
196        impl<T: AsRef<[$slice_ty]>> $crate::BitRange<$bitrange_ty>
197            for $name<T> {
198            fn bit_range(&self, msb: usize, lsb: usize) -> $bitrange_ty {
199                let bit_len = $crate::size_of::<$slice_ty>()*8;
200                let value_bit_len = $crate::size_of::<$bitrange_ty>()*8;
201                let mut value = 0;
202                for i in lsb..=msb {
203                    value <<= 1;
204                    value |= ((self.0.as_ref()[i/bit_len] >> (bit_len - i%bit_len - 1)) & 1)
205                        as $bitrange_ty;
206                }
207                value << (value_bit_len - (msb - lsb + 1)) >> (value_bit_len - (msb - lsb + 1))
208            }
209        }
210        impl<T: AsMut<[$slice_ty]>> $crate::BitRangeMut<$bitrange_ty>
211            for $name<T> {
212            fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $bitrange_ty) {
213                let bit_len = $crate::size_of::<$slice_ty>()*8;
214                let mut value = value;
215                for i in (lsb..=msb).rev() {
216                    self.0.as_mut()[i/bit_len] &= !(1 << (bit_len - i%bit_len - 1));
217                    self.0.as_mut()[i/bit_len] |= (value & 1) as $slice_ty
218                        << (bit_len - i%bit_len - 1);
219                    value >>= 1;
220                }
221            }
222        }
223    };
224    (struct $name:ident([$t:ty])) => {
225        bitfield_bitrange!(@impl_bitrange_slice $name, $t, u8);
226        bitfield_bitrange!(@impl_bitrange_slice $name, $t, u16);
227        bitfield_bitrange!(@impl_bitrange_slice $name, $t, u32);
228        bitfield_bitrange!(@impl_bitrange_slice $name, $t, u64);
229        bitfield_bitrange!(@impl_bitrange_slice $name, $t, u128);
230        bitfield_bitrange!(@impl_bitrange_slice $name, $t, i8);
231        bitfield_bitrange!(@impl_bitrange_slice $name, $t, i16);
232        bitfield_bitrange!(@impl_bitrange_slice $name, $t, i32);
233        bitfield_bitrange!(@impl_bitrange_slice $name, $t, i64);
234        bitfield_bitrange!(@impl_bitrange_slice $name, $t, i128);
235    };
236    (struct $name:ident(MSB0 [$t:ty])) => {
237        bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, u8);
238        bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, u16);
239        bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, u32);
240        bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, u64);
241        bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, u128);
242        bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, i8);
243        bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, i16);
244        bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, i32);
245        bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, i64);
246        bitfield_bitrange!(@impl_bitrange_slice_msb0 $name, $t, i128);
247    };
248    (struct $name:ident($t:ty)) => {
249        impl<T> $crate::BitRange<T> for $name where $t: $crate::BitRange<T> {
250            fn bit_range(&self, msb: usize, lsb: usize) -> T {
251                self.0.bit_range(msb, lsb)
252            }
253        }
254        impl<T> $crate::BitRangeMut<T> for $name where $t: $crate::BitRangeMut<T> {
255            fn set_bit_range(&mut self, msb: usize, lsb: usize, value: T) {
256                self.0.set_bit_range(msb, lsb, value);
257            }
258        }
259    };
260}
261
262/// Combines `bitfield_bitrange` and `bitfield_fields`.
263///
264/// The syntax of this macro is the syntax of a tuple struct, including attributes and
265/// documentation comments, followed by a semicolon, some optional elements, and finally the fields
266/// as described in the `bitfield_fields` documentation.
267///
268/// The first optional element is `no default BitRange;`. With that, no implementation of
269/// `BitRange` will be generated.
270///
271/// The second optional element is a set of lines of the form `impl <Trait>;`. The following traits are supported:
272/// * `Debug`; This will generate an implementation of `fmt::Debug` with the `bitfield_debug` macro.
273/// * `BitAnd`, `BitOr`, `BitXor`; These will generate implementations of the relevant `ops::Bit___` and `ops::Bit___Assign` traits.
274/// * `new`; This will generate a constructor that calls all of the bitfield's setter methods with an argument of the appropriate type
275///
276/// The difference with calling those macros separately is that `bitfield_fields` is called
277/// from an appropriate `impl` block. If you use the non-slice form of `bitfield_bitrange`, the
278/// default type for `bitfield_fields` will be set to the wrapped fields.
279///
280/// See the documentation of these macros for more information on their respective syntax.
281///
282/// # Example
283///
284/// ```rust
285/// # use bitfield::bitfield;
286/// # fn main() {}
287/// bitfield!{
288///   pub struct BitField1(u16);
289///   impl Debug;
290///   // The fields default to u16
291///   field1, set_field1: 10, 0;
292///   pub field2, _ : 12, 3;
293/// }
294/// ```
295///
296/// or with a custom `BitRange` and `BitRangeMut` implementation :
297/// ```rust
298/// # use bitfield::{bitfield, BitRange, BitRangeMut};
299/// # fn main() {}
300/// bitfield!{
301///   pub struct BitField1(u16);
302///   no default BitRange;
303///   impl Debug;
304///   impl BitAnd;
305///   u8;
306///   field1, set_field1: 10, 0;
307///   pub field2, _ : 12, 3;
308/// }
309/// impl BitRange<u8> for BitField1 {
310///     fn bit_range(&self, msb: usize, lsb: usize) -> u8 {
311///         let width = msb - lsb + 1;
312///         let mask = (1 << width) - 1;
313///         ((self.0 >> lsb) & mask) as u8
314///     }
315/// }
316/// impl BitRangeMut<u8> for BitField1 {
317///     fn set_bit_range(&mut self, msb: usize, lsb: usize, value: u8) {
318///         self.0 = (value as u16) << lsb;
319///     }
320/// }
321/// ```
322#[macro_export(local_inner_macros)]
323macro_rules! bitfield {
324    // Force `impl <Trait>` to always be after `no default BitRange` it the two are present.
325    // This simplify the rest of the macro.
326    ($(#[$attribute:meta])* $vis:vis struct $name:ident($($type:tt)*); $(impl $trait:ident$({$($trait_arg:tt)*})?;)+ no default BitRange; $($rest:tt)*) => {
327         bitfield!{$(#[$attribute])* $vis struct $name($($type)*); no default BitRange; $(impl $trait$({$($trait_arg)*})?;)* $($rest)*}
328     };
329
330    // If we have `impl <Trait>` without `no default BitRange`, we will still match, because when
331    // we call `bitfield_bitrange`, we add `no default BitRange`.
332    ($(#[$attribute:meta])* $vis:vis struct $name:ident([$t:ty]); no default BitRange; impl $trait:ident$({$($trait_arg:tt)*})?; $($rest:tt)*) => {
333        bitfield_impl!{$trait$({$($trait_arg)*})? for struct $name([$t]); $($rest)*}
334
335        bitfield!{$(#[$attribute])* $vis struct $name([$t]); no default BitRange;  $($rest)*}
336    };
337    ($(#[$attribute:meta])* $vis:vis struct $name:ident([$t:ty]); no default BitRange; $($rest:tt)*) => {
338        $(#[$attribute])*
339        $vis struct $name<T>(pub T);
340
341        //impl<T: AsMut<[$t]> + AsRef<[$t]>> $name<T> {
342        //    bitfield_fields!{$($rest)*}
343        //}
344        impl<T: AsRef<[$t]>> $name<T> {
345           bitfield_fields!{only getter; $($rest)*}
346        }
347        impl<T: AsMut<[$t]>> $name<T> {
348           bitfield_fields!{only setter; $($rest)*}
349        }
350    };
351    ($(#[$attribute:meta])* $vis:vis struct $name:ident([$t:ty]); $($rest:tt)*) => {
352        bitfield_bitrange!(struct $name([$t]));
353        bitfield!{$(#[$attribute])* $vis struct $name([$t]); no default BitRange; $($rest)*}
354    };
355
356    // The only difference between the MSB0 version anf the non-MSB0 version, is the BitRange
357    // implementation. We delegate everything else to the non-MSB0 version of the macro.
358    ($(#[$attribute:meta])* $vis:vis struct $name:ident(MSB0 [$t:ty]); no default BitRange; $($rest:tt)*) => {
359        bitfield!{$(#[$attribute])* $vis struct $name([$t]); no default BitRange; $($rest)*}
360    };
361    ($(#[$attribute:meta])* $vis:vis struct $name:ident(MSB0 [$t:ty]); $($rest:tt)*) => {
362        bitfield_bitrange!(struct $name(MSB0 [$t]));
363        bitfield!{$(#[$attribute])* $vis struct $name([$t]); no default BitRange; $($rest)*}
364    };
365
366    ($(#[$attribute:meta])* $vis:vis struct $name:ident($t:ty); no default BitRange; impl $trait:ident$({$($trait_arg:tt)*})?; $($rest:tt)*) => {
367        bitfield_impl!{$trait$({$($trait_arg)*})? for struct $name($t); $($rest)*}
368
369        bitfield!{$(#[$attribute])* $vis struct $name($t); no default BitRange; $($rest)*}
370    };
371    ($(#[$attribute:meta])* $vis:vis struct $name:ident($t:ty); no default BitRange; $($rest:tt)*) => {
372        $(#[$attribute])*
373        $vis struct $name(pub $t);
374
375        impl $name {
376            bitfield_fields!{$t; $($rest)*}
377         }
378    };
379    ($(#[$attribute:meta])* $vis:vis struct $name:ident($t:ty); $($rest:tt)*) => {
380        bitfield_bitrange!(struct $name($t));
381        bitfield!{$(#[$attribute])* $vis struct $name($t); no default BitRange; $($rest)*}
382    };
383}
384
385#[doc(hidden)]
386pub use core::convert::Into;
387#[doc(hidden)]
388pub use core::fmt;
389#[doc(hidden)]
390pub use core::mem::size_of;
391#[doc(hidden)]
392pub use core::ops;
393
394/// A trait to get ranges of bits.
395pub trait BitRange<T> {
396    /// Get a range of bits.
397    fn bit_range(&self, msb: usize, lsb: usize) -> T;
398}
399
400/// A trait to set ranges of bits.
401pub trait BitRangeMut<T> {
402    /// Set a range of bits.
403    fn set_bit_range(&mut self, msb: usize, lsb: usize, value: T);
404}
405
406/// A trait to get a single bit.
407///
408/// This trait is implemented for all type that implement `BitRange<u8>`.
409pub trait Bit {
410    /// Get a single bit.
411    fn bit(&self, bit: usize) -> bool;
412}
413
414/// A trait to set a single bit.
415///
416/// This trait is implemented for all type that implement `BitRangeMut<u8>`.
417pub trait BitMut {
418    /// Set a single bit.
419    fn set_bit(&mut self, bit: usize, value: bool);
420}
421
422impl<T: BitRange<u8>> Bit for T {
423    fn bit(&self, bit: usize) -> bool {
424        self.bit_range(bit, bit) != 0
425    }
426}
427
428impl<T: BitRangeMut<u8>> BitMut for T {
429    fn set_bit(&mut self, bit: usize, value: bool) {
430        self.set_bit_range(bit, bit, value as u8);
431    }
432}
433
434macro_rules! impl_bitrange_for_u {
435    ($t:ty, $bitrange_ty:ty) => {
436        impl BitRange<$bitrange_ty> for $t {
437            #[inline]
438            #[allow(clippy::cast_lossless)]
439            #[allow(clippy::manual_bits)]
440            fn bit_range(&self, msb: usize, lsb: usize) -> $bitrange_ty {
441                let bit_len = size_of::<$t>()*8;
442                let result_bit_len = size_of::<$bitrange_ty>()*8;
443                let result = ((*self << (bit_len - msb - 1)) >> (bit_len - msb - 1 + lsb))
444                    as $bitrange_ty;
445                result << (result_bit_len - (msb - lsb + 1)) >> (result_bit_len - (msb - lsb + 1))
446            }
447        }
448
449        impl BitRangeMut<$bitrange_ty> for $t {
450            #[inline]
451            #[allow(clippy::cast_lossless)]
452            #[allow(clippy::manual_bits)]
453            fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $bitrange_ty) {
454                let bit_len = size_of::<$t>()*8;
455                let mask: $t = !(0 as $t)
456                    << (bit_len - msb - 1)
457                    >> (bit_len - msb - 1 + lsb)
458                    << (lsb);
459                *self &= !mask;
460                *self |= (value as $t << lsb) & mask;
461            }
462        }
463    }
464}
465
466macro_rules! impl_bitrange_for_u_combinations {
467((),($($bitrange_ty:ty),*)) => {
468
469};
470(($t:ty),($($bitrange_ty:ty),*)) => {
471        $(impl_bitrange_for_u!{$t, $bitrange_ty})*
472};
473    (($t_head:ty, $($t_rest:ty),*),($($bitrange_ty:ty),*)) => {
474        impl_bitrange_for_u_combinations!{($t_head), ($($bitrange_ty),*)}
475        impl_bitrange_for_u_combinations!{($($t_rest),*), ($($bitrange_ty),*)}
476    };
477}
478
479impl_bitrange_for_u_combinations! {(u8, u16, u32, u64, u128), (u8, u16, u32, u64, u128)}
480impl_bitrange_for_u_combinations! {(u8, u16, u32, u64, u128), (i8, i16, i32, i64, i128)}