#[derive(Debug, Default)]
pub struct BitWriter {
out: Vec<u8>, cache: u8, bits: u8, }
impl BitWriter {
#[inline]
pub fn new() -> Self {
Self::default()
}
#[inline]
pub fn with_capacity(n: usize) -> Self {
BitWriter {
out: Vec::with_capacity(n),
cache: 0,
bits: 0,
}
}
#[inline]
pub fn reserve(&mut self, n: usize) {
self.out.reserve(n / 8);
}
#[inline]
fn push_unaligned(&mut self, b: u8) {
self.out.push(self.cache | (b >> self.bits));
self.cache = (b & ((1 << self.bits) - 1)) << (8 - self.bits);
}
#[inline]
fn reset(&mut self) {
self.cache = 0;
self.bits = 0;
}
#[inline]
pub fn push(&mut self, b: u8) {
if self.bits == 0 {
self.out.push(b);
} else {
self.push_unaligned(b);
}
}
#[inline]
pub fn push_bytes(&mut self, p: &[u8]) {
if self.bits == 0 {
self.out.extend_from_slice(p);
return;
}
for &b in p {
self.push_unaligned(b);
}
}
#[inline]
pub fn push_bit(&mut self, b: bool) {
if self.bits == 7 {
if b {
self.out.push(self.cache | 1);
} else {
self.out.push(self.cache);
}
self.reset();
return;
}
self.bits += 1;
if b {
self.cache |= 1 << (8 - self.bits);
}
}
#[inline]
pub fn push_bits(&mut self, r: u64, n: u8) {
if n == 0 {
return;
}
let mut n = n;
let r = r << (64 - n) >> (64 - n);
let new_bits = self.bits + n;
if new_bits < 8 {
self.cache |= (r as u8) << (8 - new_bits);
self.bits = new_bits;
return;
}
if new_bits > 8 {
let free = 8 - self.bits;
self.out.push(self.cache | ((r >> (n - free)) as u8));
n -= free;
while n >= 8 {
n -= 8;
self.out.push((r >> n) as u8);
}
if n > 0 {
self.cache = ((r as u8) & ((1 << n) - 1)) << (8 - n);
self.bits = n;
} else {
self.reset();
}
return;
}
self.out.push(self.cache | r as u8);
self.reset();
}
#[inline]
pub fn align(&mut self) -> u8 {
let mut skipped: u8 = 0;
if self.bits > 0 {
self.out.push(self.cache);
skipped = 8 - self.bits;
self.reset();
}
skipped
}
#[inline]
pub fn trailing_pad(&mut self, boundary: usize) -> usize {
let pad_bytes = self.out.len() % boundary;
if pad_bytes > 0 {
for _ in 0..boundary - pad_bytes {
self.out.push(0x0);
}
}
pad_bytes
}
#[inline]
pub fn into_vec(self) -> Vec<u8> {
self.out
}
#[inline]
pub fn align_vec(mut self) -> Vec<u8> {
self.align();
self.out
}
#[inline]
pub fn align_ref(&mut self) -> &[u8] {
self.align();
&self.out
}
}
impl AsRef<[u8]> for BitWriter {
#[inline]
fn as_ref(&self) -> &[u8] {
&self.out
}
}