#[derive(Default)]
pub(crate) struct BitWriter {
bytes: Vec<u8>,
cur: u8,
nbits: u8, }
impl BitWriter {
pub(crate) fn new() -> Self {
Self::default()
}
pub(crate) fn f(&mut self, value: u32, n: u8) {
for i in (0..n).rev() {
let bit = ((value >> i) & 1) as u8;
self.cur = (self.cur << 1) | bit;
self.nbits += 1;
if self.nbits == 8 {
self.bytes.push(self.cur);
self.cur = 0;
self.nbits = 0;
}
}
}
pub(crate) fn flag(&mut self, b: bool) {
self.f(b as u32, 1);
}
pub(crate) fn byte_align(&mut self) {
if self.nbits > 0 {
self.cur <<= 8 - self.nbits;
self.bytes.push(self.cur);
self.cur = 0;
self.nbits = 0;
}
}
pub(crate) fn trailing_bits(&mut self) {
self.f(1, 1);
self.byte_align();
}
pub(crate) fn into_bytes(mut self) -> Vec<u8> {
self.byte_align();
self.bytes
}
}
pub(crate) fn leb128(mut value: u64) -> Vec<u8> {
let mut out = Vec::new();
loop {
let mut byte = (value & 0x7f) as u8;
value >>= 7;
if value != 0 {
byte |= 0x80;
}
out.push(byte);
if value == 0 {
break;
}
}
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn bits_pack_msb_first() {
let mut w = BitWriter::new();
w.f(0b101, 3);
w.f(0b01, 2);
w.f(0b111, 3);
assert_eq!(w.into_bytes(), vec![0b1010_1111]);
}
#[test]
fn byte_align_pads_zero() {
let mut w = BitWriter::new();
w.f(0b1, 1);
assert_eq!(w.into_bytes(), vec![0b1000_0000]);
}
#[test]
fn leb128_known_values() {
assert_eq!(leb128(0), vec![0x00]);
assert_eq!(leb128(127), vec![0x7f]);
assert_eq!(leb128(128), vec![0x80, 0x01]);
assert_eq!(leb128(300), vec![0xac, 0x02]);
}
}