6 releases
new 0.1.7 | Feb 17, 2025 |
---|---|
0.1.6 | Feb 17, 2025 |
#510 in Encoding
541 downloads per month
27KB
112 lines
bitfld
is a no-std crate for ergonomically specifying layouts of bitfields
over integral types. While the aim is to be general-purpose, the imagined user
is a systems programmer uncomfortably hunched over an architectural manual or
hardware spec, looking to transcribe register layouts into Rust with minimal
fuss.
The heavy lifting is done by the layout!
procedural macro. Care
is taken to generate readable and efficient code. The zerocopy
crate is further leveraged for safe and efficient transmutation between integral
values and custom bitfield representations.
Features
- Generation of a simple, extensible wrapper type around the given integral base type;
- Simple, const-friendly builder pattern for constructing layout instances;
- Automatic implementations of the basic, convenient traits one would expect out
of a thin integral wrapper type:
Copy
,Clone
Eq
,PartialEq
Default
From
over the base typeDeref
andDerefMut
with a target of the underlying base typeDebug
,Display
,Binary
,LowerHex
,UpperHex
,Octal
- Specification of default and "reserved as" values, with
new()
respecting reserved-as values anddefault()
respecting both; - Custom bitfield representation types without any boilerplate;
- Iteration over individual bitfield values and metadata;
- Associated constants around masks and shifts for use in inline assembly.
For more detail, see layout!
.
Example
use bitfld::{bitfield_repr, layout};
#[bitfield_repr(u8)]
pub enum CustomFieldRepr {
Option1 = 0xa,
Option2 = 0xf,
}
layout!({
pub struct Example(u32);
{
let foo: Bits<21, 14>;
let custom: Bits<13, 10, CustomFieldRepr>;
let bar: Bits<9, 8> = 0b11;
let baz: Bit<7>;
let frob: Bits<6, 4>;
let _: Bits<3, 2> = 1;
let _: Bits<1, 0>;
}
});
fn main() {
let example = *Example::default()
.set_custom(CustomFieldRepr::Option2)
.set_frob(0x7);
assert_eq!(example.foo(), 0);
assert_eq!(example.custom().unwrap(), CustomFieldRepr::Option2);
assert_eq!(example.bar(), 0b11);
assert_eq!(example.baz(), false);
assert_eq!(example.frob(), 0x7);
assert_eq!(*example & 0b1100, 0b0100);
// Will print: `Example { custom: Option2, foo: 0x0, bar: 0x3, baz: false, frob: 0xa }`
println!("{example}");
// Or iterate over all fields and and print them individually.
for (value, metadata) in example {
println!("{}: {:x}", metadata.name, value);
}
}
bitfield_repr
is an attribute that is syntactic sugar for deriving
repr(X)
and the handful of traits expected of a custom field representation.
Why another crate for bitfields?
There are already a handful out there, so why this one too? It is the author's opinion that none of those at the time of writing this offer all of the above features (e.g., around reserved semantics or boilerplate-free, custom field representations) or the author's desired ergonomics around register modeling. For example, some constrain field specification by bit width instead of by an explicit bit range, which is not how registers are commonly described in official references (plus, the author surely can't trust himself to do mental math like that).
Dependencies
~200–630KB
~15K SLoC