[−][src]Crate modular_bitfield
Provides macros to support bitfield structs allowing for modular use of bit-enums.
The mainly provided macros are #[bitfield] for structs and
#[derive(BitfieldSpecifier)] for enums that shall be usable
within bitfield structs.
There are preset bitfield specifiers such as B1, B2,..,B64
that allow for easy bitfield usage in structs very similar to how
they work in C or C++.
- Performance of the macro generated code is as fast as its hand-written alternative.
- Compile-time checks allow for safe usage of bitfield structs and enums.
Showcase
use modular_bitfield::prelude::*; // Works with aliases - just for the showcase. type Vitamin = B12; /// Bitfield struct with 32 bits in total. #[bitfield] pub struct Example { a: bool, // Uses 1 bit b: B9, // Uses 9 bits c: Vitamin, // Uses 12 bits, works with aliases. #[bits = 3] // Optional, asserts at compiletime that `DeliveryMode` uses 3 bits. d: DeliveryMode, // Uses 3 bits e: B7, // Uses 7 bits } /// Enums that derive from `BitfieldSpecifier` /// can also be used within bitfield structs /// as shown above. #[derive(BitfieldSpecifier, Debug, PartialEq)] pub enum DeliveryMode { Fixed = 1, Lowest, SMI, RemoteRead, NMI, Init = 0, Startup = 6, External, } fn it_works() { let mut example = Example::new(); // Assert that everything is inizialized to 0. assert_eq!(example.get_a(), false); assert_eq!(example.get_b(), 0); assert_eq!(example.get_c(), 0); assert_eq!(example.get_d(), DeliveryMode::Init); assert_eq!(example.get_e(), 0); // Modify the bitfields. example.set_a(true); example.set_b(0b0001_1111_1111_u16); // Uses `u16` example.set_c(42_u16); // Uses `u16` example.set_d(DeliveryMode::Startup); example.set_e(1); // Uses `u8` // Assert the previous modifications. assert_eq!(example.get_a(), true); assert_eq!(example.get_b(), 0b0001_1111_1111_u16); assert_eq!(example.get_c(), 42); assert_eq!(example.get_d(), DeliveryMode::Startup); assert_eq!(example.get_e(), 1_u8); }
Generated Structure
From David Tolnay's procedural macro workshop:
The macro conceptualizes given structs as a sequence of bits 0..N. The bits are grouped into fields in the order specified by the struct written by the user.
The #[bitfield] attribute rewrites the caller's struct into a private byte array representation
with public getter and setter methods for each field.
The total number of bits N is required to be a multiple of 8: This is checked at compile time.
Example
The following invocation builds a struct with a total size of 32 bits or 4 bytes.
It places field a in the least significant bit of the first byte,
field b in the next three least significant bits,
field c in the remaining four most significant bits of the first byte,
and field d spanning the next three bytes.
use modular_bitfield::prelude::*; #[bitfield] pub struct MyFourBytes { a: B1, b: B3, c: B4, d: B24, }
least significant bit of third byte
┊ most significant
┊ ┊
┊ ┊
║ first byte ║ second byte ║ third byte ║ fourth byte ║
╟───────────────╫───────────────╫───────────────╫───────────────╢
║▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒║
╟─╫─────╫───────╫───────────────────────────────────────────────╢
║a║ b ║ c ║ d ║
┊ ┊
┊ ┊
least significant bit of d most significant
Re-exports
pub use modular_bitfield_impl::bitfield; |
pub use modular_bitfield_impl::BitfieldSpecifier; |
Modules
| prelude | The prelude: |
| specifiers | The default set of predefined specifiers. |
Traits
| Specifier | Trait implemented by all bitfield specifiers. |