use crate::BitstreamError;
#[derive(Debug, Default, Clone)]
pub struct BitWriter {
bytes: Vec<u8>,
bit_pos: usize,
}
impl BitWriter {
pub fn new() -> Self {
Self::default()
}
pub fn bit_pos(&self) -> usize {
self.bit_pos
}
pub fn byte_aligned(&self) -> bool {
self.bit_pos % 8 == 0
}
pub fn write_bit(&mut self, bit: u32) {
let byte_idx = self.bit_pos / 8;
if byte_idx >= self.bytes.len() {
self.bytes.push(0);
}
if bit & 1 != 0 {
let shift = 7 - (self.bit_pos % 8) as u32;
self.bytes[byte_idx] |= 1u8 << shift;
}
self.bit_pos += 1;
}
pub fn write_bits(&mut self, value: u32, n: u32) {
debug_assert!(n <= 32, "BitWriter::write_bits n={n} > 32");
for i in (0..n).rev() {
self.write_bit((value >> i) & 1);
}
}
pub fn write_bits_u64(&mut self, value: u64, n: u32) {
debug_assert!(n <= 64, "BitWriter::write_bits_u64 n={n} > 64");
for i in (0..n).rev() {
self.write_bit(((value >> i) & 1) as u32);
}
}
pub fn write_ue(&mut self, value: u32) -> Result<(), BitstreamError> {
if value == u32::MAX {
return Err(BitstreamError::invalid(
"write_ue: value u32::MAX has no representable ue(v) code",
));
}
let code_num = value + 1; let bits = 32 - code_num.leading_zeros(); let leading_zeros = bits - 1;
for _ in 0..leading_zeros {
self.write_bit(0);
}
self.write_bits(code_num, bits);
Ok(())
}
pub fn write_se(&mut self, value: i32) -> Result<(), BitstreamError> {
let code_num: u32 = if value == 0 {
0
} else if value > 0 {
(value as u32)
.checked_mul(2)
.and_then(|x| x.checked_sub(1))
.ok_or_else(|| BitstreamError::invalid("write_se: value too large for se(v)"))?
} else {
let mag = -(value as i64) as u64;
mag.checked_mul(2)
.filter(|&x| x <= u32::MAX as u64)
.map(|x| x as u32)
.ok_or_else(|| BitstreamError::invalid("write_se: value too large for se(v)"))?
};
self.write_ue(code_num)
}
pub fn align_to_byte(&mut self) {
while !self.byte_aligned() {
self.write_bit(0);
}
}
pub fn finish(self) -> Vec<u8> {
self.bytes
}
pub fn as_bytes(&self) -> &[u8] {
&self.bytes
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::bit_reader::BitReader;
#[test]
fn write_bits_matches_known_pattern() {
let mut w = BitWriter::new();
w.write_bits(0b1010, 4);
w.write_bits(0b1100, 4);
w.write_bits(0b1111_0000, 8);
assert_eq!(w.finish(), vec![0b1010_1100, 0b1111_0000]);
}
#[test]
fn ue_roundtrips_small_values() {
let mut w = BitWriter::new();
for v in 0..=10u32 {
w.write_ue(v).unwrap();
}
let bytes = w.finish();
let mut r = BitReader::new(&bytes);
for v in 0..=10u32 {
assert_eq!(r.ue().unwrap(), v);
}
}
#[test]
fn se_roundtrips_signed_values() {
let mut w = BitWriter::new();
let vals = [0, 1, -1, 2, -2, 100, -100];
for &v in &vals {
w.write_se(v).unwrap();
}
let bytes = w.finish();
let mut r = BitReader::new(&bytes);
for &v in &vals {
assert_eq!(r.se().unwrap(), v);
}
}
#[test]
fn ue_rejects_u32_max() {
let mut w = BitWriter::new();
assert!(w.write_ue(u32::MAX).is_err());
}
}