[−][src]Crate simple_bitfield
Crate to create simple C-style bitfields with the same memory structure
as the underlying data type (typically integer). Can be used in #![no_std]
environments.
Properties of such bitfields:
- they have the exact same memory layout and size as the underlying primitive type;
- their size is checked at compile-time, so it's not possible to add a field that won't fit into the underlying type;
- their fields can be accessed by name (
my_bitfield.some_field
) which aids readability; - each field has the same set of functions (
get
,set
,set_checked
and more); - each field has its own distinct type;
- it's possible to skip (and not name) any number of bits
The bitfield macro was inspired by https://guiand.xyz/blog-posts/bitfields.html.
Example:
use simple_bitfield::{bitfield, Field}; bitfield! { // Bitfield with underlying type `u32` struct MyBitfield<u32> { field1: 3, // First field (least significant) of size 3 bits field2: 9, _: 6, // Fields named `_` are skipped (offsets are preserved) field3: 1 // Last bit (closest to the highest bit of `u32`) } // Multiple bitfields can be defined within one macro invocation struct AnotherBitfield<u8> { _: 7, highest_bit: 1 } } fn main() { // Create bitfield object let mut a_bitfield = MyBitfield::new(12345); // Get the field's value (of underlying type) let field3: u32 = a_bitfield.field3.get(); println!( "{:#b} => {:#b}, {:#b}, {:#b}", u32::from(a_bitfield), // Convert bitfield to underlying type field3, a_bitfield.field2.get(), a_bitfield.field1.get() ); // Update just that field a_bitfield.field1.set(0); println!("{:#b}", u32::from(a_bitfield)); println!("{}\n{:?}", a_bitfield, a_bitfield); // MyBitfield(12344) // MyBitfield(field1: 0, field2: 7, field3: 0) // The type can be inferred, of course let another_one: AnotherBitfield::AnotherBitfield = AnotherBitfield::new(184); // Fields cannot be moved or copied! // let another_one_highest = another_one.highest_bit; // Each field has its own type let another_one_highest: &AnotherBitfield::highest_bit = &another_one.highest_bit; println!("{:#b}", another_one_highest.get()) }
These bitfields are simple
One bitfield is essentially one integer that has fields whose get
methods
return data of the same integer type. Bitfields that contain more than one integer
or any type that doesn't satisfy the Bitfield and Field traits are not yet possible.
Structs that contain multiple bitfields are possible, and their size can be preserved
via the #[repr(packed)]
attribute. Care must be taken of the field access
because code like a_bitfield.field.get()
borrows a_bitfield
, which can result in
unaligned access if the struct with the bitfields is #[repr(packed)]
.
The TestBitfield module is only present in the documentation and shows how a bitfield is structured internally.
Modules
TestBitfield | This module represents a single bitfield. |
Macros
bitfield | Creates bitfield types. |
Traits
Bitfield | The trait that's implemented for all bitfields. Used mainly to access the bitfield's underlying type, Self::BaseType. |
Field | The trait that's implemented for all fields of all bitfields.
Allows the nice |