#![warn(missing_docs)]
use std::io;
use super::{Numeric, SignedNumeric, BitQueue,
Endianness, BigEndian, LittleEndian};
use huffman::ReadHuffmanTree;
pub struct BitReader<'a, E: Endianness> {
reader: &'a mut io::Read,
bitqueue: BitQueue<E,u8>
}
impl<'a, E: Endianness> BitReader<'a, E> {
pub fn new(reader: &mut io::Read) -> BitReader<E> {
BitReader{reader: reader, bitqueue: BitQueue::new()}
}
#[inline(always)]
pub fn read_bit(&mut self) -> Result<bool, io::Error> {
if self.bitqueue.is_empty() {
self.bitqueue.set(read_byte(self.reader)?, 8);
}
Ok(self.bitqueue.pop(1) == 1)
}
pub fn read<U>(&mut self, mut bits: u32) -> Result<U, io::Error>
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(bitqueue_len)),
bitqueue_len);
bits -= bitqueue_len;
read_aligned(&mut self.reader, bits / 8, &mut acc)
.and_then(|()| read_unaligned(&mut self.reader,
bits % 8,
&mut acc,
&mut self.bitqueue))
.map(|()| acc.value())
}
} else {
Err(io::Error::new(io::ErrorKind::InvalidInput,
"excessive bits for type read"))
}
}
pub fn skip(&mut self, mut bits: u32) -> Result<(), io::Error> {
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)
.and_then(|()| skip_unaligned(&mut self.reader,
bits % 8,
&mut self.bitqueue))
}
pub fn read_bytes(&mut self, buf: &mut [u8]) -> Result<(), io::Error> {
if self.byte_aligned() {
self.reader.read_exact(buf)
} else {
for b in buf.iter_mut() {
*b = self.read::<u8>(8)?;
}
Ok(())
}
}
pub fn read_unary0(&mut self) -> Result<u32, io::Error> {
if self.bitqueue.is_empty() {
read_aligned_unary(&mut self.reader,
0b11111111,
&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,
0b11111111,
&mut self.bitqueue).map(
|u| base + u + self.bitqueue.pop_1())
} else {
Ok(self.bitqueue.pop_1())
}
}
pub fn read_unary1(&mut self) -> Result<u32, io::Error> {
if self.bitqueue.is_empty() {
read_aligned_unary(&mut self.reader,
0b00000000,
&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,
0b00000000,
&mut self.bitqueue).map(
|u| base + u + self.bitqueue.pop_0())
} else {
Ok(self.bitqueue.pop_0())
}
}
#[inline(always)]
pub fn byte_aligned(&self) -> bool {
self.bitqueue.is_empty()
}
#[inline(always)]
pub fn byte_align(&mut self) {
self.bitqueue.clear()
}
pub fn read_huffman<T>(&mut self, tree: &[ReadHuffmanTree<E,T>]) ->
Result<T,io::Error> 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(self.reader)? as usize];
}
&ReadHuffmanTree::InvalidState => {panic!("invalid state");}
}
}
}
#[inline(always)]
pub fn into_unread(self) -> (u32,u8) {
(self.bitqueue.len(), self.bitqueue.value())
}
}
impl<'a> BitReader<'a, BigEndian> {
pub fn read_signed<S>(&mut self, bits: u32) -> Result<S, io::Error>
where S: SignedNumeric {
if bits <= S::bits_size() {
let is_negative = self.read_bit()?;
let unsigned = self.read::<S>(bits - 1)?;
Ok(if is_negative {unsigned.as_negative(bits)} else {unsigned})
} else {
Err(io::Error::new(io::ErrorKind::InvalidInput,
"excessive bits for type read"))
}
}
}
impl<'a> BitReader<'a, LittleEndian> {
pub fn read_signed<S>(&mut self, bits: u32) -> Result<S, io::Error>
where S: SignedNumeric {
if bits <= S::bits_size() {
let unsigned = self.read::<S>(bits - 1)?;
let is_negative = self.read_bit()?;
Ok(if is_negative {unsigned.as_negative(bits)} else {unsigned})
} else {
Err(io::Error::new(io::ErrorKind::InvalidInput,
"excessive bits for type read"))
}
}
}
#[inline]
fn read_byte(reader: &mut io::Read) -> Result<u8,io::Error> {
let mut buf = [0; 1];
reader.read_exact(&mut buf).map(|()| buf[0])
}
fn read_aligned<E,N>(reader: &mut io::Read,
bytes: u32,
acc: &mut BitQueue<E,N>) -> Result<(), io::Error>
where E: Endianness, N: Numeric {
debug_assert!(bytes <= 8);
let mut buf = [0; 8];
reader.read_exact(&mut buf[0..bytes as usize])
.map(|()| {for b in &buf[0..bytes as usize]
{acc.push(8, N::from_u8(*b))}})
}
fn skip_aligned(reader: &mut io::Read,
mut bytes: u32) -> Result<(), io::Error> {
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<E,N>(reader: &mut io::Read,
bits: u32,
acc: &mut BitQueue<E,N>,
rem: &mut BitQueue<E,u8>) -> Result<(), io::Error>
where E: Endianness, N: Numeric {
debug_assert!(bits <= 8);
if bits > 0 {
read_byte(reader).map(|byte|
{rem.set(byte, 8);
acc.push(bits, N::from_u8(rem.pop(bits)))})
} else {
Ok(())
}
}
#[inline]
fn skip_unaligned<E>(reader: &mut io::Read,
bits: u32,
rem: &mut BitQueue<E,u8>) -> Result<(), io::Error>
where E: Endianness {
debug_assert!(bits <= 8);
if bits > 0 {
rem.set(read_byte(reader)?, 8);
rem.pop(bits);
}
Ok(())
}
#[inline]
fn read_aligned_unary<E>(reader: &mut io::Read,
continue_val: u8,
rem: &mut BitQueue<E,u8>) -> Result<u32,io::Error>
where E: Endianness {
let mut acc = 0;
let mut byte = read_byte(reader)?;
while byte == continue_val {
acc += 8;
byte = read_byte(reader)?;
}
rem.set(byte, 8);
Ok(acc)
}