use crate::stream::bits::BitsWriter;
use bitter::{BitWriter, LittleEndianWriter};
use std::io;
const UBIT_VAR_BIT_COUNTS: [u8; 4] = [0, 4, 8, 28];
const UBIT_VAR_FIELDPATH_BIT_COUNTS: [u8; 5] = [2, 4, 10, 17, 31];
const COORDINATE_RESOLUTION_FACTOR: f32 = 1.0 / (1 << 5) as f32;
const NORMAL_DENOMINATOR: u32 = (1 << 11) - 1;
const NORMAL_RESOLUTION_FACTOR: f32 = 1.0 / NORMAL_DENOMINATOR as f32;
#[doc(hidden)]
pub struct BitstreamWriter<'a> {
pub(crate) bit_writer: LittleEndianWriter<&'a mut Vec<u8>>,
}
impl<'a> BitstreamWriter<'a> {
pub fn new(buffer: &'a mut Vec<u8>) -> Self {
Self {
bit_writer: LittleEndianWriter::new(buffer),
}
}
}
impl BitsWriter for BitstreamWriter<'_> {
#[inline]
fn flush(&mut self) -> io::Result<()> {
BitWriter::flush(&mut self.bit_writer)
}
#[inline]
fn write_bits(&mut self, amount: u32, value: u64) -> io::Result<()> {
BitWriter::write_bits(&mut self.bit_writer, amount, value)
}
#[inline]
fn write_bits_unchecked(&mut self, amount: u32, value: u64) -> io::Result<()> {
BitWriter::write_bits(&mut self.bit_writer, amount, value)
}
#[inline]
fn write_bytes(&mut self, bytes: &[u8]) -> io::Result<()> {
for &byte in bytes {
self.write_bits(8, byte as u64)?;
}
Ok(())
}
#[inline]
fn write_bit(&mut self, value: bool) -> io::Result<()> {
self.write_bits(1, value as u64)
}
#[inline]
fn write_f32(&mut self, value: f32) -> io::Result<()> {
self.write_bits(32, value.to_bits() as u64)
}
#[inline]
fn write_var_u32(&mut self, value: u32) -> io::Result<()> {
self.write_var_u64(value as u64)
}
#[inline]
fn write_var_i32(&mut self, value: i32) -> io::Result<()> {
let encoded = if value < 0 {
(!(value as u32) << 1) | 1
} else {
(value as u32) << 1
};
self.write_var_u32(encoded)
}
#[inline]
fn write_var_u64(&mut self, mut value: u64) -> io::Result<()> {
loop {
let mut byte = (value & 0x7F) as u8;
value >>= 7;
if value != 0 {
byte |= 0x80;
}
self.write_bits(8, byte as u64)?;
if value == 0 {
return Ok(());
}
}
}
#[inline]
fn write_ubit_var(&mut self, value: u32) -> io::Result<()> {
let low = value & 0x0F;
if value < (1 << 4) {
self.write_bits(6, low as u64)?;
return Ok(());
}
let bucket = if value < (1 << 8) {
1
} else if value < (1 << 12) {
2
} else {
3
};
self.write_bits(6, ((bucket as u32) << 4 | low) as u64)?;
self.write_bits(UBIT_VAR_BIT_COUNTS[bucket] as u32, (value >> 4) as u64)?;
Ok(())
}
#[inline]
fn write_ubit_var_fp(&mut self, value: i32) -> io::Result<()> {
debug_assert!(
value >= 0,
"field-path values are expected to be non-negative"
);
let value = value as u32;
let bucket = if value < (1 << 2) {
0
} else if value < (1 << 4) {
1
} else if value < (1 << 10) {
2
} else if value < (1 << 17) {
3
} else {
4
};
match bucket {
0 => {
self.write_bit(true)?;
self.write_bits(UBIT_VAR_FIELDPATH_BIT_COUNTS[bucket] as u32, value as u64)?;
}
1 => {
self.write_bit(false)?;
self.write_bit(true)?;
self.write_bits(UBIT_VAR_FIELDPATH_BIT_COUNTS[bucket] as u32, value as u64)?;
}
2 => {
self.write_bit(false)?;
self.write_bit(false)?;
self.write_bit(true)?;
self.write_bits(UBIT_VAR_FIELDPATH_BIT_COUNTS[bucket] as u32, value as u64)?;
}
3 => {
self.write_bit(false)?;
self.write_bit(false)?;
self.write_bit(false)?;
self.write_bit(true)?;
self.write_bits(UBIT_VAR_FIELDPATH_BIT_COUNTS[bucket] as u32, value as u64)?;
}
_ => {
self.write_bit(false)?;
self.write_bit(false)?;
self.write_bit(false)?;
self.write_bit(false)?;
self.write_bits(UBIT_VAR_FIELDPATH_BIT_COUNTS[bucket] as u32, value as u64)?;
}
}
Ok(())
}
#[inline]
fn write_ubit_var_fp_unchecked(&mut self, value: i32) -> io::Result<()> {
self.write_ubit_var_fp(value)
}
#[inline]
fn write_u64_le(&mut self, value: u64) -> io::Result<()> {
self.write_bits(64, value)
}
#[inline]
fn write_cstring(&mut self, value: &str) -> io::Result<()> {
self.write_bytes(value.as_bytes())?;
self.write_bits(8, 0)?;
Ok(())
}
#[inline]
fn write_coordinate(&mut self, value: f32) -> io::Result<()> {
let abs = value.abs();
let int_val = abs.trunc() as u32;
let fract_val = ((abs * (1 << 5) as f32) as u32) & ((1 << 5) - 1);
self.write_bit(int_val != 0)?;
self.write_bit(fract_val != 0)?;
if int_val == 0 && fract_val == 0 {
return Ok(());
}
self.write_bit(value <= -COORDINATE_RESOLUTION_FACTOR)?;
if int_val != 0 {
self.write_bits(14, (int_val - 1) as u64)?;
}
if fract_val != 0 {
self.write_bits(5, fract_val as u64)?;
}
Ok(())
}
#[inline]
fn write_angle(&mut self, value: f32, n: u32) -> io::Result<()> {
debug_assert!(
n > 0 && n <= 32,
"angle bit counts are expected to fit into u32"
);
let modulus = 1u128 << n;
let raw = ((value / 360.0) * modulus as f32) as i128;
let raw = (raw as u128) & (modulus - 1);
self.write_bits(n, raw as u64)
}
#[inline]
fn write_normal(&mut self, value: f32) -> io::Result<()> {
let signbit = value <= -NORMAL_RESOLUTION_FACTOR;
let len = ((value * NORMAL_DENOMINATOR as f32) as i32)
.unsigned_abs()
.min(NORMAL_DENOMINATOR);
self.write_bit(signbit)?;
self.write_bits(11, len as u64)
}
#[inline]
fn write_normal_vec3(&mut self, value: [f32; 3]) -> io::Result<()> {
let x = value[0] >= NORMAL_RESOLUTION_FACTOR || value[0] <= -NORMAL_RESOLUTION_FACTOR;
let y = value[1] >= NORMAL_RESOLUTION_FACTOR || value[1] <= -NORMAL_RESOLUTION_FACTOR;
self.write_bit(x)?;
self.write_bit(y)?;
if x {
self.write_normal(value[0])?;
}
if y {
self.write_normal(value[1])?;
}
self.write_bit(value[2] <= -NORMAL_RESOLUTION_FACTOR)?;
Ok(())
}
#[inline]
fn write_bits_as_bytes(&mut self, bytes: &[u8], n: u32) -> io::Result<()> {
if n == 0 {
return Ok(());
}
let whole = (n / 8) as usize;
let rem = n % 8;
if bytes.len() < whole + usize::from(rem > 0) {
return Err(io::Error::new(
io::ErrorKind::UnexpectedEof,
"not enough source bytes for requested bit count",
));
}
for &byte in &bytes[..whole] {
self.write_bits(8, byte as u64)?;
}
if rem > 0 {
self.write_bits(rem, bytes[whole] as u64)?;
}
Ok(())
}
}