use crate::{BitStream, Endianness, Result};
use std::cell::RefCell;
use std::collections::HashMap;
use std::hash::Hash;
use std::marker::PhantomData;
pub trait BitRead<E: Endianness>: Sized {
fn read(stream: &mut BitStream<E>) -> Result<Self>;
}
pub trait BitSize {
fn bit_size() -> usize;
}
macro_rules! impl_read_int {
($type:ty, $len:expr) => {
impl<E: Endianness> BitRead<E> for $type {
#[inline]
fn read(stream: &mut BitStream<E>) -> Result<$type> {
stream.read_int::<$type>($len)
}
}
impl BitSize for $type {
#[inline]
fn bit_size() -> usize {
$len
}
}
};
}
impl_read_int!(u8, 8);
impl_read_int!(u16, 16);
impl_read_int!(u32, 32);
impl_read_int!(u64, 64);
impl_read_int!(u128, 128);
impl_read_int!(i8, 8);
impl_read_int!(i16, 16);
impl_read_int!(i32, 32);
impl_read_int!(i64, 64);
impl_read_int!(i128, 128);
impl<E: Endianness> BitRead<E> for f32 {
#[inline]
fn read(stream: &mut BitStream<E>) -> Result<f32> {
stream.read_float::<f32>()
}
}
impl BitSize for f32 {
#[inline]
fn bit_size() -> usize {
32
}
}
impl<E: Endianness> BitRead<E> for f64 {
#[inline]
fn read(stream: &mut BitStream<E>) -> Result<f64> {
stream.read_float::<f64>()
}
}
impl BitSize for f64 {
#[inline]
fn bit_size() -> usize {
64
}
}
impl<E: Endianness> BitRead<E> for bool {
#[inline]
fn read(stream: &mut BitStream<E>) -> Result<bool> {
stream.read_bool()
}
}
impl BitSize for bool {
#[inline]
fn bit_size() -> usize {
1
}
}
impl<E: Endianness> BitRead<E> for String {
#[inline]
fn read(stream: &mut BitStream<E>) -> Result<String> {
stream.read_string(None)
}
}
pub trait BitReadSized<E: Endianness>: Sized {
fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self>;
}
pub trait BitSizeSized {
fn bit_size(size: usize) -> usize;
}
macro_rules! impl_read_int_sized {
($type:ty) => {
impl<E: Endianness> BitReadSized<E> for $type {
#[inline]
fn read(stream: &mut BitStream<E>, size: usize) -> Result<$type> {
stream.read_int::<$type>(size)
}
}
impl BitSizeSized for $type {
#[inline]
fn bit_size(size: usize) -> usize {
size
}
}
};
}
impl_read_int_sized!(u8);
impl_read_int_sized!(u16);
impl_read_int_sized!(u32);
impl_read_int_sized!(u64);
impl_read_int_sized!(u128);
impl_read_int_sized!(i8);
impl_read_int_sized!(i16);
impl_read_int_sized!(i32);
impl_read_int_sized!(i64);
impl_read_int_sized!(i128);
impl<E: Endianness> BitReadSized<E> for String {
#[inline]
fn read(stream: &mut BitStream<E>, size: usize) -> Result<String> {
stream.read_string(Some(size))
}
}
impl BitSizeSized for String {
#[inline]
fn bit_size(size: usize) -> usize {
8 * size
}
}
impl<E: Endianness, T: BitRead<E>> BitRead<E> for Option<T> {
fn read(stream: &mut BitStream<E>) -> Result<Self> {
if stream.read()? {
Ok(Some(stream.read()?))
} else {
Ok(None)
}
}
}
impl<T: BitSize> BitSize for Option<T> {
#[inline]
fn bit_size() -> usize {
1 + T::bit_size()
}
}
impl<E: Endianness, T: BitReadSized<E>> BitReadSized<E> for Option<T> {
fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self> {
if stream.read()? {
Ok(Some(stream.read_sized(size)?))
} else {
Ok(None)
}
}
}
impl<T: BitSizeSized> BitSizeSized for Option<T> {
#[inline]
fn bit_size(size: usize) -> usize {
1 + T::bit_size(size)
}
}
impl<E: Endianness> BitReadSized<E> for BitStream<E> {
#[inline]
fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self> {
stream.read_bits(size)
}
}
impl<E: Endianness> BitSizeSized for BitStream<E> {
#[inline]
fn bit_size(size: usize) -> usize {
size
}
}
impl<E: Endianness, T: BitRead<E>> BitReadSized<E> for Vec<T> {
fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self> {
let mut vec = Vec::with_capacity(size);
for _ in 0..size {
vec.push(stream.read()?)
}
Ok(vec)
}
}
impl<T: BitSize> BitSizeSized for Vec<T> {
#[inline]
fn bit_size(size: usize) -> usize {
size * T::bit_size()
}
}
impl<E: Endianness, K: BitRead<E> + Eq + Hash, T: BitRead<E>> BitReadSized<E> for HashMap<K, T> {
fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self> {
let mut map = HashMap::with_capacity(size);
for _ in 0..size {
let key = stream.read()?;
let value = stream.read()?;
map.insert(key, value);
}
Ok(map)
}
}
impl<K: BitSize, T: BitSize> BitSizeSized for HashMap<K, T> {
#[inline]
fn bit_size(size: usize) -> usize {
size * (K::bit_size() + T::bit_size())
}
}
#[derive(Clone, Debug)]
pub struct LazyBitRead<T: BitRead<E> + BitSize, E: Endianness> {
source: RefCell<BitStream<E>>,
inner_type: PhantomData<T>,
}
impl<T: BitRead<E> + BitSize, E: Endianness> LazyBitRead<T, E> {
#[inline]
pub fn read(self) -> Result<T> {
self.source.borrow_mut().read::<T>()
}
}
impl<T: BitRead<E> + BitSize, E: Endianness> BitRead<E> for LazyBitRead<T, E> {
#[inline]
fn read(stream: &mut BitStream<E>) -> Result<Self> {
let bit_size = T::bit_size();
Ok(LazyBitRead {
source: RefCell::new(stream.read_bits(bit_size)?),
inner_type: PhantomData,
})
}
}
impl<T: BitRead<E> + BitSize, E: Endianness> BitSize for LazyBitRead<T, E> {
#[inline]
fn bit_size() -> usize {
T::bit_size()
}
}
#[derive(Clone, Debug)]
pub struct LazyBitReadSized<T: BitReadSized<E> + BitSizeSized, E: Endianness> {
source: RefCell<BitStream<E>>,
size: usize,
inner_type: PhantomData<T>,
}
impl<T: BitReadSized<E> + BitSizeSized, E: Endianness> LazyBitReadSized<T, E> {
#[inline]
pub fn value(self) -> Result<T> {
self.source.borrow_mut().read_sized::<T>(self.size)
}
}
impl<T: BitReadSized<E> + BitSizeSized, E: Endianness> BitReadSized<E> for LazyBitReadSized<T, E> {
#[inline]
fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self> {
let bit_size = T::bit_size(size);
Ok(LazyBitReadSized {
source: RefCell::new(stream.read_bits(bit_size)?),
inner_type: PhantomData,
size,
})
}
}
impl<T: BitReadSized<E> + BitSizeSized, E: Endianness> BitSizeSized for LazyBitReadSized<T, E> {
#[inline]
fn bit_size(size: usize) -> usize {
T::bit_size(size)
}
}