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::string::{String, ToString};
31use alloc::vec::Vec;
32use core::fmt;
33
34use crate::field::{BitOrder, Bits, ByteOrder};
35
36/// A position-aware bit-codec error (it carries a span-like position). It records the
37/// **bit offset** where decoding/encoding failed and, when the derive can supply it,
38/// the **field** being processed.
39///
40/// # Examples
41///
42/// ```
43/// use bnb::{bin, ErrorKind};
44///
45/// #[bin(big)]
46/// #[derive(Debug)]
47/// struct Pair { a: u16, b: u16 }
48///
49/// let err = Pair::decode_exact(&[0x00]).unwrap_err(); // only one byte of four
50/// assert_eq!(err.at, 0);             // the bit offset where it failed
51/// assert_eq!(err.field, Some("a"));  // the field being read (the span)
52/// assert!(matches!(err.kind, ErrorKind::UnexpectedEof { .. }));
53/// ```
54#[derive(Clone, Debug, PartialEq, Eq)]
55pub struct BitError {
56    /// The cause.
57    pub kind: ErrorKind,
58    /// Absolute bit offset where the error occurred.
59    pub at: usize,
60    /// The field being decoded/encoded when it occurred, if recorded by the
61    /// derive (the innermost field — the "span"). `None` for low-level reader
62    /// errors with no field context.
63    pub field: Option<&'static str>,
64}
65
66/// The cause of a [`BitError`]. Non-exhaustive: later phases add variants
67/// (`BadMagic`, …).
68#[derive(Clone, Debug, PartialEq, Eq)]
69#[non_exhaustive]
70pub enum ErrorKind {
71    /// Ran past the end of a finite input (a slice): `needed` bits were requested,
72    /// `remaining` were left. Definitive — distinct from [`Incomplete`](ErrorKind::Incomplete).
73    UnexpectedEof {
74        /// Bits requested.
75        needed: usize,
76        /// Bits still available.
77        remaining: usize,
78    },
79    /// A streaming source ([`StreamBitReader`]) ran out mid-message: the caller
80    /// should read more bytes and retry. `needed` is a best-effort byte hint
81    /// (`None` when unknown). See [`BitError::is_incomplete`].
82    Incomplete {
83        /// Best-effort estimate of additional bytes needed, if known.
84        needed: Option<usize>,
85    },
86    /// `decode_exact` left whole bytes unconsumed after the message.
87    TrailingBytes {
88        /// Number of trailing bytes.
89        remaining: usize,
90    },
91    /// A single field exceeded the 128-bit carrier width.
92    TooWide {
93        /// The offending width.
94        width: usize,
95    },
96    /// An I/O error while encoding to a [`std::io::Write`] sink (the `std` feature).
97    #[cfg(feature = "std")]
98    Io(std::io::ErrorKind),
99    /// A `magic` constant read off the wire did not match. Both values are the
100    /// type-erased low-bit representations ([`Bits::into_bits`]).
101    BadMagic {
102        /// The constant the codec expected.
103        expected: u128,
104        /// The value actually read.
105        found: u128,
106    },
107    /// A `try_map` conversion from the wire representation failed; `message` is the
108    /// converter's `Display` output.
109    Convert {
110        /// The converter's error, rendered.
111        message: String,
112    },
113    /// A position directive (`restore_position`/seek) ran on a non-seekable
114    /// [`Source`] (a forward-only stream). Decode from a slice ([`BitReader`]) or a
115    /// seekable source instead.
116    NotSeekable,
117    /// A [`BufSource`] hit its retention cap before the message finished — the
118    /// framed message is larger than the configured bound (never unbounded).
119    BufferFull {
120        /// The cap, in bytes.
121        cap: usize,
122    },
123}
124
125impl BitError {
126    /// Builds an error at absolute bit offset `at`, with no field recorded yet.
127    #[must_use]
128    pub fn new(kind: ErrorKind, at: usize) -> Self {
129        Self {
130            kind,
131            at,
132            field: None,
133        }
134    }
135
136    /// Builds a [`ErrorKind::BadMagic`] error (a `magic` constant mismatched) at
137    /// absolute bit offset `at`. `expected`/`found` are the type-erased low-bit
138    /// values ([`Bits::into_bits`]).
139    #[must_use]
140    pub fn bad_magic(expected: u128, found: u128, at: usize) -> Self {
141        Self::new(ErrorKind::BadMagic { expected, found }, at)
142    }
143
144    /// Builds a [`ErrorKind::Convert`] error (a `try_map` conversion failed) at
145    /// absolute bit offset `at`.
146    #[must_use]
147    pub fn convert(message: String, at: usize) -> Self {
148        Self::new(ErrorKind::Convert { message }, at)
149    }
150
151    /// Records the field being processed, **if one is not already set** — so the
152    /// innermost field (set first as the error propagates up) wins. The derive
153    /// calls this per field.
154    #[must_use]
155    pub fn in_field(mut self, field: &'static str) -> Self {
156        if self.field.is_none() {
157            self.field = Some(field);
158        }
159        self
160    }
161
162    /// Whether this is the streaming "need more bytes" signal
163    /// ([`ErrorKind::Incomplete`]) — the caller should read more and retry, as
164    /// opposed to a definitive parse failure.
165    #[must_use]
166    pub fn is_incomplete(&self) -> bool {
167        matches!(self.kind, ErrorKind::Incomplete { .. })
168    }
169}
170
171#[cfg(feature = "std")]
172impl From<std::io::Error> for BitError {
173    /// Wraps a [`std::io::Error`] as [`ErrorKind::Io`] — so a `parse_with`/`write_with`
174    /// using [`Source::as_read`]/[`Sink::as_write`] can `?` `std::io` results straight
175    /// into a `BitError`. The bit offset is unknown at this boundary (recorded as `0`);
176    /// build with [`BitError::new`] if you need the precise position.
177    fn from(e: std::io::Error) -> Self {
178        BitError::new(ErrorKind::Io(e.kind()), 0)
179    }
180}
181
182impl fmt::Display for BitError {
183    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184        match &self.kind {
185            ErrorKind::UnexpectedEof { needed, remaining } => write!(
186                f,
187                "unexpected end of input: needed {needed} bits, {remaining} remain"
188            )?,
189            ErrorKind::Incomplete { needed } => match needed {
190                Some(n) => write!(f, "incomplete: need ~{n} more bytes")?,
191                None => write!(f, "incomplete: need more bytes")?,
192            },
193            ErrorKind::TrailingBytes { remaining } => {
194                write!(f, "{remaining} trailing bytes after the message")?;
195            }
196            ErrorKind::TooWide { width } => {
197                write!(f, "field width {width} exceeds the 128-bit carrier")?;
198            }
199            #[cfg(feature = "std")]
200            ErrorKind::Io(kind) => write!(f, "I/O error: {kind:?}")?,
201            ErrorKind::BadMagic { expected, found } => {
202                write!(f, "bad magic: expected {expected:#x}, found {found:#x}")?;
203            }
204            ErrorKind::Convert { message } => {
205                write!(f, "conversion failed: {message}")?;
206            }
207            ErrorKind::NotSeekable => {
208                write!(f, "a position directive ran on a non-seekable source")?;
209            }
210            ErrorKind::BufferFull { cap } => {
211                write!(f, "buffered source exceeded its {cap}-byte cap")?;
212            }
213        }
214        write!(f, " at bit {}", self.at)?;
215        if let Some(field) = self.field {
216            write!(f, " (field `{field}`)")?;
217        }
218        Ok(())
219    }
220}
221
222impl core::error::Error for BitError {}
223
224impl From<crate::error::Error> for BitError {
225    /// Bridges a construction error (e.g. `UInt::try_new`) into a codec error, so it
226    /// `?`-propagates inside a custom `parse_with`/`write_with` fn or a converter
227    /// that returns [`BitError`]. The offset is unknown (`0`) — the codec's own
228    /// reads/writes carry the real bit offset; this is only for borrowed construction
229    /// failures with no cursor context.
230    #[inline]
231    fn from(e: crate::error::Error) -> Self {
232        BitError::convert(e.to_string(), 0)
233    }
234}
235
236/// The bit width of a [`Bits`] value's type. Generated `BIT_LEN` consts and the
237/// alignment guard call this to size a `magic` constant whose type they only have
238/// as an expression (the value is taken by reference purely to infer `T`).
239#[doc(hidden)]
240#[must_use]
241pub const fn bits_of<T: Bits>(_value: &T) -> u32 {
242    T::BITS
243}
244
245/// Reads a `magic` constant and verifies it equals `expected`, compared as
246/// type-erased bits (so `T` needs only [`Bits`] — no `Copy`/`PartialEq`, and `T`
247/// is pinned by the argument so the generated call site needs no turbofish). On
248/// mismatch: [`ErrorKind::BadMagic`] at the magic's offset.
249#[doc(hidden)]
250pub fn verify_magic<T: Bits, S: Source>(r: &mut S, expected: T) -> Result<(), BitError> {
251    let at = r.bit_pos();
252    let found: T = r.read()?;
253    let (e, g) = (expected.into_bits(), found.into_bits());
254    if e != g {
255        return Err(BitError::bad_magic(e, g, at));
256    }
257    Ok(())
258}
259
260/// Reads a wire value `W` (inferred from `f`'s argument type) and maps it to the
261/// field type `T` — backs `#[br(map = …)]`.
262///
263/// # Errors
264/// Propagates the read [`BitError`].
265#[doc(hidden)]
266pub fn read_mapped<W, T, S, F>(r: &mut S, f: F) -> Result<T, BitError>
267where
268    W: Bits,
269    S: Source,
270    F: FnOnce(W) -> T,
271{
272    let raw: W = r.read()?;
273    Ok(f(raw))
274}
275
276/// Fallible variant — backs `#[br(try_map = …)]`. A conversion error becomes an
277/// [`ErrorKind::Convert`] at the value's offset.
278///
279/// # Errors
280/// The read [`BitError`], or the converter's failure as [`ErrorKind::Convert`].
281#[doc(hidden)]
282pub fn read_try_mapped<W, T, E, S, F>(r: &mut S, f: F) -> Result<T, BitError>
283where
284    W: Bits,
285    S: Source,
286    E: fmt::Display,
287    F: FnOnce(W) -> Result<T, E>,
288{
289    let at = r.bit_pos();
290    let raw: W = r.read()?;
291    f(raw).map_err(|e| BitError::convert(e.to_string(), at))
292}
293
294/// Maps the field `T` to its wire value `W` and writes it — backs `#[bw(map = …)]`.
295///
296/// # Errors
297/// Propagates the write [`BitError`].
298#[doc(hidden)]
299pub fn write_mapped<W, T, K, F>(w: &mut K, value: &T, f: F) -> Result<(), BitError>
300where
301    W: Bits,
302    K: Sink,
303    F: FnOnce(&T) -> W,
304{
305    w.write(f(value))
306}
307
308/// A typed bit/byte amount for positioning directives — `4.bits()`, `3.bytes()` —
309/// resolving to a bit count. Bring it in with `use bnb::prelude::*`.
310///
311/// # Examples
312///
313/// ```
314/// use bnb::prelude::*;
315/// assert_eq!(4u32.bits(), 4);
316/// assert_eq!(3u32.bytes(), 24);
317/// ```
318///
319/// Used by the positioning directives, e.g. `#[br(pad_before = 2u32.bytes())]` — see
320/// [`guide::directives`](crate::guide::directives).
321pub trait BitAmount: Copy {
322    /// This many **bits**.
323    fn bits(self) -> u32;
324    /// This many **bytes** (× 8 bits).
325    fn bytes(self) -> u32;
326}
327
328macro_rules! impl_bit_amount {
329    ($($t:ty),*) => {$(
330        impl BitAmount for $t {
331            fn bits(self) -> u32 { self as u32 }
332            fn bytes(self) -> u32 { (self as u32) * 8 }
333        }
334    )*};
335}
336impl_bit_amount!(u8, u16, u32, u64, usize, i32);
337
338/// Skips `bits` forward (consuming and discarding) — backs `#[br(pad_before/after)]`.
339///
340/// # Errors
341/// Propagates the source's [`BitError`].
342#[doc(hidden)]
343pub fn skip_read<S: Source>(r: &mut S, bits: u32) -> Result<(), BitError> {
344    let mut left = bits;
345    while left > 0 {
346        let n = left.min(128);
347        r.read_bits(n)?;
348        left -= n;
349    }
350    Ok(())
351}
352
353/// Writes `bits` zero bits forward — the write dual of [`skip_read`].
354///
355/// # Errors
356/// Propagates the sink's [`BitError`].
357#[doc(hidden)]
358pub fn skip_write<K: Sink>(w: &mut K, bits: u32) -> Result<(), BitError> {
359    let mut left = bits;
360    while left > 0 {
361        let n = left.min(128);
362        w.write_bits(0, n)?;
363        left -= n;
364    }
365    Ok(())
366}
367
368/// Skips forward to the next byte boundary — backs `#[br(align_before/after)]`.
369///
370/// # Errors
371/// Propagates the source's [`BitError`].
372#[doc(hidden)]
373pub fn align_read<S: Source>(r: &mut S) -> Result<(), BitError> {
374    let pad = (8 - (r.bit_pos() % 8)) % 8;
375    skip_read(r, pad as u32)
376}
377
378/// Pads with zero bits to the next byte boundary — the write dual of [`align_read`].
379///
380/// # Errors
381/// Propagates the sink's [`BitError`].
382#[doc(hidden)]
383pub fn align_write<K: Sink>(w: &mut K) -> Result<(), BitError> {
384    let pad = (8 - (w.bit_pos() % 8)) % 8;
385    skip_write(w, pad as u32)
386}
387
388/// The wire layout: bit packing order **and** byte order, threaded through the
389/// cursors and entry points. `#[bin(big|little)]` and `#[bin(bit_order = msb|lsb)]`
390/// set it; the default is MSB-first, big-endian (RFC/network order).
391///
392/// # Examples
393///
394/// ```
395/// use bnb::{BitReader, BitOrder, ByteOrder, Layout};
396///
397/// // Read a 16-bit value little-endian instead of the default big-endian.
398/// let layout = Layout { bit: BitOrder::Msb, byte: ByteOrder::Little };
399/// let mut r = BitReader::with_layout(&[0x34, 0x12], layout);
400/// assert_eq!(r.read::<u16>().unwrap(), 0x1234);
401/// assert_eq!(Layout::default(), Layout { bit: BitOrder::Msb, byte: ByteOrder::Big });
402/// ```
403#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
404pub struct Layout {
405    /// Bit packing order — does the first bit land in the high or low bit.
406    pub bit: BitOrder,
407    /// Byte order, applied to byte-multiple values.
408    pub byte: ByteOrder,
409}
410
411/// Reverses the low `bits / 8` bytes of `raw` when little-endian and the width is a
412/// whole number of bytes (byte order applies only to byte-multiple values); a
413/// no-op for big-endian or sub-byte widths. It is its own inverse, so read and
414/// write share it.
415#[inline]
416fn apply_byte_order(raw: u128, bits: u32, byte: ByteOrder) -> u128 {
417    if byte == ByteOrder::Big || bits % 8 != 0 {
418        return raw;
419    }
420    let n = (bits / 8) as usize;
421    let le = raw.to_le_bytes();
422    let mut out = 0u128;
423    let mut i = 0;
424    while i < n {
425        out |= (le[i] as u128) << (8 * (n - 1 - i));
426        i += 1;
427    }
428    out
429}
430
431/// Extracts `n` (`<= 128`) bits starting at absolute bit offset `pos` from `buf`, in
432/// `order`, returned right-aligned in a `u128` (byte order is applied separately by
433/// `read`). The single bit-extraction routine behind every slice-backed [`Source`]
434/// ([`BitReader`], [`BufSource`], [`SeekReader`]). The caller must have bounds-checked
435/// `pos + n <= buf.len() * 8` and `n <= 128`.
436///
437/// **Fast path:** when the read is byte-aligned (`pos % 8 == 0` and `n % 8 == 0`) the
438/// bytes are accumulated whole — one iteration per byte, not per bit (≈8× fewer).
439#[inline]
440fn extract_bits(buf: &[u8], pos: usize, n: usize, order: BitOrder) -> u128 {
441    if pos % 8 == 0 && n % 8 == 0 {
442        let start = pos / 8;
443        let nbytes = n / 8;
444        let mut acc = 0u128;
445        match order {
446            // MSB-first byte-aligned == big-endian byte concatenation.
447            BitOrder::Msb => {
448                for j in 0..nbytes {
449                    acc = (acc << 8) | u128::from(buf[start + j]);
450                }
451            }
452            // LSB-first byte-aligned == little-endian byte concatenation.
453            BitOrder::Lsb => {
454                for j in 0..nbytes {
455                    acc |= u128::from(buf[start + j]) << (8 * j);
456                }
457            }
458        }
459        return acc;
460    }
461    // General path: one bit at a time (handles sub-byte offsets/widths).
462    let mut acc = 0u128;
463    match order {
464        BitOrder::Msb => {
465            for k in 0..n {
466                let p = pos + k;
467                acc = (acc << 1) | u128::from((buf[p >> 3] >> (7 - (p & 7))) & 1);
468            }
469        }
470        BitOrder::Lsb => {
471            for k in 0..n {
472                let p = pos + k;
473                acc |= u128::from((buf[p >> 3] >> (p & 7)) & 1) << k;
474            }
475        }
476    }
477    acc
478}
479
480/// Appends the low `n` (`<= 128`) bits of `value` to `out` at absolute bit offset
481/// `bit_pos`, in `order` — the write dual of [`extract_bits`], used by [`BitWriter`].
482///
483/// **Fast path:** when appending byte-aligned at the end (`bit_pos % 8 == 0`,
484/// `n % 8 == 0`, cursor at `out.len()`) the bytes are pushed whole, one per byte.
485#[inline]
486fn emit_bits(out: &mut Vec<u8>, bit_pos: usize, value: u128, n: usize, order: BitOrder) {
487    if n % 8 == 0 && bit_pos % 8 == 0 && bit_pos / 8 == out.len() {
488        let nbytes = n / 8;
489        match order {
490            BitOrder::Msb => {
491                for j in 0..nbytes {
492                    out.push((value >> (8 * (nbytes - 1 - j))) as u8);
493                }
494            }
495            BitOrder::Lsb => {
496                for j in 0..nbytes {
497                    out.push((value >> (8 * j)) as u8);
498                }
499            }
500        }
501        return;
502    }
503    for k in 0..n {
504        let p = bit_pos + k;
505        // MSB-first emits the field's high bit first (i = n-1-k); LSB-first emits its
506        // low bit first (i = k) into the byte's low bit.
507        let (i, shift) = match order {
508            BitOrder::Msb => (n - 1 - k, 7 - (p & 7)),
509            BitOrder::Lsb => (k, p & 7),
510        };
511        let byte_idx = p >> 3;
512        if byte_idx == out.len() {
513            out.push(0);
514        }
515        if (value >> i) & 1 != 0 {
516            out[byte_idx] |= 1 << shift;
517        }
518    }
519}
520
521/// A cursor that reads values at arbitrary bit offsets from a byte slice, in a
522/// chosen [`BitOrder`] (MSB-first by default — `bit 0` is the high bit of byte 0,
523/// the RFC/ETSI ASCII-art convention; LSB-first for serial/PHY layers).
524///
525/// # Examples
526///
527/// ```
528/// use bnb::{BitReader, u4, u12};
529///
530/// let mut r = BitReader::new(&[0xAB, 0xCD]);
531/// assert_eq!(r.read::<u4>().unwrap(), u4::new(0xA)); // 4 bits
532/// assert_eq!(r.read::<u12>().unwrap(), u12::new(0xBCD)); // the next 12, straddling a byte
533/// assert_eq!(r.remaining_bits(), 0);
534/// ```
535#[derive(Clone, Debug)]
536pub struct BitReader<'a> {
537    bytes: &'a [u8],
538    bit_pos: usize,
539    order: BitOrder,
540    byte: ByteOrder,
541}
542
543impl<'a> BitReader<'a> {
544    /// Wraps `bytes`, positioned at bit 0, **MSB-first**, big-endian.
545    #[must_use]
546    pub fn new(bytes: &'a [u8]) -> Self {
547        Self::with_order(bytes, BitOrder::Msb)
548    }
549
550    /// Wraps `bytes`, positioned at bit 0, in the given bit order (big-endian).
551    #[must_use]
552    pub fn with_order(bytes: &'a [u8], order: BitOrder) -> Self {
553        Self::with_layout(
554            bytes,
555            Layout {
556                bit: order,
557                byte: ByteOrder::Big,
558            },
559        )
560    }
561
562    /// Wraps `bytes`, positioned at bit 0, in the given [`Layout`] (bit + byte order).
563    #[must_use]
564    pub fn with_layout(bytes: &'a [u8], layout: Layout) -> Self {
565        Self {
566            bytes,
567            bit_pos: 0,
568            order: layout.bit,
569            byte: layout.byte,
570        }
571    }
572
573    /// The current absolute bit offset.
574    #[must_use]
575    pub fn bit_pos(&self) -> usize {
576        self.bit_pos
577    }
578
579    /// Bits not yet consumed.
580    #[must_use]
581    pub fn remaining_bits(&self) -> usize {
582        self.bytes.len() * 8 - self.bit_pos
583    }
584
585    /// Reads `n` (`<= 128`) bits into the low bits of a `u128`, MSB-first.
586    ///
587    /// # Errors
588    /// [`ErrorKind::TooWide`] if `n > 128`; [`ErrorKind::UnexpectedEof`] if fewer
589    /// than `n` bits remain. Either carries the current bit offset.
590    #[inline]
591    pub fn read_bits(&mut self, n: u32) -> Result<u128, BitError> {
592        let n = n as usize;
593        if n > 128 {
594            return Err(BitError::new(ErrorKind::TooWide { width: n }, self.bit_pos));
595        }
596        if n > self.remaining_bits() {
597            return Err(BitError::new(
598                ErrorKind::UnexpectedEof {
599                    needed: n,
600                    remaining: self.remaining_bits(),
601                },
602                self.bit_pos,
603            ));
604        }
605        let acc = extract_bits(self.bytes, self.bit_pos, n, self.order);
606        self.bit_pos += n;
607        Ok(acc)
608    }
609
610    /// Reads one [`Bits`] value of its declared width, applying the byte order to a
611    /// byte-multiple value.
612    ///
613    /// # Errors
614    /// As [`read_bits`](Self::read_bits).
615    #[inline]
616    pub fn read<T: Bits>(&mut self) -> Result<T, BitError> {
617        let raw = self.read_bits(T::BITS)?;
618        Ok(T::from_bits(apply_byte_order(raw, T::BITS, self.byte)))
619    }
620
621    /// Moves the cursor to absolute bit `pos`. This needs no `Seek` trait — the whole
622    /// buffer is in hand, so a seek is just cursor arithmetic. (Enables e.g. DNS
623    /// name-compression pointers.)
624    ///
625    /// # Errors
626    /// [`ErrorKind::UnexpectedEof`] if `pos` is past the end of the buffer.
627    pub fn seek_to_bit(&mut self, pos: usize) -> Result<(), BitError> {
628        let end = self.bytes.len() * 8;
629        if pos > end {
630            return Err(BitError::new(
631                ErrorKind::UnexpectedEof {
632                    needed: pos,
633                    remaining: end,
634                },
635                self.bit_pos,
636            ));
637        }
638        self.bit_pos = pos;
639        Ok(())
640    }
641
642    /// Advances the cursor to the next byte boundary (a no-op if already aligned).
643    pub fn align_to_byte(&mut self) {
644        self.bit_pos = (self.bit_pos + 7) & !7;
645    }
646}
647
648/// A sink that appends values at arbitrary bit offsets in a chosen [`BitOrder`]
649/// (MSB-first by default), growing a byte buffer (the final partial byte is
650/// zero-padded).
651///
652/// # Examples
653///
654/// ```
655/// use bnb::{BitWriter, u4, u12};
656///
657/// let mut w = BitWriter::new();
658/// w.write(u4::new(0xA)).unwrap();
659/// w.write(u12::new(0xBCD)).unwrap();
660/// assert_eq!(w.bit_len(), 16);
661/// assert_eq!(w.into_bytes(), [0xAB, 0xCD]);
662/// ```
663#[derive(Clone, Debug, Default)]
664pub struct BitWriter {
665    bytes: Vec<u8>,
666    bit_pos: usize,
667    order: BitOrder,
668    byte: ByteOrder,
669}
670
671impl BitWriter {
672    /// An empty **MSB-first**, big-endian writer.
673    #[must_use]
674    pub fn new() -> Self {
675        Self::default()
676    }
677
678    /// An empty writer in the given bit order (big-endian).
679    #[must_use]
680    pub fn with_order(order: BitOrder) -> Self {
681        Self::with_layout(Layout {
682            bit: order,
683            byte: ByteOrder::Big,
684        })
685    }
686
687    /// An empty writer in the given [`Layout`] (bit + byte order).
688    #[must_use]
689    pub fn with_layout(layout: Layout) -> Self {
690        Self {
691            bytes: Vec::new(),
692            bit_pos: 0,
693            order: layout.bit,
694            byte: layout.byte,
695        }
696    }
697
698    /// Bits written so far.
699    #[must_use]
700    pub fn bit_len(&self) -> usize {
701        self.bit_pos
702    }
703
704    /// Appends the low `n` (`<= 128`) bits of `value`, in the writer's bit order.
705    ///
706    /// # Errors
707    /// [`ErrorKind::TooWide`] if `n > 128`.
708    #[inline]
709    pub fn write_bits(&mut self, value: u128, n: u32) -> Result<(), BitError> {
710        let n = n as usize;
711        if n > 128 {
712            return Err(BitError::new(ErrorKind::TooWide { width: n }, self.bit_pos));
713        }
714        emit_bits(&mut self.bytes, self.bit_pos, value, n, self.order);
715        self.bit_pos += n;
716        Ok(())
717    }
718
719    /// Appends one [`Bits`] value of its declared width, applying the byte order to
720    /// a byte-multiple value.
721    ///
722    /// # Errors
723    /// As [`write_bits`](Self::write_bits).
724    #[inline]
725    pub fn write<T: Bits>(&mut self, value: T) -> Result<(), BitError> {
726        let raw = apply_byte_order(value.into_bits(), T::BITS, self.byte);
727        self.write_bits(raw, T::BITS)
728    }
729
730    /// Consumes the writer, returning the packed bytes.
731    #[must_use]
732    pub fn into_bytes(self) -> Vec<u8> {
733        self.bytes
734    }
735}
736
737/// A bit-level **input** the codec recurses over. Implemented by [`BitReader`]
738/// (in-memory slice), [`StreamBitReader`] (forward `Read`), [`BufSource`] (a
739/// retain-and-seek socket adapter), and [`SeekReader`] (`Read + Seek`); the codec is
740/// generic over `Source`, so one decoder runs over any of them — see
741/// [`guide::io`](crate::guide::io).
742///
743/// # Examples
744///
745/// ```
746/// use bnb::{BitReader, Source, u4};
747///
748/// // A reader generic over any `Source`.
749/// fn first_nibble<S: Source>(s: &mut S) -> u4 { s.read().unwrap() }
750///
751/// let mut r = BitReader::new(&[0xA5]);
752/// assert_eq!(first_nibble(&mut r), u4::new(0xA));
753/// ```
754pub trait Source {
755    /// Reads `n` (`<= 128`) bits MSB-first into the low bits of a `u128`.
756    ///
757    /// # Errors
758    /// Propagates the reader's [`BitError`].
759    fn read_bits(&mut self, n: u32) -> Result<u128, BitError>;
760
761    /// The current absolute bit offset (for position-aware errors).
762    fn bit_pos(&self) -> usize;
763
764    /// The byte order applied to a byte-multiple value (default big-endian).
765    fn byte_order(&self) -> ByteOrder {
766        ByteOrder::Big
767    }
768
769    /// Moves the cursor to absolute bit `pos`. The default — for a forward-only
770    /// source — fails with [`ErrorKind::NotSeekable`]; seekable sources (the slice
771    /// [`BitReader`]) override it. A [`SeekSource`] guarantees this works.
772    ///
773    /// # Errors
774    /// [`ErrorKind::NotSeekable`] unless the source is seekable.
775    fn seek_to_bit(&mut self, _pos: usize) -> Result<(), BitError> {
776        Err(BitError::new(ErrorKind::NotSeekable, self.bit_pos()))
777    }
778
779    /// Reads one [`Bits`] value of its declared width, applying the byte order.
780    ///
781    /// # Errors
782    /// As [`read_bits`](Source::read_bits).
783    #[inline]
784    fn read<T: Bits>(&mut self) -> Result<T, BitError> {
785        let raw = self.read_bits(T::BITS)?;
786        Ok(T::from_bits(apply_byte_order(
787            raw,
788            T::BITS,
789            self.byte_order(),
790        )))
791    }
792
793    /// Borrows this source as a [`std::io::Read`] over its bytes — for handing the
794    /// cursor to `std::io`-based code from a `#[br(parse_with = …)]` (e.g. a decoder, or
795    /// a `Read`-based parser). Reads 8 bits per byte; see [`SourceReader`]. Only with
796    /// the `std` feature.
797    #[cfg(feature = "std")]
798    fn as_read(&mut self) -> SourceReader<'_, Self>
799    where
800        Self: Sized,
801    {
802        SourceReader(self)
803    }
804}
805
806/// A [`std::io::Read`] view over a [`Source`], from [`Source::as_read`]. Each `read`
807/// pulls 8 bits per byte through [`Source::read_bits`], so it works at any bit
808/// alignment (you will normally be byte-aligned). A read failure surfaces as an
809/// `io::Error` when no bytes were produced, or ends the read short once some were — the
810/// `std::io` convention. This is the outbound dual of [`BufSource`]/[`SeekReader`] (which
811/// adapt a `std::io::Read` *into* a `Source`).
812#[cfg(feature = "std")]
813pub struct SourceReader<'a, S: Source>(&'a mut S);
814
815#[cfg(feature = "std")]
816impl<S: Source> std::io::Read for SourceReader<'_, S> {
817    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
818        for (i, slot) in buf.iter_mut().enumerate() {
819            match self.0.read_bits(8) {
820                Ok(b) => *slot = b as u8,
821                Err(e) if i == 0 => {
822                    return Err(std::io::Error::new(
823                        std::io::ErrorKind::UnexpectedEof,
824                        e.to_string(),
825                    ));
826                }
827                Err(_) => return Ok(i),
828            }
829        }
830        Ok(buf.len())
831    }
832}
833
834/// A [`Source`] that can seek (its [`seek_to_bit`](Source::seek_to_bit) is real, not
835/// the failing default). A `#[bin]` message that uses `restore_position` bounds its
836/// generated `decode_from` on this trait, so a forward-only stream is rejected at
837/// compile time. Implemented by [`BitReader`], [`BufSource`], and [`SeekReader`]
838/// (and, with the `bytes` feature, `BytesReader`).
839pub trait SeekSource: Source {}
840
841impl SeekSource for BitReader<'_> {}
842
843/// A bit-level **output** the codec writes to — the in-memory [`BitWriter`]
844/// (and, under the `bytes` feature, `BytesWriter`). Encode to any
845/// [`std::io::Write`] via a message's generated `encode` method.
846///
847/// # Examples
848///
849/// ```
850/// use bnb::{BitWriter, Sink, u4};
851///
852/// // A writer generic over any `Sink`.
853/// fn put_nibble<K: Sink>(k: &mut K, v: u4) { k.write(v).unwrap(); }
854///
855/// let mut w = BitWriter::new();
856/// put_nibble(&mut w, u4::new(0xA));
857/// put_nibble(&mut w, u4::new(0x5));
858/// assert_eq!(w.into_bytes(), [0xA5]);
859/// ```
860pub trait Sink {
861    /// Appends the low `n` (`<= 128`) bits of `value`, MSB-first.
862    ///
863    /// # Errors
864    /// Propagates the writer's [`BitError`].
865    fn write_bits(&mut self, value: u128, n: u32) -> Result<(), BitError>;
866
867    /// The number of bits written so far.
868    fn bit_pos(&self) -> usize;
869
870    /// The byte order applied to a byte-multiple value (default big-endian).
871    fn byte_order(&self) -> ByteOrder {
872        ByteOrder::Big
873    }
874
875    /// Appends one [`Bits`] value of its declared width, applying the byte order.
876    ///
877    /// # Errors
878    /// As [`write_bits`](Sink::write_bits).
879    #[inline]
880    fn write<T: Bits>(&mut self, value: T) -> Result<(), BitError> {
881        let raw = apply_byte_order(value.into_bits(), T::BITS, self.byte_order());
882        self.write_bits(raw, T::BITS)
883    }
884
885    /// Borrows this sink as a [`std::io::Write`] — the dual of [`Source::as_read`], for
886    /// handing the cursor to `std::io`-based code from a `#[bw(write_with = …)]`. Writes 8
887    /// bits per byte; see [`SinkWriter`]. Only with the `std` feature.
888    #[cfg(feature = "std")]
889    fn as_write(&mut self) -> SinkWriter<'_, Self>
890    where
891        Self: Sized,
892    {
893        SinkWriter(self)
894    }
895}
896
897/// A [`std::io::Write`] view over a [`Sink`], from [`Sink::as_write`]. Each `write`
898/// pushes 8 bits per byte through [`Sink::write_bits`]. The outbound dual of
899/// [`SourceReader`]; `flush` is a no-op (the sink owns its buffer).
900#[cfg(feature = "std")]
901pub struct SinkWriter<'a, K: Sink>(&'a mut K);
902
903#[cfg(feature = "std")]
904impl<K: Sink> std::io::Write for SinkWriter<'_, K> {
905    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
906        for &b in buf {
907            self.0
908                .write_bits(u128::from(b), 8)
909                .map_err(|e| std::io::Error::other(e.to_string()))?;
910        }
911        Ok(buf.len())
912    }
913
914    fn flush(&mut self) -> std::io::Result<()> {
915        Ok(())
916    }
917}
918
919impl Source for BitReader<'_> {
920    #[inline]
921    fn read_bits(&mut self, n: u32) -> Result<u128, BitError> {
922        BitReader::read_bits(self, n)
923    }
924    #[inline]
925    fn bit_pos(&self) -> usize {
926        self.bit_pos
927    }
928    #[inline]
929    fn byte_order(&self) -> ByteOrder {
930        self.byte
931    }
932    #[inline]
933    fn seek_to_bit(&mut self, pos: usize) -> Result<(), BitError> {
934        BitReader::seek_to_bit(self, pos)
935    }
936}
937
938impl Sink for BitWriter {
939    #[inline]
940    fn write_bits(&mut self, value: u128, n: u32) -> Result<(), BitError> {
941        BitWriter::write_bits(self, value, n)
942    }
943    #[inline]
944    fn bit_pos(&self) -> usize {
945        self.bit_pos
946    }
947    #[inline]
948    fn byte_order(&self) -> ByteOrder {
949        self.byte
950    }
951}
952
953/// A message decoded from a bit stream — the recursion point a
954/// `#[derive(BitDecode)]` struct implements (reading each field in declaration
955/// order). Leaf fields are any [`Bits`] type; nested messages recurse. Fixed- or
956/// variable-length; a fixed-length message *also* implements [`FixedBitLen`].
957///
958/// Most users reach for [`#[bin]`](macro@crate::bin) (which derives this plus
959/// [`BitEncode`] and a builder); the bare derives are the codec on its own, for fields
960/// that straddle byte boundaries.
961///
962/// # Examples
963///
964/// ```
965/// use bnb::{BitDecode, BitEncode, u4, u12};
966///
967/// // A 4-bit tag + a 12-bit length, straddling the byte boundary.
968/// #[derive(BitDecode, BitEncode, Debug, PartialEq)]
969/// struct Frame { tag: u4, len: u12 }
970///
971/// let f = Frame::decode_exact(&[0xAB, 0xCD]).unwrap();
972/// assert_eq!(f, Frame { tag: u4::new(0xA), len: u12::new(0xBCD) });
973/// assert_eq!(f.to_bytes().unwrap(), [0xAB, 0xCD]); // round-trips
974/// ```
975pub trait BitDecode: Sized {
976    /// Decodes `Self` from any [`Source`], advancing its cursor.
977    ///
978    /// # Errors
979    /// Propagates the source's [`BitError`].
980    fn bit_decode<S: Source>(r: &mut S) -> Result<Self, BitError>;
981}
982
983/// A message whose encoded length is a **compile-time constant** — i.e. it has no
984/// variable-length (`count`-driven `Vec`) field. The derive implements this only
985/// for fixed messages; it sizes a fixed byte region when the message is embedded
986/// in a byte stream (e.g. a `#[nested]` field's contribution to its parent's
987/// width). A `count`-bearing message implements [`BitDecode`]/[`BitEncode`] but
988/// **not** this.
989pub trait FixedBitLen {
990    /// Total encoded width of the message in bits — the sum of its fields' widths.
991    const BIT_LEN: u32;
992}
993
994/// A message encoded to a bit stream — the dual of [`BitDecode`].
995pub trait BitEncode {
996    /// The message's bit/byte order, used to size a fresh [`BitWriter`] when
997    /// encoding to a `Vec`/writer. The derive sets it from the struct's declared
998    /// `bit_order`/`bytes`; a hand-written impl that only ever encodes into a
999    /// caller-supplied [`Sink`] can leave the default.
1000    const LAYOUT: Layout = Layout {
1001        bit: BitOrder::Msb,
1002        byte: ByteOrder::Big,
1003    };
1004
1005    /// Encodes `self` into any [`Sink`], advancing its cursor.
1006    ///
1007    /// # Errors
1008    /// Propagates the sink's [`BitError`].
1009    fn bit_encode<K: Sink>(&self, w: &mut K) -> Result<(), BitError>;
1010}
1011
1012/// `encode(writer)` for any [`BitEncode`] message — encodes to a `Vec` (using the
1013/// type's [`LAYOUT`](BitEncode::LAYOUT)) and writes it to a [`std::io::Write`]
1014/// sink. A blanket-implemented extension trait, so bring it into scope
1015/// (`use bnb::prelude::*` or `use bnb::EncodeExt`) to call `.encode(&mut w)`.
1016/// Only available with the `std` feature; in `no_std` use [`BitEncode`]'s
1017/// generated `to_bytes`/`encode_into`.
1018#[cfg(feature = "std")]
1019pub trait EncodeExt: BitEncode {
1020    /// Encodes `self` to any [`std::io::Write`] (socket, file, `Vec`).
1021    ///
1022    /// # Errors
1023    /// [`ErrorKind::Io`] on a write failure, else the encode error.
1024    fn encode<W: std::io::Write>(&self, w: &mut W) -> Result<(), BitError>
1025    where
1026        Self: Sized,
1027    {
1028        encode_to_writer(self, w, Self::LAYOUT)
1029    }
1030}
1031
1032#[cfg(feature = "std")]
1033impl<T: BitEncode> EncodeExt for T {}
1034
1035/// The "write reserved fields as their spec value" encode path, generated for a
1036/// `#[bin]` message that has a `reserved` field. The inherent `to_spec_bytes` /
1037/// `spec_encode_into` ride on this; the `std`-only [`SpecEncodeExt`] adds
1038/// `spec_encode(writer)`.
1039pub trait SpecEncode {
1040    /// The message's bit/byte order (mirrors [`BitEncode::LAYOUT`]).
1041    const SPEC_LAYOUT: Layout;
1042
1043    /// Encodes `self` into a [`Sink`], writing reserved fields as their spec value
1044    /// (ignoring any stored override).
1045    ///
1046    /// # Errors
1047    /// Propagates the sink's [`BitError`].
1048    fn spec_bit_encode<K: Sink>(&self, w: &mut K) -> Result<(), BitError>;
1049}
1050
1051/// `spec_encode(writer)` for any [`SpecEncode`] message — the spec-value dual of
1052/// [`EncodeExt`]. Blanket-implemented; bring it into scope to call it. Only with
1053/// the `std` feature; in `no_std` use the generated `to_spec_bytes`.
1054#[cfg(feature = "std")]
1055pub trait SpecEncodeExt: SpecEncode {
1056    /// Encodes `self` to any [`std::io::Write`], reserved fields as their spec value.
1057    ///
1058    /// # Errors
1059    /// [`ErrorKind::Io`] on a write failure, else the encode error.
1060    fn spec_encode<W: std::io::Write>(&self, w: &mut W) -> Result<(), BitError>
1061    where
1062        Self: Sized,
1063    {
1064        encode_to_writer_with(w, Self::SPEC_LAYOUT, |bw| self.spec_bit_encode(bw))
1065    }
1066}
1067
1068#[cfg(feature = "std")]
1069impl<T: SpecEncode> SpecEncodeExt for T {}
1070
1071/// Polymorphic decode **with context** `A` — the companion to a `#[bin(ctx(...))]`
1072/// type's inherent `decode_with`, for hand-written generic combinators and
1073/// trait-object parsing (ctx Layer 2). Every [`BitDecode`] type is `DecodeWith<()>`
1074/// (blanket), and a ctx type is `DecodeWith<…Ctx>`, so one bound `T: DecodeWith<A>`
1075/// spans both context-free and context-taking messages. Inherent `Type::decode_with`
1076/// call sites are unaffected.
1077pub trait DecodeWith<A>: Sized {
1078    /// Decodes `Self` from a [`Source`] given `args`.
1079    ///
1080    /// # Errors
1081    /// Propagates the decode [`BitError`].
1082    fn decode_with<S: Source>(r: &mut S, args: A) -> Result<Self, BitError>;
1083}
1084
1085/// The dual of [`DecodeWith`] — polymorphic encode with context `A`.
1086pub trait EncodeWith<A> {
1087    /// Encodes `self` into a [`Sink`] given `args`.
1088    ///
1089    /// # Errors
1090    /// Propagates the encode [`BitError`].
1091    fn encode_with<K: Sink>(&self, w: &mut K, args: A) -> Result<(), BitError>;
1092}
1093
1094impl<T: BitDecode> DecodeWith<()> for T {
1095    fn decode_with<S: Source>(r: &mut S, _args: ()) -> Result<Self, BitError> {
1096        T::bit_decode(r)
1097    }
1098}
1099
1100impl<T: BitEncode> EncodeWith<()> for T {
1101    fn encode_with<K: Sink>(&self, w: &mut K, _args: ()) -> Result<(), BitError> {
1102        self.bit_encode(w)
1103    }
1104}
1105
1106// ---------------------------------------------------------------------------
1107// Entry-point helpers — the logic behind the `#[derive]`-generated inherent
1108// methods (`Type::decode`/`peek`/`decode_exact`/`encode`/`to_bytes`). Kept here
1109// so the logic lives in one place rather than monomorphized inline per type;
1110// doc-hidden because the public surface is the generated methods.
1111// ---------------------------------------------------------------------------
1112
1113/// Decodes one message from the front of `buf`, advancing `buf` past the bytes
1114/// consumed (the tail stays in `buf`). Transactional: on error `buf` is
1115/// unchanged. Backs `Type::decode`.
1116///
1117/// # Errors
1118/// Propagates the decode [`BitError`].
1119#[doc(hidden)]
1120pub fn decode_consume<T: BitDecode>(buf: &mut &[u8], layout: Layout) -> Result<T, BitError> {
1121    let input = core::mem::take(buf);
1122    let mut r = BitReader::with_layout(input, layout);
1123    match T::bit_decode(&mut r) {
1124        Ok(v) => {
1125            *buf = &input[r.bit_pos().div_ceil(8)..];
1126            Ok(v)
1127        }
1128        Err(e) => {
1129            *buf = input;
1130            Err(e)
1131        }
1132    }
1133}
1134
1135/// Decodes one message from `bytes` without consuming the caller's buffer
1136/// (tail-tolerant). Backs `Type::peek`.
1137///
1138/// # Errors
1139/// Propagates the decode [`BitError`].
1140#[doc(hidden)]
1141pub fn decode_peek<T: BitDecode>(bytes: &[u8], layout: Layout) -> Result<T, BitError> {
1142    T::bit_decode(&mut BitReader::with_layout(bytes, layout))
1143}
1144
1145/// `decode_peek` over a caller-supplied closure (no consumption requirement) — backs a
1146/// `#[bin]` enum's `peek_variant`, which runs only the dispatch decision over `bytes`.
1147///
1148/// # Errors
1149/// Propagates the closure's [`BitError`].
1150#[doc(hidden)]
1151pub fn decode_peek_with<T, F>(bytes: &[u8], layout: Layout, f: F) -> Result<T, BitError>
1152where
1153    F: FnOnce(&mut BitReader) -> Result<T, BitError>,
1154{
1155    f(&mut BitReader::with_layout(bytes, layout))
1156}
1157
1158/// `decode_exact` over a caller-supplied decode closure rather than the
1159/// [`BitDecode`] trait — backs the `ctx`-parameterized `Type::decode_with_exact`
1160/// (a `ctx` type takes a context argument, so it has no plain `bit_decode`).
1161///
1162/// # Errors
1163/// [`ErrorKind::TrailingBytes`] if whole bytes remain, else the closure's error.
1164#[doc(hidden)]
1165pub fn decode_exact_with<T, F>(bytes: &[u8], layout: Layout, f: F) -> Result<T, BitError>
1166where
1167    F: FnOnce(&mut BitReader) -> Result<T, BitError>,
1168{
1169    let mut r = BitReader::with_layout(bytes, layout);
1170    let v = f(&mut r)?;
1171    let consumed = r.bit_pos().div_ceil(8);
1172    if consumed < bytes.len() {
1173        return Err(BitError::new(
1174            ErrorKind::TrailingBytes {
1175                remaining: bytes.len() - consumed,
1176            },
1177            r.bit_pos(),
1178        ));
1179    }
1180    Ok(v)
1181}
1182
1183/// `to_bytes` over a caller-supplied encode closure — backs the `ctx`-parameterized
1184/// `Type::to_bytes_with`.
1185///
1186/// # Errors
1187/// Propagates the closure's [`BitError`].
1188#[doc(hidden)]
1189pub fn encode_to_vec_with<F>(layout: Layout, f: F) -> Result<Vec<u8>, BitError>
1190where
1191    F: FnOnce(&mut BitWriter) -> Result<(), BitError>,
1192{
1193    let mut w = BitWriter::with_layout(layout);
1194    f(&mut w)?;
1195    Ok(w.into_bytes())
1196}
1197
1198/// Decodes and requires every **whole byte** consumed; a sub-byte tail in the
1199/// final byte is treated as padding. Backs `Type::decode_exact`.
1200///
1201/// # Errors
1202/// [`ErrorKind::TrailingBytes`] if whole bytes remain, else the decode error.
1203#[doc(hidden)]
1204pub fn decode_exact<T: BitDecode>(bytes: &[u8], layout: Layout) -> Result<T, BitError> {
1205    let mut r = BitReader::with_layout(bytes, layout);
1206    let v = T::bit_decode(&mut r)?;
1207    let consumed = r.bit_pos().div_ceil(8);
1208    if consumed < bytes.len() {
1209        return Err(BitError::new(
1210            ErrorKind::TrailingBytes {
1211                remaining: bytes.len() - consumed,
1212            },
1213            r.bit_pos(),
1214        ));
1215    }
1216    Ok(v)
1217}
1218
1219/// Encodes `value` to a `Vec<u8>`. Backs `Type::to_bytes`.
1220///
1221/// # Errors
1222/// Propagates the encode [`BitError`].
1223#[doc(hidden)]
1224pub fn encode_to_vec<T: BitEncode>(value: &T, layout: Layout) -> Result<Vec<u8>, BitError> {
1225    let mut w = BitWriter::with_layout(layout);
1226    value.bit_encode(&mut w)?;
1227    Ok(w.into_bytes())
1228}
1229
1230/// Encodes `value` to any [`std::io::Write`]. Backs [`EncodeExt::encode`].
1231///
1232/// # Errors
1233/// [`ErrorKind::Io`] on a write failure, else the encode error.
1234#[cfg(feature = "std")]
1235#[doc(hidden)]
1236pub fn encode_to_writer<T: BitEncode, W: std::io::Write>(
1237    value: &T,
1238    w: &mut W,
1239    layout: Layout,
1240) -> Result<(), BitError> {
1241    let mut bw = BitWriter::with_layout(layout);
1242    value.bit_encode(&mut bw)?;
1243    let at = bw.bit_len();
1244    w.write_all(&bw.into_bytes())
1245        .map_err(|e| BitError::new(ErrorKind::Io(e.kind()), at))
1246}
1247
1248/// `encode_to_writer` over a caller-supplied encode closure — backs
1249/// [`SpecEncodeExt::spec_encode`] (whose write body differs from the plain `bit_encode`).
1250///
1251/// # Errors
1252/// [`ErrorKind::Io`] on a write failure, else the closure's error.
1253#[cfg(feature = "std")]
1254#[doc(hidden)]
1255pub fn encode_to_writer_with<W, F>(w: &mut W, layout: Layout, f: F) -> Result<(), BitError>
1256where
1257    W: std::io::Write,
1258    F: FnOnce(&mut BitWriter) -> Result<(), BitError>,
1259{
1260    let mut bw = BitWriter::with_layout(layout);
1261    f(&mut bw)?;
1262    let at = bw.bit_len();
1263    w.write_all(&bw.into_bytes())
1264        .map_err(|e| BitError::new(ErrorKind::Io(e.kind()), at))
1265}
1266
1267/// Reads a fixed `[u8; N]` byte array (`N * 8` bits) from the cursor. Backs a
1268/// `[u8; N]` payload field; `N` is inferred from the field type. Variable-length
1269/// payloads (`Vec` + `#[br(count = …)]`) take a separate push-based path that
1270/// grows by element, so an attacker-controlled count can't over-allocate.
1271///
1272/// # Errors
1273/// Propagates the source's [`BitError`].
1274#[doc(hidden)]
1275pub fn read_byte_array<const N: usize, S: Source>(r: &mut S) -> Result<[u8; N], BitError> {
1276    let mut arr = [0u8; N];
1277    for b in &mut arr {
1278        *b = r.read_bits(8)? as u8;
1279    }
1280    Ok(arr)
1281}
1282
1283/// Peeks up to `max` bytes without consuming them — reads them, then rewinds. Returns
1284/// however many are available (fewer than `max` at end-of-input). Backs variable-width
1285/// `#[bin]` enum magic dispatch (peek the longest magic, match a prefix, then seek past
1286/// the matched one). Like other seeking directives it bounds the generated `decode_from`
1287/// on [`SeekSource`]; a forward-only source fails at runtime with
1288/// [`ErrorKind::NotSeekable`].
1289///
1290/// # Errors
1291/// [`ErrorKind::NotSeekable`] if the source can't rewind.
1292#[doc(hidden)]
1293pub fn peek_bytes<S: Source>(r: &mut S, max: usize) -> Result<Vec<u8>, BitError> {
1294    let start = r.bit_pos();
1295    let mut out = Vec::with_capacity(max);
1296    for _ in 0..max {
1297        match r.read_bits(8) {
1298            Ok(b) => out.push(b as u8),
1299            Err(_) => break, // end of input — a shorter magic may still match
1300        }
1301    }
1302    r.seek_to_bit(start)?;
1303    Ok(out)
1304}
1305
1306/// Writes a fixed `[u8; N]` byte array. Backs a `[u8; N]` payload field.
1307///
1308/// # Errors
1309/// Propagates the sink's [`BitError`].
1310#[doc(hidden)]
1311pub fn write_byte_array<const N: usize, K: Sink>(arr: &[u8; N], w: &mut K) -> Result<(), BitError> {
1312    for &b in arr {
1313        w.write_bits(u128::from(b), 8)?;
1314    }
1315    Ok(())
1316}
1317
1318/// A *forward-only* bit reader over any [`std::io::Read`] — the streaming counterpart
1319/// to the in-memory [`BitReader`], for a stream you read once and don't seek.
1320///
1321/// It is bounded on `Read` **only, not `Seek`**, so it works over inputs that can't
1322/// seek (a socket, or a `&[u8]`, which is `Read` but not `Seek`). A message that needs
1323/// to seek (`#[br(restore_position)]`) won't decode through it — use a [`BufSource`] or
1324/// [`SeekReader`] for that. Reads up to 128 bits per call (the [`Source`] width
1325/// ceiling); running out mid-message yields [`ErrorKind::Incomplete`] ("read more and
1326/// retry").
1327///
1328/// # Examples
1329///
1330/// ```
1331/// use bnb::{bin, StreamBitReader};
1332///
1333/// #[bin(big)]
1334/// #[derive(Debug, PartialEq)]
1335/// struct Word { value: u32 }
1336///
1337/// // `&[u8]` is `Read` but not `Seek` — exactly the forward-only case.
1338/// let data: &[u8] = &[0x12, 0x34, 0x56, 0x78];
1339/// let mut s = StreamBitReader::new(data);
1340/// assert_eq!(Word::decode_from(&mut s).unwrap(), Word { value: 0x1234_5678 });
1341/// ```
1342#[cfg(feature = "std")]
1343#[derive(Debug)]
1344pub struct StreamBitReader<R> {
1345    inner: R,
1346    /// Leftover bits from the last partially-consumed byte, right-aligned in the low
1347    /// `lead_bits` bits (MSB-first, so they are the *high* bits of the next read).
1348    /// Always fewer than 8.
1349    lead: u32,
1350    lead_bits: u32,
1351    /// Total bits consumed so far (for position-aware errors).
1352    pos: usize,
1353}
1354
1355#[cfg(feature = "std")]
1356impl<R: std::io::Read> StreamBitReader<R> {
1357    /// Wraps a byte source.
1358    pub fn new(inner: R) -> Self {
1359        Self {
1360            inner,
1361            lead: 0,
1362            lead_bits: 0,
1363            pos: 0,
1364        }
1365    }
1366
1367    /// The total number of bits consumed so far.
1368    #[must_use]
1369    pub fn bit_pos(&self) -> usize {
1370        self.pos
1371    }
1372
1373    /// Reads `n` (`<= 128`) bits MSB-first, pulling bytes from the source as needed.
1374    ///
1375    /// # Errors
1376    /// [`ErrorKind::TooWide`] if `n > 128`; [`ErrorKind::Incomplete`] if the
1377    /// source runs out mid-field (read more and retry). Either carries the bit
1378    /// offset.
1379    pub fn read_bits(&mut self, n: u32) -> Result<u128, BitError> {
1380        if n > 128 {
1381            return Err(BitError::new(
1382                ErrorKind::TooWide { width: n as usize },
1383                self.pos,
1384            ));
1385        }
1386        let at = self.pos;
1387        // Build the result MSB-first, consuming the leftover bits then whole bytes.
1388        // The accumulator never holds more than `n` (<= 128) bits, so it can't
1389        // overflow — unlike a "shift bytes in, mask out" buffer, which is why the old
1390        // byte-accumulator capped at 64 and this caps at the full 128.
1391        let mut result: u128 = 0;
1392        let mut need = n;
1393        while need > 0 {
1394            if self.lead_bits == 0 {
1395                let mut b = [0u8; 1];
1396                if self.inner.read_exact(&mut b).is_err() {
1397                    // Ran out mid-field: "need more bytes" (buffer and retry), not a
1398                    // definitive end-of-input.
1399                    return Err(BitError::new(ErrorKind::Incomplete { needed: None }, at));
1400                }
1401                self.lead = u32::from(b[0]);
1402                self.lead_bits = 8;
1403            }
1404            let take = need.min(self.lead_bits);
1405            // The top `take` of the `lead_bits` leftover bits (MSB-first).
1406            let shift = self.lead_bits - take;
1407            let chunk = (self.lead >> shift) & ((1u32 << take) - 1);
1408            result = (result << take) | u128::from(chunk);
1409            self.lead_bits -= take;
1410            self.lead &= (1u32 << self.lead_bits) - 1; // keep the unconsumed low bits
1411            need -= take;
1412        }
1413        self.pos += n as usize;
1414        Ok(result)
1415    }
1416
1417    /// Reads one [`Bits`] value (width `<= 128`) of its declared width.
1418    ///
1419    /// # Errors
1420    /// As [`read_bits`](Self::read_bits).
1421    pub fn read<T: Bits>(&mut self) -> Result<T, BitError> {
1422        Ok(T::from_bits(self.read_bits(T::BITS)?))
1423    }
1424}
1425
1426#[cfg(feature = "std")]
1427impl<R: std::io::Read> Source for StreamBitReader<R> {
1428    fn read_bits(&mut self, n: u32) -> Result<u128, BitError> {
1429        StreamBitReader::read_bits(self, n)
1430    }
1431    fn bit_pos(&self) -> usize {
1432        self.pos
1433    }
1434}
1435
1436/// A **seekable** [`Source`] over a forward `Read` (a socket): it *retains* the bytes
1437/// it has read, so a seek-using message (`restore_position`) works over a non-seekable
1438/// stream by seeking within the retained buffer, reading more on demand. It is
1439/// **bounded** — a retention `cap` (default 64 KiB) past which it errors
1440/// [`ErrorKind::BufferFull`] rather than buffering unboundedly. The
1441/// "continuously-receiving peer that also needs to seek" case.
1442///
1443/// # Examples
1444///
1445/// ```
1446/// use bnb::{bin, BufSource};
1447///
1448/// #[bin(big)]
1449/// #[derive(Debug, PartialEq)]
1450/// struct Word { value: u32 }
1451///
1452/// let mut src = BufSource::new(&[0x12, 0x34, 0x56, 0x78][..]); // any `Read`
1453/// assert_eq!(Word::decode_from(&mut src).unwrap(), Word { value: 0x1234_5678 });
1454/// ```
1455#[cfg(feature = "std")]
1456#[derive(Clone, Debug)]
1457pub struct BufSource<R> {
1458    inner: R,
1459    buf: Vec<u8>,
1460    bit_pos: usize,
1461    cap: usize,
1462    layout: Layout,
1463    eof: bool,
1464}
1465
1466#[cfg(feature = "std")]
1467impl<R: std::io::Read> BufSource<R> {
1468    /// Wraps `inner` with the default 64 KiB retention cap, MSB-first big-endian.
1469    #[must_use]
1470    pub fn new(inner: R) -> Self {
1471        Self::with_cap(inner, 64 * 1024)
1472    }
1473
1474    /// Wraps `inner` with a retention `cap` (bytes), MSB-first big-endian.
1475    #[must_use]
1476    pub fn with_cap(inner: R, cap: usize) -> Self {
1477        Self::with_cap_and_layout(inner, cap, Layout::default())
1478    }
1479
1480    /// Wraps `inner` with a retention `cap` (bytes) and [`Layout`].
1481    #[must_use]
1482    pub fn with_cap_and_layout(inner: R, cap: usize, layout: Layout) -> Self {
1483        Self {
1484            inner,
1485            buf: Vec::new(),
1486            bit_pos: 0,
1487            cap,
1488            layout,
1489            eof: false,
1490        }
1491    }
1492
1493    /// Reads from `inner` until `buf` holds at least `byte_end` bytes (or EOF/cap).
1494    fn fill_to(&mut self, byte_end: usize) -> Result<(), BitError> {
1495        while self.buf.len() < byte_end && !self.eof {
1496            if self.buf.len() >= self.cap {
1497                return Err(BitError::new(
1498                    ErrorKind::BufferFull { cap: self.cap },
1499                    self.bit_pos,
1500                ));
1501            }
1502            let want = (byte_end - self.buf.len()).min(self.cap - self.buf.len());
1503            let start = self.buf.len();
1504            self.buf.resize(start + want, 0);
1505            match self.inner.read(&mut self.buf[start..]) {
1506                Ok(0) => {
1507                    self.buf.truncate(start);
1508                    self.eof = true;
1509                }
1510                Ok(got) => self.buf.truncate(start + got),
1511                Err(e) => {
1512                    self.buf.truncate(start);
1513                    return Err(BitError::new(ErrorKind::Io(e.kind()), self.bit_pos));
1514                }
1515            }
1516        }
1517        Ok(())
1518    }
1519}
1520
1521#[cfg(feature = "std")]
1522impl<R: std::io::Read> Source for BufSource<R> {
1523    fn read_bits(&mut self, n: u32) -> Result<u128, BitError> {
1524        if n > 128 {
1525            return Err(BitError::new(
1526                ErrorKind::TooWide { width: n as usize },
1527                self.bit_pos,
1528            ));
1529        }
1530        let byte_end = (self.bit_pos + n as usize).div_ceil(8);
1531        self.fill_to(byte_end)?;
1532        if self.buf.len() < byte_end {
1533            return Err(BitError::new(
1534                ErrorKind::Incomplete {
1535                    needed: Some(byte_end - self.buf.len()),
1536                },
1537                self.bit_pos,
1538            ));
1539        }
1540        let acc = extract_bits(&self.buf, self.bit_pos, n as usize, self.layout.bit);
1541        self.bit_pos += n as usize;
1542        Ok(acc)
1543    }
1544    fn bit_pos(&self) -> usize {
1545        self.bit_pos
1546    }
1547    fn byte_order(&self) -> ByteOrder {
1548        self.layout.byte
1549    }
1550    fn seek_to_bit(&mut self, pos: usize) -> Result<(), BitError> {
1551        // Seek within the retained buffer; a later read fills more on demand.
1552        // Backward seeks (`restore_position`) hit already-retained bytes.
1553        self.bit_pos = pos;
1554        Ok(())
1555    }
1556}
1557
1558#[cfg(feature = "std")]
1559impl<R: std::io::Read> SeekSource for BufSource<R> {}
1560
1561/// A [`SeekSource`] over a seekable reader (`Read + Seek`, e.g. a `File`): it seeks
1562/// via [`std::io::Seek`] to the byte holding the bit cursor, **without buffering** —
1563/// the large-file / container-format case. For a *non*-seekable stream that still
1564/// needs to seek, use [`BufSource`].
1565///
1566/// # Examples
1567///
1568/// ```
1569/// use bnb::{bin, SeekReader};
1570/// use std::io::Cursor;
1571///
1572/// #[bin(big)]
1573/// #[derive(Debug, PartialEq)]
1574/// struct Word { value: u32 }
1575///
1576/// let mut f = SeekReader::new(Cursor::new(vec![0x12u8, 0x34, 0x56, 0x78]));
1577/// assert_eq!(Word::decode_from(&mut f).unwrap(), Word { value: 0x1234_5678 });
1578/// ```
1579#[cfg(feature = "std")]
1580#[derive(Clone, Debug)]
1581pub struct SeekReader<R> {
1582    inner: R,
1583    bit_pos: usize,
1584    layout: Layout,
1585}
1586
1587#[cfg(feature = "std")]
1588impl<R: std::io::Read + std::io::Seek> SeekReader<R> {
1589    /// Wraps `inner` at bit 0, MSB-first big-endian.
1590    #[must_use]
1591    pub fn new(inner: R) -> Self {
1592        Self::with_layout(inner, Layout::default())
1593    }
1594
1595    /// Wraps `inner` at bit 0 with the given [`Layout`].
1596    #[must_use]
1597    pub fn with_layout(inner: R, layout: Layout) -> Self {
1598        Self {
1599            inner,
1600            bit_pos: 0,
1601            layout,
1602        }
1603    }
1604}
1605
1606#[cfg(feature = "std")]
1607impl<R: std::io::Read + std::io::Seek> Source for SeekReader<R> {
1608    fn read_bits(&mut self, n: u32) -> Result<u128, BitError> {
1609        if n > 128 {
1610            return Err(BitError::new(
1611                ErrorKind::TooWide { width: n as usize },
1612                self.bit_pos,
1613            ));
1614        }
1615        let bit_off = self.bit_pos % 8;
1616        let byte_start = (self.bit_pos / 8) as u64;
1617        let nbytes = (bit_off + n as usize).div_ceil(8);
1618        self.inner
1619            .seek(std::io::SeekFrom::Start(byte_start))
1620            .map_err(|e| BitError::new(ErrorKind::Io(e.kind()), self.bit_pos))?;
1621        let mut buf = vec![0u8; nbytes];
1622        self.inner.read_exact(&mut buf).map_err(|e| {
1623            let kind = if e.kind() == std::io::ErrorKind::UnexpectedEof {
1624                ErrorKind::UnexpectedEof {
1625                    needed: n as usize,
1626                    remaining: 0,
1627                }
1628            } else {
1629                ErrorKind::Io(e.kind())
1630            };
1631            BitError::new(kind, self.bit_pos)
1632        })?;
1633        let acc = extract_bits(&buf, bit_off, n as usize, self.layout.bit);
1634        self.bit_pos += n as usize;
1635        Ok(acc)
1636    }
1637    fn bit_pos(&self) -> usize {
1638        self.bit_pos
1639    }
1640    fn byte_order(&self) -> ByteOrder {
1641        self.layout.byte
1642    }
1643    fn seek_to_bit(&mut self, pos: usize) -> Result<(), BitError> {
1644        self.bit_pos = pos; // the actual `io::Seek` happens on the next read
1645        Ok(())
1646    }
1647}
1648
1649#[cfg(feature = "std")]
1650impl<R: std::io::Read + std::io::Seek> SeekSource for SeekReader<R> {}
1651
1652/// Zero-copy `bytes`-crate adapters (the `bytes` feature): own a `Bytes` frame to
1653/// decode, encode into a `BytesMut` you `freeze()` to a `Bytes` — the async/tokio
1654/// framing case. Off by default so the core stays dependency-light.
1655#[cfg(feature = "bytes")]
1656mod bytes_io {
1657    use super::{BitError, BitReader, BitWriter, ByteOrder, Layout, SeekSource, Sink, Source};
1658
1659    /// A [`SeekSource`](super::SeekSource) that **owns** a `bytes::Bytes` frame (no
1660    /// borrow), decoding bits from it. Constructing it from a `Bytes` is a refcount
1661    /// bump (zero copy).
1662    #[derive(Clone, Debug)]
1663    pub struct BytesReader {
1664        data: bytes::Bytes,
1665        bit_pos: usize,
1666        layout: Layout,
1667    }
1668
1669    impl BytesReader {
1670        /// Owns `data`, positioned at bit 0, MSB-first big-endian.
1671        #[must_use]
1672        pub fn new(data: bytes::Bytes) -> Self {
1673            Self::with_layout(data, Layout::default())
1674        }
1675
1676        /// Owns `data` with the given [`Layout`](super::Layout).
1677        #[must_use]
1678        pub fn with_layout(data: bytes::Bytes, layout: Layout) -> Self {
1679            Self {
1680                data,
1681                bit_pos: 0,
1682                layout,
1683            }
1684        }
1685    }
1686
1687    impl Source for BytesReader {
1688        fn read_bits(&mut self, n: u32) -> Result<u128, BitError> {
1689            let mut br = BitReader::with_layout(&self.data, self.layout);
1690            br.seek_to_bit(self.bit_pos)?;
1691            let v = br.read_bits(n)?;
1692            self.bit_pos = Source::bit_pos(&br);
1693            Ok(v)
1694        }
1695        fn bit_pos(&self) -> usize {
1696            self.bit_pos
1697        }
1698        fn byte_order(&self) -> ByteOrder {
1699            self.layout.byte
1700        }
1701        fn seek_to_bit(&mut self, pos: usize) -> Result<(), BitError> {
1702            self.bit_pos = pos;
1703            Ok(())
1704        }
1705    }
1706
1707    impl SeekSource for BytesReader {}
1708
1709    /// A [`Sink`](super::Sink) that encodes into a `bytes::BytesMut`; [`freeze`]
1710    /// hands off a zero-copy `Bytes`.
1711    ///
1712    /// [`freeze`]: BytesWriter::freeze
1713    #[derive(Clone, Debug, Default)]
1714    pub struct BytesWriter {
1715        inner: BitWriter,
1716    }
1717
1718    impl BytesWriter {
1719        /// An empty MSB-first, big-endian writer.
1720        #[must_use]
1721        pub fn new() -> Self {
1722            Self::default()
1723        }
1724
1725        /// An empty writer in the given [`Layout`](super::Layout).
1726        #[must_use]
1727        pub fn with_layout(layout: Layout) -> Self {
1728            Self {
1729                inner: BitWriter::with_layout(layout),
1730            }
1731        }
1732
1733        /// The encoded bytes as a zero-copy `Bytes` (the final partial byte is
1734        /// zero-padded).
1735        #[must_use]
1736        pub fn freeze(self) -> bytes::Bytes {
1737            bytes::Bytes::from(self.inner.into_bytes())
1738        }
1739    }
1740
1741    impl Sink for BytesWriter {
1742        fn write_bits(&mut self, value: u128, n: u32) -> Result<(), BitError> {
1743            self.inner.write_bits(value, n)
1744        }
1745        fn bit_pos(&self) -> usize {
1746            Sink::bit_pos(&self.inner)
1747        }
1748        fn byte_order(&self) -> ByteOrder {
1749            Sink::byte_order(&self.inner)
1750        }
1751    }
1752}
1753
1754#[cfg(feature = "bytes")]
1755pub use bytes_io::{BytesReader, BytesWriter};
1756
1757#[cfg(test)]
1758mod unit {
1759    use super::*;
1760    use crate::{u4, u12};
1761
1762    #[test]
1763    fn unaligned_round_trip() {
1764        let mut w = BitWriter::new();
1765        w.write(u4::new(0xA)).unwrap();
1766        w.write(u12::new(0xBCD)).unwrap();
1767        assert_eq!(w.bit_len(), 16);
1768        let bytes = w.into_bytes();
1769        assert_eq!(bytes, [0xAB, 0xCD]);
1770
1771        let mut r = BitReader::new(&bytes);
1772        assert_eq!(r.read::<u4>().unwrap(), u4::new(0xA));
1773        assert_eq!(r.read::<u12>().unwrap(), u12::new(0xBCD));
1774        assert_eq!(r.remaining_bits(), 0);
1775    }
1776
1777    #[test]
1778    fn eof_is_an_error_not_a_panic() {
1779        let mut r = BitReader::new(&[0xFF]);
1780        assert_eq!(r.read::<u4>().unwrap(), u4::new(0xF));
1781        let err = r.read_bits(8).unwrap_err();
1782        assert_eq!(
1783            err.kind,
1784            ErrorKind::UnexpectedEof {
1785                needed: 8,
1786                remaining: 4
1787            }
1788        );
1789        assert_eq!(err.at, 4, "error records the bit offset");
1790        assert!(err.field.is_none(), "no field context at the reader level");
1791    }
1792
1793    #[test]
1794    fn too_wide_is_rejected() {
1795        let mut r = BitReader::new(&[0u8; 32]);
1796        let err = r.read_bits(129).unwrap_err();
1797        assert_eq!(err.kind, ErrorKind::TooWide { width: 129 });
1798    }
1799
1800    #[test]
1801    fn stream_reader_matches_slice_up_to_128_bits() {
1802        // The `Source` contract allows reads up to 128 bits; the forward streaming
1803        // reader must agree with the slice reader across the whole range, including
1804        // wide (> 64-bit) and byte-straddling reads.
1805        let bytes: Vec<u8> = (0u8..16).collect(); // 0x00 01 02 … 0F
1806
1807        // A single 128-bit read.
1808        let mut s = StreamBitReader::new(&bytes[..]);
1809        let mut r = BitReader::new(&bytes);
1810        assert_eq!(s.read_bits(128).unwrap(), r.read_bits(128).unwrap());
1811
1812        // A 100-bit then 28-bit split (each crosses byte boundaries and the second
1813        // starts mid-byte, exercising the leftover-bits path).
1814        let mut s = StreamBitReader::new(&bytes[..]);
1815        let mut r = BitReader::new(&bytes);
1816        assert_eq!(s.read_bits(100).unwrap(), r.read_bits(100).unwrap());
1817        assert_eq!(s.read_bits(28).unwrap(), r.read_bits(28).unwrap());
1818
1819        // Over-wide is rejected at 128 now, not 64.
1820        let mut s = StreamBitReader::new(&bytes[..]);
1821        assert_eq!(
1822            s.read_bits(65).unwrap(),
1823            BitReader::new(&bytes).read_bits(65).unwrap(),
1824            "a 65-bit read used to be rejected"
1825        );
1826        let mut s = StreamBitReader::new(&bytes[..]);
1827        assert_eq!(
1828            s.read_bits(129).unwrap_err().kind,
1829            ErrorKind::TooWide { width: 129 }
1830        );
1831    }
1832}