#![no_std]
cfg_if::cfg_if! {
if #[cfg(feature = "std")] {
extern crate std;
use std::io::Result;
use std::io::{Error, ErrorKind};
use std::vec::Vec;
} else {
use core::result;
use core::fmt;
use core::cmp::min;
}
}
#[cfg(test)]
mod tests;
pub struct BitWriter {
data: Vec<u8>,
bit_count: u64,
cache: u8,
bits: u8,
}
impl BitWriter {
pub fn new() -> BitWriter {
BitWriter {
data: Vec::new(),
bit_count: 0,
cache: 0,
bits: 0,
}
}
pub fn write_u8(&mut self, v: u8, bit_count: u8) -> Result<()> {
self.write_unsigned_bits(v as u64, bit_count, 8)
}
pub fn write_u16(&mut self, v: u16, bit_count: u8) -> Result<()> {
self.write_unsigned_bits(v as u64, bit_count, 16)
}
pub fn write_u32(&mut self, v: u32, bit_count: u8) -> Result<()> {
self.write_unsigned_bits(v as u64, bit_count, 32)
}
pub fn write_u64(&mut self, v: u64, bit_count: u8) -> Result<()> {
self.write_unsigned_bits(v, bit_count, 64)
}
pub fn write_i8(&mut self, v: i8, bit_count: u8) -> Result<()> {
self.write_signed_bits(v as i64, bit_count, 8)
}
pub fn write_i16(&mut self, v: i16, bit_count: u8) -> Result<()> {
self.write_signed_bits(v as i64, bit_count, 16)
}
pub fn write_i32(&mut self, v: i32, bit_count: u8) -> Result<()> {
self.write_signed_bits(v as i64, bit_count, 32)
}
pub fn write_i64(&mut self, v: i64, bit_count: u8) -> Result<()> {
self.write_signed_bits(v, bit_count, 64)
}
pub fn write_bool(&mut self, v: bool) -> Result<()> {
self.write_unsigned_bits(v as u64, 1, 1)
}
pub fn skip(&mut self, n: u64) -> Result<()> {
for _ in 0..(n / 64) {
self.write_unsigned_bits(0, 64, 64)?;
}
let leftover = (n % 64) as u8;
if leftover != 0 {
self.write_unsigned_bits(0, leftover, 64)?;
}
Ok(())
}
pub fn align(&mut self, alignment_bytes: u32) -> Result<()> {
if alignment_bytes == 0 {
return Err(Error::new(
ErrorKind::InvalidInput,
"cannot align to 0 bytes",
));
}
let alignment_bits = alignment_bytes as u64 * 8;
let cur_alignment = self.bit_count % alignment_bits;
let bits_to_skip = (alignment_bits - cur_alignment) % alignment_bits;
self.skip(bits_to_skip)
}
pub fn write_signed_bits(&mut self, mut v: i64, n: u8, maximum_count: u8) -> Result<()> {
if n == 0 {
return Ok(());
}
if v < 0 && n != 64 {
v |= 1 << (n - 1);
}
self.write_unsigned_bits(v as u64, n, maximum_count)
}
pub fn write_unsigned_bits(&mut self, mut v: u64, mut n: u8, maximum_count: u8) -> Result<()> {
if n == 0 {
return Ok(());
}
if n > maximum_count || n > 64 {
return Err(Error::new(ErrorKind::Unsupported, "too many bits to write"));
}
if n == 64 {
v &= u64::MAX;
} else {
v &= (1 << n) - 1;
}
self.bit_count += n as u64;
let new_bits = self.bits + n;
if new_bits < 8 {
self.cache |= (v as u8) << (8 - new_bits);
self.bits = new_bits;
return Ok(());
}
if new_bits >= 8 {
let free_buffer = 8 - self.bits;
let new_cache = (v >> (n - free_buffer)) as u8;
self.data.push(self.cache | new_cache);
n -= free_buffer;
while n >= 8 {
n -= 8;
self.data.push((v >> n) as u8);
}
}
self.cache = 0;
self.bits = n;
if n > 0 {
let mask = ((1 << n) as u8) - 1;
self.cache = ((v as u8) & mask) << (8 - n);
}
Ok(())
}
pub fn write(&mut self, data: &Vec<u8>) -> Result<()> {
if self.bits == 0 {
self.bit_count += 8 * data.len() as u64;
self.data.extend(data);
return Ok(());
}
for byte in data {
match self.write_u8(*byte, 8) {
Ok(()) => (),
Err(e) => return Err(e),
}
}
Ok(())
}
pub fn close(&mut self) -> Result<()> {
self.align(1)?;
Ok(())
}
pub fn bit_count(&self) -> u64 {
self.bit_count
}
pub fn data(&self) -> &Vec<u8> {
&self.data
}
}