use crate::error::{CodecError, CodecResult};
pub struct BoolDecoder<'a> {
data: &'a [u8],
pos: usize,
range: u32,
value: u32,
bits_left: i32,
}
impl<'a> BoolDecoder<'a> {
pub fn new(data: &'a [u8]) -> CodecResult<Self> {
if data.is_empty() {
return Err(CodecError::InvalidBitstream(
"Empty data for boolean decoder".to_string(),
));
}
let mut decoder = Self {
data,
pos: 0,
range: 255,
value: 0,
bits_left: 0,
};
decoder.fill()?;
Ok(decoder)
}
#[allow(clippy::unnecessary_wraps)]
fn fill(&mut self) -> CodecResult<()> {
while self.bits_left < 8 {
if self.pos < self.data.len() {
self.value = (self.value << 8) | u32::from(self.data[self.pos]);
self.pos += 1;
} else {
self.value <<= 8;
}
self.bits_left += 8;
}
Ok(())
}
pub fn read_bool(&mut self, prob: u8) -> CodecResult<bool> {
let split = 1 + (((self.range - 1) * u32::from(prob)) >> 8);
let bigsplit = split << 8;
let result = if self.value >= bigsplit {
self.range -= split;
self.value -= bigsplit;
true
} else {
self.range = split;
false
};
while self.range < 128 {
self.range <<= 1;
self.value <<= 1;
self.bits_left -= 1;
if self.bits_left < 0 {
self.fill()?;
}
}
Ok(result)
}
#[inline]
pub fn read_bit(&mut self) -> CodecResult<bool> {
self.read_bool(128)
}
pub fn read_literal(&mut self, n: u8) -> CodecResult<u32> {
let mut value = 0u32;
for _ in 0..n {
value = (value << 1) | u32::from(self.read_bit()?);
}
Ok(value)
}
#[allow(clippy::cast_possible_wrap)]
pub fn read_signed_literal(&mut self, n: u8) -> CodecResult<i32> {
let value = self.read_literal(n)? as i32;
let sign = self.read_bit()?;
if sign {
Ok(-value)
} else {
Ok(value)
}
}
#[must_use]
pub const fn bytes_consumed(&self) -> usize {
self.pos
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bool_decoder_new() {
let data = [0x00, 0x01, 0x02];
let decoder = BoolDecoder::new(&data).expect("should succeed");
assert!(decoder.bytes_consumed() >= 1);
}
#[test]
fn test_empty_data() {
let data: [u8; 0] = [];
assert!(BoolDecoder::new(&data).is_err());
}
#[test]
fn test_read_bit() {
let data = [0x00, 0x00, 0x00, 0x00];
let mut decoder = BoolDecoder::new(&data).expect("should succeed");
for _ in 0..16 {
let _ = decoder.read_bit();
}
}
#[test]
fn test_read_literal() {
let data = [0xFF, 0xFF, 0xFF, 0xFF];
let mut decoder = BoolDecoder::new(&data).expect("should succeed");
let _ = decoder.read_literal(8);
}
#[test]
fn test_read_signed_literal() {
let data = [0xFF, 0xFF, 0xFF, 0xFF];
let mut decoder = BoolDecoder::new(&data).expect("should succeed");
let _ = decoder.read_signed_literal(4);
}
}