#![allow(dead_code)]
#[derive(Debug, thiserror::Error, PartialEq, Eq)]
pub enum BitError {
#[error("attempted to read past end of bitstream")]
Eof,
#[error("Exp-Golomb leading-zero run exceeded 31 bits")]
ExpGolombOverflow,
#[error("u(n)/i(n) requested {0} bits, max supported is 32")]
TooManyBits(u32),
#[error("malformed rbsp_trailing_bits(): expected stop_one_bit then zeros")]
BadTrailingBits,
}
pub type BitResult<T> = Result<T, BitError>;
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 bits_remaining(&self) -> usize {
if self.byte_pos >= self.data.len() {
0
} else {
(self.data.len() - self.byte_pos) * 8 - self.bit_pos as usize
}
}
pub fn byte_aligned(&self) -> bool {
self.bit_pos == 0
}
pub fn u(&mut self, bits: u32) -> BitResult<u32> {
if bits > 32 {
return Err(BitError::TooManyBits(bits));
}
if self.bits_remaining() < bits as usize {
return Err(BitError::Eof);
}
let mut value: u32 = 0;
for _ in 0..bits {
value = (value << 1) | self.read_bit_unchecked() as u32;
}
Ok(value)
}
pub fn i(&mut self, bits: u32) -> BitResult<i32> {
let raw = self.u(bits)?;
if bits == 0 {
return Ok(0);
}
let sign_bit = 1u32 << (bits - 1);
Ok(if bits == 32 {
raw as i32
} else if raw & sign_bit != 0 {
(raw | !((1u32 << bits) - 1)) as i32
} else {
raw as i32
})
}
pub fn f(&mut self, bits: u32) -> BitResult<u32> {
self.u(bits)
}
pub fn ue(&mut self) -> BitResult<u32> {
self.read_codenum()
}
pub fn se(&mut self) -> BitResult<i32> {
let k = self.read_codenum()?;
Ok(if k & 1 == 1 {
k.div_ceil(2) as i32
} else {
-((k / 2) as i32)
})
}
pub fn te(&mut self, x_max: u32) -> BitResult<u32> {
if x_max == 0 {
Ok(0)
} else if x_max == 1 {
Ok(if self.u(1)? == 0 { 1 } else { 0 })
} else {
self.ue()
}
}
pub fn more_rbsp_data(&self) -> bool {
if self.bits_remaining() == 0 {
return false;
}
let mut last_one: Option<(usize, u8)> = None;
for byte_idx in 0..self.data.len() {
let b = self.data[byte_idx];
if b == 0 {
continue;
}
for bit_idx in 0..8u8 {
if (b >> (7 - bit_idx)) & 1 == 1 {
last_one = Some((byte_idx, bit_idx));
}
}
}
match last_one {
None => false,
Some((b, bi)) => match self.byte_pos.cmp(&b) {
core::cmp::Ordering::Less => true,
core::cmp::Ordering::Equal => self.bit_pos < bi,
core::cmp::Ordering::Greater => false,
},
}
}
pub fn rbsp_trailing_bits(&mut self) -> BitResult<()> {
if self.u(1)? != 1 {
return Err(BitError::BadTrailingBits);
}
while !self.byte_aligned() {
if self.u(1)? != 0 {
return Err(BitError::BadTrailingBits);
}
}
Ok(())
}
fn read_codenum(&mut self) -> BitResult<u32> {
let mut leading_zeros: u32 = 0;
loop {
if self.bits_remaining() == 0 {
return Err(BitError::Eof);
}
if self.read_bit_unchecked() == 1 {
break;
}
leading_zeros += 1;
if leading_zeros > 31 {
return Err(BitError::ExpGolombOverflow);
}
}
let suffix = if leading_zeros == 0 {
0
} else {
self.u(leading_zeros)?
};
Ok((1u32 << leading_zeros) - 1 + suffix)
}
fn read_bit_unchecked(&mut self) -> u8 {
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;
}
bit
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn u_reads_msb_first() {
let mut r = BitReader::new(&[0b1010_1100, 0b1111_0000]);
assert_eq!(r.u(1).unwrap(), 1);
assert_eq!(r.u(3).unwrap(), 0b010);
assert_eq!(r.u(4).unwrap(), 0b1100);
assert_eq!(r.u(8).unwrap(), 0b1111_0000);
assert_eq!(r.u(1).unwrap_err(), BitError::Eof);
}
#[test]
fn u_zero_bits_yields_zero() {
let mut r = BitReader::new(&[0xff]);
assert_eq!(r.u(0).unwrap(), 0);
assert_eq!(r.position(), (0, 0));
}
#[test]
fn u_full_32_bits() {
let mut r = BitReader::new(&[0x12, 0x34, 0x56, 0x78]);
assert_eq!(r.u(32).unwrap(), 0x1234_5678);
}
#[test]
fn i_sign_extends() {
let mut r = BitReader::new(&[0b1111_0000]);
assert_eq!(r.i(4).unwrap(), -1);
assert_eq!(r.i(4).unwrap(), 0);
let mut r = BitReader::new(&[0b1000_0000]);
assert_eq!(r.i(8).unwrap(), -128);
}
#[test]
fn ue_table_9_1_values() {
let cases: &[(&[u8], &[u32])] = &[
(&[0b1000_0000], &[0]),
(&[0b0100_0000], &[1]),
(&[0b0110_0000], &[2]),
(&[0b0010_0000], &[3]),
(&[0b0010_1000], &[4]),
(&[0b0011_0000], &[5]),
(&[0b0011_1000], &[6]),
(&[0b0001_0000], &[7]),
(&[0b1010_0110], &[0, 1, 2]),
];
for (bytes, want) in cases {
let mut r = BitReader::new(bytes);
for &v in *want {
assert_eq!(r.ue().unwrap(), v, "input bytes {:08b}", bytes[0]);
}
}
}
#[test]
fn se_table_9_3_mapping() {
let cases: &[(u8, i32)] = &[
(0b1000_0000, 0),
(0b0100_0000, 1),
(0b0110_0000, -1),
(0b0010_0000, 2),
(0b0010_1000, -2),
(0b0011_0000, 3),
(0b0011_1000, -3),
];
for (byte, want) in cases {
let bytes = [*byte];
let mut r = BitReader::new(&bytes);
assert_eq!(r.se().unwrap(), *want);
}
}
#[test]
fn te_x_max_one_inverts_bit() {
let mut r = BitReader::new(&[0b1000_0000]);
assert_eq!(r.te(1).unwrap(), 0); assert_eq!(r.te(1).unwrap(), 1);
let mut r = BitReader::new(&[0b0100_0000]);
assert_eq!(r.te(7).unwrap(), 1);
}
#[test]
fn te_x_max_zero_consumes_no_bits() {
let mut r = BitReader::new(&[0xFFu8, 0xFFu8]);
assert_eq!(r.te(0).unwrap(), 0);
let (byte, bit) = r.position();
assert_eq!((byte, bit), (0, 0));
}
#[test]
fn more_rbsp_data_locates_stop_bit() {
let mut r = BitReader::new(&[0b1100_0000]);
assert_eq!(r.ue().unwrap(), 0);
assert!(!r.more_rbsp_data());
let mut r = BitReader::new(&[0b1110_0000]);
assert_eq!(r.ue().unwrap(), 0);
assert!(r.more_rbsp_data());
assert_eq!(r.ue().unwrap(), 0);
assert!(!r.more_rbsp_data());
}
#[test]
fn rbsp_trailing_bits_consumes_stop_and_pad() {
let mut r = BitReader::new(&[0b1110_0000]);
r.u(2).unwrap(); r.rbsp_trailing_bits().unwrap();
assert_eq!(r.bits_remaining(), 0);
}
#[test]
fn rbsp_trailing_bits_rejects_missing_stop_bit() {
let mut r = BitReader::new(&[0b0000_0000]);
assert_eq!(
r.rbsp_trailing_bits().unwrap_err(),
BitError::BadTrailingBits
);
}
#[test]
fn ue_reports_eof() {
let mut r = BitReader::new(&[0x00]);
assert_eq!(r.ue().unwrap_err(), BitError::Eof);
}
#[test]
fn ue_rejects_oversize_leading_zero_run() {
let bytes = [0x00, 0x00, 0x00, 0x00, 0b1000_0000];
let mut r = BitReader::new(&bytes);
assert_eq!(r.ue().unwrap_err(), BitError::ExpGolombOverflow);
let bytes = [0u8; 16];
let mut r = BitReader::new(&bytes);
assert_eq!(r.ue().unwrap_err(), BitError::ExpGolombOverflow);
}
#[test]
fn ue_accepts_31_leading_zeros_max_codenum() {
let mut bits: Vec<u8> = Vec::new();
bits.extend(std::iter::repeat_n(0, 31));
bits.push(1); bits.extend(std::iter::repeat_n(1, 31)); bits.push(0); let mut bytes = [0u8; 8];
for (i, &b) in bits.iter().enumerate() {
if b != 0 {
bytes[i / 8] |= 1 << (7 - (i % 8));
}
}
let mut r = BitReader::new(&bytes);
assert_eq!(r.ue().unwrap(), u32::MAX - 1);
}
}