Modular Bitfields for Rust
This crate implements the #[bitfield]
macros introduced and specified in David Tolnay's procedural macro workshop.
Check out his workshop and learn from it!
Thanks go to David Tolnay for designing the specification for the macros implemented in modular_bitfield
.
Showcase
use *;
// Works with aliases - just for the showcase.
type Vitamin = B12;
/// Bitfield struct with 32 bits in total.
/// Enums that derive from `BitfieldSpecifier`
/// can also be used within bitfield structs
/// as shown above.
Advantages
- Safety: Macro embraced enums and structs are checked for valid structure during compilation time.
- Speed: Generated code is as fast as handwritten code.
- Modularity: Enums can be used modular within bitfield structs.
Benchmarks
Below are some benchmarks between the hand-written code and the macro-generated code for some example getters and setters that cover a decent variety of use cases.
We can conclude that the macro-generated code is as fast as hand-written code would be. Please file a PR if you see a way to improve either side.
cargo bench
to run the benchmarkscargo test --benches
to run the benchmark tests
generated::get_a ... bench: 99 ns/iter (+/- 4)
generated::get_b ... bench: 98 ns/iter (+/- 4)
generated::get_c ... bench: 98 ns/iter (+/- 14)
generated::get_d ... bench: 97 ns/iter (+/- 2)
generated::get_e ... bench: 99 ns/iter (+/- 2)
generated::set_a ... bench: 481 ns/iter (+/- 19)
generated::set_b ... bench: 627 ns/iter (+/- 37)
generated::set_c ... bench: 507 ns/iter (+/- 35)
generated::set_d ... bench: 622 ns/iter (+/- 24)
generated::set_e ... bench: 459 ns/iter (+/- 16)
handwritten::get_a ... bench: 99 ns/iter (+/- 3)
handwritten::get_b ... bench: 102 ns/iter (+/- 14)
handwritten::get_c ... bench: 102 ns/iter (+/- 8)
handwritten::get_d ... bench: 100 ns/iter (+/- 20)
handwritten::get_e ... bench: 98 ns/iter (+/- 6)
handwritten::set_a ... bench: 582 ns/iter (+/- 20)
handwritten::set_b ... bench: 614 ns/iter (+/- 35)
handwritten::set_c ... bench: 533 ns/iter (+/- 18)
handwritten::set_d ... bench: 606 ns/iter (+/- 21)
handwritten::set_e ... bench: 456 ns/iter (+/- 21)
Future Plans
- Add
no_std
support behind crate feature. - Add
u128
support behind crate feature.- No default because it might explode compilation times.
- Implement non-powers-of-two enums. (Specs from workshop.)
- Implement codegen for tuple structs
- Example
struct Example(B1, B7, B8)
with gettersget_0
andset_0
forB1
get_1
andset_1
forB7
get_2
andset_2
forB8
- Example
- Implement safe
try_set_*
for bitfield structs as checked setters that won't panic upon out of bounds input. - Implement unsafe
set_*_unchecked
for bitfield struct to allow users to avoid bounds checking.