Skip to main content

impl_bits

Macro impl_bits 

Source
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());