use super::error::{Error, Result};
#[derive(Clone, Copy)]
pub struct BitReader<'a> {
data: &'a [u8],
byte_pos: usize,
cache: u64,
ncache: u32,
}
impl<'a> BitReader<'a> {
#[must_use]
pub fn new(data: &'a [u8]) -> Self {
Self {
data,
byte_pos: 0,
cache: 0,
ncache: 0,
}
}
#[must_use]
pub fn bit_position(&self) -> u64 {
(self.byte_pos as u64)
.saturating_mul(8)
.saturating_sub(u64::from(self.ncache))
}
#[must_use]
pub fn bits_remaining(&self) -> u64 {
(self.data.len() * 8) as u64 - self.bit_position()
}
#[must_use]
pub fn bits_range(&self, start: u64, end: u64) -> Vec<bool> {
let mut out = Vec::with_capacity(end.saturating_sub(start) as usize);
for pos in start..end {
let byte = self.data[(pos / 8) as usize];
out.push(byte & (0x80 >> (pos % 8)) != 0);
}
out
}
#[inline(always)]
fn refill(&mut self) {
if self.ncache > 56 {
return;
}
let rem = self.data.len().saturating_sub(self.byte_pos);
if rem == 0 {
return;
}
if self.ncache == 0 && rem >= 8 {
let s = &self.data[self.byte_pos..self.byte_pos + 8];
self.cache = u64::from_be_bytes([s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7]]);
self.byte_pos += 8;
self.ncache = 64;
return;
}
while self.ncache <= 56 && self.byte_pos < self.data.len() {
self.cache |= u64::from(self.data[self.byte_pos]) << (56 - self.ncache);
self.byte_pos += 1;
self.ncache += 8;
}
}
#[inline(always)]
pub fn read_bit(&mut self) -> Result<bool> {
if self.ncache == 0 {
self.refill();
if self.ncache == 0 {
return Err(Error::UnexpectedEnd);
}
}
let b = self.cache & (1u64 << 63) != 0;
self.cache <<= 1;
self.ncache -= 1;
Ok(b)
}
#[inline(always)]
pub fn try_peek12(&mut self) -> Option<u32> {
if self.ncache < 12 {
self.refill();
if self.ncache < 12 {
return None;
}
}
Some((self.cache >> 52) as u32)
}
#[inline(always)]
pub fn eat(&mut self, n: u32) {
self.cache <<= n;
self.ncache -= n;
}
#[cfg(test)]
#[must_use]
pub fn with_position(data: &'a [u8], byte_pos: usize) -> Self {
Self {
data,
byte_pos: byte_pos.min(data.len()),
cache: 0,
ncache: 0,
}
}
#[cfg(test)]
#[must_use]
pub fn byte_position(&self) -> usize {
(self.bit_position() / 8) as usize
}
#[cfg(test)]
#[must_use]
pub fn is_byte_aligned(&self) -> bool {
self.bit_position().is_multiple_of(8)
}
#[cfg(test)]
pub fn align_to_byte(&mut self) -> Result<()> {
self.byte_align()
}
#[inline(always)]
pub fn read(&mut self, n: u32) -> Result<u32> {
if n == 0 {
return Ok(0);
}
if n > 32 {
return Err(Error::Format("bit read wider than 32"));
}
if self.ncache < n {
self.refill();
if self.ncache < n {
return Err(Error::UnexpectedEnd);
}
}
let v = (self.cache >> (64 - n)) as u32;
self.cache <<= n;
self.ncache -= n;
Ok(v)
}
pub fn read_u32(&mut self, n: u32) -> Result<u32> {
self.read(n)
}
#[cfg(test)]
pub fn read_u1(&mut self) -> Result<u32> {
self.read(1)
}
#[cfg(test)]
pub fn read_i32(&mut self, n: u32) -> Result<i32> {
let u = self.read(n)?;
if n == 0 {
return Ok(0);
}
let sign = 1u32 << (n - 1);
if u & sign == 0 {
Ok(u as i32)
} else {
Ok((u as i32) - (1i32 << n))
}
}
#[cfg(test)]
pub fn read_u64(&mut self, n: u32) -> Result<u64> {
if n <= 32 {
return Ok(u64::from(self.read(n)?));
}
let hi = u64::from(self.read(n - 32)?);
let lo = u64::from(self.read(32)?);
Ok((hi << 32) | lo)
}
#[inline(always)]
pub fn peek_u32(&mut self, n: u32) -> Result<u32> {
if n == 0 {
return Ok(0);
}
if n > 32 {
return Err(Error::Format("bit read wider than 32"));
}
if self.ncache < n {
self.refill();
if self.ncache < n {
return Err(Error::UnexpectedEnd);
}
}
Ok((self.cache >> (64 - n)) as u32)
}
#[cfg(test)]
pub fn consume(&mut self, n: u32) -> Result<()> {
self.skip(n)
}
pub fn skip(&mut self, n: u32) -> Result<()> {
if self.bits_remaining() < u64::from(n) {
return Err(Error::UnexpectedEnd);
}
let mut left = n;
if left <= self.ncache {
self.cache <<= left;
self.ncache -= left;
return Ok(());
}
left -= self.ncache;
self.cache = 0;
self.ncache = 0;
self.byte_pos += (left / 8) as usize;
left %= 8;
if left > 0 {
self.refill();
self.cache <<= left;
self.ncache -= left;
}
Ok(())
}
pub fn byte_align(&mut self) -> Result<()> {
let rem = (self.bit_position() % 8) as u32;
if rem != 0 {
self.skip(8 - rem)?;
}
Ok(())
}
}
#[derive(Default)]
pub struct BitWriter {
buf: Vec<u8>,
acc: u8,
bits: u8,
}
impl BitWriter {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn from_vec(mut buf: Vec<u8>) -> Self {
buf.clear();
Self {
buf,
acc: 0,
bits: 0,
}
}
pub fn write(&mut self, value: u32, n: u32) {
if n == 0 {
return;
}
for i in (0..n).rev() {
let bit = ((value >> i) & 1) as u8;
self.acc = (self.acc << 1) | bit;
self.bits += 1;
if self.bits == 8 {
self.buf.push(self.acc);
self.acc = 0;
self.bits = 0;
}
}
}
pub fn write_u32(&mut self, value: u32, n: u32) {
self.write(value, n)
}
pub fn write_bit(&mut self, bit: bool) {
self.write(u32::from(bit), 1);
}
#[must_use]
pub fn bit_len(&self) -> u64 {
(self.buf.len() as u64) * 8 + u64::from(self.bits)
}
#[must_use]
pub fn finish(mut self) -> Vec<u8> {
if self.bits > 0 {
self.acc <<= 8 - self.bits;
self.buf.push(self.acc);
}
self.buf
}
}
#[cfg(test)]
#[path = "bits_tests.rs"]
mod bits_tests;