#[derive(Debug, Clone, Copy, Default)]
pub struct BitReader {
acc: u64,
nbits: u32,
}
impl BitReader {
pub const fn new() -> Self {
Self { acc: 0, nbits: 0 }
}
pub fn feed(&mut self, byte: u8) {
debug_assert!(self.nbits <= 56, "BitReader overflow: drain before feeding");
self.acc |= (byte as u64) << self.nbits;
self.nbits += 8;
}
pub const fn bits_available(&self) -> u32 {
self.nbits
}
pub fn peek(&self, n: u32) -> u64 {
debug_assert!(n <= self.nbits);
if n == 0 {
0
} else {
self.acc & ((1u64 << n) - 1)
}
}
pub fn drop_bits(&mut self, n: u32) {
debug_assert!(n <= self.nbits);
self.acc >>= n;
self.nbits -= n;
}
pub fn align_to_byte(&mut self) {
let drop = self.nbits & 7;
self.drop_bits(drop);
}
pub fn reset(&mut self) {
self.acc = 0;
self.nbits = 0;
}
}
#[cfg(feature = "alloc")]
#[derive(Debug, Clone, Default)]
pub struct BitWriter {
acc: u64,
nbits: u32,
}
#[cfg(feature = "alloc")]
impl BitWriter {
pub const fn new() -> Self {
Self { acc: 0, nbits: 0 }
}
pub fn write(&mut self, value: u32, n: u32, out: &mut alloc::vec::Vec<u8>) {
debug_assert!(n <= 32);
let masked = if n == 0 {
0
} else if n == 64 {
value as u64
} else {
(value as u64) & ((1u64 << n) - 1)
};
self.acc |= masked << self.nbits;
self.nbits += n;
while self.nbits >= 8 {
out.push(self.acc as u8);
self.acc >>= 8;
self.nbits -= 8;
}
}
pub fn align(&mut self, out: &mut alloc::vec::Vec<u8>) {
if self.nbits > 0 {
out.push(self.acc as u8);
self.acc = 0;
self.nbits = 0;
}
}
#[allow(dead_code)]
pub const fn pending_bits(&self) -> u32 {
self.nbits
}
}
pub const fn reverse_bits(mut v: u32, n: u32) -> u32 {
let mut out = 0u32;
let mut i = 0;
while i < n {
out = (out << 1) | (v & 1);
v >>= 1;
i += 1;
}
out
}