use crate::error::{Error, Result};
const COORD_INTEGER_BITS: usize = 14;
const COORD_FRACTIONAL_BITS: usize = 5;
const COORD_DENOMINATOR: f32 = (1 << COORD_FRACTIONAL_BITS) as f32;
const COORD_RESOLUTION: f32 = 1.0 / COORD_DENOMINATOR;
const NORMAL_FRACTIONAL_BITS: usize = 11;
const NORMAL_DENOMINATOR: f32 = ((1 << NORMAL_FRACTIONAL_BITS) - 1) as f32;
const NORMAL_RESOLUTION: f32 = 1.0 / NORMAL_DENOMINATOR;
pub struct BitReader<'a> {
data: &'a [u8],
position: usize,
total_bits: usize,
}
impl<'a> BitReader<'a> {
#[inline]
pub fn new(data: &'a [u8]) -> Self {
Self {
data,
position: 0,
total_bits: data.len() * 8,
}
}
#[inline]
pub fn bits_remaining(&self) -> usize {
self.total_bits.saturating_sub(self.position)
}
#[inline]
pub fn position(&self) -> usize {
self.position
}
#[inline]
pub fn read_bits(&mut self, n: usize) -> Result<u64> {
if n == 0 {
return Ok(0);
}
if n > 64 || self.position + n > self.total_bits {
return Err(Error::Overflow {
needed: n,
available: self.bits_remaining(),
});
}
let value = self.peek_bits_unchecked(n);
self.position += n;
Ok(value)
}
#[inline]
pub fn peek_bits(&self, n: usize) -> Result<u64> {
if n == 0 {
return Ok(0);
}
if n > 64 || self.position + n > self.total_bits {
return Err(Error::Overflow {
needed: n,
available: self.bits_remaining(),
});
}
Ok(self.peek_bits_unchecked(n))
}
#[inline(always)]
fn peek_bits_unchecked(&self, n: usize) -> u64 {
let byte_pos = self.position / 8;
let bit_offset = self.position % 8;
let remaining_bytes = self.data.len() - byte_pos;
let mut buf = [0u8; 8];
if remaining_bytes >= 8 {
buf.copy_from_slice(&self.data[byte_pos..byte_pos + 8]);
} else {
buf[..remaining_bytes]
.copy_from_slice(&self.data[byte_pos..byte_pos + remaining_bytes]);
}
let raw = u64::from_le_bytes(buf);
(raw >> bit_offset) & mask(n)
}
#[inline]
pub fn read_bool(&mut self) -> Result<bool> {
Ok(self.read_bits(1)? != 0)
}
#[inline]
pub fn read_u8(&mut self) -> Result<u8> {
Ok(self.read_bits(8)? as u8)
}
#[inline]
pub fn read_u16(&mut self) -> Result<u16> {
Ok(self.read_bits(16)? as u16)
}
#[inline]
pub fn read_u32(&mut self) -> Result<u32> {
Ok(self.read_bits(32)? as u32)
}
#[inline]
pub fn read_u64(&mut self) -> Result<u64> {
self.read_bits(64)
}
#[inline]
pub fn read_f32(&mut self) -> Result<f32> {
Ok(f32::from_bits(self.read_bits(32)? as u32))
}
pub fn read_bytes(&mut self, buf: &mut [u8]) -> Result<()> {
let needed = buf.len() * 8;
if self.position + needed > self.total_bits {
return Err(Error::Overflow {
needed,
available: self.bits_remaining(),
});
}
if self.position.is_multiple_of(8) {
let byte_pos = self.position / 8;
buf.copy_from_slice(&self.data[byte_pos..byte_pos + buf.len()]);
self.position += needed;
return Ok(());
}
for byte in buf.iter_mut() {
*byte = self.peek_bits_unchecked(8) as u8;
self.position += 8;
}
Ok(())
}
pub fn read_bits_to_bytes(&mut self, buf: &mut [u8], bits: usize) -> Result<()> {
let full_bytes = bits / 8;
let remaining_bits = bits % 8;
if remaining_bits == 0 {
return self.read_bytes(&mut buf[..full_bytes]);
}
if full_bytes > 0 {
self.read_bytes(&mut buf[..full_bytes])?;
}
buf[full_bytes] = self.read_bits(remaining_bits)? as u8;
Ok(())
}
pub fn read_uvarint32(&mut self) -> Result<u32> {
let mut result: u32 = 0;
for i in 0..5 {
let byte = self.read_u8()? as u32;
result |= (byte & 0x7F) << (7 * i);
if byte & 0x80 == 0 {
return Ok(result);
}
}
Ok(result)
}
pub fn read_uvarint64(&mut self) -> Result<u64> {
let mut result: u64 = 0;
for i in 0..10 {
let byte = self.read_u8()? as u64;
result |= (byte & 0x7F) << (7 * i);
if byte & 0x80 == 0 {
return Ok(result);
}
}
Ok(result)
}
pub fn read_varint32(&mut self) -> Result<i32> {
let n = self.read_uvarint32()?;
Ok(((n >> 1) as i32) ^ -((n & 1) as i32))
}
pub fn read_varint64(&mut self) -> Result<i64> {
let n = self.read_uvarint64()?;
Ok(((n >> 1) as i64) ^ -((n & 1) as i64))
}
pub fn read_ubitvar(&mut self) -> Result<u32> {
let ret = self.read_bits(6)? as u32;
match ret & (16 | 32) {
16 => Ok((ret & 15) | (self.read_bits(4)? as u32) << 4),
32 => Ok((ret & 15) | (self.read_bits(8)? as u32) << 4),
48 => Ok((ret & 15) | (self.read_bits(28)? as u32) << 4),
_ => Ok(ret),
}
}
pub fn read_ubitvarfp(&mut self) -> Result<u32> {
if self.read_bool()? {
return Ok(self.read_bits(2)? as u32);
}
if self.read_bool()? {
return Ok(self.read_bits(4)? as u32);
}
if self.read_bool()? {
return Ok(self.read_bits(10)? as u32);
}
if self.read_bool()? {
return Ok(self.read_bits(17)? as u32);
}
Ok(self.read_bits(31)? as u32)
}
pub fn read_bitcoord(&mut self) -> Result<f32> {
let has_int = self.read_bool()?;
let has_frac = self.read_bool()?;
if !has_int && !has_frac {
return Ok(0.0);
}
let negative = self.read_bool()?;
let mut value = 0.0f32;
if has_int {
value += self.read_bits(COORD_INTEGER_BITS)? as f32 + 1.0;
}
if has_frac {
value += self.read_bits(COORD_FRACTIONAL_BITS)? as f32 * COORD_RESOLUTION;
}
if negative {
value = -value;
}
Ok(value)
}
pub fn read_bitnormal(&mut self) -> Result<f32> {
let negative = self.read_bool()?;
let frac = self.read_bits(NORMAL_FRACTIONAL_BITS)? as f32;
let mut value = frac * NORMAL_RESOLUTION;
if negative {
value = -value;
}
Ok(value)
}
pub fn read_bitvec3coord(&mut self) -> Result<[f32; 3]> {
let has_x = self.read_bool()?;
let has_y = self.read_bool()?;
let has_z = self.read_bool()?;
let x = if has_x { self.read_bitcoord()? } else { 0.0 };
let y = if has_y { self.read_bitcoord()? } else { 0.0 };
let z = if has_z { self.read_bitcoord()? } else { 0.0 };
Ok([x, y, z])
}
pub fn read_bitvec3normal(&mut self) -> Result<[f32; 3]> {
let has_x = self.read_bool()?;
let has_y = self.read_bool()?;
let x = if has_x { self.read_bitnormal()? } else { 0.0 };
let y = if has_y { self.read_bitnormal()? } else { 0.0 };
let z_sign = self.read_bool()?;
let z_sq = 1.0 - x * x - y * y;
let z = if z_sq > 0.0 { z_sq.sqrt() } else { 0.0 };
let z = if z_sign { -z } else { z };
Ok([x, y, z])
}
pub fn read_bitangle(&mut self, n: usize) -> Result<f32> {
let raw = self.read_bits(n)? as f32;
let shift = (1u64 << n) as f32;
Ok(raw * 360.0 / shift)
}
pub fn read_string(&mut self) -> Result<String> {
let mut bytes = Vec::new();
loop {
let b = self.read_u8()?;
if b == 0 {
break;
}
bytes.push(b);
}
Ok(String::from_utf8_lossy(&bytes).into_owned())
}
pub fn read_string_into(&mut self, buf: &mut [u8]) -> Result<usize> {
let mut i = 0;
loop {
let b = self.read_u8()?;
if b == 0 {
break;
}
if i < buf.len() {
buf[i] = b;
i += 1;
}
}
Ok(i)
}
pub fn read_string_raw(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
let start = buf.len();
loop {
let b = self.read_u8()?;
if b == 0 {
break;
}
buf.push(b);
}
Ok(buf.len() - start)
}
pub fn skip_bits(&mut self, n: usize) -> Result<()> {
if self.position + n > self.total_bits {
return Err(Error::Overflow {
needed: n,
available: self.bits_remaining(),
});
}
self.position += n;
Ok(())
}
pub fn skip_varint(&mut self) -> Result<()> {
for _ in 0..10 {
let byte = self.read_u8()?;
if byte & 0x80 == 0 {
return Ok(());
}
}
Ok(())
}
pub fn skip_bitcoord(&mut self) -> Result<()> {
let has_int = self.read_bool()?;
let has_frac = self.read_bool()?;
if !has_int && !has_frac {
return Ok(());
}
self.skip_bits(1)?;
if has_int {
self.skip_bits(COORD_INTEGER_BITS)?;
}
if has_frac {
self.skip_bits(COORD_FRACTIONAL_BITS)?;
}
Ok(())
}
pub fn skip_bitnormal(&mut self) -> Result<()> {
self.skip_bits(1 + NORMAL_FRACTIONAL_BITS)
}
pub fn skip_bitvec3coord(&mut self) -> Result<()> {
let has_x = self.read_bool()?;
let has_y = self.read_bool()?;
let has_z = self.read_bool()?;
if has_x {
self.skip_bitcoord()?;
}
if has_y {
self.skip_bitcoord()?;
}
if has_z {
self.skip_bitcoord()?;
}
Ok(())
}
pub fn skip_bitvec3normal(&mut self) -> Result<()> {
let has_x = self.read_bool()?;
let has_y = self.read_bool()?;
if has_x {
self.skip_bitnormal()?;
}
if has_y {
self.skip_bitnormal()?;
}
self.skip_bits(1)?;
Ok(())
}
pub fn skip_string(&mut self) -> Result<()> {
loop {
let b = self.read_u8()?;
if b == 0 {
return Ok(());
}
}
}
}
#[inline(always)]
fn mask(n: usize) -> u64 {
if n >= 64 { u64::MAX } else { (1u64 << n) - 1 }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_read_bits_basic() {
let data = [0b10110100, 0b11001010];
let mut br = BitReader::new(&data);
assert_eq!(br.read_bits(1).unwrap(), 0);
assert_eq!(br.read_bits(1).unwrap(), 0);
assert_eq!(br.read_bits(1).unwrap(), 1);
assert_eq!(br.read_bits(1).unwrap(), 0);
assert_eq!(br.read_bits(1).unwrap(), 1);
assert_eq!(br.read_bits(1).unwrap(), 1);
assert_eq!(br.read_bits(1).unwrap(), 0);
assert_eq!(br.read_bits(1).unwrap(), 1);
}
#[test]
fn test_read_byte() {
let data = [0xAB, 0xCD];
let mut br = BitReader::new(&data);
assert_eq!(br.read_u8().unwrap(), 0xAB);
assert_eq!(br.read_u8().unwrap(), 0xCD);
}
#[test]
fn test_read_across_boundary() {
let data = [0xFF, 0x00, 0xFF];
let mut br = BitReader::new(&data);
br.read_bits(4).unwrap();
let val = br.read_bits(8).unwrap();
assert_eq!(val, 0x0F);
}
#[test]
fn test_read_bool() {
let data = [0b10000001];
let mut br = BitReader::new(&data);
assert!(br.read_bool().unwrap());
assert!(!br.read_bool().unwrap());
}
#[test]
fn test_overflow() {
let data = [0xFF];
let mut br = BitReader::new(&data);
br.read_bits(8).unwrap();
assert!(br.read_bits(1).is_err());
}
#[test]
fn test_uvarint32() {
let data = [0xAC, 0x02];
let mut br = BitReader::new(&data);
assert_eq!(br.read_uvarint32().unwrap(), 300);
}
#[test]
fn test_varint32_negative() {
let data = [0x01];
let mut br = BitReader::new(&data);
assert_eq!(br.read_varint32().unwrap(), -1);
}
#[test]
fn test_varint32_positive() {
let data = [0x02];
let mut br = BitReader::new(&data);
assert_eq!(br.read_varint32().unwrap(), 1);
}
#[test]
fn test_read_f32() {
let val: f32 = 1.5;
let data = val.to_bits().to_le_bytes();
let mut br = BitReader::new(&data);
let read_val = br.read_f32().unwrap();
assert!((read_val - val).abs() < f32::EPSILON);
}
#[test]
fn test_read_string() {
let data = b"hello\0world";
let mut br = BitReader::new(data);
assert_eq!(br.read_string().unwrap(), "hello");
}
#[test]
fn test_bits_remaining() {
let data = [0xFF, 0xFF];
let mut br = BitReader::new(&data);
assert_eq!(br.bits_remaining(), 16);
br.read_bits(5).unwrap();
assert_eq!(br.bits_remaining(), 11);
}
#[test]
fn test_skip_bits() {
let data = [0b11110000, 0b10101010];
let mut br = BitReader::new(&data);
br.skip_bits(4).unwrap();
assert_eq!(br.read_bits(4).unwrap(), 0b1111);
}
#[test]
fn test_peek_bits() {
let data = [0xAB];
let br = BitReader::new(&data);
assert_eq!(br.peek_bits(8).unwrap(), 0xAB);
assert_eq!(br.position(), 0);
}
#[test]
fn test_ubitvar() {
let data = [0b00000101];
let mut br = BitReader::new(&data);
assert_eq!(br.read_ubitvar().unwrap(), 5);
}
#[test]
fn test_bitangle() {
let data = [0x00, 0x00, 0x00, 0x00];
let mut br = BitReader::new(&data);
assert!((br.read_bitangle(16).unwrap() - 0.0).abs() < f32::EPSILON);
}
}