Expand description
#[derive(BitsBuilder)] — a required-by-default builder.
The infix with_* setters are infallible and start from an all-zero value, so a
field you forget is silently zero. The builder closes that gap: every field is
required unless opted out, and build() returns an error naming the first
unset one.
use bnb::{bitfield, u4, BitsBuilder};
#[bitfield(u16, bits = msb)]
#[derive(BitsBuilder, Clone, Copy)]
struct State {
opcode: u4,
flags: u8,
rcode: u4,
}
let s = State::builder()
.opcode(u4::new(2))
.flags(0)
.rcode(u4::new(3))
.build()
.unwrap();
assert_eq!(s.opcode().value(), 2);Forget a required field and build() tells you which — at run time, by name:
let err = State::builder().opcode(u4::new(2)).rcode(u4::new(3)).build().unwrap_err();
assert_eq!(err, BuilderError::MissingField("flags"));
assert_eq!(err.field(), Some("flags"));§Opting a field out: #[builder(default)]
Mark a field optional with #[builder(default)] (uses Default::default() if
unset) or #[builder(default = expr)] (uses expr):
use bnb::{bitfield, u4, BitsBuilder};
#[bitfield(u16, bits = msb)]
#[derive(BitsBuilder, Clone, Copy)]
struct State {
opcode: u4,
#[builder(default)] // 0 if unset
flags: u8,
#[builder(default = u4::new(1))] // a custom default if unset
rcode: u4,
}
let s = State::builder().opcode(u4::new(2)).build().unwrap(); // flags + rcode defaulted
assert_eq!(s.flags(), 0);
assert_eq!(s.rcode().value(), 1);§On plain structs and the #[bitfield] intercept
#[derive(BitsBuilder)] also works on a plain struct, and #[bin] generates the
same builder automatically (you don’t write the derive there). On a #[bitfield],
the attribute collapses the struct to one integer before a normal derive could
see the fields, so #[bitfield] itself intercepts the BitsBuilder marker — which
is why it must sit above the #[derive(...)]:
use bnb::{bitfield, u4, BitsBuilder};
#[bitfield(u8, bits = msb)] // must be above the derive
#[derive(BitsBuilder, Clone, Copy)]
struct Nibble { hi: u4, lo: u4 }
assert_eq!(Nibble::builder().hi(u4::new(0xA)).lo(u4::new(0xB)).build().unwrap().hi().value(), 0xA);In a #[bin] message the builder is generated for you and is where the
validate soundness hook runs — see
bin_codec.