Skip to main content

arc_mac/
bitreader_be.rs

1// SPDX-License-Identifier: MIT
2//! Big-endian (MSB-first) bit reader shared by the StuffIt Huffman (method 3)
3//! and LZAH (method 5) codecs. Matches XADMaster's `CSInputNextBit` /
4//! `CSInputNextBitString` (the non-`LE` variants).
5
6/// MSB-first bit reader over a byte slice. Past EOF reads as zero bits.
7pub struct BitReaderBE<'a> {
8    data: &'a [u8],
9    pos: usize,
10    buf: u64,
11    nbits: u32,
12}
13
14impl<'a> BitReaderBE<'a> {
15    pub fn new(data: &'a [u8]) -> Self {
16        BitReaderBE {
17            data,
18            pos: 0,
19            buf: 0,
20            nbits: 0,
21        }
22    }
23
24    fn fill(&mut self) {
25        while self.nbits <= 56 && self.pos < self.data.len() {
26            self.buf = (self.buf << 8) | self.data[self.pos] as u64;
27            self.pos += 1;
28            self.nbits += 8;
29        }
30    }
31
32    /// Read `n` bits (1..=32), MSB-first.
33    pub fn next_bits(&mut self, n: u32) -> u32 {
34        if n == 0 {
35            return 0;
36        }
37        if self.nbits < n {
38            self.fill();
39        }
40        if self.nbits < n {
41            let avail = self.nbits;
42            let v = if avail == 0 {
43                0
44            } else {
45                ((self.buf << (n - avail)) & mask(n)) as u32
46            };
47            self.buf = 0;
48            self.nbits = 0;
49            return v;
50        }
51        let v = ((self.buf >> (self.nbits - n)) & mask(n)) as u32;
52        self.nbits -= n;
53        v
54    }
55
56    pub fn next_bit(&mut self) -> u32 {
57        self.next_bits(1)
58    }
59}
60
61fn mask(n: u32) -> u64 {
62    if n >= 64 {
63        u64::MAX
64    } else {
65        (1u64 << n) - 1
66    }
67}