macro_rules! impl_bits {
(
impl Bits for $t:ty {
const BITS: u32 = $bits:expr;
const fn into_bits($self_:ident) -> u128 $into:block
const fn from_bits($raw:ident: u128) -> Self $from:block
}
) => { ... };
}Expand description
Implements Bits for a hand-written field type from one pair of const fn
conversion bodies — the supported way to make a custom type usable as a
#[bitfield] field.
The accessors #[bitfield] generates are const fn, and a const fn cannot
call trait methods on stable Rust — so alongside its Bits impl, a field
type needs the same conversions reachable as inherent const fns. This macro
emits both from one definition: the trait impl delegates to the inherent
pair, so the two can never disagree, and the pair’s naming stays an
implementation detail of the crate.
The bodies must satisfy the Bits contract: into_bits yields the value in
the low BITS bits of a u128, from_bits reconstructs from the low BITS
bits (higher bits ignored), and the two round-trip.
use bnb::{bitfield, u7};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct Percent(u7);
bnb::impl_bits! {
impl Bits for Percent {
const BITS: u32 = 7;
const fn into_bits(self) -> u128 { self.0.value() as u128 }
const fn from_bits(raw: u128) -> Self { Percent(u7::from_raw(raw as u8)) }
}
}
// `Percent` now nests as a `#[bitfield]` field like any built-in `Bits` type.
#[bitfield(u8, bits = msb)]
#[derive(Clone, Copy)]
struct Meter { pct: Percent, on: bool }
let m = Meter::new().with_pct(Percent(u7::new(42))).with_on(true);
assert_eq!(m.pct(), Percent(u7::new(42)));
assert!(m.on());