#![allow(dead_code)]
use crate::error::Error;
pub(crate) struct HeaderBits<'a> {
bytes: &'a [u8],
pos: usize,
}
impl<'a> HeaderBits<'a> {
pub(crate) const fn new(bytes: &'a [u8]) -> Self {
Self { bytes, pos: 0 }
}
pub(crate) fn read(&mut self, n: u32) -> Result<u32, Error> {
debug_assert!(n <= 32);
if n == 0 {
return Ok(0);
}
let end = self.pos + n as usize;
if end > self.bytes.len() * 8 {
return Err(Error::Corrupt);
}
let mut value: u32 = 0;
for i in 0..n as usize {
let bit_idx = self.pos + i;
let b = (self.bytes[bit_idx / 8] >> (bit_idx % 8)) & 1;
value |= (b as u32) << i;
}
self.pos = end;
Ok(value)
}
pub(crate) fn read_u64(&mut self, n: u32) -> Result<u64, Error> {
debug_assert!(n <= 64);
if n == 0 {
return Ok(0);
}
let end = self.pos + n as usize;
if end > self.bytes.len() * 8 {
return Err(Error::Corrupt);
}
let mut value: u64 = 0;
for i in 0..n as usize {
let bit_idx = self.pos + i;
let b = (self.bytes[bit_idx / 8] >> (bit_idx % 8)) & 1;
value |= (b as u64) << i;
}
self.pos = end;
Ok(value)
}
}
pub(crate) struct FseBits<'a> {
pub(crate) payload: &'a [u8],
pub(crate) n_bits: i32,
pub(crate) accum: u64,
pub(crate) end: usize,
}
impl<'a> FseBits<'a> {
pub(crate) fn new_with_stub(payload: &'a [u8], stub_bits: u32) -> Result<Self, Error> {
debug_assert!(stub_bits <= 7);
if payload.is_empty() {
return Ok(Self {
payload,
n_bits: -(stub_bits as i32),
accum: 0,
end: 0,
});
}
let mut s = Self {
payload,
n_bits: 0,
accum: 0,
end: payload.len(),
};
s.end -= 1;
let last = payload[s.end] as u64;
s.accum = last & ((1u64 << stub_bits) - 1);
s.n_bits = stub_bits as i32;
Ok(s)
}
pub(crate) fn refill(&mut self) {
while self.n_bits <= 56 && self.end > 0 {
self.end -= 1;
let b = self.payload[self.end] as u64;
self.accum |= b << self.n_bits;
self.n_bits += 8;
}
}
pub(crate) fn pull(&mut self, n: u32) -> Result<u64, Error> {
if (self.n_bits as u32) < n {
return Err(Error::Corrupt);
}
let mask = if n == 64 { u64::MAX } else { (1u64 << n) - 1 };
let v = self.accum & mask;
self.accum >>= n;
self.n_bits -= n as i32;
Ok(v)
}
}