Skip to main content

simple_bitfield/
lib.rs

1#![no_std]
2
3
4//! Crate to create simple C-style bitfields with the same memory structure
5//! as the underlying data type (typically integer). Can be used in `#![no_std]` environments.
6//! 
7//! Properties of such bitfields:
8//!  * they have the exact same memory layout and size as the underlying primitive type;
9//!  * their size is checked at compile-time, so it's not possible to add a field that won't fit into the underlying type;
10//!  * their fields can be accessed by name (`my_bitfield.some_field`) which aids readability;
11//!  * each field has the same set of functions (`get`, `set`, `set_checked` and more);
12//!  * each field has its own distinct type;
13//!  * it's possible to skip (and not name) any number of bits
14//!
15//! The [bitfield] macro was inspired by [https://guiand.xyz/blog-posts/bitfields.html](https://guiand.xyz/blog-posts/bitfields.html).
16//! 
17//! ## Example:
18//! ```
19//! use simple_bitfield::{bitfield, Field};
20//! 
21//! bitfield! {
22//!     // Bitfield with underlying type `u32`
23//!     struct MyBitfield<u32> {
24//!         field1: 3, // First field (least significant) of size 3 bits
25//!         field2: 9,
26//!         _: 6,      // Fields named `_` are skipped (offsets are preserved)
27//!         field3: 1  // Last bit (closest to the highest bit of `u32`)
28//!     }
29//! 
30//!     // Multiple bitfields can be defined within one macro invocation
31//!    struct AnotherBitfield<u8> {
32//!        _: 7,
33//!        highest_bit: 1
34//!    }
35//! }
36//!
37//! fn main() {
38//!    // Create bitfield object
39//!    let mut a_bitfield = MyBitfield::new(12345);
40//!
41//!    // Get the field's value (of underlying type)
42//!    let field3: u32 = a_bitfield.field3.get();
43//!
44//!    println!(
45//!        "{:#b} => {:#b}, {:#b}, {:#b}",
46//!        u32::from(a_bitfield), // Convert bitfield to underlying type
47//!        field3,
48//!        a_bitfield.field2.get(),
49//!        a_bitfield.field1.get()
50//!    );
51//!
52//!    // Update just that field
53//!    a_bitfield.field1.set(0);
54//!
55//!    println!("{:#b}", u32::from(a_bitfield));
56//!
57//!    println!("{}\n{:?}", a_bitfield, a_bitfield);
58//!    // MyBitfield(12344)
59//!    // MyBitfield(field1: 0, field2: 7, field3: 0)
60//!
61//!    // The type can be inferred, of course
62//!    let another_one: AnotherBitfield::AnotherBitfield = AnotherBitfield::new(184);
63//!    
64//!    // Fields cannot be moved or copied!
65//!    // let another_one_highest = another_one.highest_bit;
66//!
67//!    // Each field has its own type
68//!    let another_one_highest: &AnotherBitfield::highest_bit = &another_one.highest_bit;
69//!    println!("{:#b}", another_one_highest.get())
70//! }
71//! ```
72//!
73//! ## These bitfields are _simple_
74//! One bitfield is essentially one integer that has fields whose `get` methods
75//! return data of the same integer type. Bitfields that contain more than one integer
76//! or any type that doesn't satisfy the [Bitfield] and [Field] traits are not yet possible.
77//!
78//! Structs that contain multiple bitfields _are_ possible, and their size can be preserved
79//! via the `#[repr(packed)]` attribute. Care must be taken of the field access
80//! because code like `a_bitfield.field.get()` borrows `a_bitfield`, which can result in
81//! unaligned access if the struct with the bitfields is `#[repr(packed)]`.
82//!
83//! The [TestBitfield] module is only present in the documentation and shows how a bitfield is structured internally.
84
85use core::{
86    ops::{ Shl, Shr, BitAnd, BitOrAssign, BitXorAssign },
87    fmt::{ Debug, Display }
88};
89
90#[doc(hidden)]
91pub use static_assertions::const_assert;
92
93pub trait Bitfield {
94    //! The trait that's implemented for all bitfields.
95    //! Used mainly to access the bitfield's underlying type, [Self::BaseType].
96
97    /// The bitfield's underlying type.
98    type BaseType: Copy + Debug + Display;
99    
100    /// The maximum number of bits that the bitfield can hold.
101    /// Used for compile-time checking that no newly added field requires a [Self::BaseType] wider than this.
102    const MAX_BITS: u8 = 8 * core::mem::size_of::<Self::BaseType>() as u8;
103}
104
105pub trait Field<B: Bitfield>
106    where B::BaseType:
107        Shl<u8, Output=B::BaseType> +
108        Shr<u8, Output=B::BaseType> +
109        BitAnd<Output=B::BaseType> +
110        BitOrAssign + BitXorAssign + PartialEq
111{
112    //! The trait that's implemented for all fields of all bitfields.
113    //! Allows the nice `my_bitfield.some_field.get()` syntax.
114
115    /// The field's size _in bits_. Specified by the user.
116    const SIZE: u8;
117
118    /// The field's offset from the underlying value's least significant bit,
119    /// _in bits_.
120    ///
121    /// The first field's offset is 0, the second field's offset is
122    /// `previous_field::SIZE` and so on. Computed automatically.
123    const OFFSET: u8;
124
125    /// The field's mask that can be used to extract the last [Self::SIZE] bits from any `B::BaseType`.
126    /// Computed automatically.
127    ///
128    /// Example usage:
129    /// ```
130    /// use simple_bitfield::{ bitfield, Field };
131    ///
132    /// bitfield! {
133    ///     struct TestBitfield<u32> {
134    ///         field1: 4
135    ///     }
136    /// }
137    ///
138    /// fn main() {
139    ///     let the_bf = TestBitfield::new(123);
140    ///
141    ///     assert_eq!(TestBitfield::field1::MASK, 0b1111);
142    ///     assert_eq!(0b1011_1010 & TestBitfield::field1::MASK, 0b1010);
143    /// }
144    /// ```
145    const MASK: B::BaseType;
146    
147    /// Returns `true` if the field is not equal to zero.
148    fn is_set(&self) -> bool;
149    
150    /// `true` if the field is within the bitfield's bounds. Used for compile-time checking.
151    const VALID: bool = Self::SIZE + Self::OFFSET <= B::MAX_BITS;
152    
153    /// Returns the size of a field _at runtime_, while [Self::SIZE] is used on the _type_ of the field at compile-time.
154    fn size(&self) -> u8 { Self::SIZE }
155
156    /// Returns the offset of a field _at runtime_, while [Self::OFFSET] is used on the _type_ of the field at compile-time.
157    fn offset(&self) -> u8 { Self::OFFSET }
158
159    /// Returns the mask of a field _at runtime_, while [Self::MASK] is used on the _type_ of the field at compile-time.
160    fn mask(&self) -> B::BaseType { Self::MASK }
161    
162    /// Returns the current value of the field.
163    ///
164    /// Example:
165    /// ```
166    /// use simple_bitfield::{ bitfield, Field };
167    ///
168    /// bitfield! {
169    ///     struct TestBitfield<u32> {
170    ///         field1: 4
171    ///     }
172    /// }
173    ///
174    /// fn main() {
175    ///     let my_bitfield = TestBitfield::new(0b10_1111);
176    ///
177    ///     assert_eq!(my_bitfield.field1.get(), 0b1111);
178    /// }
179    /// ```
180    fn get(&self) -> B::BaseType {
181        let data_ptr: *const B::BaseType = self as *const Self as *const B::BaseType;
182        
183        (unsafe { *data_ptr } >> Self::OFFSET) & Self::MASK
184    }
185    
186    /// Sets the value of a field. If the value is wider than the field,
187    /// the value's lowest [Self::SIZE] bits will be used.
188    ///
189    /// Example:
190    /// ```
191    /// use simple_bitfield::{ bitfield, Field };
192    ///
193    /// bitfield! {
194    ///     struct TestBitfield<u32> {
195    ///         field1: 4
196    ///     }
197    /// }
198    ///
199    /// fn main() {
200    ///     let mut my_bitfield = TestBitfield::new(0b10_1111);  // Must be mutable
201    ///
202    ///     my_bitfield.field1.set(0b1_1100);
203    ///     assert_eq!(my_bitfield.field1.get(), 0b1100);
204    /// }
205    /// ```
206    fn set(&mut self, new_value: B::BaseType) {
207        let data_ptr: *mut B::BaseType = self as *const Self as *mut B::BaseType;
208        
209        let old_value: B::BaseType = self.get() << Self::OFFSET;
210        
211        unsafe {
212            *data_ptr ^= old_value;
213            *data_ptr |= (new_value & Self::MASK) << Self::OFFSET
214        }
215    }
216
217    /// Sets the value of a field. If the value is wider than the field,
218    /// returns an `Err` result containing the value's lowest [Self::SIZE] bits
219    /// and doesn't modify the field.
220    ///
221    /// Example:
222    /// ```
223    /// use simple_bitfield::{ bitfield, Field };
224    ///
225    /// bitfield! {
226    ///     struct TestBitfield<u32> {
227    ///         field1: 4
228    ///     }
229    /// }
230    ///
231    /// fn main() {
232    ///     let mut my_bitfield = TestBitfield::new(0b10_1111);  // Must be mutable
233    ///
234    ///     assert_eq!(
235    ///         my_bitfield.field1.set_checked(0b1_1100),
236    ///         Err(0b1100)
237    ///     );
238    ///
239    ///     // The field's value didn't change
240    ///     assert_eq!(my_bitfield.field1.get(), 0b1111);
241    /// }
242    /// ```
243    fn set_checked(&mut self, new_value: B::BaseType) -> Result<(), B::BaseType> {
244        let masked = new_value & Self::MASK;
245
246        if masked != new_value {
247            Err(masked)
248        } else {
249            self.set(masked);
250
251            Ok(())
252        }
253    }
254}
255
256/// Generates the format args for all fields of a bitfield.
257///
258/// The result looks like this: `field_low: value, field: value, field_high: value`. Used internally.
259#[macro_export]
260#[doc(hidden)]
261macro_rules! gen_format_debug {
262    ($self:ident) => { format_args!("{}", "") };
263    ($self:ident | $first_field:ident) => {
264        format_args!(
265            "{}: {:?}",
266            // Can't just refer to `self` because it's a keyword?!
267            // So have to pass it from call site
268            stringify!($first_field), $self.$first_field.get()
269        )
270    };
271    ($self:ident | $first_field:ident | $second_field:ident $(| $other_field:ident)*) => {
272        format_args!(
273            "{}: {:?}, {}",
274            stringify!($first_field), $self.$first_field.get(),
275            $crate::gen_format_debug!($self | $second_field $(| $other_field)*)
276        )
277    };
278}
279
280
281/// Creates bitfield types.
282///
283/// Adapted from [https://guiand.xyz/blog-posts/bitfields.html](https://guiand.xyz/blog-posts/bitfields.html)
284///
285/// Example:
286/// ```
287/// use core::mem::{size_of, size_of_val};
288/// use simple_bitfield::{
289///     bitfield, Field // For field access
290/// };
291///
292/// bitfield!{
293///     struct BitfieldName<u8> {
294///         first_two_bits: 2,
295///         three_more_bits: 3
296///     }
297///
298///     struct AnotherBitfield<u32> {
299///         _: 31, // Skip first 31 bits
300///         last_bit: 1
301///     }
302/// }
303///
304/// # pub fn main() {
305/// let value: u8 = 0b111_011_10;
306/// let my_bitfield: BitfieldName::BitfieldName = BitfieldName::new(value);
307/// let another_bitfield = AnotherBitfield::new(value.into());
308///
309/// assert_eq!(
310///     size_of_val(&my_bitfield),
311///     size_of::<u8>()
312/// );
313/// assert_eq!(
314///     size_of_val(&my_bitfield),
315///     size_of::<u8>()
316/// );
317///
318/// assert_eq!(my_bitfield.first_two_bits.size(), 2);
319/// assert_eq!(my_bitfield.three_more_bits.size(), 3);
320///
321/// assert_eq!(my_bitfield.first_two_bits.get(), value & 0b11);
322/// assert_eq!(
323///     my_bitfield.three_more_bits.get(),
324///     (value >> my_bitfield.first_two_bits.size()) & 0b111
325/// );
326///
327/// assert_eq!(another_bitfield.last_bit.get(), 0);
328/// # }
329/// ```
330///
331/// The bitfield `BitfieldName` is actually a module. The type that holds the data is `BitfieldName::BitfieldName`,
332/// which is unique for each bitfield. Each field is a zero-size struct that cannot be instantiated separately from the bitfield.
333/// The memory representation of the bitfield is exactly the same as that of the underlying type.
334#[macro_export]
335macro_rules! bitfield {
336    ($($(#[$attr:meta])* $visibility:vis struct $bitfield_name:ident < $big_type:ty > { $($field:tt : $size:literal),* })*) => {$(
337        // Construct the whole module
338        #[allow(non_snake_case)]
339        #[allow(dead_code)]
340        $visibility mod $bitfield_name {
341            //! This module represents a single bitfield.
342
343            /// Struct with the actual data.
344            #[repr(transparent)]
345            #[derive(Copy, Clone)]
346            $(#[$attr])*
347            pub struct $bitfield_name($big_type);
348            impl $crate::Bitfield for $bitfield_name {
349                type BaseType = $big_type;
350            }
351
352            impl From<$big_type> for $bitfield_name
353            {
354                fn from(val: $big_type) -> Self {
355                    Self(val)
356                }
357            }
358
359            impl From<$bitfield_name> for $big_type {
360                fn from(val: $bitfield_name) -> Self {
361                    val.0
362                }
363            }
364
365            /// Creates a new bitfield
366            pub const fn new(val: $big_type) -> $bitfield_name {
367                // Can't use `val.into()` because `into` is not `const`.
368                $bitfield_name(val)
369            }
370
371            /* Generate a zero-sized (!!) `struct` for each `$field`
372             * and a zero-sized (!!) `struct Field` whose elements are objects of these structs.
373             */
374            $crate::bitfield!{
375                impl
376                $($field : $size),* end_marker // List of fields to process
377    
378                Fields, // Name of the struct that will hold the resulting fields
379                $bitfield_name, // Name of the underlying bitfield struct that holds the actual data
380                0, // Offset of the current bitfield
381                processed // Empty (!) list of processed field names
382            }
383
384            $crate::const_assert!(Fields::VALID);
385
386            /// Implement this so that accesses to fields of `$bitfield_name`
387            /// actually access the zero-sized struct `Fields`
388            impl core::ops::Deref for $bitfield_name {
389                type Target = Fields;
390
391                fn deref(&self) -> &Self::Target {
392                    // We go through Deref here because Fields MUST NOT be moveable.
393                    unsafe { &*(self as *const Self as *const Fields) } 
394                }
395            }
396
397            impl core::ops::DerefMut for $bitfield_name {
398                fn deref_mut(&mut self) -> &mut Self::Target {
399                    // We go through Deref here because Fields MUST NOT be moveable.
400                    unsafe { &mut *(self as *mut Self as *mut Fields) } 
401                }
402            }
403        }
404    )*};
405
406    (impl end_marker $struct_name:ident, $bitfield_type:ty, $curr_offset:expr, processed $(| $field_processed:ident)*) => {
407        /// Struct whose fields' names' are those of the bitfield's fields.
408        ///
409        /// When accessing a field of a bitfield like `some_bitfield.a_field`, a reference to `some_bitfield` is created
410        /// and `unsafe`ly treated as a reference to _this struct_.
411        /// However, this should actually be OK because this struct can't be constructed since none of its fields can be constructed.
412        ///
413        /// This struct's size is zero:
414        /// ```
415        /// use simple_bitfield::bitfield;
416        ///
417        /// bitfield!{
418        ///     struct BitfieldName<u8> {
419        ///         first_two_bits: 2,
420        ///         three_more_bits: 3
421        ///     }
422        /// }
423        ///
424        /// # fn main() {
425        /// assert_eq!(core::mem::size_of::<BitfieldName::Fields>(), 0);
426        /// # }
427        /// ```
428        #[repr(C)]
429        pub struct $struct_name {
430            $(pub $field_processed: $field_processed),*
431        }
432
433        impl $struct_name {
434            /// `true` if ALL fields are valid, `false` otherwise
435            const VALID: bool = $(<$field_processed as $crate::Field<$bitfield_type>>::VALID &)* true;
436        }
437
438        impl core::fmt::Display for $bitfield_type {
439            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::result::Result<(), core::fmt::Error> {
440                write!(f, "{}({})", stringify!($bitfield_type), self.0)
441            }
442        }
443
444        impl core::fmt::Debug for $bitfield_type {
445            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::result::Result<(), core::fmt::Error> {
446                use $crate::Field; // because `gen_format` accesses fields
447
448                write!(f, "{}", format_args!(
449                    "{}({})", stringify!($bitfield_type),
450                    $crate::gen_format_debug!(self $(| $field_processed)*)
451                ))
452            }
453        }
454    };
455
456    (impl _ : $size:literal $(, $other_field:tt : $other_size:literal)* end_marker $struct_name:ident, $bitfield_type:ty, $curr_offset:expr, processed $(| $field_processed:ident)*) => {
457        // Skip field that's equal to `_`
458        $crate::bitfield!{
459            impl
460            $($other_field : $other_size),* end_marker
461            $struct_name, $bitfield_type,
462            $curr_offset + $size,
463            processed $(| $field_processed)*
464        }
465    };
466
467    (impl $field:ident : $size:literal $(, $other_field:tt : $other_size:literal)* end_marker $struct_name:ident, $bitfield_type:ty, $curr_offset:expr, processed $(| $field_processed:ident)*) => {
468        // Create one field
469
470        /// The bitfield's field. Can't be constructed outside of a bitfield.
471        ///
472        /// It's actually a struct of size ZERO and implements `Field<UnderlyingBitfieldType>`, so that its value can be obtained with `get()` and changed with `set()`.
473        ///
474        /// This struct cannot be constructed explicitly:
475        /// ```compile_fail
476        /// use simple_bitfield::bitfield;
477        ///
478        /// bitfield!{
479        ///     struct BitfieldName<u8> {
480        ///         first_two_bits: 2,
481        ///         three_more_bits: 3
482        ///     }
483        /// }
484        ///
485        /// # fn main() {
486        /// let tried_to_construct_field = BitfieldName::first_two_bits(());
487        /// # }
488        /// ```
489        #[allow(non_camel_case_types)]
490        pub struct $field(());
491        /*
492         * `struct thing(())` is a "unit-valued tuple struct",
493         * basically the same as `struct thing(<any type>)`,
494         * which can be constucted like `thing(<value of type>)`,
495         * but the constructor is invisible outside the module.
496         *
497         * https://stackoverflow.com/questions/50162597/what-are-the-differences-between-the-multiple-ways-to-create-zero-sized-structs
498        */
499
500        #[allow(dead_code)]
501        impl $crate::Field<$bitfield_type> for $field {
502            const SIZE: u8 = $size;
503            const OFFSET: u8 = $curr_offset;
504            const MASK: <$bitfield_type as $crate::Bitfield>::BaseType = (1 << Self::SIZE) - 1;
505
506            #[inline]
507            fn is_set(&self) -> bool {
508                self.get() != 0
509            }
510        }
511
512        $crate::const_assert!(<$field as $crate::Field<$bitfield_type>>::VALID);
513
514        // Process the next fields
515        $crate::bitfield!{
516            impl
517            $($other_field : $other_size),* end_marker // Schedule the next fields
518            $struct_name, $bitfield_type, // Pass along
519            $curr_offset + $size, // INCREMENT the current offset!!
520            processed $(| $field_processed)* | $field // Add the field name to processed fields
521            /* The trick with field names being separated by pipes (`|`) like `| $field`
522             * is needed because `$(| $field_processed)*` may be empty, but we apparently need SOME separator,
523             * so the separator must be in front of the field name
524             */
525        }
526    }
527}
528
529
530#[cfg(doc)]
531bitfield! {
532    pub struct TestBitfield<u32> {
533        field_1: 2,
534        _: 3,
535        field_2: 5
536    }
537}
538
539
540// Should be AFTER the macro definition
541#[cfg(test)]
542mod tests;