Skip to main content

naia_serde/
bit_reader.rs

1// BitReader
2//
3// Internals: bits are consumed from a u32 scratch register, refilled one byte
4// at a time from the wire buffer. Bits are stored LSB-first, matching the
5// writer's encoding, which lets the decoder accumulate values without any
6// reverse_bits call. u32 scratch keeps all operations native on wasm32.
7
8use crate::SerdeErr;
9
10pub struct BitReader<'b> {
11    state: BitReaderState,
12    buffer: &'b [u8],
13}
14
15impl<'b> BitReader<'b> {
16    pub fn new(buffer: &'b [u8]) -> Self {
17        Self {
18            state: BitReaderState {
19                scratch: 0,
20                scratch_bits: 0,
21                buffer_index: 0,
22            },
23            buffer,
24        }
25    }
26
27    pub fn bytes_len(&self) -> usize {
28        self.buffer.len()
29    }
30
31    pub fn to_owned(&self) -> OwnedBitReader {
32        OwnedBitReader {
33            state: self.state,
34            buffer: self.buffer.into(),
35        }
36    }
37
38    #[inline(always)]
39    pub fn read_bit(&mut self) -> Result<bool, SerdeErr> {
40        if self.state.scratch_bits == 0 {
41            if self.state.buffer_index == self.buffer.len() {
42                return Err(SerdeErr);
43            }
44            self.state.scratch = self.buffer[self.state.buffer_index] as u32;
45            self.state.buffer_index += 1;
46            self.state.scratch_bits = 8;
47        }
48        let bit = self.state.scratch & 1 != 0;
49        self.state.scratch >>= 1;
50        self.state.scratch_bits -= 1;
51        Ok(bit)
52    }
53
54    #[inline(always)]
55    pub(crate) fn read_byte(&mut self) -> Result<u8, SerdeErr> {
56        // Fast path: a full byte is already in scratch.
57        if self.state.scratch_bits >= 8 {
58            let byte = (self.state.scratch & 0xFF) as u8;
59            self.state.scratch >>= 8;
60            self.state.scratch_bits -= 8;
61            return Ok(byte);
62        }
63        // General path: accumulate 8 bits LSB-first.
64        let mut output = 0u8;
65        for i in 0..8u8 {
66            if self.read_bit()? {
67                output |= 1 << i;
68            }
69        }
70        Ok(output)
71    }
72}
73
74// OwnedBitReader
75
76pub struct OwnedBitReader {
77    state: BitReaderState,
78    buffer: Box<[u8]>,
79}
80
81impl OwnedBitReader {
82    pub fn new(buffer: &[u8]) -> Self {
83        Self {
84            state: BitReaderState {
85                scratch: 0,
86                scratch_bits: 0,
87                buffer_index: 0,
88            },
89            buffer: buffer.into(),
90        }
91    }
92
93    pub fn borrow(&'_ self) -> BitReader<'_> {
94        BitReader {
95            state: self.state,
96            buffer: &self.buffer,
97        }
98    }
99
100    pub fn take_buffer(self) -> Box<[u8]> {
101        self.buffer
102    }
103}
104
105// BitReaderState
106#[derive(Copy, Clone)]
107struct BitReaderState {
108    scratch: u32,
109    scratch_bits: u32,
110    buffer_index: usize,
111}