Skip to main content

bnb/
bitstream.rs

1//! A bit-level stream codec — read/write fields at arbitrary *bit* offsets, not
2//! just byte boundaries.
3//!
4//! A byte-oriented `Read + Seek` codec can only address byte boundaries, so a field
5//! that starts mid-byte (a 108-bit DMR payload, a 48-bit sync pattern) forces
6//! hand-rolled backward seeks and nibble shifts.
7//! [`BitReader`]/[`BitWriter`] track a **bit** cursor over a byte buffer and
8//! read/write any [`Bits`] value (`u1`..`u127`, `#[bitfield]`, `#[derive(BitEnum)]`)
9//! directly — bit-aware *and* fast (shift/mask, no `bitvec`).
10//!
11//! The wire [`Layout`] is configurable: bit order (MSB-first default — bit 0 is the
12//! high bit of byte 0, the RFC/ETSI convention — or LSB-first) and byte order (big-
13//! endian default, or little-endian for byte-multiple values).
14//!
15//! ```
16//! use bnb::{u4, u12, BitReader, BitWriter};
17//!
18//! // Pack a 4-bit then a 12-bit field into a 16-bit (2-byte) stream.
19//! let mut w = BitWriter::new();
20//! w.write(u4::new(0xA)).unwrap();
21//! w.write(u12::new(0xBCD)).unwrap();
22//! let bytes = w.into_bytes();
23//! assert_eq!(bytes, [0xAB, 0xCD]);
24//!
25//! let mut r = BitReader::new(&bytes);
26//! assert_eq!(r.read::<u4>().unwrap(), u4::new(0xA));
27//! assert_eq!(r.read::<u12>().unwrap(), u12::new(0xBCD));
28//! ```
29
30use alloc::boxed::Box;
31use alloc::string::{String, ToString};
32use alloc::vec::Vec;
33use core::any::Any;
34use core::fmt;
35
36use crate::field::{BitOrder, Bits, ByteOrder};
37
38/// A position-aware bit-codec error (it carries a span-like position). It records the
39/// **bit offset** where decoding/encoding failed and, when the derive can supply it,
40/// the **field** being processed.
41///
42/// # Examples
43///
44/// ```
45/// use bnb::{bin, ErrorKind};
46///
47/// #[bin(big)]
48/// #[derive(Debug)]
49/// struct Pair { a: u16, b: u16 }
50///
51/// let err = Pair::decode_exact(&[0x00]).unwrap_err(); // only one byte of four
52/// assert_eq!(err.at, 0);             // the bit offset where it failed
53/// assert_eq!(err.field, Some("a"));  // the field being read (the span)
54/// assert!(matches!(err.kind, ErrorKind::UnexpectedEof { .. }));
55/// ```
56#[derive(Clone, Debug, PartialEq, Eq)]
57#[non_exhaustive]
58pub struct BitError {
59    /// The cause.
60    pub kind: ErrorKind,
61    /// Absolute bit offset where the error occurred.
62    pub at: usize,
63    /// The field being decoded/encoded when it occurred, if recorded by the
64    /// derive (the innermost field — the "span"). `None` for low-level reader
65    /// errors with no field context.
66    pub field: Option<&'static str>,
67}
68
69/// The cause of a [`BitError`]. `#[non_exhaustive]`: new variants may be added
70/// without a major version bump, so match with a wildcard arm.
71#[derive(Clone, Debug, PartialEq, Eq)]
72#[non_exhaustive]
73pub enum ErrorKind {
74    /// Ran past the end of a finite input (a slice): `needed` bits were requested,
75    /// `remaining` were left. Definitive — distinct from [`Incomplete`](ErrorKind::Incomplete).
76    UnexpectedEof {
77        /// Bits requested.
78        needed: usize,
79        /// Bits still available.
80        remaining: usize,
81    },
82    /// A streaming source ([`StreamBitReader`]) ran out mid-message: the caller
83    /// should read more bytes and retry. `needed` is a best-effort byte hint
84    /// (`None` when unknown). See [`BitError::is_incomplete`].
85    Incomplete {
86        /// Best-effort estimate of additional bytes needed, if known.
87        needed: Option<usize>,
88    },
89    /// `decode_exact` left whole bytes unconsumed after the message.
90    TrailingBytes {
91        /// Number of trailing bytes.
92        remaining: usize,
93    },
94    /// A single field exceeded the 128-bit carrier width.
95    TooWide {
96        /// The offending width.
97        width: usize,
98    },
99    /// An I/O error while encoding to a [`std::io::Write`] sink (the `std` feature).
100    #[cfg(feature = "std")]
101    Io(std::io::ErrorKind),
102    /// A `magic` constant read off the wire did not match. Both values are the
103    /// type-erased low-bit representations ([`Bits::into_bits`]).
104    BadMagic {
105        /// The constant the codec expected.
106        expected: u128,
107        /// The value actually read.
108        found: u128,
109    },
110    /// A `try_map` conversion from the wire representation failed; `message` is the
111    /// converter's `Display` output.
112    Convert {
113        /// The converter's error, rendered.
114        message: String,
115    },
116    /// A position directive (`restore_position`/seek) ran on a non-seekable
117    /// [`Source`] (a forward-only stream). Decode from a slice ([`BitReader`]) or a
118    /// seekable source instead.
119    NotSeekable,
120    /// A [`BufSource`] hit its retention cap before the message finished — the
121    /// framed message is larger than the configured bound (never unbounded).
122    BufferFull {
123        /// The cap, in bytes.
124        cap: usize,
125    },
126}
127
128impl BitError {
129    /// Builds an error at absolute bit offset `at`, with no field recorded yet.
130    #[must_use]
131    pub fn new(kind: ErrorKind, at: usize) -> Self {
132        Self {
133            kind,
134            at,
135            field: None,
136        }
137    }
138
139    /// Builds a [`ErrorKind::BadMagic`] error (a `magic` constant mismatched) at
140    /// absolute bit offset `at`. `expected`/`found` are the type-erased low-bit
141    /// values ([`Bits::into_bits`]).
142    #[must_use]
143    pub fn bad_magic(expected: u128, found: u128, at: usize) -> Self {
144        Self::new(ErrorKind::BadMagic { expected, found }, at)
145    }
146
147    /// Builds a [`ErrorKind::Convert`] error (a `try_map` conversion failed) at
148    /// absolute bit offset `at`.
149    #[must_use]
150    pub fn convert(message: String, at: usize) -> Self {
151        Self::new(ErrorKind::Convert { message }, at)
152    }
153
154    /// Records the field being processed, **if one is not already set** — so the
155    /// innermost field (set first as the error propagates up) wins. The derive
156    /// calls this per field.
157    #[must_use]
158    pub fn in_field(mut self, field: &'static str) -> Self {
159        if self.field.is_none() {
160            self.field = Some(field);
161        }
162        self
163    }
164
165    /// Whether this is the streaming "need more bytes" signal
166    /// ([`ErrorKind::Incomplete`]) — the caller should read more and retry, as
167    /// opposed to a definitive parse failure.
168    #[must_use]
169    pub fn is_incomplete(&self) -> bool {
170        matches!(self.kind, ErrorKind::Incomplete { .. })
171    }
172}
173
174#[cfg(feature = "std")]
175impl From<std::io::Error> for BitError {
176    /// Wraps a [`std::io::Error`] as [`ErrorKind::Io`] — so a `parse_with`/`write_with`
177    /// using [`Source::as_read`]/[`Sink::as_write`] can `?` `std::io` results straight
178    /// into a `BitError`. The bit offset is unknown at this boundary (recorded as `0`);
179    /// build with [`BitError::new`] if you need the precise position.
180    fn from(e: std::io::Error) -> Self {
181        BitError::new(ErrorKind::Io(e.kind()), 0)
182    }
183}
184
185impl fmt::Display for BitError {
186    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187        match &self.kind {
188            ErrorKind::UnexpectedEof { needed, remaining } => write!(
189                f,
190                "unexpected end of input: needed {needed} bits, {remaining} remain"
191            )?,
192            ErrorKind::Incomplete { needed } => match needed {
193                Some(n) => write!(f, "incomplete: need ~{n} more bytes")?,
194                None => write!(f, "incomplete: need more bytes")?,
195            },
196            ErrorKind::TrailingBytes { remaining } => {
197                write!(f, "{remaining} trailing bytes after the message")?;
198            }
199            ErrorKind::TooWide { width } => {
200                write!(f, "field width {width} exceeds the 128-bit carrier")?;
201            }
202            #[cfg(feature = "std")]
203            ErrorKind::Io(kind) => write!(f, "I/O error: {kind:?}")?,
204            ErrorKind::BadMagic { expected, found } => {
205                write!(f, "bad magic: expected {expected:#x}, found {found:#x}")?;
206            }
207            ErrorKind::Convert { message } => {
208                write!(f, "conversion failed: {message}")?;
209            }
210            ErrorKind::NotSeekable => {
211                write!(f, "a position directive ran on a non-seekable source")?;
212            }
213            ErrorKind::BufferFull { cap } => {
214                write!(f, "buffered source exceeded its {cap}-byte cap")?;
215            }
216        }
217        write!(f, " at bit {}", self.at)?;
218        if let Some(field) = self.field {
219            write!(f, " (field `{field}`)")?;
220        }
221        Ok(())
222    }
223}
224
225impl core::error::Error for BitError {}
226
227impl From<crate::error::WidthError> for BitError {
228    /// Bridges a construction error (e.g. `UInt::try_new`) into a codec error, so it
229    /// `?`-propagates inside a custom `parse_with`/`write_with` fn or a converter
230    /// that returns [`BitError`]. The offset is unknown (`0`) — the codec's own
231    /// reads/writes carry the real bit offset; this is only for borrowed construction
232    /// failures with no cursor context.
233    #[inline]
234    fn from(e: crate::error::WidthError) -> Self {
235        BitError::convert(e.to_string(), 0)
236    }
237}
238
239/// The bit width of a [`Bits`] value's type. Generated `BIT_LEN` consts and the
240/// alignment guard call this to size a `magic` constant whose type they only have
241/// as an expression (the value is taken by reference purely to infer `T`).
242#[doc(hidden)]
243#[must_use]
244pub const fn bits_of<T: Bits>(_value: &T) -> u32 {
245    T::BITS
246}
247
248/// Reads a `magic` constant and verifies it equals `expected`, compared as
249/// type-erased bits (so `T` needs only [`Bits`] — no `Copy`/`PartialEq`, and `T`
250/// is pinned by the argument so the generated call site needs no turbofish). On
251/// mismatch: [`ErrorKind::BadMagic`] at the magic's offset.
252#[doc(hidden)]
253pub fn verify_magic<T: Bits, S: Source>(r: &mut S, expected: T) -> Result<(), BitError> {
254    let at = r.bit_pos();
255    let found: T = r.read()?;
256    let (e, g) = (expected.into_bits(), found.into_bits());
257    if e != g {
258        return Err(BitError::bad_magic(e, g, at));
259    }
260    Ok(())
261}
262
263/// Reads a wire value `W` (inferred from `f`'s argument type) and maps it to the
264/// field type `T` — backs `#[br(map = …)]`.
265///
266/// # Errors
267/// Propagates the read [`BitError`].
268#[doc(hidden)]
269pub fn read_mapped<W, T, S, F>(r: &mut S, f: F) -> Result<T, BitError>
270where
271    W: Bits,
272    S: Source,
273    F: FnOnce(W) -> T,
274{
275    let raw: W = r.read()?;
276    Ok(f(raw))
277}
278
279/// Fallible variant — backs `#[br(try_map = …)]`. A conversion error becomes an
280/// [`ErrorKind::Convert`] at the value's offset.
281///
282/// # Errors
283/// The read [`BitError`], or the converter's failure as [`ErrorKind::Convert`].
284#[doc(hidden)]
285pub fn read_try_mapped<W, T, E, S, F>(r: &mut S, f: F) -> Result<T, BitError>
286where
287    W: Bits,
288    S: Source,
289    E: fmt::Display,
290    F: FnOnce(W) -> Result<T, E>,
291{
292    let at = r.bit_pos();
293    let raw: W = r.read()?;
294    f(raw).map_err(|e| BitError::convert(e.to_string(), at))
295}
296
297/// Maps the field `T` to its wire value `W` and writes it — backs `#[bw(map = …)]`.
298///
299/// # Errors
300/// Propagates the write [`BitError`].
301#[doc(hidden)]
302pub fn write_mapped<W, T, K, F>(w: &mut K, value: &T, f: F) -> Result<(), BitError>
303where
304    W: Bits,
305    K: Sink,
306    F: FnOnce(&T) -> W,
307{
308    w.write(f(value))
309}
310
311/// Decodes a whole wire **message** `W` (a `BitDecode`, inferred from `f`'s argument) and
312/// maps it to the logical type — backs struct-level `#[bin(map = …)]`. The message dual of
313/// [`read_mapped`] (whose `W` is a single `Bits` field).
314///
315/// # Errors
316/// Propagates the decode [`BitError`].
317#[doc(hidden)]
318pub fn decode_mapped_msg<W, T, S, F>(r: &mut S, f: F) -> Result<T, BitError>
319where
320    W: BitDecode,
321    S: Source,
322    F: FnOnce(W) -> T,
323{
324    Ok(f(W::bit_decode(r)?))
325}
326
327/// Fallible message map — backs struct-level `#[bin(try_map = …)]`. A conversion error
328/// becomes an [`ErrorKind::Convert`] at the message's start offset.
329///
330/// # Errors
331/// The decode [`BitError`], or the converter's failure as [`ErrorKind::Convert`].
332#[doc(hidden)]
333pub fn decode_try_mapped_msg<W, T, E, S, F>(r: &mut S, f: F) -> Result<T, BitError>
334where
335    W: BitDecode,
336    S: Source,
337    E: fmt::Display,
338    F: FnOnce(W) -> Result<T, E>,
339{
340    let at = r.bit_pos();
341    let w = W::bit_decode(r)?;
342    f(w).map_err(|e| BitError::convert(e.to_string(), at))
343}
344
345/// Maps the logical type to its wire **message** `W` (a `BitEncode`) and encodes it —
346/// backs struct-level `#[bin(bw_map = …)]`. The message dual of [`write_mapped`].
347///
348/// # Errors
349/// Propagates the encode [`BitError`].
350#[doc(hidden)]
351pub fn encode_mapped_msg<W, T, K, F>(w: &mut K, value: &T, f: F) -> Result<(), BitError>
352where
353    W: BitEncode,
354    K: Sink,
355    F: FnOnce(&T) -> W,
356{
357    f(value).bit_encode(w)
358}
359
360/// A typed bit/byte amount for positioning directives — `4.bits()`, `3.bytes()` —
361/// resolving to a bit count. Bring it in with `use bnb::prelude::*`.
362///
363/// # Examples
364///
365/// ```
366/// use bnb::prelude::*;
367/// assert_eq!(4u32.bits(), 4);
368/// assert_eq!(3u32.bytes(), 24);
369/// ```
370///
371/// Used by the positioning directives, e.g. `#[br(pad_before = 2u32.bytes())]` — see
372/// [`guide::directives`](crate::guide::directives).
373pub trait BitAmount: Copy + sealed::Sealed {
374    /// This many **bits**.
375    fn bits(self) -> u32;
376    /// This many **bytes** (× 8 bits).
377    fn bytes(self) -> u32;
378}
379
380macro_rules! impl_bit_amount {
381    ($($t:ty),*) => {$(
382        impl BitAmount for $t {
383            fn bits(self) -> u32 { self as u32 }
384            fn bytes(self) -> u32 { (self as u32) * 8 }
385        }
386    )*};
387}
388impl_bit_amount!(u8, u16, u32, u64, usize, i16, i32, i64, isize);
389// Seal the `BitAmount` types that aren't already sealed by `CountPrefix`
390// (`u8, u16, u32, u64` get their `Sealed` impl from `count_prefix_prim!`).
391impl sealed::Sealed for usize {}
392impl sealed::Sealed for i16 {}
393impl sealed::Sealed for i32 {}
394impl sealed::Sealed for i64 {}
395impl sealed::Sealed for isize {}
396
397/// Skips `bits` forward (consuming and discarding) — backs `#[br(pad_before/after)]`.
398///
399/// # Errors
400/// Propagates the source's [`BitError`].
401#[doc(hidden)]
402pub fn skip_read<S: Source>(r: &mut S, bits: u32) -> Result<(), BitError> {
403    let mut left = bits;
404    while left > 0 {
405        let n = left.min(128);
406        r.read_bits(n)?;
407        left -= n;
408    }
409    Ok(())
410}
411
412/// Writes `bits` zero bits forward — the write dual of [`skip_read`].
413///
414/// # Errors
415/// Propagates the sink's [`BitError`].
416#[doc(hidden)]
417pub fn skip_write<K: Sink>(w: &mut K, bits: u32) -> Result<(), BitError> {
418    let mut left = bits;
419    while left > 0 {
420        let n = left.min(128);
421        w.write_bits(0, n)?;
422        left -= n;
423    }
424    Ok(())
425}
426
427/// Skips forward to the next byte boundary — backs `#[br(align_before/after)]`.
428///
429/// # Errors
430/// Propagates the source's [`BitError`].
431#[doc(hidden)]
432pub fn align_read<S: Source>(r: &mut S) -> Result<(), BitError> {
433    let pad = (8 - (r.bit_pos() % 8)) % 8;
434    skip_read(r, pad as u32)
435}
436
437/// Pads with zero bits to the next byte boundary — the write dual of [`align_read`].
438///
439/// # Errors
440/// Propagates the sink's [`BitError`].
441#[doc(hidden)]
442pub fn align_write<K: Sink>(w: &mut K) -> Result<(), BitError> {
443    let pad = (8 - (w.bit_pos() % 8)) % 8;
444    skip_write(w, pad as u32)
445}
446
447/// The wire layout: bit packing order **and** byte order, threaded through the
448/// cursors and entry points. `#[bin(big|little)]` and `#[bin(bits = msb|lsb)]`
449/// set it; the default is MSB-first, big-endian (RFC/network order).
450///
451/// # Examples
452///
453/// ```
454/// use bnb::{BitReader, BitOrder, ByteOrder, Layout};
455///
456/// // Read a 16-bit value little-endian instead of the default big-endian.
457/// let layout = Layout { bit: BitOrder::Msb, byte: ByteOrder::Little };
458/// let mut r = BitReader::with_layout(&[0x34, 0x12], layout);
459/// assert_eq!(r.read::<u16>().unwrap(), 0x1234);
460/// assert_eq!(Layout::default(), Layout { bit: BitOrder::Msb, byte: ByteOrder::Big });
461/// ```
462#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
463pub struct Layout {
464    /// Bit packing order — does the first bit land in the high or low bit.
465    pub bit: BitOrder,
466    /// Byte order, applied to byte-multiple values.
467    pub byte: ByteOrder,
468}
469
470/// Reverses the low `bits / 8` bytes of `raw` when the declared byte order differs from the
471/// bit order's **natural** layout, and the width is a whole number of bytes (byte order
472/// applies only to byte-multiple values); a no-op otherwise. It is its own inverse, so read
473/// and write share it.
474///
475/// The natural layout is what the bit cursor produces with no transform: MSB-first emits a
476/// value's high bits first, so its bytes land **big-endian**; LSB-first emits low bits first,
477/// so its bytes land **little-endian** (bit *k* of the value goes to stream bit *k* — exactly
478/// the DBC/"Intel" layout `raw |= v << start; frame = raw.to_le_bytes()`). So the transform
479/// swaps only for `Msb`+`Little` and `Lsb`+`Big`; `Msb`+`Big` (network order) and
480/// `Lsb`+`Little` (DBC Intel, SMB) are identities. See `DESIGN.md` § byte order × bit order.
481#[inline]
482fn apply_byte_order(raw: u128, bits: u32, bit: BitOrder, byte: ByteOrder) -> u128 {
483    let natural = match bit {
484        BitOrder::Msb => ByteOrder::Big,
485        BitOrder::Lsb => ByteOrder::Little,
486    };
487    if byte == natural || bits % 8 != 0 {
488        return raw;
489    }
490    let n = (bits / 8) as usize;
491    let le = raw.to_le_bytes();
492    let mut out = 0u128;
493    let mut i = 0;
494    while i < n {
495        out |= (le[i] as u128) << (8 * (n - 1 - i));
496        i += 1;
497    }
498    out
499}
500
501/// Extracts `n` (`<= 128`) bits starting at absolute bit offset `pos` from `buf`, in
502/// `order`, returned right-aligned in a `u128` (byte order is applied separately by
503/// `read`). The single bit-extraction routine behind every slice-backed [`Source`]
504/// ([`BitReader`], [`BufSource`], [`SeekReader`]). The caller must have bounds-checked
505/// `pos + n <= buf.len() * 8` and `n <= 128`.
506///
507/// **Fast path:** when the read is byte-aligned (`pos % 8 == 0` and `n % 8 == 0`) the
508/// bytes are accumulated whole — one iteration per byte, not per bit (≈8× fewer).
509#[inline]
510fn extract_bits(buf: &[u8], pos: usize, n: usize, order: BitOrder) -> u128 {
511    if pos % 8 == 0 && n % 8 == 0 {
512        let start = pos / 8;
513        let nbytes = n / 8;
514        let mut acc = 0u128;
515        match order {
516            // MSB-first byte-aligned == big-endian byte concatenation.
517            BitOrder::Msb => {
518                for j in 0..nbytes {
519                    acc = (acc << 8) | u128::from(buf[start + j]);
520                }
521            }
522            // LSB-first byte-aligned == little-endian byte concatenation.
523            BitOrder::Lsb => {
524                for j in 0..nbytes {
525                    acc |= u128::from(buf[start + j]) << (8 * j);
526                }
527            }
528        }
529        return acc;
530    }
531    // General path: one bit at a time (handles sub-byte offsets/widths).
532    let mut acc = 0u128;
533    match order {
534        BitOrder::Msb => {
535            for k in 0..n {
536                let p = pos + k;
537                acc = (acc << 1) | u128::from((buf[p >> 3] >> (7 - (p & 7))) & 1);
538            }
539        }
540        BitOrder::Lsb => {
541            for k in 0..n {
542                let p = pos + k;
543                acc |= u128::from((buf[p >> 3] >> (p & 7)) & 1) << k;
544            }
545        }
546    }
547    acc
548}
549
550/// Appends the low `n` (`<= 128`) bits of `value` to `out` at absolute bit offset
551/// `bit_pos`, in `order` — the write dual of [`extract_bits`], used by [`BitWriter`].
552///
553/// **Fast path:** when appending byte-aligned at the end (`bit_pos % 8 == 0`,
554/// `n % 8 == 0`, cursor at `out.len()`) the bytes are pushed whole, one per byte.
555#[inline]
556fn emit_bits(out: &mut Vec<u8>, bit_pos: usize, value: u128, n: usize, order: BitOrder) {
557    if n % 8 == 0 && bit_pos % 8 == 0 && bit_pos / 8 == out.len() {
558        let nbytes = n / 8;
559        match order {
560            BitOrder::Msb => {
561                for j in 0..nbytes {
562                    out.push((value >> (8 * (nbytes - 1 - j))) as u8);
563                }
564            }
565            BitOrder::Lsb => {
566                for j in 0..nbytes {
567                    out.push((value >> (8 * j)) as u8);
568                }
569            }
570        }
571        return;
572    }
573    for k in 0..n {
574        let p = bit_pos + k;
575        // MSB-first emits the field's high bit first (i = n-1-k); LSB-first emits its
576        // low bit first (i = k) into the byte's low bit.
577        let (i, shift) = match order {
578            BitOrder::Msb => (n - 1 - k, 7 - (p & 7)),
579            BitOrder::Lsb => (k, p & 7),
580        };
581        let byte_idx = p >> 3;
582        if byte_idx == out.len() {
583            out.push(0);
584        }
585        if (value >> i) & 1 != 0 {
586            out[byte_idx] |= 1 << shift;
587        }
588    }
589}
590
591/// A cursor that reads values at arbitrary bit offsets from a byte slice, in a
592/// chosen [`BitOrder`] (MSB-first by default — `bit 0` is the high bit of byte 0,
593/// the RFC/ETSI ASCII-art convention; LSB-first for serial/PHY layers).
594///
595/// # Examples
596///
597/// ```
598/// use bnb::{BitReader, u4, u12};
599///
600/// let mut r = BitReader::new(&[0xAB, 0xCD]);
601/// assert_eq!(r.read::<u4>().unwrap(), u4::new(0xA)); // 4 bits
602/// assert_eq!(r.read::<u12>().unwrap(), u12::new(0xBCD)); // the next 12, straddling a byte
603/// assert_eq!(r.remaining_bits(), 0);
604/// ```
605#[derive(Clone, Debug)]
606pub struct BitReader<'a> {
607    bytes: &'a [u8],
608    bit_pos: usize,
609    order: BitOrder,
610    byte: ByteOrder,
611}
612
613impl<'a> BitReader<'a> {
614    /// Wraps `bytes`, positioned at bit 0, **MSB-first**, big-endian.
615    #[must_use]
616    pub fn new(bytes: &'a [u8]) -> Self {
617        Self::with_order(bytes, BitOrder::Msb)
618    }
619
620    /// Wraps `bytes`, positioned at bit 0, in the given bit order (big-endian).
621    #[must_use]
622    pub fn with_order(bytes: &'a [u8], order: BitOrder) -> Self {
623        Self::with_layout(
624            bytes,
625            Layout {
626                bit: order,
627                byte: ByteOrder::Big,
628            },
629        )
630    }
631
632    /// Wraps `bytes`, positioned at bit 0, in the given [`Layout`] (bit + byte order).
633    #[must_use]
634    pub fn with_layout(bytes: &'a [u8], layout: Layout) -> Self {
635        Self {
636            bytes,
637            bit_pos: 0,
638            order: layout.bit,
639            byte: layout.byte,
640        }
641    }
642
643    /// The current absolute bit offset.
644    #[must_use]
645    pub fn bit_pos(&self) -> usize {
646        self.bit_pos
647    }
648
649    /// Bits not yet consumed.
650    #[must_use]
651    pub fn remaining_bits(&self) -> usize {
652        self.bytes.len() * 8 - self.bit_pos
653    }
654
655    /// Reads `n` (`<= 128`) bits into the low bits of a `u128`, in the reader's
656    /// bit order (MSB-first by default).
657    ///
658    /// # Errors
659    /// [`ErrorKind::TooWide`] if `n > 128`; [`ErrorKind::UnexpectedEof`] if fewer
660    /// than `n` bits remain. Either carries the current bit offset.
661    #[inline]
662    pub fn read_bits(&mut self, n: u32) -> Result<u128, BitError> {
663        let n = n as usize;
664        if n > 128 {
665            return Err(BitError::new(ErrorKind::TooWide { width: n }, self.bit_pos));
666        }
667        if n > self.remaining_bits() {
668            return Err(BitError::new(
669                ErrorKind::UnexpectedEof {
670                    needed: n,
671                    remaining: self.remaining_bits(),
672                },
673                self.bit_pos,
674            ));
675        }
676        let acc = extract_bits(self.bytes, self.bit_pos, n, self.order);
677        self.bit_pos += n;
678        Ok(acc)
679    }
680
681    /// Reads one [`Bits`] value of its declared width, applying the byte order to a
682    /// byte-multiple value.
683    ///
684    /// # Errors
685    /// As [`read_bits`](Self::read_bits).
686    #[inline]
687    pub fn read<T: Bits>(&mut self) -> Result<T, BitError> {
688        let raw = self.read_bits(T::BITS)?;
689        Ok(T::from_bits(apply_byte_order(
690            raw,
691            T::BITS,
692            self.order,
693            self.byte,
694        )))
695    }
696
697    /// Moves the cursor to absolute bit `pos`. This needs no `Seek` trait — the whole
698    /// buffer is in hand, so a seek is just cursor arithmetic. (Enables e.g. DNS
699    /// name-compression pointers.)
700    ///
701    /// # Errors
702    /// [`ErrorKind::UnexpectedEof`] if `pos` is past the end of the buffer.
703    pub fn seek_to_bit(&mut self, pos: usize) -> Result<(), BitError> {
704        let end = self.bytes.len() * 8;
705        if pos > end {
706            return Err(BitError::new(
707                ErrorKind::UnexpectedEof {
708                    needed: pos,
709                    remaining: end,
710                },
711                self.bit_pos,
712            ));
713        }
714        self.bit_pos = pos;
715        Ok(())
716    }
717
718    /// Advances the cursor to the next byte boundary (a no-op if already aligned).
719    pub fn align_to_byte(&mut self) {
720        self.bit_pos = (self.bit_pos + 7) & !7;
721    }
722}
723
724/// A sink that appends values at arbitrary bit offsets in a chosen [`BitOrder`]
725/// (MSB-first by default), growing a byte buffer (the final partial byte is
726/// zero-padded).
727///
728/// # Examples
729///
730/// ```
731/// use bnb::{BitWriter, u4, u12};
732///
733/// let mut w = BitWriter::new();
734/// w.write(u4::new(0xA)).unwrap();
735/// w.write(u12::new(0xBCD)).unwrap();
736/// assert_eq!(w.bit_len(), 16);
737/// assert_eq!(w.into_bytes(), [0xAB, 0xCD]);
738/// ```
739#[derive(Default)]
740pub struct BitWriter {
741    bytes: Vec<u8>,
742    bit_pos: usize,
743    order: BitOrder,
744    byte: ByteOrder,
745    /// Optional per-encode scratch (see [`Sink::scratch`]); not part of the written bytes.
746    scratch: Option<Box<dyn Any>>,
747}
748
749// Hand-written so the public `Clone`/`Debug` API survives the (un-`Clone`, un-`Debug`)
750// `scratch` slot. Cloning starts a fresh encode session, so the scratch is **not**
751// carried (a clone gets `None`); `Debug` reports only its presence.
752impl Clone for BitWriter {
753    fn clone(&self) -> Self {
754        Self {
755            bytes: self.bytes.clone(),
756            bit_pos: self.bit_pos,
757            order: self.order,
758            byte: self.byte,
759            scratch: None,
760        }
761    }
762}
763
764impl fmt::Debug for BitWriter {
765    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
766        f.debug_struct("BitWriter")
767            .field("bytes", &self.bytes)
768            .field("bit_pos", &self.bit_pos)
769            .field("order", &self.order)
770            .field("byte", &self.byte)
771            .field("scratch", &self.scratch.is_some())
772            .finish()
773    }
774}
775
776impl BitWriter {
777    /// An empty **MSB-first**, big-endian writer.
778    #[must_use]
779    pub fn new() -> Self {
780        Self::default()
781    }
782
783    /// An empty writer in the given bit order (big-endian).
784    #[must_use]
785    pub fn with_order(order: BitOrder) -> Self {
786        Self::with_layout(Layout {
787            bit: order,
788            byte: ByteOrder::Big,
789        })
790    }
791
792    /// An empty writer in the given [`Layout`] (bit + byte order).
793    #[must_use]
794    pub fn with_layout(layout: Layout) -> Self {
795        Self {
796            bytes: Vec::new(),
797            bit_pos: 0,
798            order: layout.bit,
799            byte: layout.byte,
800            scratch: None,
801        }
802    }
803
804    /// Attach a type-erased **scratch** value, reachable from any codec during the encode
805    /// via [`Sink::scratch`] and recovered by [`downcast_mut`](Any::downcast_mut).
806    ///
807    /// The escape hatch for codecs that need mutable state shared across a whole message's
808    /// fields — a back-reference / compression dictionary (e.g. DNS name compression). The
809    /// scratch lives for the encode and is dropped by [`into_bytes`](Self::into_bytes); it
810    /// is never written to the output and is not carried by [`Clone`].
811    ///
812    /// ```
813    /// use bnb::{BitWriter, Sink};
814    ///
815    /// let mut w = BitWriter::new().with_scratch(Box::new(0u32));
816    /// if let Some(n) = w.scratch().and_then(|s| s.downcast_mut::<u32>()) {
817    ///     *n += 1;
818    /// }
819    /// assert_eq!(w.scratch().and_then(|s| s.downcast_ref::<u32>()), Some(&1));
820    /// ```
821    #[must_use]
822    pub fn with_scratch(mut self, scratch: Box<dyn Any>) -> Self {
823        self.scratch = Some(scratch);
824        self
825    }
826
827    /// Bits written so far.
828    #[must_use]
829    pub fn bit_len(&self) -> usize {
830        self.bit_pos
831    }
832
833    /// Appends the low `n` (`<= 128`) bits of `value`, in the writer's bit order.
834    ///
835    /// # Errors
836    /// [`ErrorKind::TooWide`] if `n > 128`.
837    #[inline]
838    pub fn write_bits(&mut self, value: u128, n: u32) -> Result<(), BitError> {
839        let n = n as usize;
840        if n > 128 {
841            return Err(BitError::new(ErrorKind::TooWide { width: n }, self.bit_pos));
842        }
843        emit_bits(&mut self.bytes, self.bit_pos, value, n, self.order);
844        self.bit_pos += n;
845        Ok(())
846    }
847
848    /// Appends one [`Bits`] value of its declared width, applying the byte order to
849    /// a byte-multiple value.
850    ///
851    /// # Errors
852    /// As [`write_bits`](Self::write_bits).
853    #[inline]
854    pub fn write<T: Bits>(&mut self, value: T) -> Result<(), BitError> {
855        let raw = apply_byte_order(value.into_bits(), T::BITS, self.order, self.byte);
856        self.write_bits(raw, T::BITS)
857    }
858
859    /// Consumes the writer, returning the packed bytes.
860    #[must_use]
861    pub fn into_bytes(self) -> Vec<u8> {
862        self.bytes
863    }
864}
865
866/// A bit-level **input** the codec recurses over. Implemented by [`BitReader`]
867/// (in-memory slice), [`StreamBitReader`] (forward `Read`), [`BufSource`] (a
868/// retain-and-seek socket adapter), and [`SeekReader`] (`Read + Seek`); the codec is
869/// generic over `Source`, so one decoder runs over any of them — see
870/// [`guide::io`](crate::guide::io).
871///
872/// # Examples
873///
874/// ```
875/// use bnb::{BitReader, Source, u4};
876///
877/// // A reader generic over any `Source`.
878/// fn first_nibble<S: Source>(s: &mut S) -> u4 { s.read().unwrap() }
879///
880/// let mut r = BitReader::new(&[0xA5]);
881/// assert_eq!(first_nibble(&mut r), u4::new(0xA));
882/// ```
883pub trait Source: sealed::Sealed {
884    /// Reads `n` (`<= 128`) bits into the low bits of a `u128`, in the source's
885    /// bit order (MSB-first by default).
886    ///
887    /// # Errors
888    /// Propagates the reader's [`BitError`].
889    fn read_bits(&mut self, n: u32) -> Result<u128, BitError>;
890
891    /// The current absolute bit offset (for position-aware errors).
892    fn bit_pos(&self) -> usize;
893
894    /// The byte order applied to a byte-multiple value (default big-endian).
895    fn byte_order(&self) -> ByteOrder {
896        ByteOrder::Big
897    }
898
899    /// The bit order this source reads in (default MSB-first). Paired with
900    /// [`byte_order`](Source::byte_order) to decide whether a byte-multiple value needs its
901    /// bytes swapped — each bit order has a *natural* byte layout (big-endian under MSB,
902    /// little-endian under LSB), and only the opposite declaration swaps.
903    fn bit_order(&self) -> BitOrder {
904        BitOrder::Msb
905    }
906
907    /// Moves the cursor to absolute bit `pos`. The default — for a forward-only
908    /// source — fails with [`ErrorKind::NotSeekable`]; seekable sources (the slice
909    /// [`BitReader`]) override it. A [`SeekSource`] guarantees this works.
910    ///
911    /// # Errors
912    /// [`ErrorKind::NotSeekable`] unless the source is seekable.
913    fn seek_to_bit(&mut self, _pos: usize) -> Result<(), BitError> {
914        Err(BitError::new(ErrorKind::NotSeekable, self.bit_pos()))
915    }
916
917    /// Reads one [`Bits`] value of its declared width, applying the byte order.
918    ///
919    /// # Errors
920    /// As [`read_bits`](Source::read_bits).
921    #[inline]
922    fn read<T: Bits>(&mut self) -> Result<T, BitError> {
923        let raw = self.read_bits(T::BITS)?;
924        Ok(T::from_bits(apply_byte_order(
925            raw,
926            T::BITS,
927            self.bit_order(),
928            self.byte_order(),
929        )))
930    }
931
932    /// Reads `n` bytes into a fresh `Vec` (at any bit offset — the bytes need not be
933    /// aligned). The bulk form of the per-byte `read::<u8>()` loop, for blob/payload
934    /// reads in custom codecs and container formats.
935    ///
936    /// `n` is often attacker-controlled, so **nothing is pre-allocated from it**: bytes
937    /// are pushed as they are read, bounded by the input — a hostile huge `n` against a
938    /// short source is a fast [`UnexpectedEof`](ErrorKind::UnexpectedEof), not an
939    /// allocation. (An implementation may override with a byte-aligned fast path; the
940    /// default is the correct-first per-byte loop.)
941    ///
942    /// # Errors
943    /// As [`read_bits`](Source::read_bits).
944    fn read_bytes(&mut self, n: usize) -> Result<alloc::vec::Vec<u8>, BitError> {
945        let mut v = alloc::vec::Vec::new();
946        for _ in 0..n {
947            v.push(self.read::<u8>()?);
948        }
949        Ok(v)
950    }
951
952    /// Fills `buf` with bytes from the source — the no-alloc dual of
953    /// [`read_bytes`](Source::read_bytes), for fixed scratch buffers and tight
954    /// `no_std` paths.
955    ///
956    /// # Errors
957    /// As [`read_bits`](Source::read_bits).
958    fn read_into(&mut self, buf: &mut [u8]) -> Result<(), BitError> {
959        for slot in buf.iter_mut() {
960            *slot = self.read::<u8>()?;
961        }
962        Ok(())
963    }
964
965    /// Borrows this source as a [`std::io::Read`] over its bytes — for handing the
966    /// cursor to `std::io`-based code from a `#[br(parse_with = …)]` (e.g. a decoder, or
967    /// a `Read`-based parser). Reads 8 bits per byte; see [`SourceReader`]. Only with
968    /// the `std` feature.
969    #[cfg(feature = "std")]
970    fn as_read(&mut self) -> SourceReader<'_, Self>
971    where
972        Self: Sized,
973    {
974        SourceReader(self)
975    }
976}
977
978/// A [`std::io::Read`] view over a [`Source`], from [`Source::as_read`]. Each `read`
979/// pulls 8 bits per byte through [`Source::read_bits`], so it works at any bit
980/// alignment (you will normally be byte-aligned). A read failure surfaces as an
981/// `io::Error` when no bytes were produced, or ends the read short once some were — the
982/// `std::io` convention. This is the outbound dual of [`BufSource`]/[`SeekReader`] (which
983/// adapt a `std::io::Read` *into* a `Source`).
984#[cfg(feature = "std")]
985pub struct SourceReader<'a, S: Source>(&'a mut S);
986
987#[cfg(feature = "std")]
988impl<S: Source> std::io::Read for SourceReader<'_, S> {
989    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
990        for (i, slot) in buf.iter_mut().enumerate() {
991            match self.0.read_bits(8) {
992                Ok(b) => *slot = b as u8,
993                Err(e) if i == 0 => {
994                    // Map the actual failure — only a genuine end-of-input is `UnexpectedEof`;
995                    // a non-EOF error (e.g. `NotSeekable`, `Convert`) must not masquerade as one.
996                    let kind = match e.kind {
997                        ErrorKind::UnexpectedEof { .. } | ErrorKind::Incomplete { .. } => {
998                            std::io::ErrorKind::UnexpectedEof
999                        }
1000                        _ => std::io::ErrorKind::InvalidData,
1001                    };
1002                    return Err(std::io::Error::new(kind, e.to_string()));
1003                }
1004                Err(_) => return Ok(i),
1005            }
1006        }
1007        Ok(buf.len())
1008    }
1009}
1010
1011/// A [`Source`] that can seek (its [`seek_to_bit`](Source::seek_to_bit) is real, not
1012/// the failing default). A `#[bin]` message that uses `restore_position` bounds its
1013/// generated `decode` on this trait, so a forward-only stream is rejected at
1014/// compile time. Implemented by [`BitReader`], [`BufSource`], and [`SeekReader`]
1015/// (and, with the `bytes` feature, `BytesReader`).
1016pub trait SeekSource: Source {}
1017
1018impl SeekSource for BitReader<'_> {}
1019
1020/// A bit-level **output** the codec writes to — the in-memory [`BitWriter`]
1021/// (and, under the `bytes` feature, `BytesWriter`). Encode to any
1022/// [`std::io::Write`] via a message's generated `encode` method.
1023///
1024/// # Examples
1025///
1026/// ```
1027/// use bnb::{BitWriter, Sink, u4};
1028///
1029/// // A writer generic over any `Sink`.
1030/// fn put_nibble<K: Sink>(k: &mut K, v: u4) { k.write(v).unwrap(); }
1031///
1032/// let mut w = BitWriter::new();
1033/// put_nibble(&mut w, u4::new(0xA));
1034/// put_nibble(&mut w, u4::new(0x5));
1035/// assert_eq!(w.into_bytes(), [0xA5]);
1036/// ```
1037pub trait Sink: sealed::Sealed {
1038    /// Appends the low `n` (`<= 128`) bits of `value`, in the sink's bit order
1039    /// (MSB-first by default).
1040    ///
1041    /// # Errors
1042    /// Propagates the writer's [`BitError`].
1043    fn write_bits(&mut self, value: u128, n: u32) -> Result<(), BitError>;
1044
1045    /// The number of bits written so far.
1046    fn bit_pos(&self) -> usize;
1047
1048    /// The byte order applied to a byte-multiple value (default big-endian).
1049    fn byte_order(&self) -> ByteOrder {
1050        ByteOrder::Big
1051    }
1052
1053    /// The bit order this sink writes in (default MSB-first). Paired with
1054    /// [`byte_order`](Sink::byte_order) exactly as on [`Source`]: each bit order has a
1055    /// *natural* byte layout (big-endian under MSB, little-endian under LSB), and only the
1056    /// opposite declaration swaps a byte-multiple value.
1057    fn bit_order(&self) -> BitOrder {
1058        BitOrder::Msb
1059    }
1060
1061    /// A type-erased, **encode-scoped scratch** value for codecs that need mutable state
1062    /// shared across a whole message's fields — a back-reference / compression dictionary
1063    /// (e.g. DNS name compression). Recover the concrete type with
1064    /// [`downcast_mut`](Any::downcast_mut).
1065    ///
1066    /// Returns `None` unless the sink was built carrying one (see
1067    /// [`BitWriter::with_scratch`]); the default sink has none. The scratch is the shared
1068    /// thread the `Sink` already provides — since one sink is passed by `&mut` through
1069    /// every field's encode, a value stored here is visible to them all.
1070    fn scratch(&mut self) -> Option<&mut dyn Any> {
1071        None
1072    }
1073
1074    /// Appends one [`Bits`] value of its declared width, applying the byte order.
1075    ///
1076    /// # Errors
1077    /// As [`write_bits`](Sink::write_bits).
1078    #[inline]
1079    fn write<T: Bits>(&mut self, value: T) -> Result<(), BitError> {
1080        let raw = apply_byte_order(
1081            value.into_bits(),
1082            T::BITS,
1083            self.bit_order(),
1084            self.byte_order(),
1085        );
1086        self.write_bits(raw, T::BITS)
1087    }
1088
1089    /// Appends a run of bytes — the bulk dual of [`Source::read_bytes`], replacing the
1090    /// per-byte `write(b)?` loop in custom codecs. Works at any bit offset.
1091    ///
1092    /// # Errors
1093    /// As [`write_bits`](Sink::write_bits).
1094    fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), BitError> {
1095        for &b in bytes {
1096            self.write(b)?;
1097        }
1098        Ok(())
1099    }
1100
1101    /// Borrows this sink as a [`std::io::Write`] — the dual of [`Source::as_read`], for
1102    /// handing the cursor to `std::io`-based code from a `#[bw(write_with = …)]`. Writes 8
1103    /// bits per byte; see [`SinkWriter`]. Only with the `std` feature.
1104    #[cfg(feature = "std")]
1105    fn as_write(&mut self) -> SinkWriter<'_, Self>
1106    where
1107        Self: Sized,
1108    {
1109        SinkWriter(self)
1110    }
1111}
1112
1113/// A [`std::io::Write`] view over a [`Sink`], from [`Sink::as_write`]. Each `write`
1114/// pushes 8 bits per byte through [`Sink::write_bits`]. The outbound dual of
1115/// [`SourceReader`]; `flush` is a no-op (the sink owns its buffer).
1116#[cfg(feature = "std")]
1117pub struct SinkWriter<'a, K: Sink>(&'a mut K);
1118
1119#[cfg(feature = "std")]
1120impl<K: Sink> std::io::Write for SinkWriter<'_, K> {
1121    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
1122        for &b in buf {
1123            self.0
1124                .write_bits(u128::from(b), 8)
1125                .map_err(|e| std::io::Error::other(e.to_string()))?;
1126        }
1127        Ok(buf.len())
1128    }
1129
1130    fn flush(&mut self) -> std::io::Result<()> {
1131        Ok(())
1132    }
1133}
1134
1135impl sealed::Sealed for BitReader<'_> {}
1136
1137impl Source for BitReader<'_> {
1138    #[inline]
1139    fn read_bits(&mut self, n: u32) -> Result<u128, BitError> {
1140        BitReader::read_bits(self, n)
1141    }
1142    #[inline]
1143    fn bit_pos(&self) -> usize {
1144        self.bit_pos
1145    }
1146    #[inline]
1147    fn byte_order(&self) -> ByteOrder {
1148        self.byte
1149    }
1150    #[inline]
1151    fn bit_order(&self) -> BitOrder {
1152        self.order
1153    }
1154    #[inline]
1155    fn seek_to_bit(&mut self, pos: usize) -> Result<(), BitError> {
1156        BitReader::seek_to_bit(self, pos)
1157    }
1158}
1159
1160impl sealed::Sealed for BitWriter {}
1161
1162impl Sink for BitWriter {
1163    #[inline]
1164    fn write_bits(&mut self, value: u128, n: u32) -> Result<(), BitError> {
1165        BitWriter::write_bits(self, value, n)
1166    }
1167    #[inline]
1168    fn bit_pos(&self) -> usize {
1169        self.bit_pos
1170    }
1171    #[inline]
1172    fn byte_order(&self) -> ByteOrder {
1173        self.byte
1174    }
1175    #[inline]
1176    fn bit_order(&self) -> BitOrder {
1177        self.order
1178    }
1179    #[inline]
1180    fn scratch(&mut self) -> Option<&mut dyn Any> {
1181        self.scratch.as_deref_mut()
1182    }
1183}
1184
1185/// A message decoded from a bit stream — the recursion point a
1186/// `#[derive(BitDecode)]` struct implements (reading each field in declaration
1187/// order). Leaf fields are any [`Bits`] type; nested messages recurse. Fixed- or
1188/// variable-length; a fixed-length message *also* implements [`FixedBitLen`].
1189///
1190/// Most users reach for [`#[bin]`](macro@crate::bin) (which derives this plus
1191/// [`BitEncode`] and a builder); the bare derives are the codec on its own, for fields
1192/// that straddle byte boundaries.
1193///
1194/// # Examples
1195///
1196/// ```
1197/// use bnb::{BitDecode, BitEncode, u4, u12};
1198///
1199/// // A 4-bit tag + a 12-bit length, straddling the byte boundary.
1200/// #[derive(BitDecode, BitEncode, Debug, PartialEq)]
1201/// struct Frame { tag: u4, len: u12 }
1202///
1203/// let f = Frame::decode_exact(&[0xAB, 0xCD]).unwrap();
1204/// assert_eq!(f, Frame { tag: u4::new(0xA), len: u12::new(0xBCD) });
1205/// assert_eq!(f.to_bytes().unwrap(), [0xAB, 0xCD]); // round-trips
1206/// ```
1207pub trait BitDecode: Sized {
1208    /// Decodes `Self` from any [`Source`], advancing its cursor.
1209    ///
1210    /// # Errors
1211    /// Propagates the source's [`BitError`].
1212    fn bit_decode<S: Source>(r: &mut S) -> Result<Self, BitError>;
1213}
1214
1215/// A message whose encoded length is a **compile-time constant** — i.e. it has no
1216/// variable-length (`count`-driven `Vec`) field. The derive implements this only
1217/// for fixed messages; it sizes a fixed byte region when the message is embedded
1218/// as a field in another message (its contribution to the parent's width). A
1219/// `count`-bearing message implements [`BitDecode`]/[`BitEncode`] but **not** this.
1220/// `Bits` leaves also implement it (their `BIT_LEN` is `Bits::BITS`), so a field's
1221/// width is computed uniformly whether it's a leaf or a nested message.
1222pub trait FixedBitLen {
1223    /// Total encoded width of the message in bits — the sum of its fields' widths.
1224    const BIT_LEN: u32;
1225}
1226
1227/// A message encoded to a bit stream — the dual of [`BitDecode`].
1228///
1229/// Encoding has two forms: the required [`bit_encode`](Self::bit_encode)
1230/// is **verbatim** (exactly what's stored), and [`canonical_bit_encode`](Self::canonical_bit_encode)
1231/// is **canonical** (`reserved` → spec value, `calc` → recomputed). The default canonical
1232/// impl just calls `bit_encode`, so the two are identical unless a `#[bin]` message has a
1233/// `reserved` or non-`temp` `calc` field — in which case the derive overrides it.
1234pub trait BitEncode {
1235    /// The message's bit/byte order, used to size a fresh [`BitWriter`] when
1236    /// encoding to a `Vec`/writer. The derive sets it from the struct's declared
1237    /// `bit_order`/`bytes`; a hand-written impl that only ever encodes into a
1238    /// caller-supplied [`Sink`] can leave the default.
1239    const LAYOUT: Layout = Layout {
1240        bit: BitOrder::Msb,
1241        byte: ByteOrder::Big,
1242    };
1243
1244    /// Encodes `self` **verbatim** into any [`Sink`], advancing its cursor.
1245    ///
1246    /// # Errors
1247    /// Propagates the sink's [`BitError`].
1248    fn bit_encode<K: Sink>(&self, w: &mut K) -> Result<(), BitError>;
1249
1250    /// Encodes `self`'s **canonical** form into any [`Sink`]: `reserved` fields as their
1251    /// spec value, `calc` fields recomputed. Defaults to [`bit_encode`](Self::bit_encode)
1252    /// (verbatim == canonical) for messages with no `reserved`/`calc` field.
1253    ///
1254    /// # Errors
1255    /// Propagates the sink's [`BitError`].
1256    fn canonical_bit_encode<K: Sink>(&self, w: &mut K) -> Result<(), BitError> {
1257        self.bit_encode(w)
1258    }
1259}
1260
1261// A `Bits` leaf (a `uN`, a `#[bitfield]`, a `BitEnum`/`#[bitflags]`) is *also* field-codable:
1262// it decodes by reading its `BITS` bits and encodes by writing them. This lets `#[bin]` treat
1263// **every** field uniformly through `bit_decode`/`bit_encode`, so it needs no `#[nested]` marker
1264// to choose between "read bits" and "recurse into a message". (The `Bits` packing role — the
1265// reason these types exist — is untouched; this only *adds* the stream-codec impls.) No blanket
1266// `impl<T: Bits>` is possible (it would collide with the per-message derives under coherence),
1267// so the leaves are covered concretely here and the macros emit one for each user `Bits` type.
1268macro_rules! bits_leaf_codec {
1269    ($($t:ty),* $(,)?) => {$(
1270        impl BitDecode for $t {
1271            #[inline]
1272            fn bit_decode<S: Source>(r: &mut S) -> Result<Self, BitError> {
1273                r.read::<$t>()
1274            }
1275        }
1276        impl BitEncode for $t {
1277            #[inline]
1278            fn bit_encode<K: Sink>(&self, w: &mut K) -> Result<(), BitError> {
1279                w.write(*self)
1280            }
1281        }
1282        // A leaf's fixed width is its `Bits::BITS`, so `#[bin]` can size it the same way it
1283        // sizes a fixed nested message — uniformly via `FixedBitLen`.
1284        impl FixedBitLen for $t {
1285            const BIT_LEN: u32 = <$t as Bits>::BITS;
1286        }
1287    )*};
1288}
1289bits_leaf_codec!(u8, u16, u32, u64, u128, bool);
1290
1291// `std::net` address types as `#[bin]` fields — the network-codec convenience the protocols
1292// dogfooding surfaced (IPv4 headers otherwise model addresses as a raw `u32`). An address
1293// serializes as its `to_bits`/`from_bits` integer, so it follows the struct's byte order like
1294// any other integer field: in a `#[bin(big)]` message that's the octets in network order
1295// (`192.168.1.1` → `C0 A8 01 01`), which is what every real protocol wants. `std` only, since
1296// the types are `std::net`.
1297macro_rules! ip_addr_codec {
1298    ($($t:ty => $int:ty, $bits:expr);* $(;)?) => {$(
1299        #[cfg(feature = "std")]
1300        impl BitDecode for $t {
1301            #[inline]
1302            fn bit_decode<S: Source>(r: &mut S) -> Result<Self, BitError> {
1303                Ok(<$t>::from_bits(r.read::<$int>()?))
1304            }
1305        }
1306        #[cfg(feature = "std")]
1307        impl BitEncode for $t {
1308            #[inline]
1309            fn bit_encode<K: Sink>(&self, w: &mut K) -> Result<(), BitError> {
1310                w.write(self.to_bits())
1311            }
1312        }
1313        #[cfg(feature = "std")]
1314        impl FixedBitLen for $t {
1315            const BIT_LEN: u32 = $bits;
1316        }
1317    )*};
1318}
1319ip_addr_codec!(
1320    std::net::Ipv4Addr => u32, 32;
1321    std::net::Ipv6Addr => u128, 128;
1322);
1323
1324impl<T, const N: usize> BitDecode for crate::int::UInt<T, N>
1325where
1326    crate::int::UInt<T, N>: Bits,
1327{
1328    #[inline]
1329    fn bit_decode<S: Source>(r: &mut S) -> Result<Self, BitError> {
1330        r.read::<Self>()
1331    }
1332}
1333
1334impl<T, const N: usize> BitEncode for crate::int::UInt<T, N>
1335where
1336    crate::int::UInt<T, N>: Bits,
1337{
1338    #[inline]
1339    fn bit_encode<K: Sink>(&self, w: &mut K) -> Result<(), BitError> {
1340        w.write(*self)
1341    }
1342}
1343
1344impl<T, const N: usize> FixedBitLen for crate::int::UInt<T, N>
1345where
1346    crate::int::UInt<T, N>: Bits,
1347{
1348    const BIT_LEN: u32 = <Self as Bits>::BITS;
1349}
1350
1351/// Seals [`CountPrefix`] and [`codecs::leb128::Varint`](crate::codecs::leb128::Varint):
1352/// the impl set is crate-owned (all wire-integer widths are already covered), so growing
1353/// it later is non-breaking while a downstream impl can never observe a bound change.
1354pub(crate) mod sealed {
1355    /// The sealing supertrait — unnameable downstream, so the traits above cannot be
1356    /// implemented outside this crate.
1357    pub trait Sealed {}
1358}
1359
1360/// Checked length ⇄ wire-prefix conversions: the types usable as a length/count prefix —
1361/// by the [`#[brw(count_prefix = <Ty>)]`](macro@crate::bin) directive and by the
1362/// [`codecs::prefixed`](crate::codecs::prefixed) string codec.
1363///
1364/// The prefix is computed from `len()` on encode and turned back into an element count on
1365/// decode. `try_from_count` is **checked and never truncates**: the length is widened (never
1366/// narrowed) before the range compare, so 300 elements against a `u8` prefix is
1367/// [`WidthError::ValueTooLarge`] — not a silently wrapped `44`.
1368///
1369/// [`WidthError::ValueTooLarge`]: crate::WidthError::ValueTooLarge
1370#[diagnostic::on_unimplemented(
1371    message = "`{Self}` cannot be a `count_prefix` type",
1372    note = "supported prefix types: u8, u16, u32, u64, u128 and the arbitrary-width `uN` aliases (e.g. `u12`)",
1373    note = "this trait is sealed — the supported prefix types are built in"
1374)]
1375pub trait CountPrefix: Bits + sealed::Sealed {
1376    /// The prefix for a collection of `len` elements, or [`WidthError::ValueTooLarge`] when
1377    /// `len` exceeds the prefix's range.
1378    fn try_from_count(len: usize) -> core::result::Result<Self, crate::error::WidthError>
1379    where
1380        Self: Sized;
1381
1382    /// The prefix as an element count.
1383    ///
1384    /// For a `u64`/`u128` prefix on a 32-bit target this is a wrapping narrow — the same
1385    /// `n as usize` the hand-written triad performs; harmless under the codec's
1386    /// push-based count loop (no pre-allocation, bounded by the input).
1387    fn to_count(self) -> usize;
1388}
1389
1390macro_rules! count_prefix_prim {
1391    ($($t:ty),* $(,)?) => {$(
1392        impl sealed::Sealed for $t {}
1393
1394        impl CountPrefix for $t {
1395            #[inline]
1396            fn try_from_count(len: usize) -> core::result::Result<Self, crate::error::WidthError> {
1397                <$t>::try_from(len).map_err(|_| crate::error::WidthError::ValueTooLarge {
1398                    value: len as u128,
1399                    bits: <$t>::BITS,
1400                })
1401            }
1402
1403            #[inline]
1404            fn to_count(self) -> usize {
1405                self as usize
1406            }
1407        }
1408    )*};
1409}
1410count_prefix_prim!(u8, u16, u32, u64, u128);
1411
1412macro_rules! count_prefix_uint {
1413    ($($t:ty),* $(,)?) => {$(
1414        impl<const N: usize> sealed::Sealed for crate::int::UInt<$t, N> {}
1415
1416        impl<const N: usize> CountPrefix for crate::int::UInt<$t, N> {
1417            #[inline]
1418            fn try_from_count(len: usize) -> core::result::Result<Self, crate::error::WidthError> {
1419                // Widen-then-compare: narrowing first (`len as $t`) would truncate
1420                // *before* the range check and let an oversized length slip through.
1421                let wide = len as u128;
1422                if wide > Self::MASK as u128 {
1423                    return Err(crate::error::WidthError::ValueTooLarge {
1424                        value: wide,
1425                        bits: N as u32,
1426                    });
1427                }
1428                Ok(Self::from_raw(len as $t))
1429            }
1430
1431            #[inline]
1432            fn to_count(self) -> usize {
1433                self.value() as usize
1434            }
1435        }
1436    )*};
1437}
1438count_prefix_uint!(u8, u16, u32, u64, u128);
1439
1440/// `encode(writer)` for any [`BitEncode`] message — encodes to a `Vec` (using the type's
1441/// [`LAYOUT`](BitEncode::LAYOUT)) **verbatim** and writes it to a [`std::io::Write`] sink.
1442/// A blanket-implemented extension trait, so bring it into scope
1443/// (`use bnb::prelude::*` or `use bnb::EncodeExt`) to call `.encode(&mut w)`. Only
1444/// with the `std` feature; in `no_std` use the generated `to_bytes`/`to_canonical_bytes`, or
1445/// [`bit_encode`](BitEncode::bit_encode)/[`canonical_bit_encode`](BitEncode::canonical_bit_encode)
1446/// over a [`Sink`].
1447#[cfg(feature = "std")]
1448pub trait EncodeExt: BitEncode {
1449    /// Encodes `self` **verbatim** to any [`std::io::Write`] (socket, file, `Vec`) — exactly
1450    /// what's stored. For the canonical form, encode `self.to_canonical().encode(&mut w)`, or
1451    /// use the inherent `to_bytes` (verbatim) / `to_canonical_bytes` (canonical) instead.
1452    ///
1453    /// # Errors
1454    /// [`ErrorKind::Io`] on a write failure, else the encode error.
1455    fn encode<W: std::io::Write>(&self, w: &mut W) -> Result<(), BitError>
1456    where
1457        Self: Sized,
1458    {
1459        encode_to_writer_with(w, Self::LAYOUT, |bw| self.bit_encode(bw))
1460    }
1461}
1462
1463#[cfg(feature = "std")]
1464impl<T: BitEncode> EncodeExt for T {}
1465
1466/// Polymorphic decode **with context** `A` — the companion to a `#[bin(ctx(...))]`
1467/// type's inherent `decode_with`, for hand-written generic combinators and
1468/// trait-object parsing (ctx Layer 2). Every [`BitDecode`] type is `DecodeWith<()>`
1469/// (blanket), and a ctx type is `DecodeWith<…Ctx>`, so one bound `T: DecodeWith<A>`
1470/// spans both context-free and context-taking messages. Inherent `Type::decode_with`
1471/// call sites are unaffected.
1472pub trait DecodeWith<A>: Sized {
1473    /// Decodes `Self` from a [`Source`] given `args`.
1474    ///
1475    /// # Errors
1476    /// Propagates the decode [`BitError`].
1477    fn decode_with<S: Source>(r: &mut S, args: A) -> Result<Self, BitError>;
1478}
1479
1480/// The dual of [`DecodeWith`] — polymorphic encode with context `A`.
1481pub trait EncodeWith<A> {
1482    /// Encodes `self` into a [`Sink`] given `args`.
1483    ///
1484    /// # Errors
1485    /// Propagates the encode [`BitError`].
1486    fn encode_with<K: Sink>(&self, w: &mut K, args: A) -> Result<(), BitError>;
1487}
1488
1489impl<T: BitDecode> DecodeWith<()> for T {
1490    fn decode_with<S: Source>(r: &mut S, _args: ()) -> Result<Self, BitError> {
1491        T::bit_decode(r)
1492    }
1493}
1494
1495impl<T: BitEncode> EncodeWith<()> for T {
1496    fn encode_with<K: Sink>(&self, w: &mut K, _args: ()) -> Result<(), BitError> {
1497        self.bit_encode(w)
1498    }
1499}
1500
1501// ---------------------------------------------------------------------------
1502// Entry-point helpers — the logic behind the `#[derive]`-generated inherent
1503// methods (`Type::decode`/`peek`/`decode_exact`/`encode`/`to_bytes`). Kept here
1504// so the logic lives in one place rather than monomorphized inline per type;
1505// doc-hidden because the public surface is the generated methods.
1506// ---------------------------------------------------------------------------
1507
1508/// Decode every message from `bytes` into a `Vec`, with the message's own byte/bit order baked
1509/// in — bit-aware, so messages that don't end on byte boundaries reassemble correctly. Backs
1510/// `Type::decode_all`. The buffer must hold whole messages (a partial tail is an error).
1511///
1512/// # Errors
1513/// The first decode [`BitError`] (e.g. a truncated trailing message).
1514#[doc(hidden)]
1515pub fn decode_all<T: BitDecode>(bytes: &[u8], layout: Layout) -> Result<Vec<T>, BitError> {
1516    let mut r = BitReader::with_layout(bytes, layout);
1517    let mut out = Vec::new();
1518    while r.remaining_bits() > 0 {
1519        let before = r.bit_pos();
1520        let item = T::bit_decode(&mut r)?;
1521        if r.bit_pos() == before {
1522            break; // a zero-width `T` makes no progress — stop without pushing a spurious
1523            // element (and without spinning forever).
1524        }
1525        out.push(item);
1526    }
1527    Ok(out)
1528}
1529
1530/// A lazy iterator decoding successive `T` from `bytes` (layout baked in) until the buffer is
1531/// drained, ending after the first error if one occurs. Backs `Type::decode_iter`.
1532#[doc(hidden)]
1533pub fn decode_iter<T: BitDecode>(
1534    bytes: &[u8],
1535    layout: Layout,
1536) -> impl Iterator<Item = Result<T, BitError>> + '_ {
1537    let mut r = BitReader::with_layout(bytes, layout);
1538    let mut stopped = false;
1539    core::iter::from_fn(move || {
1540        if stopped || r.remaining_bits() == 0 {
1541            return None;
1542        }
1543        let before = r.bit_pos();
1544        match T::bit_decode(&mut r) {
1545            Ok(v) => {
1546                stopped = r.bit_pos() == before; // stop if a zero-width message made no progress
1547                Some(Ok(v))
1548            }
1549            Err(e) => {
1550                stopped = true;
1551                Some(Err(e))
1552            }
1553        }
1554    })
1555}
1556
1557/// Decodes one message from `bytes` without consuming the caller's buffer
1558/// (tail-tolerant). Backs `Type::peek`.
1559///
1560/// # Errors
1561/// Propagates the decode [`BitError`].
1562#[doc(hidden)]
1563pub fn decode_peek<T: BitDecode>(bytes: &[u8], layout: Layout) -> Result<T, BitError> {
1564    T::bit_decode(&mut BitReader::with_layout(bytes, layout))
1565}
1566
1567/// `decode_peek` over a caller-supplied closure (no consumption requirement) — backs a
1568/// `#[bin]` enum's `peek_variant`, which runs only the dispatch decision over `bytes`.
1569///
1570/// # Errors
1571/// Propagates the closure's [`BitError`].
1572#[doc(hidden)]
1573pub fn decode_peek_with<T, F>(bytes: &[u8], layout: Layout, f: F) -> Result<T, BitError>
1574where
1575    F: FnOnce(&mut BitReader) -> Result<T, BitError>,
1576{
1577    f(&mut BitReader::with_layout(bytes, layout))
1578}
1579
1580/// `decode_exact` over a caller-supplied decode closure rather than the
1581/// [`BitDecode`] trait — backs the `ctx`-parameterized `Type::decode_with_exact`
1582/// (a `ctx` type takes a context argument, so it has no plain `bit_decode`).
1583///
1584/// # Errors
1585/// [`ErrorKind::TrailingBytes`] if whole bytes remain, else the closure's error.
1586#[doc(hidden)]
1587pub fn decode_exact_with<T, F>(bytes: &[u8], layout: Layout, f: F) -> Result<T, BitError>
1588where
1589    F: FnOnce(&mut BitReader) -> Result<T, BitError>,
1590{
1591    let mut r = BitReader::with_layout(bytes, layout);
1592    let v = f(&mut r)?;
1593    let consumed = r.bit_pos().div_ceil(8);
1594    if consumed < bytes.len() {
1595        return Err(BitError::new(
1596            ErrorKind::TrailingBytes {
1597                remaining: bytes.len() - consumed,
1598            },
1599            r.bit_pos(),
1600        ));
1601    }
1602    Ok(v)
1603}
1604
1605/// `to_bytes` over a caller-supplied encode closure — backs the `ctx`-parameterized
1606/// `Type::to_bytes_with`.
1607///
1608/// # Errors
1609/// Propagates the closure's [`BitError`].
1610#[doc(hidden)]
1611pub fn encode_to_vec_with<F>(layout: Layout, f: F) -> Result<Vec<u8>, BitError>
1612where
1613    F: FnOnce(&mut BitWriter) -> Result<(), BitError>,
1614{
1615    let mut w = BitWriter::with_layout(layout);
1616    f(&mut w)?;
1617    Ok(w.into_bytes())
1618}
1619
1620/// Decodes and requires every **whole byte** consumed; a sub-byte tail in the
1621/// final byte is treated as padding. Backs `Type::decode_exact`.
1622///
1623/// # Errors
1624/// [`ErrorKind::TrailingBytes`] if whole bytes remain, else the decode error.
1625#[doc(hidden)]
1626pub fn decode_exact<T: BitDecode>(bytes: &[u8], layout: Layout) -> Result<T, BitError> {
1627    let mut r = BitReader::with_layout(bytes, layout);
1628    let v = T::bit_decode(&mut r)?;
1629    let consumed = r.bit_pos().div_ceil(8);
1630    if consumed < bytes.len() {
1631        return Err(BitError::new(
1632            ErrorKind::TrailingBytes {
1633                remaining: bytes.len() - consumed,
1634            },
1635            r.bit_pos(),
1636        ));
1637    }
1638    Ok(v)
1639}
1640
1641/// Encodes `value` to a `Vec<u8>`. Backs `Type::to_bytes`.
1642///
1643/// # Errors
1644/// Propagates the encode [`BitError`].
1645#[doc(hidden)]
1646pub fn encode_to_vec<T: BitEncode>(value: &T, layout: Layout) -> Result<Vec<u8>, BitError> {
1647    let mut w = BitWriter::with_layout(layout);
1648    value.bit_encode(&mut w)?;
1649    Ok(w.into_bytes())
1650}
1651
1652/// Encodes `value` to any [`std::io::Write`]. Backs [`EncodeExt::encode`].
1653///
1654/// # Errors
1655/// [`ErrorKind::Io`] on a write failure, else the encode error.
1656/// Encode to a [`std::io::Write`] over a caller-supplied encode closure — backs
1657/// [`EncodeExt::encode`] (the closure picks `bit_encode` vs `canonical_bit_encode`).
1658///
1659/// # Errors
1660/// [`ErrorKind::Io`] on a write failure, else the closure's error.
1661#[cfg(feature = "std")]
1662#[doc(hidden)]
1663pub fn encode_to_writer_with<W, F>(w: &mut W, layout: Layout, f: F) -> Result<(), BitError>
1664where
1665    W: std::io::Write,
1666    F: FnOnce(&mut BitWriter) -> Result<(), BitError>,
1667{
1668    let mut bw = BitWriter::with_layout(layout);
1669    f(&mut bw)?;
1670    let at = bw.bit_len();
1671    w.write_all(&bw.into_bytes())
1672        .map_err(|e| BitError::new(ErrorKind::Io(e.kind()), at))
1673}
1674
1675/// Reads a fixed `[u8; N]` byte array (`N * 8` bits) from the cursor. Backs a
1676/// `[u8; N]` payload field; `N` is inferred from the field type. Variable-length
1677/// payloads (`Vec` + `#[br(count = …)]`) take a separate push-based path that
1678/// grows by element, so an attacker-controlled count can't over-allocate.
1679///
1680/// # Errors
1681/// Propagates the source's [`BitError`].
1682#[doc(hidden)]
1683pub fn read_byte_array<const N: usize, S: Source>(r: &mut S) -> Result<[u8; N], BitError> {
1684    let mut arr = [0u8; N];
1685    for b in &mut arr {
1686        *b = r.read_bits(8)? as u8;
1687    }
1688    Ok(arr)
1689}
1690
1691/// Peeks up to `max` bytes without consuming them — reads them, then rewinds. Returns
1692/// however many are available (fewer than `max` at end-of-input). Backs variable-width
1693/// `#[bin]` enum magic dispatch (peek the longest magic, match a prefix, then seek past
1694/// the matched one). Like other seeking directives it bounds the generated `decode`
1695/// on [`SeekSource`]; a forward-only source fails at runtime with
1696/// [`ErrorKind::NotSeekable`].
1697///
1698/// # Errors
1699/// [`ErrorKind::NotSeekable`] if the source can't rewind.
1700#[doc(hidden)]
1701pub fn peek_bytes<S: Source>(r: &mut S, max: usize) -> Result<Vec<u8>, BitError> {
1702    let start = r.bit_pos();
1703    let mut out = Vec::with_capacity(max);
1704    for _ in 0..max {
1705        match r.read_bits(8) {
1706            Ok(b) => out.push(b as u8),
1707            Err(_) => break, // end of input — a shorter magic may still match
1708        }
1709    }
1710    r.seek_to_bit(start)?;
1711    Ok(out)
1712}
1713
1714/// Writes a fixed `[u8; N]` byte array. Backs a `[u8; N]` payload field.
1715///
1716/// # Errors
1717/// Propagates the sink's [`BitError`].
1718#[doc(hidden)]
1719pub fn write_byte_array<const N: usize, K: Sink>(arr: &[u8; N], w: &mut K) -> Result<(), BitError> {
1720    for &b in arr {
1721        w.write_bits(u128::from(b), 8)?;
1722    }
1723    Ok(())
1724}
1725
1726/// A *forward-only* bit reader over any [`std::io::Read`] — the streaming counterpart
1727/// to the in-memory [`BitReader`], for a stream you read once and don't seek.
1728///
1729/// It is bounded on `Read` **only, not `Seek`**, so it works over inputs that can't
1730/// seek (a socket, or a `&[u8]`, which is `Read` but not `Seek`). A message that needs
1731/// to seek (`#[br(restore_position)]`) won't decode through it — use a [`BufSource`] or
1732/// [`SeekReader`] for that. Reads up to 128 bits per call (the [`Source`] width
1733/// ceiling); running out mid-message yields [`ErrorKind::Incomplete`] ("read more and
1734/// retry").
1735///
1736/// # Examples
1737///
1738/// ```
1739/// use bnb::{bin, StreamBitReader};
1740///
1741/// #[bin(big)]
1742/// #[derive(Debug, PartialEq)]
1743/// struct Word { value: u32 }
1744///
1745/// // `&[u8]` is `Read` but not `Seek` — exactly the forward-only case.
1746/// let data: &[u8] = &[0x12, 0x34, 0x56, 0x78];
1747/// let mut s = StreamBitReader::new(data);
1748/// assert_eq!(Word::decode(&mut s).unwrap(), Word { value: 0x1234_5678 });
1749/// ```
1750#[cfg(feature = "std")]
1751#[derive(Debug)]
1752pub struct StreamBitReader<R> {
1753    inner: R,
1754    /// Leftover bits from the last partially-consumed byte, right-aligned in the low
1755    /// `lead_bits` bits. Always fewer than 8. Consumed high-first under `Msb`, low-first
1756    /// under `Lsb`.
1757    lead: u32,
1758    lead_bits: u32,
1759    /// Total bits consumed so far (for position-aware errors).
1760    pos: usize,
1761    /// The bit/byte order this source decodes in. `read_bits` honors the **bit** order
1762    /// (like every other `Source`); **byte** order is applied to whole values by
1763    /// [`read`](Self::read) / `Source::read`.
1764    layout: Layout,
1765}
1766
1767#[cfg(feature = "std")]
1768impl<R: std::io::Read> StreamBitReader<R> {
1769    /// Wraps a byte source, decoding in the default **MSB-first, big-endian** order. For a
1770    /// `#[bin(little)]`/`bits = lsb` message, use [`with_layout`](Self::with_layout) with
1771    /// that type's [`LAYOUT`](BitEncode::LAYOUT), or the decode reads the wrong order.
1772    pub fn new(inner: R) -> Self {
1773        Self::with_layout(inner, Layout::default())
1774    }
1775
1776    /// Wraps a byte source, decoding in the given [`Layout`] (bit + byte order) — pass a
1777    /// message's `LAYOUT` so a non-default-order `#[bin]` type round-trips over a stream.
1778    pub fn with_layout(inner: R, layout: Layout) -> Self {
1779        Self {
1780            inner,
1781            lead: 0,
1782            lead_bits: 0,
1783            pos: 0,
1784            layout,
1785        }
1786    }
1787
1788    /// The total number of bits consumed so far.
1789    #[must_use]
1790    pub fn bit_pos(&self) -> usize {
1791        self.pos
1792    }
1793
1794    /// Reads `n` (`<= 128`) bits in the source's [bit order](Layout), pulling bytes from
1795    /// the source as needed. This matches every other [`Source`]: byte order is applied to
1796    /// whole values by [`read`](Self::read) / `Source::read`, not here.
1797    ///
1798    /// # Errors
1799    /// [`ErrorKind::TooWide`] if `n > 128`; [`ErrorKind::Incomplete`] if the
1800    /// source runs out mid-field (read more and retry). Either carries the bit
1801    /// offset.
1802    pub fn read_bits(&mut self, n: u32) -> Result<u128, BitError> {
1803        if n > 128 {
1804            return Err(BitError::new(
1805                ErrorKind::TooWide { width: n as usize },
1806                self.pos,
1807            ));
1808        }
1809        let at = self.pos;
1810        // Consume the leftover bits of the current byte, then whole bytes, honoring the
1811        // source's bit order so a streaming read matches the slice-backed sources exactly
1812        // (`extract_bits`). The accumulator never holds more than `n` (<= 128) bits, so it
1813        // can't overflow.
1814        let mut result: u128 = 0;
1815        let mut need = n;
1816        let mut placed = 0u32; // bits already placed (the LSB-path result cursor)
1817        while need > 0 {
1818            if self.lead_bits == 0 {
1819                let mut b = [0u8; 1];
1820                if self.inner.read_exact(&mut b).is_err() {
1821                    // Ran out mid-field: "need more bytes" (buffer and retry), not a
1822                    // definitive end-of-input.
1823                    return Err(BitError::new(ErrorKind::Incomplete { needed: None }, at));
1824                }
1825                self.lead = u32::from(b[0]);
1826                self.lead_bits = 8;
1827            }
1828            let take = need.min(self.lead_bits);
1829            match self.layout.bit {
1830                // MSB-first: consume the *high* `take` bits, accumulate high-to-low.
1831                BitOrder::Msb => {
1832                    let shift = self.lead_bits - take;
1833                    let chunk = (self.lead >> shift) & ((1u32 << take) - 1);
1834                    result = (result << take) | u128::from(chunk);
1835                    self.lead_bits -= take;
1836                    self.lead &= (1u32 << self.lead_bits) - 1; // keep the unconsumed low bits
1837                }
1838                // LSB-first: consume the *low* `take` bits, place them at the bit cursor.
1839                BitOrder::Lsb => {
1840                    let chunk = self.lead & ((1u32 << take) - 1);
1841                    result |= u128::from(chunk) << placed;
1842                    self.lead >>= take; // drop the consumed low bits
1843                    self.lead_bits -= take;
1844                }
1845            }
1846            placed += take;
1847            need -= take;
1848        }
1849        self.pos += n as usize;
1850        Ok(result)
1851    }
1852
1853    /// Reads one [`Bits`] value (width `<= 128`) of its declared width, applying the
1854    /// source's byte order to whole values — matching [`BitReader::read`] and
1855    /// `Source::read`, so `sr.read::<T>()` agrees with `T::decode(&mut sr)`.
1856    ///
1857    /// # Errors
1858    /// As [`read_bits`](Self::read_bits).
1859    pub fn read<T: Bits>(&mut self) -> Result<T, BitError> {
1860        let raw = self.read_bits(T::BITS)?;
1861        Ok(T::from_bits(apply_byte_order(
1862            raw,
1863            T::BITS,
1864            self.layout.bit,
1865            self.layout.byte,
1866        )))
1867    }
1868}
1869
1870#[cfg(feature = "std")]
1871impl<R: std::io::Read> sealed::Sealed for StreamBitReader<R> {}
1872
1873#[cfg(feature = "std")]
1874impl<R: std::io::Read> Source for StreamBitReader<R> {
1875    fn read_bits(&mut self, n: u32) -> Result<u128, BitError> {
1876        StreamBitReader::read_bits(self, n)
1877    }
1878    fn bit_pos(&self) -> usize {
1879        self.pos
1880    }
1881    fn byte_order(&self) -> ByteOrder {
1882        self.layout.byte
1883    }
1884    fn bit_order(&self) -> BitOrder {
1885        self.layout.bit
1886    }
1887}
1888
1889/// A **seekable** [`Source`] over a forward `Read` (a socket): it *retains* the bytes
1890/// it has read, so a seek-using message (`restore_position`) works over a non-seekable
1891/// stream by seeking within the retained buffer, reading more on demand. It is
1892/// **bounded** — a retention `cap` (default 64 KiB) past which it errors
1893/// [`ErrorKind::BufferFull`] rather than buffering unboundedly. The
1894/// "continuously-receiving peer that also needs to seek" case.
1895///
1896/// # Examples
1897///
1898/// ```
1899/// use bnb::{bin, BufSource};
1900///
1901/// #[bin(big)]
1902/// #[derive(Debug, PartialEq)]
1903/// struct Word { value: u32 }
1904///
1905/// let mut src = BufSource::new(&[0x12, 0x34, 0x56, 0x78][..]); // any `Read`
1906/// assert_eq!(Word::decode(&mut src).unwrap(), Word { value: 0x1234_5678 });
1907/// ```
1908#[cfg(feature = "std")]
1909#[derive(Clone, Debug)]
1910pub struct BufSource<R> {
1911    inner: R,
1912    buf: Vec<u8>,
1913    bit_pos: usize,
1914    cap: usize,
1915    layout: Layout,
1916    eof: bool,
1917}
1918
1919#[cfg(feature = "std")]
1920impl<R: std::io::Read> BufSource<R> {
1921    /// Wraps `inner` with the default 64 KiB retention cap, MSB-first big-endian.
1922    #[must_use]
1923    pub fn new(inner: R) -> Self {
1924        Self::with_capacity(inner, 64 * 1024)
1925    }
1926
1927    /// Wraps `inner` with a retention `cap` (bytes), MSB-first big-endian.
1928    #[must_use]
1929    pub fn with_capacity(inner: R, cap: usize) -> Self {
1930        Self::with_capacity_and_layout(inner, cap, Layout::default())
1931    }
1932
1933    /// Wraps `inner` with a retention `cap` (bytes) and [`Layout`].
1934    #[must_use]
1935    pub fn with_capacity_and_layout(inner: R, cap: usize, layout: Layout) -> Self {
1936        Self {
1937            inner,
1938            buf: Vec::new(),
1939            bit_pos: 0,
1940            cap,
1941            layout,
1942            eof: false,
1943        }
1944    }
1945
1946    /// Reads from `inner` until `buf` holds at least `byte_end` bytes (or EOF/cap).
1947    fn fill_to(&mut self, byte_end: usize) -> Result<(), BitError> {
1948        while self.buf.len() < byte_end && !self.eof {
1949            if self.buf.len() >= self.cap {
1950                return Err(BitError::new(
1951                    ErrorKind::BufferFull { cap: self.cap },
1952                    self.bit_pos,
1953                ));
1954            }
1955            let want = (byte_end - self.buf.len()).min(self.cap - self.buf.len());
1956            let start = self.buf.len();
1957            self.buf.resize(start + want, 0);
1958            match self.inner.read(&mut self.buf[start..]) {
1959                Ok(0) => {
1960                    self.buf.truncate(start);
1961                    self.eof = true;
1962                }
1963                Ok(got) => self.buf.truncate(start + got),
1964                Err(e) => {
1965                    self.buf.truncate(start);
1966                    return Err(BitError::new(ErrorKind::Io(e.kind()), self.bit_pos));
1967                }
1968            }
1969        }
1970        Ok(())
1971    }
1972}
1973
1974#[cfg(feature = "std")]
1975impl<R: std::io::Read> sealed::Sealed for BufSource<R> {}
1976
1977#[cfg(feature = "std")]
1978impl<R: std::io::Read> Source for BufSource<R> {
1979    fn read_bits(&mut self, n: u32) -> Result<u128, BitError> {
1980        if n > 128 {
1981            return Err(BitError::new(
1982                ErrorKind::TooWide { width: n as usize },
1983                self.bit_pos,
1984            ));
1985        }
1986        let byte_end = (self.bit_pos + n as usize).div_ceil(8);
1987        self.fill_to(byte_end)?;
1988        if self.buf.len() < byte_end {
1989            return Err(BitError::new(
1990                ErrorKind::Incomplete {
1991                    needed: Some(byte_end - self.buf.len()),
1992                },
1993                self.bit_pos,
1994            ));
1995        }
1996        let acc = extract_bits(&self.buf, self.bit_pos, n as usize, self.layout.bit);
1997        self.bit_pos += n as usize;
1998        Ok(acc)
1999    }
2000    fn bit_pos(&self) -> usize {
2001        self.bit_pos
2002    }
2003    fn byte_order(&self) -> ByteOrder {
2004        self.layout.byte
2005    }
2006    fn bit_order(&self) -> BitOrder {
2007        self.layout.bit
2008    }
2009    fn seek_to_bit(&mut self, pos: usize) -> Result<(), BitError> {
2010        // Seek within the retained buffer; a later read fills more on demand.
2011        // Backward seeks (`restore_position`) hit already-retained bytes.
2012        self.bit_pos = pos;
2013        Ok(())
2014    }
2015}
2016
2017#[cfg(feature = "std")]
2018impl<R: std::io::Read> SeekSource for BufSource<R> {}
2019
2020/// A **push/pull, bit-aware** decode buffer for incremental framing.
2021///
2022/// Feed bytes with [`push`](Self::push) as they arrive — from a socket, a channel, a callback,
2023/// anything that delivers bytes — and take whole messages off the front with [`pull`](Self::pull),
2024/// which returns `Ok(None)` when it needs more bytes (push more and call again).
2025///
2026/// Unlike a byte cursor (`bytes::BytesMut::advance`), `BitBuf` tracks a **bit** position, so a
2027/// stream of messages that *don't* end on byte boundaries (bit-packed frames) reassembles cleanly:
2028/// `pull` advances past the consumed whole bytes and retains any partial trailing byte for the
2029/// next message. It's the *pushable*, in-memory counterpart to [`BufSource`] (which pulls from a
2030/// `Read`). `no_std`-compatible (`alloc` only).
2031///
2032/// **Reclaim is deferred and in place.** `pull` doesn't drain consumed bytes — the next
2033/// [`push`](Self::push)/[`try_push`](Self::try_push) reclaims them in place (one memmove, only when
2034/// it avoids a reallocation), so a steady push/pull loop reuses the same allocation without
2035/// per-message churn. For a guaranteed-fixed footprint (real-time / `no_std`), construct a
2036/// [`bounded`](Self::bounded) buffer: it allocates once, [`try_push`](Self::try_push) refuses bytes
2037/// past the cap instead of growing, and [`grow`](Self::grow) is the only thing that reallocates.
2038///
2039/// `BitBuf` is also a [`SeekSource`], so it reads through the same [`decode`](crate::BitDecode)
2040/// entry points as every other cursor: `Type::decode(&mut bitbuf)` advances its cursor (then call
2041/// [`compact`](Self::compact) to reclaim). For streaming, prefer [`pull`](Self::pull) — it bakes
2042/// the message's own [`LAYOUT`](BitEncode::LAYOUT) (so `little`/`lsb` messages are always correct),
2043/// decodes **and** reclaims, and reports "need more bytes" as `Ok(None)`. The bare `Source` path
2044/// instead uses the buffer's own [`with_layout`](Self::with_layout) order (default msb/big).
2045///
2046/// ```
2047/// use bnb::{bin, BitBuf};
2048/// #[bin(big)]
2049/// #[derive(Debug, PartialEq, Eq)]
2050/// struct Ping { seq: u16 }
2051///
2052/// let mut bb = BitBuf::new();
2053/// bb.push(&[0x00]);                                  // only half of the first message
2054/// assert_eq!(bb.pull::<Ping>().unwrap(), None);      // not a whole message yet
2055/// bb.push(&[0x01, 0x00, 0x02]);                      // rest of msg 1 + all of msg 2
2056/// assert_eq!(bb.pull::<Ping>().unwrap(), Some(Ping { seq: 1 }));
2057/// assert_eq!(bb.pull::<Ping>().unwrap(), Some(Ping { seq: 2 }));
2058/// assert_eq!(bb.pull::<Ping>().unwrap(), None);      // drained
2059/// ```
2060///
2061#[derive(Debug, Default, Clone)]
2062pub struct BitBuf {
2063    /// Buffered bytes. The bytes before `cursor`'s byte are **consumed** (dead) — physically
2064    /// reclaimed lazily (on a [`push`](Self::push) that would otherwise grow, or [`compact`](Self::compact)),
2065    /// not on every [`pull`](Self::pull), so a push/pull loop doesn't churn memory.
2066    buf: Vec<u8>,
2067    /// Live read position, in bits, into `buf` (`0..=buf.len() * 8`).
2068    cursor: usize,
2069    /// `Some(cap)` for a **bounded** buffer (alloc-once: [`try_push`](Self::try_push) never grows
2070    /// past `cap`, [`grow`](Self::grow) raises it explicitly); `None` for an auto-growing buffer.
2071    cap: Option<usize>,
2072    /// Byte/bit order for the [`Source`] impl (the `decode(&mut bitbuf)` path); default msb/big.
2073    layout: Layout,
2074}
2075
2076impl BitBuf {
2077    /// An empty auto-growing buffer (msb/big order for the [`Source`] path).
2078    #[must_use]
2079    pub fn new() -> Self {
2080        Self::default()
2081    }
2082
2083    /// An empty auto-growing buffer with room for `cap` bytes before reallocating. Like
2084    /// [`new`](Self::new) but pre-reserved; it still grows past `cap` on demand (use
2085    /// [`bounded`](Self::bounded) for a hard cap).
2086    #[must_use]
2087    pub fn with_capacity(cap: usize) -> Self {
2088        Self {
2089            buf: Vec::with_capacity(cap),
2090            cursor: 0,
2091            cap: None,
2092            layout: Layout::default(),
2093        }
2094    }
2095
2096    /// An empty **bounded** buffer: it allocates `cap` bytes once and never reallocates on its own.
2097    /// [`try_push`](Self::try_push) refuses bytes that would exceed `cap` (reclaiming consumed
2098    /// bytes first), and [`grow`](Self::grow) is the only thing that allocates again — so a
2099    /// real-time / `no_std` caller can guarantee a fixed footprint.
2100    #[must_use]
2101    pub fn bounded(cap: usize) -> Self {
2102        Self {
2103            buf: Vec::with_capacity(cap),
2104            cursor: 0,
2105            cap: Some(cap),
2106            layout: Layout::default(),
2107        }
2108    }
2109
2110    /// Set the byte/bit order used by the [`Source`] impl (the `decode(&mut bitbuf)` path).
2111    /// [`pull`](Self::pull) ignores this — it always bakes the message's own `LAYOUT`.
2112    #[must_use]
2113    pub fn with_layout(mut self, layout: Layout) -> Self {
2114        self.layout = layout;
2115        self
2116    }
2117
2118    /// The buffer's hard capacity in bytes for a [`bounded`](Self::bounded) buffer, or `None` if
2119    /// it auto-grows.
2120    #[must_use]
2121    pub fn capacity(&self) -> Option<usize> {
2122        self.cap
2123    }
2124
2125    /// Reclaim consumed whole bytes (drain everything before the cursor's byte) when doing so
2126    /// avoids a reallocation or the dead prefix has grown to dominate the live bytes. Keeps the
2127    /// footprint near the working set without compacting on every push.
2128    fn make_room(&mut self, additional: usize) {
2129        let dead = self.cursor / 8;
2130        if dead == 0 {
2131            return;
2132        }
2133        let live = self.buf.len() - dead;
2134        let would_grow = self.buf.len() + additional > self.buf.capacity();
2135        if would_grow || dead >= live {
2136            self.buf.drain(..dead);
2137            self.cursor -= dead * 8;
2138        }
2139    }
2140
2141    /// Append freshly-received bytes to the back of the buffer, growing (reallocating) if needed.
2142    /// Consumed bytes are reclaimed in place first when that avoids a reallocation. For a hard,
2143    /// alloc-free cap, use [`bounded`](Self::bounded) + [`try_push`](Self::try_push).
2144    pub fn push(&mut self, bytes: &[u8]) {
2145        self.make_room(bytes.len());
2146        self.buf.extend_from_slice(bytes);
2147    }
2148
2149    /// Append bytes **without reallocating**, reclaiming consumed bytes in place to make room.
2150    ///
2151    /// # Errors
2152    /// [`CapacityError`] if the bytes don't fit a [`bounded`](Self::bounded) buffer's capacity
2153    /// (the live bytes plus the new bytes exceed `cap`). On an unbounded buffer it always
2154    /// succeeds (growing if needed), so prefer [`push`](Self::push) there.
2155    pub fn try_push(&mut self, bytes: &[u8]) -> Result<(), CapacityError> {
2156        let live = self.buf.len() - self.cursor / 8;
2157        if let Some(cap) = self.cap {
2158            if live + bytes.len() > cap {
2159                return Err(CapacityError {
2160                    cap,
2161                    requested: live + bytes.len(),
2162                });
2163            }
2164        }
2165        self.make_room(bytes.len());
2166        self.buf.extend_from_slice(bytes);
2167        Ok(())
2168    }
2169
2170    /// Grow a [`bounded`](Self::bounded) buffer's capacity by `additional` bytes (raising the cap
2171    /// and reserving the space — the one operation that reallocates a bounded buffer). On an
2172    /// unbounded buffer it just reserves.
2173    pub fn grow(&mut self, additional: usize) {
2174        if let Some(cap) = &mut self.cap {
2175            *cap += additional;
2176        }
2177        self.buf.reserve(additional);
2178    }
2179
2180    /// The number of unconsumed bits currently buffered.
2181    #[must_use]
2182    pub fn bit_len(&self) -> usize {
2183        self.buf.len() * 8 - self.cursor
2184    }
2185
2186    /// Whether no unconsumed bits remain.
2187    #[must_use]
2188    pub fn is_empty(&self) -> bool {
2189        self.bit_len() == 0
2190    }
2191
2192    /// Drop all buffered bytes and reset the cursor (keeps the allocation and any bound).
2193    pub fn clear(&mut self) {
2194        self.buf.clear();
2195        self.cursor = 0;
2196    }
2197
2198    /// Physically reclaim the fully-consumed whole bytes now (drop everything before the cursor's
2199    /// byte), keeping any partial trailing byte. [`pull`](Self::pull) defers this; call it
2200    /// yourself when consuming via the [`Source`] path (`decode(&mut bitbuf)`) to bound the buffer.
2201    pub fn compact(&mut self) {
2202        let whole = self.cursor / 8;
2203        self.buf.drain(..whole);
2204        self.cursor -= whole * 8;
2205    }
2206
2207    /// Decode the next complete message off the front, advancing past the bytes it consumed.
2208    ///
2209    /// Returns `Ok(None)` when the buffer doesn't yet hold a whole message — push more bytes and
2210    /// call again; the cursor is left untouched, so the retry is free. A malformed message is an
2211    /// `Err`. The byte/bit order is taken from `T`'s [`LAYOUT`](BitEncode::LAYOUT), so it decodes
2212    /// `little`/`lsb` messages correctly regardless of [`with_layout`](Self::with_layout).
2213    ///
2214    /// Consumed bytes are **not** drained here — they are reclaimed in place by the next
2215    /// [`push`](Self::push)/[`try_push`](Self::try_push) (or an explicit [`compact`](Self::compact)),
2216    /// so a steady push/pull loop reuses the same allocation without per-message memmoves.
2217    ///
2218    /// # Errors
2219    /// A codec [`BitError`] for a malformed message.
2220    pub fn pull<T: BitDecode + BitEncode>(&mut self) -> Result<Option<T>, BitError> {
2221        if self.cursor >= self.buf.len() * 8 {
2222            return Ok(None);
2223        }
2224        let mut r = BitReader::with_layout(&self.buf, <T as BitEncode>::LAYOUT);
2225        r.seek_to_bit(self.cursor)?;
2226        match T::bit_decode(&mut r) {
2227            Ok(msg) => {
2228                self.cursor = r.bit_pos(); // advance past the message; reclaim is deferred
2229                Ok(Some(msg))
2230            }
2231            // Only a partial message is buffered — wait for more (cursor untouched, retry-safe).
2232            Err(e)
2233                if matches!(
2234                    e.kind,
2235                    ErrorKind::UnexpectedEof { .. } | ErrorKind::Incomplete { .. }
2236                ) =>
2237            {
2238                Ok(None)
2239            }
2240            Err(e) => Err(e),
2241        }
2242    }
2243}
2244
2245/// The error [`BitBuf::try_push`] returns when bytes won't fit a [`bounded`](BitBuf::bounded)
2246/// buffer — the live (unconsumed) bytes plus the new bytes exceed its fixed `cap`. Grow it with
2247/// [`BitBuf::grow`], or drain messages with [`pull`](BitBuf::pull) before pushing more.
2248#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2249#[non_exhaustive]
2250pub struct CapacityError {
2251    /// The buffer's fixed capacity, in bytes.
2252    pub cap: usize,
2253    /// The bytes that were needed (live bytes + the rejected push).
2254    pub requested: usize,
2255}
2256
2257impl fmt::Display for CapacityError {
2258    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2259        write!(
2260            f,
2261            "bitbuf is full: {} bytes needed exceeds the {}-byte capacity",
2262            self.requested, self.cap
2263        )
2264    }
2265}
2266
2267impl core::error::Error for CapacityError {}
2268
2269impl sealed::Sealed for BitBuf {}
2270
2271impl Source for BitBuf {
2272    fn read_bits(&mut self, n: u32) -> Result<u128, BitError> {
2273        let mut r = BitReader::with_layout(&self.buf, self.layout);
2274        r.seek_to_bit(self.cursor)?;
2275        let v = r.read_bits(n)?;
2276        self.cursor = r.bit_pos();
2277        Ok(v)
2278    }
2279
2280    fn bit_pos(&self) -> usize {
2281        self.cursor
2282    }
2283
2284    fn byte_order(&self) -> ByteOrder {
2285        self.layout.byte
2286    }
2287    fn bit_order(&self) -> BitOrder {
2288        self.layout.bit
2289    }
2290
2291    fn seek_to_bit(&mut self, pos: usize) -> Result<(), BitError> {
2292        // Validate against the buffered bits (mirrors BitReader's bounds), then move the cursor.
2293        let mut probe = BitReader::with_layout(&self.buf, self.layout);
2294        probe.seek_to_bit(pos)?;
2295        self.cursor = pos;
2296        Ok(())
2297    }
2298}
2299
2300impl SeekSource for BitBuf {}
2301
2302/// A [`SeekSource`] over a seekable reader (`Read + Seek`, e.g. a `File`): it seeks
2303/// via [`std::io::Seek`] to the byte holding the bit cursor, **without buffering** —
2304/// the large-file / container-format case. For a *non*-seekable stream that still
2305/// needs to seek, use [`BufSource`].
2306///
2307/// # Examples
2308///
2309/// ```
2310/// use bnb::{bin, SeekReader};
2311/// use std::io::Cursor;
2312///
2313/// #[bin(big)]
2314/// #[derive(Debug, PartialEq)]
2315/// struct Word { value: u32 }
2316///
2317/// let mut f = SeekReader::new(Cursor::new(vec![0x12u8, 0x34, 0x56, 0x78]));
2318/// assert_eq!(Word::decode(&mut f).unwrap(), Word { value: 0x1234_5678 });
2319/// ```
2320#[cfg(feature = "std")]
2321#[derive(Clone, Debug)]
2322pub struct SeekReader<R> {
2323    inner: R,
2324    bit_pos: usize,
2325    layout: Layout,
2326}
2327
2328#[cfg(feature = "std")]
2329impl<R: std::io::Read + std::io::Seek> SeekReader<R> {
2330    /// Wraps `inner` at bit 0, MSB-first big-endian.
2331    #[must_use]
2332    pub fn new(inner: R) -> Self {
2333        Self::with_layout(inner, Layout::default())
2334    }
2335
2336    /// Wraps `inner` at bit 0 with the given [`Layout`].
2337    #[must_use]
2338    pub fn with_layout(inner: R, layout: Layout) -> Self {
2339        Self {
2340            inner,
2341            bit_pos: 0,
2342            layout,
2343        }
2344    }
2345}
2346
2347#[cfg(feature = "std")]
2348impl<R: std::io::Read + std::io::Seek> sealed::Sealed for SeekReader<R> {}
2349
2350#[cfg(feature = "std")]
2351impl<R: std::io::Read + std::io::Seek> Source for SeekReader<R> {
2352    fn read_bits(&mut self, n: u32) -> Result<u128, BitError> {
2353        if n > 128 {
2354            return Err(BitError::new(
2355                ErrorKind::TooWide { width: n as usize },
2356                self.bit_pos,
2357            ));
2358        }
2359        let bit_off = self.bit_pos % 8;
2360        let byte_start = (self.bit_pos / 8) as u64;
2361        let nbytes = (bit_off + n as usize).div_ceil(8);
2362        self.inner
2363            .seek(std::io::SeekFrom::Start(byte_start))
2364            .map_err(|e| BitError::new(ErrorKind::Io(e.kind()), self.bit_pos))?;
2365        let mut buf = vec![0u8; nbytes];
2366        self.inner.read_exact(&mut buf).map_err(|e| {
2367            let kind = if e.kind() == std::io::ErrorKind::UnexpectedEof {
2368                ErrorKind::UnexpectedEof {
2369                    needed: n as usize,
2370                    remaining: 0,
2371                }
2372            } else {
2373                ErrorKind::Io(e.kind())
2374            };
2375            BitError::new(kind, self.bit_pos)
2376        })?;
2377        let acc = extract_bits(&buf, bit_off, n as usize, self.layout.bit);
2378        self.bit_pos += n as usize;
2379        Ok(acc)
2380    }
2381    fn bit_pos(&self) -> usize {
2382        self.bit_pos
2383    }
2384    fn byte_order(&self) -> ByteOrder {
2385        self.layout.byte
2386    }
2387    fn bit_order(&self) -> BitOrder {
2388        self.layout.bit
2389    }
2390    fn seek_to_bit(&mut self, pos: usize) -> Result<(), BitError> {
2391        self.bit_pos = pos; // the actual `io::Seek` happens on the next read
2392        Ok(())
2393    }
2394}
2395
2396#[cfg(feature = "std")]
2397impl<R: std::io::Read + std::io::Seek> SeekSource for SeekReader<R> {}
2398
2399/// Zero-copy `bytes`-crate adapters (the `bytes` feature): own a `Bytes` frame to
2400/// decode, encode into a `BytesMut` you `freeze()` to a `Bytes` — the async/tokio
2401/// framing case. Off by default so the core stays dependency-light.
2402#[cfg(feature = "bytes")]
2403mod bytes_io {
2404    use super::{
2405        BitError, BitOrder, BitReader, BitWriter, ByteOrder, Layout, SeekSource, Sink, Source,
2406    };
2407
2408    /// A [`SeekSource`](super::SeekSource) that **owns** a `bytes::Bytes` frame (no
2409    /// borrow), decoding bits from it. Constructing it from a `Bytes` is a refcount
2410    /// bump (zero copy).
2411    #[derive(Clone, Debug)]
2412    pub struct BytesReader {
2413        data: bytes::Bytes,
2414        bit_pos: usize,
2415        layout: Layout,
2416    }
2417
2418    impl BytesReader {
2419        /// Owns `data`, positioned at bit 0, MSB-first big-endian.
2420        #[must_use]
2421        pub fn new(data: bytes::Bytes) -> Self {
2422            Self::with_layout(data, Layout::default())
2423        }
2424
2425        /// Owns `data` with the given [`Layout`](super::Layout).
2426        #[must_use]
2427        pub fn with_layout(data: bytes::Bytes, layout: Layout) -> Self {
2428            Self {
2429                data,
2430                bit_pos: 0,
2431                layout,
2432            }
2433        }
2434    }
2435
2436    impl super::sealed::Sealed for BytesReader {}
2437
2438    impl Source for BytesReader {
2439        fn read_bits(&mut self, n: u32) -> Result<u128, BitError> {
2440            let mut br = BitReader::with_layout(&self.data, self.layout);
2441            br.seek_to_bit(self.bit_pos)?;
2442            let v = br.read_bits(n)?;
2443            self.bit_pos = Source::bit_pos(&br);
2444            Ok(v)
2445        }
2446        fn bit_pos(&self) -> usize {
2447            self.bit_pos
2448        }
2449        fn byte_order(&self) -> ByteOrder {
2450            self.layout.byte
2451        }
2452        fn bit_order(&self) -> BitOrder {
2453            self.layout.bit
2454        }
2455        fn seek_to_bit(&mut self, pos: usize) -> Result<(), BitError> {
2456            self.bit_pos = pos;
2457            Ok(())
2458        }
2459    }
2460
2461    impl SeekSource for BytesReader {}
2462
2463    /// A [`Sink`](super::Sink) that encodes into a `bytes::BytesMut`; [`freeze`]
2464    /// hands off a zero-copy `Bytes`.
2465    ///
2466    /// [`freeze`]: BytesWriter::freeze
2467    #[derive(Clone, Debug, Default)]
2468    pub struct BytesWriter {
2469        inner: BitWriter,
2470    }
2471
2472    impl BytesWriter {
2473        /// An empty MSB-first, big-endian writer.
2474        #[must_use]
2475        pub fn new() -> Self {
2476            Self::default()
2477        }
2478
2479        /// An empty writer in the given [`Layout`](super::Layout).
2480        #[must_use]
2481        pub fn with_layout(layout: Layout) -> Self {
2482            Self {
2483                inner: BitWriter::with_layout(layout),
2484            }
2485        }
2486
2487        /// The encoded bytes as a zero-copy `Bytes` (the final partial byte is
2488        /// zero-padded).
2489        #[must_use]
2490        pub fn freeze(self) -> bytes::Bytes {
2491            bytes::Bytes::from(self.inner.into_bytes())
2492        }
2493    }
2494
2495    impl super::sealed::Sealed for BytesWriter {}
2496
2497    impl Sink for BytesWriter {
2498        fn write_bits(&mut self, value: u128, n: u32) -> Result<(), BitError> {
2499            self.inner.write_bits(value, n)
2500        }
2501        fn bit_pos(&self) -> usize {
2502            Sink::bit_pos(&self.inner)
2503        }
2504        fn byte_order(&self) -> ByteOrder {
2505            Sink::byte_order(&self.inner)
2506        }
2507        fn bit_order(&self) -> BitOrder {
2508            Sink::bit_order(&self.inner)
2509        }
2510    }
2511}
2512
2513#[cfg(feature = "bytes")]
2514pub use bytes_io::{BytesReader, BytesWriter};
2515
2516#[cfg(test)]
2517mod unit {
2518    use super::*;
2519    use crate::{u4, u12};
2520
2521    #[test]
2522    fn unaligned_round_trip() {
2523        let mut w = BitWriter::new();
2524        w.write(u4::new(0xA)).unwrap();
2525        w.write(u12::new(0xBCD)).unwrap();
2526        assert_eq!(w.bit_len(), 16);
2527        let bytes = w.into_bytes();
2528        assert_eq!(bytes, [0xAB, 0xCD]);
2529
2530        let mut r = BitReader::new(&bytes);
2531        assert_eq!(r.read::<u4>().unwrap(), u4::new(0xA));
2532        assert_eq!(r.read::<u12>().unwrap(), u12::new(0xBCD));
2533        assert_eq!(r.remaining_bits(), 0);
2534    }
2535
2536    #[test]
2537    fn eof_is_an_error_not_a_panic() {
2538        let mut r = BitReader::new(&[0xFF]);
2539        assert_eq!(r.read::<u4>().unwrap(), u4::new(0xF));
2540        let err = r.read_bits(8).unwrap_err();
2541        assert_eq!(
2542            err.kind,
2543            ErrorKind::UnexpectedEof {
2544                needed: 8,
2545                remaining: 4
2546            }
2547        );
2548        assert_eq!(err.at, 4, "error records the bit offset");
2549        assert!(err.field.is_none(), "no field context at the reader level");
2550    }
2551
2552    #[test]
2553    fn too_wide_is_rejected() {
2554        let mut r = BitReader::new(&[0u8; 32]);
2555        let err = r.read_bits(129).unwrap_err();
2556        assert_eq!(err.kind, ErrorKind::TooWide { width: 129 });
2557    }
2558
2559    #[test]
2560    fn stream_reader_matches_slice_up_to_128_bits() {
2561        // The `Source` contract allows reads up to 128 bits; the forward streaming
2562        // reader must agree with the slice reader across the whole range, including
2563        // wide (> 64-bit) and byte-straddling reads.
2564        let bytes: Vec<u8> = (0u8..16).collect(); // 0x00 01 02 … 0F
2565
2566        // A single 128-bit read.
2567        let mut s = StreamBitReader::new(&bytes[..]);
2568        let mut r = BitReader::new(&bytes);
2569        assert_eq!(s.read_bits(128).unwrap(), r.read_bits(128).unwrap());
2570
2571        // A 100-bit then 28-bit split (each crosses byte boundaries and the second
2572        // starts mid-byte, exercising the leftover-bits path).
2573        let mut s = StreamBitReader::new(&bytes[..]);
2574        let mut r = BitReader::new(&bytes);
2575        assert_eq!(s.read_bits(100).unwrap(), r.read_bits(100).unwrap());
2576        assert_eq!(s.read_bits(28).unwrap(), r.read_bits(28).unwrap());
2577
2578        // Over-wide is rejected at 128 now, not 64.
2579        let mut s = StreamBitReader::new(&bytes[..]);
2580        assert_eq!(
2581            s.read_bits(65).unwrap(),
2582            BitReader::new(&bytes).read_bits(65).unwrap(),
2583            "a 65-bit read used to be rejected"
2584        );
2585        let mut s = StreamBitReader::new(&bytes[..]);
2586        assert_eq!(
2587            s.read_bits(129).unwrap_err().kind,
2588            ErrorKind::TooWide { width: 129 }
2589        );
2590    }
2591
2592    #[test]
2593    fn stream_reader_honors_every_layout() {
2594        // The streaming reader must agree with the slice reader in *all four* bit/byte
2595        // orders — not just the default `Msb`/`Big`. (An earlier `read_bits` hardcoded
2596        // MSB-first extraction, so `Lsb` layouts decoded wrong here alone; and the
2597        // inherent `read` skipped byte order, so it disagreed with `T::decode`.)
2598        let bytes: Vec<u8> = (0u8..16).collect();
2599        for bit in [BitOrder::Msb, BitOrder::Lsb] {
2600            for byte in [ByteOrder::Big, ByteOrder::Little] {
2601                let layout = Layout { bit, byte };
2602
2603                // `read_bits` parity across widths + a mid-byte split (byte-aligned and not).
2604                let mut s = StreamBitReader::with_layout(&bytes[..], layout);
2605                let mut r = BitReader::with_layout(&bytes, layout);
2606                for n in [12u32, 20, 96] {
2607                    assert_eq!(
2608                        s.read_bits(n).unwrap(),
2609                        r.read_bits(n).unwrap(),
2610                        "read_bits({n}) diverged for {bit:?}/{byte:?}"
2611                    );
2612                }
2613
2614                // The inherent `read` must apply byte order, matching the slice reader's
2615                // typed read (and therefore `T::decode`).
2616                let mut s = StreamBitReader::with_layout(&bytes[..], layout);
2617                let mut r = BitReader::with_layout(&bytes, layout);
2618                assert_eq!(
2619                    s.read::<u16>().unwrap(),
2620                    r.read::<u16>().unwrap(),
2621                    "read::<u16> diverged for {bit:?}/{byte:?}"
2622                );
2623                assert_eq!(
2624                    s.read::<u32>().unwrap(),
2625                    r.read::<u32>().unwrap(),
2626                    "read::<u32> diverged for {bit:?}/{byte:?}"
2627                );
2628            }
2629        }
2630    }
2631
2632    // --- BitError: Display for every ErrorKind, and the offset/field suffix --------
2633
2634    use alloc::string::{String, ToString};
2635
2636    #[test]
2637    fn display_unexpected_eof() {
2638        let e = BitError::new(
2639            ErrorKind::UnexpectedEof {
2640                needed: 16,
2641                remaining: 8,
2642            },
2643            0,
2644        );
2645        assert_eq!(
2646            e.to_string(),
2647            "unexpected end of input: needed 16 bits, 8 remain at bit 0"
2648        );
2649    }
2650
2651    #[test]
2652    fn display_incomplete_with_and_without_hint() {
2653        assert_eq!(
2654            BitError::new(ErrorKind::Incomplete { needed: Some(3) }, 8).to_string(),
2655            "incomplete: need ~3 more bytes at bit 8",
2656        );
2657        assert_eq!(
2658            BitError::new(ErrorKind::Incomplete { needed: None }, 8).to_string(),
2659            "incomplete: need more bytes at bit 8",
2660        );
2661    }
2662
2663    #[test]
2664    fn display_trailing_too_wide_not_seekable_buffer_full() {
2665        assert_eq!(
2666            BitError::new(ErrorKind::TrailingBytes { remaining: 2 }, 16).to_string(),
2667            "2 trailing bytes after the message at bit 16",
2668        );
2669        assert_eq!(
2670            BitError::new(ErrorKind::TooWide { width: 129 }, 0).to_string(),
2671            "field width 129 exceeds the 128-bit carrier at bit 0",
2672        );
2673        assert_eq!(
2674            BitError::new(ErrorKind::NotSeekable, 4).to_string(),
2675            "a position directive ran on a non-seekable source at bit 4",
2676        );
2677        assert_eq!(
2678            BitError::new(ErrorKind::BufferFull { cap: 64 }, 0).to_string(),
2679            "buffered source exceeded its 64-byte cap at bit 0",
2680        );
2681    }
2682
2683    #[test]
2684    fn display_bad_magic_and_convert() {
2685        assert_eq!(
2686            BitError::bad_magic(0xCAFE, 0x0000, 0).to_string(),
2687            "bad magic: expected 0xcafe, found 0x0 at bit 0",
2688        );
2689        assert_eq!(
2690            BitError::convert(String::from("nope"), 8).to_string(),
2691            "conversion failed: nope at bit 8",
2692        );
2693    }
2694
2695    #[test]
2696    fn display_appends_field_span_when_set() {
2697        let e = BitError::new(ErrorKind::TooWide { width: 200 }, 12).in_field("payload");
2698        assert_eq!(
2699            e.to_string(),
2700            "field width 200 exceeds the 128-bit carrier at bit 12 (field `payload`)"
2701        );
2702    }
2703
2704    #[test]
2705    fn display_io_kind() {
2706        let e = BitError::new(ErrorKind::Io(std::io::ErrorKind::BrokenPipe), 0);
2707        assert!(e.to_string().starts_with("I/O error:"));
2708    }
2709
2710    // --- BitError constructors and the two From bridges ----------------------------
2711
2712    #[test]
2713    fn in_field_records_only_the_innermost() {
2714        let e = BitError::new(ErrorKind::NotSeekable, 0)
2715            .in_field("inner")
2716            .in_field("outer"); // ignored — inner already set
2717        assert_eq!(e.field, Some("inner"));
2718    }
2719
2720    #[test]
2721    fn is_incomplete_is_true_only_for_incomplete() {
2722        assert!(BitError::new(ErrorKind::Incomplete { needed: None }, 0).is_incomplete());
2723        assert!(!BitError::new(ErrorKind::NotSeekable, 0).is_incomplete());
2724    }
2725
2726    #[test]
2727    fn construction_error_bridges_to_a_convert_error() {
2728        let e: BitError = crate::error::WidthError::ValueTooLarge { value: 99, bits: 4 }.into();
2729        assert!(matches!(e.kind, ErrorKind::Convert { .. }));
2730        assert_eq!(e.at, 0);
2731        assert!(e.to_string().contains("does not fit in 4 bits"));
2732    }
2733
2734    #[test]
2735    fn io_error_bridges_to_an_io_kind() {
2736        let e: BitError = std::io::Error::new(std::io::ErrorKind::TimedOut, "x").into();
2737        assert_eq!(e.kind, ErrorKind::Io(std::io::ErrorKind::TimedOut));
2738        assert_eq!(e.at, 0);
2739    }
2740
2741    // --- BitWriter: the LSB-order constructor and the over-wide guard ---------------
2742
2743    #[test]
2744    fn writer_with_order_lsb_packs_first_field_in_the_low_bits() {
2745        let mut w = BitWriter::with_order(BitOrder::Lsb);
2746        w.write(u4::new(0xA)).unwrap(); // -> low nibble
2747        w.write(u4::new(0xB)).unwrap(); // -> high nibble
2748        assert_eq!(w.into_bytes(), [0xBA]);
2749    }
2750
2751    #[test]
2752    fn cursor_layout_matrix_bit_and_byte_order_are_independent() {
2753        // The two axes — `bit` (how a sub-byte field packs) and `byte` (how a byte-multiple
2754        // value serializes) — must compose independently at the cursor level (`extract_bits`/
2755        // `emit_bits`/`apply_byte_order`). Write a nibble pair (bit-order sensitive) then a u16
2756        // word (byte-order sensitive) under each of the four layouts.
2757        let combos = [
2758            (BitOrder::Msb, ByteOrder::Big),
2759            (BitOrder::Msb, ByteOrder::Little),
2760            (BitOrder::Lsb, ByteOrder::Big),
2761            (BitOrder::Lsb, ByteOrder::Little),
2762        ];
2763        let mut encs = Vec::new();
2764        for (bit, byte) in combos {
2765            let layout = Layout { bit, byte };
2766            let mut w = BitWriter::with_layout(layout);
2767            w.write(u4::new(0xA)).unwrap();
2768            w.write(u4::new(0xB)).unwrap();
2769            w.write(0x1234u16).unwrap();
2770            let bytes = w.into_bytes();
2771            // Every layout round-trips through a reader with the same layout.
2772            let mut r = BitReader::with_layout(&bytes, layout);
2773            assert_eq!(r.read::<u4>().unwrap(), u4::new(0xA));
2774            assert_eq!(r.read::<u4>().unwrap(), u4::new(0xB));
2775            assert_eq!(r.read::<u16>().unwrap(), 0x1234);
2776            encs.push(bytes);
2777        }
2778        // All four corners are golden under the natural-layout rule (`apply_byte_order`):
2779        // each bit order has a natural byte layout — big-endian under MSB, little-endian
2780        // under LSB (the DBC-Intel layout) — and the byte-order knob swaps a byte-multiple
2781        // value only when it differs from that natural layout.
2782        assert_eq!(encs[0], [0xAB, 0x12, 0x34]); // msb / big    (natural — no swap)
2783        assert_eq!(encs[1], [0xAB, 0x34, 0x12]); // msb / little (differs — word swaps)
2784        assert_eq!(encs[2], [0xBA, 0x12, 0x34]); // lsb / big    (differs — word swaps)
2785        assert_eq!(encs[3], [0xBA, 0x34, 0x12]); // lsb / little (natural — no swap)
2786        // Flipping byte order changes only the word's bytes, never the nibble byte.
2787        assert_eq!(encs[0][0], encs[1][0]);
2788        assert_ne!(encs[0][1..], encs[1][1..]);
2789        assert_eq!(encs[2][0], encs[3][0]);
2790        assert_ne!(encs[2][1..], encs[3][1..]);
2791        // All four corners are pairwise distinct — neither axis aliases the other.
2792        for i in 0..encs.len() {
2793            for j in (i + 1)..encs.len() {
2794                assert_ne!(encs[i], encs[j], "layout corners {i} and {j} alias");
2795            }
2796        }
2797    }
2798
2799    #[test]
2800    fn write_bits_rejects_over_128() {
2801        let mut w = BitWriter::new();
2802        assert_eq!(
2803            w.write_bits(0, 129).unwrap_err().kind,
2804            ErrorKind::TooWide { width: 129 }
2805        );
2806    }
2807
2808    // --- Source/Sink trait DEFAULT methods, via minimal in-test impls --------------
2809
2810    /// A forward-only `Source` that overrides only the two required methods, so calling
2811    /// the rest exercises the trait's default `byte_order`/`seek_to_bit`/`read`.
2812    struct TinySource<'a> {
2813        bytes: &'a [u8],
2814        pos: usize,
2815    }
2816    impl sealed::Sealed for TinySource<'_> {}
2817
2818    impl Source for TinySource<'_> {
2819        fn read_bits(&mut self, n: u32) -> Result<u128, BitError> {
2820            let n = n as usize;
2821            let total = self.bytes.len() * 8;
2822            if self.pos + n > total {
2823                return Err(BitError::new(
2824                    ErrorKind::UnexpectedEof {
2825                        needed: n,
2826                        remaining: total - self.pos,
2827                    },
2828                    self.pos,
2829                ));
2830            }
2831            let mut acc = 0u128;
2832            for k in 0..n {
2833                let p = self.pos + k;
2834                acc = (acc << 1) | u128::from((self.bytes[p >> 3] >> (7 - (p & 7))) & 1);
2835            }
2836            self.pos += n;
2837            Ok(acc)
2838        }
2839        fn bit_pos(&self) -> usize {
2840            self.pos
2841        }
2842    }
2843
2844    #[test]
2845    fn source_default_byte_order_is_big() {
2846        let s = TinySource {
2847            bytes: &[0],
2848            pos: 0,
2849        };
2850        assert_eq!(s.byte_order(), ByteOrder::Big);
2851    }
2852
2853    #[test]
2854    fn source_default_seek_is_not_seekable() {
2855        let mut s = TinySource {
2856            bytes: &[0, 0],
2857            pos: 0,
2858        };
2859        assert_eq!(s.seek_to_bit(8).unwrap_err().kind, ErrorKind::NotSeekable);
2860    }
2861
2862    #[test]
2863    fn source_default_read_dispatches_through_read_bits() {
2864        let mut s = TinySource {
2865            bytes: &[0xAB, 0xCD],
2866            pos: 0,
2867        };
2868        assert_eq!(s.read::<u8>().unwrap(), 0xAB);
2869        assert_eq!(s.read::<u8>().unwrap(), 0xCD);
2870    }
2871
2872    /// A `Sink` that overrides only the required methods, exercising the default
2873    /// `byte_order`/`write`.
2874    struct TinySink {
2875        out: Vec<u8>,
2876        bit: usize,
2877    }
2878    impl sealed::Sealed for TinySink {}
2879
2880    impl Sink for TinySink {
2881        fn write_bits(&mut self, value: u128, n: u32) -> Result<(), BitError> {
2882            let n = n as usize;
2883            for k in 0..n {
2884                let p = self.bit + k;
2885                if p >> 3 == self.out.len() {
2886                    self.out.push(0);
2887                }
2888                if (value >> (n - 1 - k)) & 1 != 0 {
2889                    self.out[p >> 3] |= 1 << (7 - (p & 7));
2890                }
2891            }
2892            self.bit += n;
2893            Ok(())
2894        }
2895        fn bit_pos(&self) -> usize {
2896            self.bit
2897        }
2898    }
2899
2900    #[test]
2901    fn sink_default_byte_order_is_big() {
2902        let s = TinySink {
2903            out: Vec::new(),
2904            bit: 0,
2905        };
2906        assert_eq!(s.byte_order(), ByteOrder::Big);
2907    }
2908
2909    #[test]
2910    fn sink_default_write_dispatches_through_write_bits() {
2911        let mut s = TinySink {
2912            out: Vec::new(),
2913            bit: 0,
2914        };
2915        s.write(0xABu8).unwrap();
2916        s.write(0xCDu8).unwrap();
2917        assert_eq!(s.out, [0xAB, 0xCD]);
2918    }
2919
2920    // --- BitEncode/DecodeWith defaults for a leaf type -----------------------------
2921
2922    #[test]
2923    fn leaf_canonical_encode_defaults_to_verbatim() {
2924        let mut a = BitWriter::new();
2925        let mut b = BitWriter::new();
2926        BitEncode::bit_encode(&0xABCDu16, &mut a).unwrap();
2927        BitEncode::canonical_bit_encode(&0xABCDu16, &mut b).unwrap();
2928        assert_eq!(a.into_bytes(), b.into_bytes());
2929    }
2930
2931    #[test]
2932    fn leaf_decode_with_and_encode_with_unit_args() {
2933        let mut r = BitReader::new(&[0xAB, 0xCD]);
2934        assert_eq!(
2935            <u16 as DecodeWith<()>>::decode_with(&mut r, ()).unwrap(),
2936            0xABCD
2937        );
2938        let mut w = BitWriter::new();
2939        EncodeWith::encode_with(&0xABCDu16, &mut w, ()).unwrap();
2940        assert_eq!(w.into_bytes(), [0xAB, 0xCD]);
2941    }
2942
2943    #[test]
2944    fn bitbuf_bounded_reports_its_capacity() {
2945        assert_eq!(BitBuf::bounded(64).capacity(), Some(64));
2946        assert_eq!(BitBuf::new().capacity(), None);
2947        assert_eq!(BitBuf::with_capacity(64).capacity(), None); // pre-reserved, not a hard cap
2948    }
2949
2950    #[test]
2951    fn capacity_error_display() {
2952        let e = CapacityError {
2953            cap: 4,
2954            requested: 5,
2955        };
2956        assert_eq!(
2957            e.to_string(),
2958            "bitbuf is full: 5 bytes needed exceeds the 4-byte capacity"
2959        );
2960    }
2961
2962    #[test]
2963    fn count_prefix_primitive_boundaries() {
2964        // In-range: exact fit at the top of the range.
2965        assert_eq!(u8::try_from_count(255).unwrap(), 255u8);
2966        // Out of range: checked, not wrapped.
2967        assert_eq!(
2968            u8::try_from_count(256).unwrap_err(),
2969            crate::error::WidthError::ValueTooLarge {
2970                value: 256,
2971                bits: 8
2972            }
2973        );
2974        assert_eq!(u16::try_from_count(65_535).unwrap(), 65_535u16);
2975        assert_eq!(u8::to_count(200), 200);
2976        assert_eq!(u32::to_count(70_000), 70_000);
2977    }
2978
2979    #[test]
2980    fn count_prefix_uint_boundaries() {
2981        // u12: 4095 fits, 4096 does not.
2982        assert_eq!(u12::try_from_count(4095).unwrap(), u12::new(4095));
2983        assert_eq!(
2984            u12::try_from_count(4096).unwrap_err(),
2985            crate::error::WidthError::ValueTooLarge {
2986                value: 4096,
2987                bits: 12
2988            }
2989        );
2990        assert_eq!(u12::new(4095).to_count(), 4095);
2991    }
2992
2993    #[test]
2994    fn count_prefix_uint_never_truncates_before_the_check() {
2995        // 300 as u8 would wrap to 44 — a masked `from_raw`/`try_new(len as u8)` path
2996        // would then accept it. The widen-then-compare must reject instead.
2997        assert_eq!(
2998            u4::try_from_count(300).unwrap_err(),
2999            crate::error::WidthError::ValueTooLarge {
3000                value: 300,
3001                bits: 4
3002            }
3003        );
3004    }
3005
3006    #[test]
3007    fn count_prefix_round_trips() {
3008        for len in [0usize, 1, 15, 255, 4095] {
3009            assert_eq!(u16::try_from_count(len).unwrap().to_count(), len);
3010            assert_eq!(u12::try_from_count(len).unwrap().to_count(), len);
3011        }
3012    }
3013
3014    #[test]
3015    fn bulk_bytes_round_trip() {
3016        let mut w = BitWriter::new();
3017        w.write_bytes(&[0xDE, 0xAD, 0xBE, 0xEF]).unwrap();
3018        let bytes = w.into_bytes();
3019        assert_eq!(bytes, [0xDE, 0xAD, 0xBE, 0xEF]);
3020        let mut r = BitReader::new(&bytes);
3021        assert_eq!(r.read_bytes(4).unwrap(), [0xDE, 0xAD, 0xBE, 0xEF]);
3022        assert_eq!(r.remaining_bits(), 0);
3023    }
3024
3025    #[test]
3026    fn bulk_bytes_work_at_a_bit_offset() {
3027        // Bytes need not be aligned: write a nibble, then bytes straddling.
3028        let mut w = BitWriter::new();
3029        w.write(u4::new(0xF)).unwrap();
3030        w.write_bytes(&[0xAB, 0xCD]).unwrap();
3031        let bytes = w.into_bytes();
3032        assert_eq!(bytes, [0xFA, 0xBC, 0xD0]);
3033        let mut r = BitReader::new(&bytes);
3034        assert_eq!(r.read::<u4>().unwrap(), u4::new(0xF));
3035        assert_eq!(r.read_bytes(2).unwrap(), [0xAB, 0xCD]);
3036    }
3037
3038    #[test]
3039    fn read_bytes_hostile_length_is_eof_not_alloc() {
3040        // A huge n against a 2-byte source: push-per-byte means a fast EOF, no
3041        // pre-allocation from the untrusted length.
3042        let mut r = BitReader::new(&[0x01, 0x02]);
3043        let err = r.read_bytes(usize::MAX).unwrap_err();
3044        assert!(matches!(err.kind, ErrorKind::UnexpectedEof { .. }));
3045    }
3046
3047    #[test]
3048    fn read_into_fills_and_errors_short() {
3049        let mut r = BitReader::new(&[0x0A, 0x0B, 0x0C]);
3050        let mut buf = [0u8; 3];
3051        r.read_into(&mut buf).unwrap();
3052        assert_eq!(buf, [0x0A, 0x0B, 0x0C]);
3053
3054        let mut r = BitReader::new(&[0x0A]);
3055        let mut buf = [0u8; 3];
3056        let err = r.read_into(&mut buf).unwrap_err();
3057        assert!(matches!(err.kind, ErrorKind::UnexpectedEof { .. }));
3058    }
3059}
3060
3061#[cfg(test)]
3062mod component {
3063    //! Component tests: one runtime adapter in isolation (the I/O ladder over the
3064    //! bit cursors). `cargo test component` runs these alongside the other layers.
3065    /// `bitstream_source.rs` — Generic recursion over `Source` (ROADMAP Phase 1, chunk B1): one derived
3066    mod source {
3067
3068        use bnb::{BitDecode, BitEncode, BitReader, BitWriter, StreamBitReader, u4, u12};
3069
3070        #[derive(BitDecode, BitEncode, Debug, PartialEq, Eq)]
3071        struct Word {
3072            a: u4,
3073            b: u12, // 16 bits; all <= 64 so the streaming reader handles it too
3074        }
3075
3076        #[test]
3077        fn decodes_over_slice_and_stream_identically() {
3078            let word = Word {
3079                a: u4::new(0xA),
3080                b: u12::new(0xBCD),
3081            };
3082            let mut w = BitWriter::new();
3083            word.bit_encode(&mut w).unwrap();
3084            let bytes = w.into_bytes();
3085            assert_eq!(bytes, [0xAB, 0xCD]);
3086
3087            // Source 1 — in-memory slice cursor (random-access, full power).
3088            let mut slice = BitReader::new(&bytes);
3089            assert_eq!(Word::bit_decode(&mut slice).unwrap(), word);
3090
3091            // Source 2 — a forward `Read` (`&[u8]` is `Read` but NOT `Seek`); same code,
3092            // no rewrite, no Seek requirement.
3093            let mut stream = StreamBitReader::new(&bytes[..]);
3094            assert_eq!(Word::bit_decode(&mut stream).unwrap(), word);
3095        }
3096
3097        #[test]
3098        fn stream_reader_honors_a_little_endian_layout() {
3099            use bnb::{Layout, bin};
3100            #[bin(little)]
3101            #[derive(Debug, PartialEq)]
3102            struct Le {
3103                v: u32,
3104            }
3105            let bytes = Le { v: 0x1122_3344 }.to_bytes().unwrap();
3106            assert_eq!(bytes, [0x44, 0x33, 0x22, 0x11]); // little-endian on the wire
3107
3108            // A default stream reader would misread it big-endian; with the type's layout
3109            // it decodes correctly over a forward `Read`.
3110            let mut stream = StreamBitReader::with_layout(&bytes[..], <Le as BitEncode>::LAYOUT);
3111            assert_eq!(Le::bit_decode(&mut stream).unwrap(), Le { v: 0x1122_3344 });
3112            // (The default `new` reader, big-endian, would read the bytes reversed.)
3113            let mut msb = StreamBitReader::with_layout(&bytes[..], Layout::default());
3114            assert_ne!(Le::bit_decode(&mut msb).unwrap().v, 0x1122_3344);
3115        }
3116    }
3117
3118    /// `bitstream_seek.rs` — Spike (DESIGN §11): seeking is free on the in-memory cursor, and a
3119    mod seek {
3120
3121        use bnb::{BitReader, StreamBitReader, u4};
3122
3123        #[test]
3124        fn seek_and_align_need_no_seek_trait() {
3125            // 3 bytes: 0xAB, 0xCD, 0xEF.
3126            let bytes = [0xABu8, 0xCD, 0xEF];
3127            let mut r = BitReader::new(&bytes);
3128
3129            // Read a nibble, jump to an absolute bit offset, read, then jump back —
3130            // exactly the move DNS name-compression needs, with no Seek machinery.
3131            assert_eq!(r.read::<u4>().unwrap(), u4::new(0xA));
3132            r.seek_to_bit(16).unwrap(); // -> third byte
3133            assert_eq!(r.read_bits(8).unwrap(), 0xEF);
3134            r.seek_to_bit(4).unwrap(); // back to the low nibble of byte 0
3135            assert_eq!(r.read::<u4>().unwrap(), u4::new(0xB));
3136
3137            // align_to_byte snaps the cursor forward to the next byte boundary.
3138            r.seek_to_bit(9).unwrap();
3139            r.align_to_byte();
3140            assert_eq!(r.bit_pos(), 16);
3141
3142            // Seeking past the end is a clean error, not a panic.
3143            assert!(r.seek_to_bit(999).is_err());
3144        }
3145
3146        #[test]
3147        fn forward_only_stream_reader_requires_only_read() {
3148            // `&[u8]` implements `std::io::Read` but NOT `std::io::Seek`. That this
3149            // compiles and runs is the whole point: forward bit parsing drops the Seek
3150            // requirement binrw imposes uniformly.
3151            let data = [0xABu8, 0xCD];
3152            let src: &[u8] = &data;
3153            let mut r = StreamBitReader::new(src);
3154
3155            assert_eq!(r.read::<u4>().unwrap(), u4::new(0xA));
3156            assert_eq!(r.read::<u4>().unwrap(), u4::new(0xB));
3157            assert_eq!(r.read_bits(8).unwrap(), 0xCD);
3158            // Past the end -> error, not panic.
3159            assert!(r.read_bits(1).is_err());
3160        }
3161    }
3162
3163    /// `bitstream_entry.rs` — Entry points (ROADMAP Phase 1, chunk B2): `decode`/`peek`/`decode_exact`/
3164    mod entry {
3165
3166        use bnb::{
3167            BitDecode, BitEncode, BitReader, EncodeExt, ErrorKind, StreamBitReader, u4, u12,
3168        };
3169        use std::io::Cursor;
3170
3171        #[derive(BitDecode, BitEncode, Debug, PartialEq, Eq, Clone, Copy)]
3172        struct Word {
3173            a: u4,
3174            b: u12,
3175        }
3176
3177        fn sample() -> (Word, [u8; 2]) {
3178            (
3179                Word {
3180                    a: u4::new(0xA),
3181                    b: u12::new(0xBCD),
3182                },
3183                [0xAB, 0xCD],
3184            )
3185        }
3186
3187        #[test]
3188        fn to_bytes_peek_and_tail_tolerance() {
3189            let (w, bytes) = sample();
3190            assert_eq!(w.to_bytes().unwrap(), bytes);
3191            assert_eq!(Word::peek(&bytes).unwrap(), w);
3192
3193            // peek is tail-tolerant: a trailing byte is ignored.
3194            let mut padded = bytes.to_vec();
3195            padded.push(0xFF);
3196            assert_eq!(Word::peek(&padded).unwrap(), w);
3197        }
3198
3199        #[test]
3200        fn decode_advances_a_cursor() {
3201            let (w, bytes) = sample();
3202            let mut both = bytes.to_vec();
3203            both.extend_from_slice(&bytes); // two messages back to back
3204
3205            let mut cur = BitReader::new(&both);
3206            assert_eq!(Word::decode(&mut cur).unwrap(), w);
3207            assert_eq!(cur.bit_pos(), 16, "advanced past the first message");
3208            assert_eq!(Word::decode(&mut cur).unwrap(), w);
3209            assert_eq!(cur.bit_pos(), both.len() * 8, "consumed both");
3210        }
3211
3212        #[test]
3213        fn decode_all_and_iter_collect_back_to_back() {
3214            let (w, bytes) = sample();
3215            let mut both = bytes.to_vec();
3216            both.extend_from_slice(&bytes);
3217
3218            // decode_all — eager; decode_iter — lazy. Both layout-baked and bit-aware.
3219            assert_eq!(Word::decode_all(&both).unwrap(), vec![w, w]);
3220            let collected: Result<Vec<_>, _> = Word::decode_iter(&both).collect();
3221            assert_eq!(collected.unwrap(), vec![w, w]);
3222        }
3223
3224        #[test]
3225        fn decode_all_of_a_zero_width_type_yields_nothing() {
3226            use bnb::{BitDecode, BitError, Layout, Source};
3227            #[derive(Debug, PartialEq)]
3228            struct Zero;
3229            impl BitDecode for Zero {
3230                fn bit_decode<S: Source>(_r: &mut S) -> Result<Self, BitError> {
3231                    Ok(Zero)
3232                }
3233            }
3234            // A zero-width type makes no progress; over a non-empty buffer `decode_all` must
3235            // yield an empty `Vec` (not one spurious element) and not spin.
3236            let out: Vec<Zero> =
3237                bnb::__private::decode_all(&[0xFF, 0xFF], Layout::default()).unwrap();
3238            assert!(out.is_empty());
3239        }
3240
3241        #[test]
3242        fn decode_errors_on_short_cursor() {
3243            let short = [0xABu8]; // one byte; Word needs two
3244            let mut cur = BitReader::new(&short);
3245            let err = Word::decode(&mut cur).unwrap_err();
3246            assert!(matches!(err.kind, ErrorKind::UnexpectedEof { .. }));
3247        }
3248
3249        #[test]
3250        fn decode_exact_rejects_trailing_bytes() {
3251            let (w, bytes) = sample();
3252            assert_eq!(Word::decode_exact(&bytes).unwrap(), w);
3253
3254            let mut padded = bytes.to_vec();
3255            padded.push(0xFF);
3256            let err = Word::decode_exact(&padded).unwrap_err();
3257            assert_eq!(err.kind, ErrorKind::TrailingBytes { remaining: 1 });
3258        }
3259
3260        #[test]
3261        fn encode_to_any_write() {
3262            let (w, bytes) = sample();
3263            let mut sink = Cursor::new(Vec::new());
3264            w.encode(&mut sink).unwrap();
3265            assert_eq!(sink.into_inner(), bytes);
3266        }
3267
3268        #[test]
3269        fn encode_io_error_is_reported() {
3270            struct Full;
3271            impl std::io::Write for Full {
3272                fn write(&mut self, _: &[u8]) -> std::io::Result<usize> {
3273                    Err(std::io::Error::new(std::io::ErrorKind::WriteZero, "full"))
3274                }
3275                fn flush(&mut self) -> std::io::Result<()> {
3276                    Ok(())
3277                }
3278            }
3279            let (w, _) = sample();
3280            let err = w.encode(&mut Full).unwrap_err();
3281            assert_eq!(err.kind, ErrorKind::Io(std::io::ErrorKind::WriteZero));
3282        }
3283
3284        #[test]
3285        fn decode_explicit_cursor() {
3286            let (w, bytes) = sample();
3287            let mut r = BitReader::new(&bytes);
3288            assert_eq!(Word::decode(&mut r).unwrap(), w);
3289        }
3290
3291        #[test]
3292        fn streaming_shortfall_is_incomplete_not_eof() {
3293            let (_, bytes) = sample();
3294            // Only the first byte available over a stream: the shortfall is the retry
3295            // signal, not a definitive EOF.
3296            let mut stream = StreamBitReader::new(&bytes[..1]);
3297            let err = Word::decode(&mut stream).unwrap_err();
3298            assert!(err.is_incomplete(), "stream shortfall is incomplete: {err}");
3299            assert!(matches!(err.kind, ErrorKind::Incomplete { .. }));
3300            assert_eq!(err.field, Some("b"), "still records the field span");
3301        }
3302    }
3303
3304    /// `bitstream_errors.rs` — Position-aware errors (ROADMAP Phase 1): a decode/encode failure reports the
3305    mod errors {
3306
3307        use bnb::{BitDecode, BitEncode, BitError, BitReader, BitWriter, ErrorKind, u4, u12};
3308
3309        #[derive(BitDecode, BitEncode, Debug, PartialEq, Eq)]
3310        struct Header {
3311            a: u4,
3312            b: u12, // a + b = 16 bits
3313        }
3314
3315        #[test]
3316        fn round_trips() {
3317            let h = Header {
3318                a: u4::new(0xA),
3319                b: u12::new(0xBCD),
3320            };
3321            let mut w = BitWriter::new();
3322            h.bit_encode(&mut w).unwrap();
3323            let bytes = w.into_bytes();
3324            assert_eq!(bytes, [0xAB, 0xCD]);
3325
3326            let mut r = BitReader::new(&bytes);
3327            assert_eq!(Header::bit_decode(&mut r).unwrap(), h);
3328        }
3329
3330        #[test]
3331        fn decode_eof_reports_offset_and_field() {
3332            // One byte: `a` (4 bits) decodes; `b` (12 bits) runs off the end at bit 4.
3333            let bytes = [0xAB];
3334            let mut r = BitReader::new(&bytes);
3335            let err: BitError = Header::bit_decode(&mut r).unwrap_err();
3336
3337            assert_eq!(err.field, Some("b"), "names the field that failed");
3338            assert_eq!(err.at, 4, "records the bit offset where decoding stopped");
3339            assert_eq!(
3340                err.kind,
3341                ErrorKind::UnexpectedEof {
3342                    needed: 12,
3343                    remaining: 4
3344                }
3345            );
3346
3347            let msg = err.to_string();
3348            assert!(msg.contains("field `b`"), "message names the field: {msg}");
3349            assert!(msg.contains("at bit 4"), "message names the offset: {msg}");
3350        }
3351
3352        #[test]
3353        fn innermost_field_wins_the_span() {
3354            // The error originates in `b`'s read; the outer struct must not overwrite it.
3355            let mut r = BitReader::new(&[0xAB]);
3356            let err = Header::bit_decode(&mut r).unwrap_err();
3357            assert_eq!(err.field, Some("b"));
3358        }
3359    }
3360
3361    /// `bin_io_adapter.rs` — `Source::as_read` / `Sink::as_write`: hand a bnb cursor to `std::io`-based code
3362    mod io_adapter {
3363
3364        use bnb::{BitError, Sink, Source, bin};
3365        use std::io::{Read, Write};
3366
3367        // A length-prefixed blob, read and written through std::io::Read/Write *views* over the
3368        // bnb cursor — exactly how you'd drop in a `Read`/`Write`-based parser or a stream
3369        // wrapper (decompressor, checksummer, …) from a custom codec.
3370        fn read_blob<S: Source>(r: &mut S) -> Result<Vec<u8>, BitError> {
3371            let len: u8 = r.read()?;
3372            let mut buf = vec![0u8; len as usize];
3373            r.as_read().read_exact(&mut buf)?; // io::Error -> BitError via `?`
3374            Ok(buf)
3375        }
3376
3377        fn write_blob<K: Sink>(blob: &[u8], w: &mut K) -> Result<(), BitError> {
3378            w.write(u8::try_from(blob.len()).unwrap())?;
3379            w.as_write().write_all(blob)?;
3380            Ok(())
3381        }
3382
3383        #[bin(big)]
3384        #[derive(Debug, PartialEq)]
3385        struct Msg {
3386            #[br(parse_with = read_blob)]
3387            #[bw(write_with = write_blob)]
3388            data: Vec<u8>,
3389        }
3390
3391        #[test]
3392        fn as_read_as_write_roundtrip_through_std_io() {
3393            let m = Msg {
3394                data: vec![0xDE, 0xAD, 0xBE, 0xEF],
3395            };
3396            let bytes = m.to_bytes().unwrap();
3397            assert_eq!(bytes, [0x04, 0xDE, 0xAD, 0xBE, 0xEF]);
3398            assert_eq!(Msg::decode_exact(&bytes).unwrap(), m);
3399        }
3400
3401        #[test]
3402        fn as_read_short_read_reports_eof() {
3403            use bnb::BitReader;
3404            // Only 2 bytes available but the length prefix claims 4 -> read_exact hits EOF,
3405            // which surfaces as a BitError (not a panic).
3406            let mut r = BitReader::new(&[0x04, 0xAA, 0xBB]);
3407            assert!(read_blob(&mut r).is_err());
3408        }
3409    }
3410
3411    /// `bin_buf_source.rs` — `BufSource` (ROADMAP Phase 3): a seekable `Source` over a forward `Read`. It
3412    mod buf_source {
3413
3414        use bnb::{BufSource, ErrorKind, Source, bin, u4};
3415
3416        // A forward-only reader (a socket-like stream) yielding one byte per `read`.
3417        struct Chunked {
3418            data: Vec<u8>,
3419            pos: usize,
3420        }
3421        impl std::io::Read for Chunked {
3422            fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
3423                if self.pos >= self.data.len() || buf.is_empty() {
3424                    return Ok(0);
3425                }
3426                buf[0] = self.data[self.pos];
3427                self.pos += 1;
3428                Ok(1)
3429            }
3430        }
3431
3432        #[bin]
3433        #[derive(Debug, PartialEq, Eq, Clone)]
3434        struct Frame {
3435            flags: u4,
3436            #[br(restore_position)]
3437            peek: u8,
3438            value: u16,
3439        }
3440
3441        #[test]
3442        fn seek_using_message_over_a_nonseekable_stream() {
3443            // Wire bytes from the restore_position round-trip: flags=5, value=0xABCD.
3444            let wire = vec![0x5A, 0xBC, 0xD0];
3445            let mut src = BufSource::new(Chunked { data: wire, pos: 0 });
3446            let f = Frame::decode(&mut src).unwrap();
3447            assert_eq!(f.value, 0xABCD);
3448            assert_eq!(f.peek, 0xAB, "the rewind re-read retained bytes");
3449        }
3450
3451        #[test]
3452        fn retention_cap_bounds_the_buffer() {
3453            // A 1-byte cap; reading a 16-bit value needs 2 bytes -> BufferFull.
3454            let mut src = BufSource::with_capacity(
3455                Chunked {
3456                    data: vec![0xFF; 8],
3457                    pos: 0,
3458                },
3459                1,
3460            );
3461            let err = src.read_bits(16).unwrap_err();
3462            assert!(matches!(err.kind, ErrorKind::BufferFull { cap: 1 }));
3463        }
3464
3465        #[test]
3466        fn over_wide_read_is_rejected() {
3467            let mut src = BufSource::new(Chunked {
3468                data: vec![0u8; 32],
3469                pos: 0,
3470            });
3471            assert!(matches!(
3472                src.read_bits(129).unwrap_err().kind,
3473                ErrorKind::TooWide { width: 129 }
3474            ));
3475        }
3476
3477        #[test]
3478        fn running_out_mid_field_is_incomplete() {
3479            // Only one byte is available, but a 16-bit read needs two — the stream ends (EOF)
3480            // partway through, which is the streaming "need more" signal, not a definitive EOF.
3481            let mut src = BufSource::new(Chunked {
3482                data: vec![0xAB],
3483                pos: 0,
3484            });
3485            assert!(matches!(
3486                src.read_bits(16).unwrap_err().kind,
3487                ErrorKind::Incomplete { .. }
3488            ));
3489        }
3490
3491        #[test]
3492        fn an_io_error_from_the_reader_propagates() {
3493            struct Failing;
3494            impl std::io::Read for Failing {
3495                fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> {
3496                    Err(std::io::Error::new(
3497                        std::io::ErrorKind::ConnectionReset,
3498                        "boom",
3499                    ))
3500                }
3501            }
3502            let mut src = BufSource::new(Failing);
3503            assert!(matches!(
3504                src.read_bits(8).unwrap_err().kind,
3505                ErrorKind::Io(_)
3506            ));
3507        }
3508    }
3509
3510    /// `bin_seek_reader.rs` — `SeekReader` (ROADMAP Phase 3b): a `SeekSource` over a `Read + Seek` (a file-like)
3511    mod seek_reader {
3512
3513        use bnb::{SeekReader, bin, u4};
3514        use std::io::Cursor;
3515
3516        #[bin]
3517        #[derive(Debug, PartialEq, Eq, Clone)]
3518        struct Frame {
3519            flags: u4,
3520            #[br(restore_position)]
3521            peek: u8,
3522            value: u16,
3523        }
3524
3525        #[test]
3526        fn seek_reader_over_a_file_like_source() {
3527            let wire = vec![0x5A, 0xBC, 0xD0]; // flags=5, value=0xABCD (restore_position layout)
3528            let mut src = SeekReader::new(Cursor::new(wire));
3529            let f = Frame::decode(&mut src).unwrap();
3530            assert_eq!(f.value, 0xABCD);
3531            assert_eq!(f.peek, 0xAB, "rewound and re-read via io::Seek");
3532        }
3533
3534        #[test]
3535        fn over_wide_read_is_rejected() {
3536            use bnb::{ErrorKind, Source};
3537            let mut src = SeekReader::new(Cursor::new(vec![0u8; 32]));
3538            assert!(matches!(
3539                src.read_bits(129).unwrap_err().kind,
3540                ErrorKind::TooWide { width: 129 }
3541            ));
3542        }
3543
3544        #[test]
3545        fn reading_past_the_end_is_unexpected_eof() {
3546            use bnb::ErrorKind;
3547            #[bin(big)]
3548            #[derive(Debug)]
3549            struct Quad {
3550                v: u32,
3551            }
3552            // Only two of the four needed bytes are present.
3553            let mut src = SeekReader::new(Cursor::new(vec![0x12, 0x34]));
3554            assert!(matches!(
3555                Quad::decode(&mut src).unwrap_err().kind,
3556                ErrorKind::UnexpectedEof { .. }
3557            ));
3558        }
3559
3560        #[test]
3561        fn little_endian_layout_is_honored() {
3562            #[bin(little)]
3563            #[derive(Debug, PartialEq)]
3564            struct Le {
3565                v: u32,
3566            }
3567            // `with_layout` carries the message's little-endian order onto the reader.
3568            let mut src = SeekReader::with_layout(
3569                Cursor::new(vec![0x78, 0x56, 0x34, 0x12]),
3570                <Le as bnb::BitEncode>::LAYOUT,
3571            );
3572            assert_eq!(Le::decode(&mut src).unwrap(), Le { v: 0x1234_5678 });
3573        }
3574    }
3575
3576    /// `bitbuf.rs` — `BitBuf` — a push/pull, bit-aware incremental decode buffer.
3577    mod bitbuf {
3578
3579        use bnb::{BitBuf, BitDecode, BitEncode, BitWriter, bin, u4};
3580
3581        #[bin(big)]
3582        #[derive(Debug, PartialEq, Eq, Clone, Copy)]
3583        struct Frame {
3584            tag: u4,
3585            val: u8,
3586        } // 12 bits — a non-byte-aligned boundary
3587
3588        #[bin(little)]
3589        #[derive(Debug, PartialEq, Eq, Clone, Copy)]
3590        struct LeMsg {
3591            a: u16,
3592            b: u32,
3593        } // little-endian, byte-aligned (6 bytes)
3594
3595        #[test]
3596        fn pull_is_none_until_a_whole_message_arrives_then_reclaims() {
3597            let m = LeMsg {
3598                a: 0x1234,
3599                b: 0xDEAD_BEEF,
3600            };
3601            let bytes = m.to_bytes().unwrap();
3602
3603            let mut bb = BitBuf::new();
3604            bb.push(&bytes[..3]); // only part of the message
3605            assert_eq!(bb.pull::<LeMsg>().unwrap(), None); // wait for more — buffer untouched
3606            assert_eq!(bb.bit_len(), 24);
3607
3608            bb.push(&bytes[3..]); // the rest
3609            assert_eq!(bb.pull::<LeMsg>().unwrap(), Some(m)); // decodes (little-endian honored via LAYOUT)
3610            assert!(bb.is_empty()); // consumed bytes reclaimed
3611            assert_eq!(bb.pull::<LeMsg>().unwrap(), None);
3612        }
3613
3614        #[test]
3615        fn reassembles_sub_byte_boundary_messages_across_pushes() {
3616            let f1 = Frame {
3617                tag: u4::new(0xA),
3618                val: 0x12,
3619            };
3620            let f2 = Frame {
3621                tag: u4::new(0xB),
3622                val: 0x34,
3623            };
3624            // Pack contiguously: 24 bits / 3 bytes, with f2 starting at bit 12 (mid-byte).
3625            let mut w = BitWriter::new();
3626            f1.bit_encode(&mut w).unwrap();
3627            f2.bit_encode(&mut w).unwrap();
3628            let wire = w.into_bytes();
3629
3630            let mut bb = BitBuf::new();
3631            let mut out = Vec::new();
3632            // f1 spans the chunk boundary; the bit cursor keeps f2's sub-byte alignment.
3633            for chunk in [&wire[0..1], &wire[1..3]] {
3634                bb.push(chunk);
3635                while let Some(f) = bb.pull::<Frame>().unwrap() {
3636                    out.push(f);
3637                }
3638            }
3639            assert_eq!(out, vec![f1, f2]);
3640            assert!(bb.is_empty());
3641        }
3642
3643        #[test]
3644        fn clear_and_capacity() {
3645            let mut bb = BitBuf::with_capacity(64);
3646            bb.push(&[1, 2, 3]);
3647            assert_eq!(bb.bit_len(), 24);
3648            bb.clear();
3649            assert!(bb.is_empty());
3650        }
3651
3652        // BitBuf is a Source: it reads through the same `bit_decode` entry the renamed `decode` uses.
3653        // The default-order buffer reads a big message; `with_layout` reads a little one (this also
3654        // proves byte order is applied exactly once — no double-ordering in the Source delegation).
3655        #[test]
3656        fn reads_as_a_source_respecting_layout() {
3657            // big message via a default (msb/big) BitBuf
3658            let f = Frame {
3659                tag: u4::new(0xC),
3660                val: 0x9A,
3661            };
3662            let mut bb = BitBuf::new();
3663            bb.push(&f.to_bytes().unwrap());
3664            assert_eq!(<Frame as BitDecode>::bit_decode(&mut bb).unwrap(), f);
3665
3666            // little message via a layout-configured BitBuf (byte-aligned, so compact fully drains)
3667            let m = LeMsg {
3668                a: 0x1234,
3669                b: 0xDEAD_BEEF,
3670            };
3671            let mut bb = BitBuf::new().with_layout(<LeMsg as BitEncode>::LAYOUT);
3672            bb.push(&m.to_bytes().unwrap());
3673            let got = <LeMsg as BitDecode>::bit_decode(&mut bb).unwrap();
3674            assert_eq!(got, m); // would be byte-swapped if ordering double-applied
3675            bb.compact(); // Source path doesn't auto-reclaim
3676            assert!(bb.is_empty());
3677        }
3678
3679        // BitBuf is a `SeekSource`, so a `restore_position` message decodes over it through the
3680        // `decode` cursor path — exercising BitBuf's `seek_to_bit` (the rewind).
3681        #[test]
3682        fn as_a_seek_source_a_restore_position_message_decodes() {
3683            #[bin(big)]
3684            #[derive(Debug, PartialEq, Eq)]
3685            struct Peeked {
3686                #[br(restore_position)]
3687                tag: u8,
3688                full: u16,
3689            }
3690            let mut bb = BitBuf::new();
3691            bb.push(&[0xAB, 0xCD]);
3692            let p = Peeked::decode(&mut bb).unwrap();
3693            assert_eq!((p.tag, p.full), (0xAB, 0xABCD));
3694        }
3695
3696        // --- bounded (alloc-once) mode -----------------------------------------------------
3697
3698        #[bin(big)]
3699        #[derive(Debug, PartialEq, Eq)]
3700        struct Two {
3701            v: u16,
3702        }
3703
3704        #[test]
3705        fn bounded_try_push_respects_capacity_then_reclaims_in_place() {
3706            use bnb::CapacityError;
3707            let mut bb = BitBuf::bounded(4);
3708            assert_eq!(bb.capacity(), Some(4));
3709            bb.try_push(&[0x00, 0x01]).unwrap(); // 2 bytes
3710            bb.try_push(&[0x00, 0x02]).unwrap(); // 4 bytes — full
3711            // a 5th byte can't fit until something is drained
3712            assert!(matches!(
3713                bb.try_push(&[0xFF]),
3714                Err(CapacityError { cap: 4, .. })
3715            ));
3716            // drain one message → 2 live bytes; the dead prefix is reclaimed in place to fit more
3717            assert_eq!(bb.pull::<Two>().unwrap(), Some(Two { v: 1 }));
3718            bb.try_push(&[0x00, 0x03]).unwrap();
3719            assert_eq!(bb.pull::<Two>().unwrap(), Some(Two { v: 2 }));
3720            assert_eq!(bb.pull::<Two>().unwrap(), Some(Two { v: 3 }));
3721            assert!(bb.is_empty());
3722        }
3723
3724        #[test]
3725        fn grow_raises_a_bounded_capacity() {
3726            let mut bb = BitBuf::bounded(2);
3727            bb.try_push(&[0x00, 0x01]).unwrap();
3728            assert!(bb.try_push(&[0x02]).is_err()); // full at 2
3729            bb.grow(2); // the one explicit allocation
3730            assert_eq!(bb.capacity(), Some(4));
3731            bb.try_push(&[0x02, 0x03]).unwrap();
3732            assert_eq!(bb.bit_len(), 32);
3733        }
3734
3735        #[test]
3736        fn unbounded_try_push_never_fails() {
3737            let mut bb = BitBuf::new();
3738            assert_eq!(bb.capacity(), None);
3739            bb.try_push(&[1, 2, 3]).unwrap(); // no cap → grows, never errors
3740            assert_eq!(bb.bit_len(), 24);
3741        }
3742
3743        #[test]
3744        fn a_streaming_push_pull_loop_stays_within_a_tiny_cap() {
3745            // Pushed one message at a time and drained immediately, a bounded buffer reuses the same
3746            // allocation forever: each try_push fits because the prior message was reclaimed in place.
3747            let mut bb = BitBuf::bounded(2);
3748            for i in 0..100u16 {
3749                bb.try_push(&i.to_be_bytes()).unwrap();
3750                assert_eq!(bb.pull::<Two>().unwrap(), Some(Two { v: i }));
3751            }
3752            assert!(bb.is_empty());
3753        }
3754    }
3755
3756    #[cfg(feature = "bytes")]
3757    /// `bin_bytes.rs` — `bytes` integration (ROADMAP Phase 3, the `bytes` feature): zero-copy
3758    mod bytes_adapters {
3759
3760        use bnb::{BitEncode, BytesReader, BytesWriter, bin, u4, u12};
3761
3762        #[bin]
3763        #[derive(Debug, PartialEq, Eq, Clone)]
3764        struct Frame {
3765            a: u4,
3766            b: u12,
3767        }
3768
3769        #[test]
3770        fn round_trip_through_bytes() {
3771            let f = Frame {
3772                a: u4::new(0xA),
3773                b: u12::new(0x123),
3774            };
3775
3776            // Encode into a BytesWriter, then freeze to a zero-copy Bytes.
3777            let mut w = BytesWriter::new();
3778            f.bit_encode(&mut w).unwrap();
3779            let frozen = w.freeze();
3780            assert_eq!(&frozen[..], &[0xA1, 0x23]);
3781
3782            // Decode from an owned Bytes via BytesReader.
3783            let mut r = BytesReader::new(frozen.clone());
3784            let decoded = Frame::decode(&mut r).unwrap();
3785            assert_eq!(decoded, f);
3786        }
3787
3788        // A `restore_position` message decodes over `BytesReader` (a `SeekSource`), exercising its
3789        // `bit_pos`/`seek_to_bit`. The frame is produced via `BytesWriter::freeze` (no `bytes::` name).
3790        #[test]
3791        fn bytes_reader_seek_and_bit_pos() {
3792            use bnb::{Sink, Source};
3793            #[bin(big)]
3794            #[derive(Debug, PartialEq, Eq)]
3795            struct Peeked {
3796                #[br(restore_position)]
3797                tag: u8,
3798                full: u16,
3799            }
3800            let mut w = BytesWriter::new();
3801            w.write(0xABu8).unwrap();
3802            w.write(0xCDu8).unwrap();
3803            let mut r = BytesReader::new(w.freeze());
3804            assert_eq!(r.bit_pos(), 0);
3805            let p = Peeked::decode(&mut r).unwrap();
3806            assert_eq!((p.tag, p.full), (0xAB, 0xABCD));
3807        }
3808
3809        #[test]
3810        fn bytes_writer_with_layout_and_bit_pos() {
3811            use bnb::{BitOrder, ByteOrder, Layout, Sink};
3812            let mut w = BytesWriter::with_layout(Layout {
3813                bit: BitOrder::Lsb,
3814                byte: ByteOrder::Big,
3815            });
3816            assert_eq!(w.bit_pos(), 0);
3817            w.write(u4::new(0xA)).unwrap();
3818            assert_eq!(w.bit_pos(), 4);
3819        }
3820    }
3821}