use std::io::{Read, Seek, SeekFrom};
use super::BitsReader;
#[doc(hidden)]
pub struct SeekableReader<R: Read + Seek> {
underlying_stream: R,
read_buffer: Vec<u8>,
read_position: usize,
bytes_in_buffer: usize,
bytes_read_total: usize,
lookahead_buffer: u64,
lookahead_bit_count: u32,
string_buffer: [u8; 4096],
}
const BUFFER_SIZE: usize = 65536;
impl<R: Read + Seek> SeekableReader<R> {
pub fn new(mut stream: R) -> std::io::Result<Self> {
let mut buffer = vec![0u8; BUFFER_SIZE];
let buffer_len = stream.read(&mut buffer)?;
let mut reader = SeekableReader {
underlying_stream: stream,
read_buffer: buffer,
read_position: 0,
bytes_in_buffer: buffer_len,
bytes_read_total: 0,
lookahead_buffer: 0,
lookahead_bit_count: 0,
string_buffer: [0; 4096],
};
reader.refill();
Ok(reader)
}
fn refill_internal_buffer(&mut self) -> std::io::Result<usize> {
if self.read_position < self.bytes_in_buffer / 2 {
return Ok(0);
}
if self.read_position >= self.bytes_in_buffer {
let bytes_read = self.underlying_stream.read(&mut self.read_buffer)?;
self.bytes_in_buffer = bytes_read;
self.read_position = 0;
return Ok(bytes_read);
}
let remaining = self.bytes_in_buffer - self.read_position;
if remaining > 0 {
self.read_buffer.copy_within(self.read_position..self.bytes_in_buffer, 0);
}
let bytes_read = self.underlying_stream.read(&mut self.read_buffer[remaining..])?;
self.bytes_in_buffer = remaining + bytes_read;
self.read_position = 0;
Ok(bytes_read)
}
}
impl<R: Read + Seek> BitsReader for SeekableReader<R> {
#[inline(always)]
fn refill(&mut self) {
unsafe {
while self.lookahead_bit_count <= 32 {
if self.read_position < self.bytes_in_buffer {
let remaining = self.bytes_in_buffer - self.read_position;
if remaining >= 4 {
let ptr = self.read_buffer.as_ptr().add(self.read_position) as *const u32;
self.lookahead_buffer |= (ptr.read_unaligned().to_le() as u64) << self.lookahead_bit_count;
self.lookahead_bit_count += 32;
self.read_position += 4;
self.bytes_read_total += 4;
} else {
let byte = *self.read_buffer.get_unchecked(self.read_position);
self.lookahead_buffer |= (byte as u64) << self.lookahead_bit_count;
self.lookahead_bit_count += 8;
self.read_position += 1;
self.bytes_read_total += 1;
}
} else {
if self.refill_internal_buffer().unwrap_or(0) == 0 {
break;
}
}
}
}
}
#[inline(always)]
fn read_bits(&mut self, amount: u32) -> u32 {
if self.lookahead_bit_count < amount {
self.refill();
}
self.read_bits_unchecked(amount)
}
#[inline(always)]
fn read_bits_unchecked(&mut self, amount: u32) -> u32 {
debug_assert!(amount <= 32);
debug_assert!(self.lookahead_bit_count >= amount);
let mask = if amount == 32 {
u32::MAX
} else {
(1u32 << amount) - 1
};
let result = (self.lookahead_buffer as u32) & mask;
self.lookahead_buffer >>= amount;
self.lookahead_bit_count -= amount;
result
}
#[inline(always)]
fn read_bytes(&mut self, amount: u32) -> Vec<u8> {
let mut bytes = vec![0u8; amount as usize];
let mut bytes_read = 0;
unsafe {
while self.lookahead_bit_count >= 8 && bytes_read < amount {
*bytes.get_unchecked_mut(bytes_read as usize) = (self.lookahead_buffer & 0xFF) as u8;
self.lookahead_buffer >>= 8;
self.lookahead_bit_count -= 8;
bytes_read += 1;
}
while bytes_read < amount {
if self.read_position >= self.bytes_in_buffer {
if self.refill_internal_buffer().unwrap_or(0) == 0 {
break;
}
}
let available = self.bytes_in_buffer - self.read_position;
let needed = (amount - bytes_read) as usize;
let to_copy = available.min(needed);
if to_copy > 0 {
let src = self.read_buffer.as_ptr().add(self.read_position);
let dst = bytes.as_mut_ptr().add(bytes_read as usize);
std::ptr::copy_nonoverlapping(src, dst, to_copy);
self.read_position += to_copy;
self.bytes_read_total += to_copy;
bytes_read += to_copy as u32;
} else {
break;
}
}
}
bytes
}
#[inline]
fn read_bool(&mut self) -> bool {
self.read_bits_unchecked(1) == 1
}
#[inline]
fn read_f32(&mut self) -> f32 {
f32::from_bits(self.read_bits(32))
}
#[inline]
fn read_var_u32(&mut self) -> u32 {
let mut x: u32 = 0;
let mut shift: u32 = 0;
loop {
if self.lookahead_bit_count < 8 {
self.refill();
}
let byte = self.read_bits_unchecked(8) as u8;
x |= ((byte & 0x7F) as u32) << shift;
if (byte & 0x80) == 0 || shift == 35 {
return x;
}
shift += 7;
}
}
#[inline]
fn read_var_u64(&mut self) -> u64 {
let mut x: u64 = 0;
let mut y: u8 = 0;
let mut byte: u8;
loop {
if self.lookahead_bit_count < 8 {
self.refill();
}
byte = self.read_bits_unchecked(8) as u8;
x |= (byte as u64 & 0x7F) << y;
y += 7;
if (byte & 0x80) == 0 {
return x;
}
}
}
#[inline]
fn read_var_i32(&mut self) -> i32 {
let ux = self.read_var_u32() as i32;
if ux & 1 != 0 {
return !(ux >> 1);
}
ux >> 1
}
#[inline]
fn read_ubit_var(&mut self) -> u32 {
const UBV_COUNT: [u8; 4] = [0, 4, 8, 28];
self.refill();
let a = self.read_bits_unchecked(6);
let b = a >> 4;
if a == 0 {
return b;
}
(a & 15) | (self.read_bits_unchecked(UBV_COUNT[b as usize] as u32) << 4)
}
#[inline]
fn read_ubit_var_fp(&mut self) -> i32 {
const UBVFP_COUNT: [u8; 5] = [2, 4, 10, 17, 31];
let mut i: u8 = 0;
self.refill();
while i < 4 && !self.read_bool() {
i += 1
}
self.read_bits_unchecked(UBVFP_COUNT[i as usize] as u32) as i32
}
#[inline]
fn read_ubit_var_fp_unchecked(&mut self) -> i32 {
const UBVFP_COUNT: [u8; 5] = [2, 4, 10, 17, 31];
let mut i: u8 = 0;
while i < 4 && !self.read_bool() {
i += 1
}
self.read_bits_unchecked(UBVFP_COUNT[i as usize] as u32) as i32
}
#[inline]
fn read_normal(&mut self) -> f32 {
const NORMAL_FACTOR: f32 = (1.0 / (1 << 11) as f32) - 1.0;
let is_neg = self.read_bool();
let len = self.read_bits_unchecked(11) as f32;
let normal = len * NORMAL_FACTOR;
match is_neg {
true => -normal,
false => normal,
}
}
#[inline]
fn read_normal_vec3(&mut self) -> [f32; 3] {
self.refill();
let mut vec = [0.0f32; 3];
let x = self.read_bool();
let y = self.read_bool();
vec[0] = match x {
true => self.read_normal(),
false => vec[0],
};
vec[1] = match y {
true => self.read_normal(),
false => vec[1],
};
vec[2] = match (vec[0] * vec[0] + vec[1] * vec[1]) as f64 {
x if x < 1.0 => (1.0 - x).sqrt() as f32,
_ => vec[2],
};
vec[2] = match self.read_bool() {
true => -vec[2],
false => vec[2],
};
vec
}
#[inline]
fn read_u64_le(&mut self) -> u64 {
let b1 = self.read_bits(8) as u64;
let b2 = self.read_bits(8) as u64;
let b3 = self.read_bits(8) as u64;
let b4 = self.read_bits(8) as u64;
let b5 = self.read_bits(8) as u64;
let b6 = self.read_bits(8) as u64;
let b7 = self.read_bits(8) as u64;
let b8 = self.read_bits(8) as u64;
b1 | (b2 << 8) | (b3 << 16) | (b4 << 24) |
(b5 << 32) | (b6 << 40) | (b7 << 48) | (b8 << 56)
}
#[inline]
fn read_cstring(&mut self) -> String {
let mut i = 0;
let mut byte: u8;
self.refill();
loop {
if self.lookahead_bit_count < 8 {
self.refill();
if self.lookahead_bit_count < 8 {
break;
}
}
byte = self.read_bits_unchecked(8) as u8;
if byte == 0 {
return String::from_utf8_lossy(&self.string_buffer[..i]).into_owned();
}
if i >= self.string_buffer.len() {
break;
}
self.string_buffer[i] = byte;
i += 1;
}
String::from_utf8_lossy(&self.string_buffer[..i]).into_owned()
}
#[inline]
fn read_coordinate(&mut self) -> f32 {
const COORD_FACTOR: f32 = 1.0 / (1 << 5) as f32;
self.refill();
let mut value = 0f32;
let mut int_val = self.read_bits_unchecked(1);
let mut fract_val = self.read_bits_unchecked(1);
if int_val != 0 || fract_val != 0 {
let signbit = self.read_bits_unchecked(1);
if int_val != 0 {
int_val = self.read_bits_unchecked(14) + 1;
}
if fract_val != 0 {
fract_val = self.read_bits_unchecked(5);
}
value = (int_val as f32) + (fract_val as f32) * COORD_FACTOR;
if signbit == 1 {
value = -value;
}
}
value
}
#[inline]
fn read_angle(&mut self, n: u32) -> f32 {
(self.read_bits(n) as f32) * 360.0 / (1 << n) as f32
}
#[inline]
fn read_bits_as_bytes(&mut self, n: u32) -> Vec<u8> {
let bits = n % 8;
let bytes = (n / 8) as usize;
let mut tmp = vec![0; bytes];
for i in 0..bytes {
tmp[i] = self.read_bits(8) as u8;
}
if bits > 0 {
tmp.push(self.read_bits(bits) as u8);
}
tmp
}
#[inline]
fn remaining_bytes(&self) -> usize {
(self.bytes_in_buffer - self.read_position) + (self.lookahead_bit_count as usize / 8)
}
#[inline]
fn seek(&mut self, offset: usize) {
if self.underlying_stream.seek(SeekFrom::Start(offset as u64)).is_ok() {
self.read_position = 0;
self.bytes_in_buffer = 0;
self.bytes_read_total = offset;
self.lookahead_buffer = 0;
self.lookahead_bit_count = 0;
if let Ok(bytes_read) = self.underlying_stream.read(&mut self.read_buffer) {
self.bytes_in_buffer = bytes_read;
}
self.refill();
}
}
}