Skip to main content

rar_stream/decompress/
bit_reader.rs

1//! Bit reader for compressed data streams.
2//!
3//! Reads bits from a byte stream, LSB first (RAR convention).
4
5use super::{DecompressError, Result};
6
7/// Bit reader that reads from a byte slice.
8pub struct BitReader<'a> {
9    data: &'a [u8],
10    pos: usize,
11    bit_pos: u32,
12    /// Current bit buffer (up to 32 bits)
13    buffer: u32,
14    /// Bits available in buffer
15    bits_in_buffer: u32,
16}
17
18impl<'a> BitReader<'a> {
19    /// Create a new bit reader from a byte slice.
20    pub fn new(data: &'a [u8]) -> Self {
21        let mut reader = Self {
22            data,
23            pos: 0,
24            bit_pos: 0,
25            buffer: 0,
26            bits_in_buffer: 0,
27        };
28        reader.fill_buffer();
29        reader
30    }
31
32    /// Fill the buffer with more bytes.
33    fn fill_buffer(&mut self) {
34        while self.bits_in_buffer <= 24 && self.pos < self.data.len() {
35            self.buffer |= (self.data[self.pos] as u32) << (24 - self.bits_in_buffer);
36            self.bits_in_buffer += 8;
37            self.pos += 1;
38        }
39    }
40
41    /// Peek at the next n bits without consuming them.
42    #[inline]
43    pub fn peek_bits(&self, n: u32) -> u32 {
44        debug_assert!(n <= 16);
45        self.buffer >> (32 - n)
46    }
47
48    /// Read n bits and advance the position.
49    #[inline]
50    pub fn read_bits(&mut self, n: u32) -> Result<u32> {
51        debug_assert!(n <= 16);
52        
53        if n > self.bits_in_buffer && self.pos >= self.data.len() {
54            return Err(DecompressError::UnexpectedEof);
55        }
56
57        let value = self.peek_bits(n);
58        self.advance_bits(n);
59        Ok(value)
60    }
61
62    /// Advance by n bits.
63    #[inline]
64    pub fn advance_bits(&mut self, n: u32) {
65        self.buffer <<= n;
66        self.bits_in_buffer = self.bits_in_buffer.saturating_sub(n);
67        self.bit_pos += n;
68        self.fill_buffer();
69    }
70
71    /// Read a single bit.
72    #[inline]
73    pub fn read_bit(&mut self) -> Result<bool> {
74        Ok(self.read_bits(1)? != 0)
75    }
76
77    /// Read a single byte (8 bits).
78    #[inline]
79    pub fn read_byte(&mut self) -> Option<u8> {
80        self.read_bits(8).ok().map(|v| v as u8)
81    }
82
83    /// Align to byte boundary by skipping remaining bits in current byte.
84    #[inline]
85    pub fn align_to_byte(&mut self) {
86        let bits_used_in_byte = self.bit_pos % 8;
87        if bits_used_in_byte > 0 {
88            let skip = 8 - bits_used_in_byte;
89            self.advance_bits(skip);
90        }
91    }
92
93    /// Get the current bit position.
94    pub fn bit_position(&self) -> u64 {
95        self.bit_pos as u64
96    }
97
98    /// Get the current byte position (bytes consumed from stream).
99    pub fn byte_position(&self) -> usize {
100        self.pos
101    }
102
103    /// Check if at end of data.
104    pub fn is_eof(&self) -> bool {
105        self.bits_in_buffer == 0 && self.pos >= self.data.len()
106    }
107
108    /// Remaining bits available.
109    pub fn remaining_bits(&self) -> u64 {
110        self.bits_in_buffer as u64 + ((self.data.len() - self.pos) as u64 * 8)
111    }
112}
113
114#[cfg(test)]
115mod tests {
116    use super::*;
117
118    #[test]
119    fn test_read_bits() {
120        let data = [0b10110100, 0b11001010];
121        let mut reader = BitReader::new(&data);
122
123        assert_eq!(reader.read_bits(4).unwrap(), 0b1011);
124        assert_eq!(reader.read_bits(4).unwrap(), 0b0100);
125        assert_eq!(reader.read_bits(8).unwrap(), 0b11001010);
126    }
127
128    #[test]
129    fn test_peek_bits() {
130        let data = [0b10110100];
131        let reader = BitReader::new(&data);
132
133        assert_eq!(reader.peek_bits(4), 0b1011);
134        assert_eq!(reader.peek_bits(8), 0b10110100);
135    }
136
137    #[test]
138    fn test_eof() {
139        let data = [0xFF];
140        let mut reader = BitReader::new(&data);
141
142        assert!(!reader.is_eof());
143        reader.read_bits(8).unwrap();
144        assert!(reader.is_eof());
145    }
146}