use crate::{Error, Result};
pub struct BitReader<'a> {
data: &'a [u8],
byte_pos: usize,
bit_pos: u8,
}
impl<'a> BitReader<'a> {
pub fn new(data: &'a [u8]) -> Self {
Self {
data,
byte_pos: 0,
bit_pos: 0,
}
}
pub fn position(&self) -> (usize, u8) {
(self.byte_pos, self.bit_pos)
}
pub fn seek(&mut self, byte_pos: usize, bit_pos: u8) -> Result<()> {
if byte_pos >= self.data.len() || (byte_pos == self.data.len() - 1 && bit_pos > 7) {
return Err(Error::BitstreamError("Seek position out of bounds".into()));
}
self.byte_pos = byte_pos;
self.bit_pos = bit_pos;
Ok(())
}
pub fn available_bits(&self) -> usize {
if self.byte_pos >= self.data.len() {
return 0;
}
(self.data.len() - self.byte_pos - 1) * 8 + (8 - self.bit_pos as usize)
}
pub fn read_bit(&mut self) -> Result<bool> {
if self.byte_pos >= self.data.len() {
return Err(Error::UnexpectedEof);
}
let bit = (self.data[self.byte_pos] >> (7 - self.bit_pos)) & 1;
self.bit_pos += 1;
if self.bit_pos == 8 {
self.bit_pos = 0;
self.byte_pos += 1;
}
Ok(bit != 0)
}
pub fn read_bits(&mut self, n: u32) -> Result<u32> {
if n > 32 {
return Err(Error::BitstreamError(
"Cannot read more than 32 bits".into(),
));
}
let mut value = 0u32;
for _ in 0..n {
value = (value << 1) | (self.read_bit()? as u32);
}
Ok(value)
}
pub fn read_flag(&mut self) -> Result<bool> {
self.read_bit()
}
pub fn read_u8(&mut self) -> Result<u8> {
self.read_bits(8).map(|v| v as u8)
}
pub fn read_u16(&mut self) -> Result<u16> {
self.read_bits(16).map(|v| v as u16)
}
pub fn peek_bits(&mut self, n: u32) -> Result<u32> {
let saved_byte = self.byte_pos;
let saved_bit = self.bit_pos;
let value = self.read_bits(n)?;
self.byte_pos = saved_byte;
self.bit_pos = saved_bit;
Ok(value)
}
pub fn skip_bits(&mut self, n: u32) -> Result<()> {
for _ in 0..n {
self.read_bit()?;
}
Ok(())
}
pub fn byte_aligned(&self) -> bool {
self.bit_pos == 0
}
pub fn align_to_byte(&mut self) {
if self.bit_pos != 0 {
self.bit_pos = 0;
self.byte_pos += 1;
}
}
pub fn more_rbsp_data(&self) -> bool {
if self.byte_pos >= self.data.len() {
return false;
}
if self.byte_pos == self.data.len() - 1 {
let remaining_byte = self.data[self.byte_pos];
if self.bit_pos >= 8 {
return false;
}
let bits_left = 8 - self.bit_pos;
if bits_left == 0 || bits_left > 8 {
return false;
}
let shift_amount = self.bit_pos;
let remaining_bits = remaining_byte << shift_amount;
let stop_pattern = 0x80;
return remaining_bits != stop_pattern;
}
true
}
pub fn rbsp_trailing_bits(&mut self) -> Result<()> {
if !self.read_flag()? {
return Err(Error::BitstreamError("Expected rbsp_stop_one_bit".into()));
}
while !self.byte_aligned() {
if self.read_flag()? {
return Err(Error::BitstreamError(
"Expected rbsp_alignment_zero_bit".into(),
));
}
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_read_bits() {
let data = vec![0b10110011, 0b01010101];
let mut reader = BitReader::new(&data);
assert_eq!(reader.read_bits(4).unwrap(), 0b1011);
assert_eq!(reader.read_bits(4).unwrap(), 0b0011);
assert_eq!(reader.read_bits(8).unwrap(), 0b01010101);
}
#[test]
fn test_read_flag() {
let data = vec![0b10000000, 0b01000000];
let mut reader = BitReader::new(&data);
assert_eq!(reader.read_flag().unwrap(), true);
assert_eq!(reader.read_flag().unwrap(), false);
}
#[test]
fn test_peek_bits() {
let data = vec![0b11110000];
let mut reader = BitReader::new(&data);
assert_eq!(reader.peek_bits(4).unwrap(), 0b1111);
assert_eq!(reader.read_bits(4).unwrap(), 0b1111);
assert_eq!(reader.read_bits(4).unwrap(), 0b0000);
}
#[test]
fn test_byte_alignment() {
let data = vec![0xff, 0x00];
let mut reader = BitReader::new(&data);
assert!(reader.byte_aligned());
reader.read_bits(3).unwrap();
assert!(!reader.byte_aligned());
reader.align_to_byte();
assert!(reader.byte_aligned());
assert_eq!(reader.byte_pos, 1);
}
#[test]
fn test_more_rbsp_data() {
let data = vec![0x80];
let reader = BitReader::new(&data);
assert!(!reader.more_rbsp_data());
let data = vec![0xC0]; let reader = BitReader::new(&data);
assert!(reader.more_rbsp_data());
}
}