#![warn(missing_docs)]
use std::io;
use super::{huffman::ReadHuffmanTree, BitQueue, Endianness, Numeric, SignedNumeric};
pub struct BitReader<R: io::Read, E: Endianness> {
reader: R,
bitqueue: BitQueue<E, u8>,
}
impl<R: io::Read, E: Endianness> BitReader<R, E> {
pub fn new(reader: R) -> BitReader<R, E> {
BitReader {
reader,
bitqueue: BitQueue::new(),
}
}
pub fn endian(reader: R, _endian: E) -> BitReader<R, E> {
BitReader {
reader,
bitqueue: BitQueue::new(),
}
}
#[inline]
pub fn into_reader(self) -> R {
self.reader
}
#[inline(always)]
pub fn read_bit(&mut self) -> io::Result<bool> {
if self.bitqueue.is_empty() {
self.bitqueue.set(read_byte(&mut self.reader)?, 8);
}
Ok(self.bitqueue.pop(1) == 1)
}
pub fn read<U>(&mut self, mut bits: u32) -> io::Result<U>
where
U: Numeric,
{
if bits <= U::bits_size() {
let bitqueue_len = self.bitqueue.len();
if bits <= bitqueue_len {
Ok(U::from_u8(self.bitqueue.pop(bits)))
} else {
let mut acc =
BitQueue::from_value(U::from_u8(self.bitqueue.pop_all()), bitqueue_len);
bits -= bitqueue_len;
read_aligned(&mut self.reader, bits / 8, &mut acc)?;
read_unaligned(&mut self.reader, bits % 8, &mut acc, &mut self.bitqueue)?;
Ok(acc.value())
}
} else {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"excessive bits for type read",
))
}
}
#[inline]
pub fn read_signed<S>(&mut self, bits: u32) -> io::Result<S>
where
S: SignedNumeric,
{
E::read_signed(self, bits)
}
pub fn skip(&mut self, mut bits: u32) -> io::Result<()> {
use std::cmp::min;
let to_drop = min(self.bitqueue.len(), bits);
if to_drop != 0 {
self.bitqueue.drop(to_drop);
bits -= to_drop;
}
skip_aligned(&mut self.reader, bits / 8)?;
skip_unaligned(&mut self.reader, bits % 8, &mut self.bitqueue)
}
pub fn read_bytes(&mut self, buf: &mut [u8]) -> io::Result<()> {
if self.byte_aligned() {
self.reader.read_exact(buf)
} else {
for b in buf.iter_mut() {
*b = self.read(8)?;
}
Ok(())
}
}
pub fn read_unary0(&mut self) -> io::Result<u32> {
if self.bitqueue.is_empty() {
read_aligned_unary(&mut self.reader, 0b1111_1111, &mut self.bitqueue)
.map(|u| u + self.bitqueue.pop_1())
} else if self.bitqueue.all_1() {
let base = self.bitqueue.len();
self.bitqueue.clear();
read_aligned_unary(&mut self.reader, 0b1111_1111, &mut self.bitqueue)
.map(|u| base + u + self.bitqueue.pop_1())
} else {
Ok(self.bitqueue.pop_1())
}
}
pub fn read_unary1(&mut self) -> io::Result<u32> {
if self.bitqueue.is_empty() {
read_aligned_unary(&mut self.reader, 0b0000_0000, &mut self.bitqueue)
.map(|u| u + self.bitqueue.pop_0())
} else if self.bitqueue.all_0() {
let base = self.bitqueue.len();
self.bitqueue.clear();
read_aligned_unary(&mut self.reader, 0b0000_0000, &mut self.bitqueue)
.map(|u| base + u + self.bitqueue.pop_0())
} else {
Ok(self.bitqueue.pop_0())
}
}
#[inline]
pub fn byte_aligned(&self) -> bool {
self.bitqueue.is_empty()
}
#[inline]
pub fn byte_align(&mut self) {
self.bitqueue.clear()
}
pub fn read_huffman<T>(&mut self, tree: &[ReadHuffmanTree<E, T>]) -> io::Result<T>
where
T: Clone,
{
let mut result: &ReadHuffmanTree<E, T> = &tree[self.bitqueue.to_state()];
loop {
match result {
ReadHuffmanTree::Done(ref value, ref queue_val, ref queue_bits, _) => {
self.bitqueue.set(*queue_val, *queue_bits);
return Ok(value.clone());
}
ReadHuffmanTree::Continue(ref tree) => {
result = &tree[read_byte(&mut self.reader)? as usize];
}
ReadHuffmanTree::InvalidState => {
panic!("invalid state");
}
}
}
}
#[inline]
pub fn into_unread(self) -> (u32, u8) {
(self.bitqueue.len(), self.bitqueue.value())
}
}
#[inline]
fn read_byte<R>(mut reader: R) -> io::Result<u8>
where
R: io::Read,
{
let mut buf = [0; 1];
reader.read_exact(&mut buf).map(|()| buf[0])
}
fn read_aligned<R, E, N>(mut reader: R, bytes: u32, acc: &mut BitQueue<E, N>) -> io::Result<()>
where
R: io::Read,
E: Endianness,
N: Numeric,
{
debug_assert!(bytes <= 16);
if bytes > 0 {
let mut buf = [0; 16];
reader.read_exact(&mut buf[0..bytes as usize])?;
for b in &buf[0..bytes as usize] {
acc.push(8, N::from_u8(*b));
}
}
Ok(())
}
fn skip_aligned<R>(mut reader: R, mut bytes: u32) -> io::Result<()>
where
R: io::Read,
{
use std::cmp::min;
let mut buf = [0; 8];
while bytes > 0 {
let to_read = min(8, bytes);
reader.read_exact(&mut buf[0..to_read as usize])?;
bytes -= to_read;
}
Ok(())
}
#[inline]
fn read_unaligned<R, E, N>(
reader: R,
bits: u32,
acc: &mut BitQueue<E, N>,
rem: &mut BitQueue<E, u8>,
) -> io::Result<()>
where
R: io::Read,
E: Endianness,
N: Numeric,
{
debug_assert!(bits <= 8);
if bits > 0 {
rem.set(read_byte(reader)?, 8);
acc.push(bits, N::from_u8(rem.pop(bits)));
}
Ok(())
}
#[inline]
fn skip_unaligned<R, E>(reader: R, bits: u32, rem: &mut BitQueue<E, u8>) -> io::Result<()>
where
R: io::Read,
E: Endianness,
{
debug_assert!(bits <= 8);
if bits > 0 {
rem.set(read_byte(reader)?, 8);
rem.pop(bits);
}
Ok(())
}
#[inline]
fn read_aligned_unary<R, E>(
mut reader: R,
continue_val: u8,
rem: &mut BitQueue<E, u8>,
) -> io::Result<u32>
where
R: io::Read,
E: Endianness,
{
let mut acc = 0;
let mut byte = read_byte(reader.by_ref())?;
while byte == continue_val {
acc += 8;
byte = read_byte(reader.by_ref())?;
}
rem.set(byte, 8);
Ok(acc)
}