use std::io::{self, ErrorKind};
pub(crate) struct BitReader<'a> {
buffer: &'a [u8],
offset: usize,
}
impl<'a> BitReader<'a> {
pub fn new(buffer: &'a [u8]) -> Self {
BitReader { buffer, offset: 0 }
}
pub fn read_bits(&mut self, num_bits: usize) -> Result<u64, io::Error> {
let mut value: u64 = 0;
let mut bits_read = 0;
while bits_read < num_bits {
let byte_index = self.offset / 8;
let bit_offset = self.offset % 8;
if byte_index >= self.buffer.len() {
return Err(io::Error::new(
ErrorKind::UnexpectedEof,
"Buffer underflow while reading bits",
));
}
let byte = self.buffer[byte_index];
let bits_to_read = std::cmp::min(num_bits - bits_read, 8 - bit_offset);
let mask = if bits_to_read >= 8 {
0xFF
} else {
(1u8 << bits_to_read) - 1
};
let bits_value = (byte >> (8 - bit_offset - bits_to_read)) & mask;
value = (value << bits_to_read) | (bits_value as u64);
self.offset += bits_to_read;
bits_read += bits_to_read;
}
Ok(value)
}
pub fn read_uimsbf(&mut self, num_bits: usize) -> Result<u64, io::Error> {
self.read_bits(num_bits)
}
pub fn read_bslbf(&mut self, num_bits: usize) -> Result<u64, io::Error> {
self.read_bits(num_bits)
}
pub fn read_rpchof(&mut self, num_bits: usize) -> Result<u64, io::Error> {
self.read_bits(num_bits)
}
pub fn skip_bits(&mut self, num_bits: usize) -> Result<(), io::Error> {
let new_offset = self.offset + num_bits;
if new_offset / 8 > self.buffer.len() {
return Err(io::Error::new(
ErrorKind::UnexpectedEof,
"Buffer underflow while skipping bits",
));
}
self.offset = new_offset;
Ok(())
}
pub fn get_offset(&self) -> usize {
self.offset
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bit_reader_basic() {
let buffer = vec![0b10101010, 0b11110000];
let mut reader = BitReader::new(&buffer);
assert_eq!(reader.read_bits(4).unwrap(), 10);
assert_eq!(reader.read_bits(4).unwrap(), 10);
assert_eq!(reader.read_bits(8).unwrap(), 240);
}
#[test]
fn test_bit_reader_cross_byte() {
let buffer = vec![0b10101010, 0b11110000];
let mut reader = BitReader::new(&buffer);
assert_eq!(reader.read_bits(6).unwrap(), 42);
assert_eq!(reader.read_bits(6).unwrap(), 47);
}
#[test]
fn test_bit_reader_skip() {
let buffer = vec![0b10101010, 0b11110000];
let mut reader = BitReader::new(&buffer);
reader.skip_bits(4).unwrap();
assert_eq!(reader.read_bits(4).unwrap(), 10);
}
#[test]
fn test_bit_reader_overflow() {
let buffer = vec![0b10101010];
let mut reader = BitReader::new(&buffer);
assert!(reader.read_bits(16).is_err());
}
}