Skip to main content

Crate bnb

Crate bnb 

Source
Expand description

bnb — an owned, bit-aware binary codec: ergonomic, fast bit/byte field types and the unified #[bin] whole-message codec.

It provides, designed to compose:

  • Arbitrary-width integers (u1..u127, via UInt) for sub-byte fields — a dependency-free replacement for arbitrary-int.
  • #[bitfield] — an attribute macro that packs typed fields into a single backing integer with explicit, independent control of bit order (MSB/LSB-first) and byte order (big/little). It generates getters, immutable with_* setters, raw access, and allocation-free *_bytes conversions.
  • #[derive(BitEnum)] — enum ⇄ integer at a chosen width, with an optional #[catch_all] variant that preserves unknown values (the dual-use convention).
  • #[bin] — the unified whole-message codec (see below): reads/writes a struct at arbitrary bit offsets, with a rich, binrw-inspired directive surface.

The aim is to collapse a whole stack of overlapping helpers — modular-bitfield(-msb), bitfield-struct, bitbybit, arbitrary-int, num_enum, and a binrw-style codec — into one fast, integer-backed (shift/mask, no bitvec) crate. See Inspiration.

§Example — a DNS-style 16-bit header field

use bnb::{bitfield, BitEnum, u4, u5, u7};

#[derive(BitEnum, Clone, Copy, Debug, PartialEq, Eq)]
#[bit_enum(u4)]
enum RCode {
    NoError,   // 0
    FormErr,   // 1
    ServFail,  // 2
    #[catch_all]
    Other(u4), // any other 4-bit value
}

// MSB-first packing (network/RFC order), big-endian on the wire.
#[bitfield(u16, bits = msb, bytes = be)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct State {
    opcode: u5,   // first field -> high bits
    flags:  Flags,
    rcode:  RCode, // last field -> low bits
}

let s = State::new()
    .with_opcode(u5::new(2))
    .with_rcode(RCode::ServFail);
assert_eq!(s.rcode(), RCode::ServFail);
// opcode occupies bits 11..=15 (the high 5 of the u16).
assert_eq!(s.to_be_bytes()[0] >> 3, 2);

§Bit order vs. byte order

These are independent knobs, which is the whole point:

  • bits = msb | lsb — does the first declared field land in the high or low bits of the backing integer. Default: msb (matches RFC ASCII-art layouts).
  • bytes = be | le — endianness of the backing integer when serialized. Default: be.

§The #[bin] codec

Whole-message bit-aware codec: #[bin] (magic/count/ctx/map/if/calc·temp/reserved/ positioning/validate) over a Source/SeekSource/BufSource/SeekReader I/O ladder, with an opt-in bytes feature for async framing.

§Feature flags & no_std

bnb is no_std-compatible — it always needs alloc (the codec produces Vec<u8> and owns variable-length payloads), but not std. Build with default-features = false for an embedded target.

Without std you still get the full macro surface plus: decode from a &[u8] (BitReader, Type::decode/decode_exact/peek/decode_from) and encode to a Vec<u8> (Type::to_bytes/to_spec_bytes, encode_into over a Sink). You lose only the streaming std::io adapters and encode(&mut impl Write); on no_std, encode with to_bytes() and write the bytes to your transport yourself.

§Inspiration

bnb stands on the shoulders of several excellent crates, collapsing their capabilities into one: the arbitrary-width integers of arbitrary-int; the bitfield packing of modular-bitfield, bitfield-struct, and bitbybit; the enum ⇄ integer mapping of num_enum; and — most of all — the declarative, bidirectional codec design of binrw, whose #[br]/#[bw] attribute vocabulary #[bin] deliberately echoes so the two feel like one toolkit. bnb shares no code with these crates; it is a from-scratch implementation, extended to do the one thing a byte-oriented Read + Seek codec cannot: read and write fields at arbitrary bit offsets. See ACKNOWLEDGMENTS.md for the full credit.

§Guide

The guide module is a set of worked, runnable walkthroughs — start there for a tour of the crate and the rationale behind each piece. Reading order:

  1. guide::quick_start — a five-minute tour of every macro.
  2. guide::numbers — the arbitrary-width integers (u1..u127) and the Bits trait that lets everything compose.
  3. guide::bitfields#[bitfield]: bit order, byte order, widths and ranges, nesting.
  4. guide::enums#[derive(BitEnum)]: catch-all vs. closed, num_enum parity.
  5. guide::flags#[bitflags]: single-bit flag sets with set algebra.
  6. guide::builders#[derive(BitsBuilder)]: the required-by-default builder.
  7. guide::bin_codec#[bin]: a whole protocol header, end to end.
  8. guide::directives — the field-directive reference, one example each.
  9. guide::dispatch#[bin] on an enum: tagged-union dispatch by wire magic or off-wire tag.
  10. guide::io — the Source/Sink I/O ladder (slice, stream, socket, file, bytes).
  11. guide::errors — position-aware errors and the streaming Incomplete signal.
  12. guide::dual_use — the compliant-by-default-but-violatable philosophy.
  13. guide::composition — how the pieces nest and size each other.

Re-exports§

pub use bitstream::BitAmount;
pub use bitstream::BitDecode;
pub use bitstream::BitEncode;
pub use bitstream::BitError;
pub use bitstream::BitReader;
pub use bitstream::BitWriter;
pub use bitstream::DecodeWith;
pub use bitstream::EncodeWith;
pub use bitstream::ErrorKind;
pub use bitstream::FixedBitLen;
pub use bitstream::Layout;
pub use bitstream::SeekSource;
pub use bitstream::Sink;
pub use bitstream::Source;
pub use bitstream::SpecEncode;
pub use bitstream::BufSource;
pub use bitstream::EncodeExt;
pub use bitstream::SeekReader;
pub use bitstream::SinkWriter;
pub use bitstream::SourceReader;
pub use bitstream::SpecEncodeExt;
pub use bitstream::StreamBitReader;
pub use builder::BuilderError;
pub use error::Error;
pub use error::Result;
pub use error::UnknownDiscriminant;
pub use int::UInt;
pub use int::*;

Modules§

bitstream
A bit-level stream codec — read/write fields at arbitrary bit offsets, not just byte boundaries.
builder
Support types for #[derive(BitsBuilder)] and #[bin].
error
The crate’s error type and result alias.
guide
The bnb guide — worked, runnable walkthroughs.
int
Arbitrary-width unsigned integers (u1..u127) — the substrate for sub-byte bitfield fields. Replaces the arbitrary-int dependency.
prelude
Common imports for the codec — the typed positioning amounts (4.bits(), 3.bytes()) used by #[br(pad_before = …)] etc., plus the encode extension traits that carry encode(writer)/spec_encode(writer) (the std feature).

Enums§

BitOrder
Bit packing order within a bitfield: does the first declared field occupy the most-significant or least-significant bits of the backing integer.
ByteOrder
Byte order of a bitfield’s backing integer when it is serialized.

Traits§

BitEnum
Marker trait implemented by #[derive(BitEnum)] enums: a Bits value whose representation is an integer discriminant of a fixed width.
Bitfield
The seam every #[bitfield] struct implements — the stable interface the #[bin] codec builds on, independent of how the fields are accessed.
Bits
A value that occupies a fixed number of bits within a bitfield.

Attribute Macros§

bin
#[bin] — the unified whole-message bit codec. One attribute that folds the read codec (BitDecode), the write codec (BitEncode), and a required-by-default builder (BitsBuilder) over a struct of bnb::Bits fields, read and written at arbitrary bit offsets.
bitfield
Packs the annotated struct’s fields into a single backing integer.
bitflags
Packs named single-bit flags into one backing integer, with set algebra.

Derive Macros§

BitDecode
Derives a bnb::BitDecode impl that reads the struct’s named fields, in declaration order, from a bit cursor (a bnb::BitReader).
BitEncode
Derives a bnb::BitEncode impl — the dual of BitDecode, writing the struct’s named fields in order to a bnb::BitWriter bit cursor. Shares BitDecode’s right-tool guard and #[bit_stream(...)] override.
BitEnum
Derives an enum ⇄ integer mapping of a fixed bit width.
BitsBuilder
Generates a derive_builder-style builder for a struct (or, when listed in a #[bitfield]’s derives, for the bitfield — intercepted by #[bitfield]).