use crate::error::{LhaResult, LhaError, DecompressionError};
use crate::stub_io::Read;
type BitBuf = usize;
const BITBUF_BYTESIZE: usize = size_of::<BitBuf>();
const BITBUF_BITSIZE: u32 = BitBuf::BITS;
pub trait UBits: Copy {
const BITS: u32;
fn from_bits(bitbuf: BitBuf) -> Self;
}
pub trait BitRead {
type Error;
fn read_bit(&mut self) -> Result<bool, LhaError<Self::Error>>;
fn read_bits<T: UBits>(&mut self, n: u32) -> Result<T, LhaError<Self::Error>>;
#[allow(dead_code)]
fn by_ref(&mut self) -> &mut Self {
self
}
}
#[derive(Debug)]
pub struct BitStream<R> {
inner: R,
bits_buf: BitBuf,
}
macro_rules! impl_ubits {
($ty:ty) => {
impl UBits for $ty {
const BITS: u32 = <$ty>::BITS;
#[inline(always)]
fn from_bits(bitbuf: BitBuf) -> Self {
bitbuf as $ty
}
}
};
}
impl_ubits!(u8);
impl_ubits!(u16);
impl_ubits!(u32);
impl_ubits!(usize);
#[cfg(feature = "extend")]
impl_ubits!(u64);
#[cfg(feature = "extend")]
impl_ubits!(u128);
impl<R: Read> BitStream<R> {
pub fn new(inner: R) -> BitStream<R> {
BitStream { inner, bits_buf: 1 << (BITBUF_BITSIZE - 1) }
}
pub fn into_inner(self) -> R {
self.inner
}
pub fn get_ref(&self) -> &R {
&self.inner
}
pub fn get_mut(&mut self) -> &mut R {
&mut self.inner
}
#[inline]
fn next_bits(&mut self, n: u32) -> LhaResult<BitBuf, R> {
debug_assert!(n != 0 && n <= BITBUF_BITSIZE);
let have_bits = BITBUF_BITSIZE - self.bits_buf.trailing_zeros() - 1;
let res = self.bits_buf >> (BITBUF_BITSIZE - n);
if n <= have_bits {
self.bits_buf <<= n;
return Ok(res)
}
let missing_bits = n - have_bits;
let mut buf = [0u8;BITBUF_BYTESIZE];
let bits_read = 8u32 * self.inner.read_all(&mut buf)
.map_err(LhaError::Io)? as u32;
if bits_read < missing_bits {
return Err(LhaError::Io(R::unexpected_eof()))
}
let new_bits: BitBuf = BitBuf::from_be_bytes(buf);
let res = res & (res - 1)
| new_bits >> (BITBUF_BITSIZE - missing_bits);
self.bits_buf = if missing_bits == BITBUF_BITSIZE {
0
}
else {
new_bits << missing_bits
} | 1 << (BITBUF_BITSIZE - 1 - (bits_read - missing_bits));
Ok(res)
}
}
impl<R: BitRead> BitRead for &mut R {
type Error = R::Error;
#[inline]
fn read_bit(&mut self) -> Result<bool, LhaError<Self::Error>> {
(*self).read_bit()
}
#[inline]
fn read_bits<T: UBits>(&mut self, n: u32) -> Result<T, LhaError<Self::Error>> {
(*self).read_bits(n)
}
}
impl<R: Read> BitRead for BitStream<R> {
type Error = R::Error;
#[inline]
fn read_bit(&mut self) -> Result<bool, LhaError<Self::Error>> {
self.next_bits(1).map(|bits| bits != 0)
}
fn read_bits<T: UBits>(&mut self, n: u32) -> Result<T, LhaError<Self::Error>> {
match n {
0 => Ok(0),
n if n <= T::BITS => self.next_bits(n),
_ => Err(LhaError::Decompress(DecompressionError::BitSizeOverflow))
}.map(T::from_bits)
}
}
#[cfg(feature = "std")]
#[cfg(test)]
mod tests {
use std::io;
use super::*;
#[test]
fn bit_stream_works() {
assert_eq!(BITBUF_BYTESIZE, size_of::<usize>());
assert!(BITBUF_BITSIZE >= 32);
assert_eq!(BITBUF_BITSIZE, BITBUF_BYTESIZE as u32 * 8);
let mut somebits: &[u8] = &[];
let mut brdr = BitStream::new(&mut somebits);
let err: io::Error = brdr.read_bit().unwrap_err().into();
assert_eq!(err.kind(), io::ErrorKind::UnexpectedEof);
let err: io::Error = brdr.read_bits::<usize>(BITBUF_BITSIZE).unwrap_err().into();
assert_eq!(err.kind(), io::ErrorKind::UnexpectedEof);
let mut somebits: &[u8] = &[0];
let mut brdr = BitStream::new(&mut somebits);
for _ in 0..8 {
assert_eq!(brdr.read_bit().unwrap(), false);
}
let mut somebits: &[u8] = &[!0];
let mut brdr = BitStream::new(&mut somebits);
for _ in 0..8 {
assert_eq!(brdr.read_bit().unwrap(), true);
}
let mut somebits: &[u8] = &[0b01001100, 0b01110000, 0b11110000, 0b01111100, 0b00001111, 0b11000000, 0b01111111,
0b00000000, 0b11111111, 0b00000000, 0b01111111, 0b11000000, 0b00001111, 0b11111100,
0b00000000, 0b01111111, 0b11110000, 0b00000000, 0b11111111, 0b11110000, 0b00000000,
0b01111111, 0b11111100, 0b00000000, 0b00001111, 0b11111111, 0b11000000, 0b00000000,
0b01111111, 0b11111111];
assert_eq!(brdr.read_bits::<usize>(0).unwrap(), 0);
let mut brdr = BitStream::new(&mut somebits);
for n in 1..16 {
assert_eq!(brdr.read_bits::<u16>(n).unwrap(), 0);
assert_eq!(brdr.read_bits::<u16>(n).unwrap(), (1 << n) - 1);
}
assert_eq!(brdr.read_bits::<usize>(0).unwrap(), 0);
let err: io::Error = brdr.read_bit().unwrap_err().into();
assert_eq!(err.kind(), io::ErrorKind::UnexpectedEof);
let mut somebits: &[u8] = &[1,2,3,4,5,6,7,8];
let mut brdr = BitStream::new(&mut somebits);
assert_eq!(brdr.get_ref(), &&mut &[1,2,3,4,5,6,7,8]);
assert_eq!(brdr.get_mut(), &mut &mut &[1,2,3,4,5,6,7,8]);
assert!(matches!(brdr.by_ref(), &mut BitStream {..}));
assert!(matches!((&mut brdr.by_ref()).read_bits::<usize>(u32::MAX).unwrap_err(),
LhaError::Decompress(DecompressionError::BitSizeOverflow)));
assert!(matches!((&mut brdr.by_ref()).read_bits::<u8>(u8::BITS + 1).unwrap_err(),
LhaError::Decompress(DecompressionError::BitSizeOverflow)));
assert!(matches!((&mut brdr.by_ref()).read_bits::<u16>(u16::BITS + 1).unwrap_err(),
LhaError::Decompress(DecompressionError::BitSizeOverflow)));
assert!(matches!((&mut brdr.by_ref()).read_bits::<u32>(u32::BITS + 1).unwrap_err(),
LhaError::Decompress(DecompressionError::BitSizeOverflow)));
#[cfg(target_pointer_width = "64")]
{
assert_eq!(BITBUF_BITSIZE, 64);
assert_eq!(brdr.read_bits::<usize>(BITBUF_BITSIZE).unwrap(), 0x0102030405060708);
}
#[cfg(target_pointer_width = "32")]
{
assert_eq!(BITBUF_BITSIZE, 32);
assert_eq!(brdr.read_bits::<usize>(BITBUF_BITSIZE).unwrap(), 0x01020304);
}
}
}