7 releases (4 breaking)
0.5.1 | Feb 19, 2020 |
---|---|
0.5.0 | Feb 19, 2020 |
0.4.0 | Feb 16, 2020 |
0.3.0 | Feb 11, 2020 |
0.1.1 | Feb 10, 2020 |
#1289 in Development tools
17KB
272 lines
Macros for working with bitfields.
This crate contains the bitfield!
macro and BitEnum
derive.
bitfield!
is used to generate (const fn
) getter and setter methods on bitfields.
BitEnum
allows an enum to be used as a field value.
Example
use bitbash::{bitfield, BitEnum};
bitfield! {
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Foo(u16);
pub new(bar);
derive_debug;
pub field bar: Bar = [0..3];
pub field baz: usize = [3..7] ~ [8..12];
pub field quux: bool = [7];
}
#[derive(BitEnum, Copy, Clone, PartialEq, Eq, Debug)]
pub enum Bar {
A = 0b101,
B = 0b010,
}
fn main() {
let mut foo = Foo::new(Bar::A).with_baz(0xcd);
foo.set_quux(true);
assert_eq!(foo.bar(), Bar::A);
assert_eq!(foo.baz(), 0xcd);
assert!(foo.quux());
assert_eq!(foo.0, ((Bar::A as u16) << 0) | (0xd << 3) | (0xc << 8) | (1 << 7));
}
bitfield!
macro
Supported structs
The bitfield!
macro supports three kinds of structs: a tuple struct of an unsigned integer, a tuple struct of an array of unsigned integers, and a regular struct.
bitfield! {
struct Foo(u8);
field a: bool = [7];
}
bitfield! {
struct Bar([u32; 2]);
field a: bool = 0[7];
field b: bool = 1[7];
}
bitfield! {
struct Baz {
_padding: [u32; 1],
apple: u32,
banana: u32,
}
field a: bool = apple[7];
}
Regular structs may contain types that are not unsigned integers, however they cannot be referred to by field
s.
(pub
) field
A field
statement defines in which bits a value is stored.
Fields can refer to a single bit, a range of bits, a concatenation of bits, or a mapping of bits in the value to bits in the bitfield:
bitfield! {
struct Foo([u32; 2]);
field single: bool = 0[0];
field range: u8 = 0[0..8];
field concatenation: u16 = 0[0..8] ~ 1[8..16];
field mapping: u32 {
[8..16] => 1[8..16],
[31] => 0[31],
}
}
By default, three methods are generated for each field: a getter, a setter, and a builder:
fn field_name(&self) -> Value;
fn set_field_name(&mut self, value: Value);
fn with_field_name(self, value: Value) -> Self;
To only generate the getter, use the #[ro]
attribute.
To make the setter and builder of a pub field
private, use the #[private_write]
attribute.
When a field is read, its bits must be a valid representation of the value. When a field is written, only the bits in the value that are referred to by the field may be set. If these requirements are not met a panic occurs.
Referring to bits that do not exist causes either a compile-time error or a runtime error, depending on whether const fn
code was generated.
Construction of values is done entirely in safe code. Moreover, no unsafe code is generated by the macros in this crate.
(pub
) new()
When the new()
statement is specified, an fn new()
method that zero-initializes the bitfield is generated.
Fields for which zero is not a valid representation can be passed as parameters to the new()
statement to generate a method which takes their initial values as parameters:
bitfield! {
struct Foo(u32);
new(a);
field a: Bar = [0..3];
}
#[derive(BitEnum)]
enum Bar {
A = 0b101,
B = 0b010,
}
fn main() {
let _ = Foo::new(Bar::A);
}
When the bitfield has been constructed, the new
method reads all fields to ensure that no invalid representations exist in the bitfield.
This behaviour can be disabled by using the #[disable_check]
attribute.
new()
does not support structs that contain types that are not (arrays of) unsigned integers.
derive_debug
The derive_debug
statement implements core::fmt::Debug
for the bitfield.
The underlying representation is not printed.
const fn
To generate const fn
methods, build the bitbash crate with the "const"
feature.
Alternatively, use the bitflags_const!
macro.
A nightly compiler is required and the #![feature(const_fn, const_panic, const_if_match, const_mut_refs)]
features must be enabled.
ConvertRepr
trait
Bitfield values must implement the ConvertRepr
trait.
It is implemented for all unsigned integer types and types that derive BitEnum
.
The try_from_repr
and into_repr
methods are used in non-const fn
bitfields.
Implement const_try_from_repr
and const_into_repr
on your types to also use them in const fn
bitfields.
BitEnum
derive
The BitEnum
derive implements ConvertRepr
for C-style enums.
Enums that derive BitEnum
can be used in both const fn
and non-const fn
bitfields.
Dependencies
~1.5MB
~37K SLoC