use crate::endianness::{BigEndian, LittleEndian};
use crate::{BitReadStream, Endianness, Result};
use std::borrow::Cow;
use std::cell::RefCell;
use std::cmp::min;
use std::collections::HashMap;
use std::hash::Hash;
use std::marker::PhantomData;
use std::mem::{size_of, MaybeUninit};
use std::rc::Rc;
use std::sync::Arc;
pub trait BitRead<'a, E: Endianness>: Sized {
fn read(stream: &mut BitReadStream<'a, E>) -> Result<Self>;
#[doc(hidden)]
#[inline]
unsafe fn read_unchecked(stream: &mut BitReadStream<'a, E>, _end: bool) -> Result<Self> {
Self::read(stream)
}
#[inline]
fn skip(stream: &mut BitReadStream<'a, E>) -> Result<()> {
match Self::bit_size() {
Some(size) => stream.skip_bits(size),
None => Self::read(stream).map(|_| ()),
}
}
#[inline]
fn bit_size() -> Option<usize> {
None
}
}
macro_rules! impl_read_int {
($type:ty) => {
impl<E: Endianness> BitRead<'_, E> for $type {
#[inline]
fn read(stream: &mut BitReadStream<E>) -> Result<$type> {
stream.read_int::<$type>(<$type>::BITS as usize)
}
#[inline]
unsafe fn read_unchecked(stream: &mut BitReadStream<E>, end: bool) -> Result<$type> {
Ok(stream.read_int_unchecked::<$type>(<$type>::BITS as usize, end))
}
#[inline]
fn bit_size() -> Option<usize> {
Some(<$type>::BITS as usize)
}
}
};
}
macro_rules! impl_read_int_nonzero {
($type:ty) => {
impl BitRead<'_, LittleEndian> for Option<$type> {
#[inline]
fn read(stream: &mut BitReadStream<LittleEndian>) -> Result<Self> {
Ok(<$type>::new(stream.read()?))
}
#[inline]
unsafe fn read_unchecked(
stream: &mut BitReadStream<LittleEndian>,
end: bool,
) -> Result<Self> {
Ok(<$type>::new(
stream.read_int_unchecked(size_of::<$type>() * 8, end),
))
}
#[inline]
fn bit_size() -> Option<usize> {
Some(size_of::<$type>() * 8)
}
}
impl BitRead<'_, BigEndian> for Option<$type> {
#[inline]
fn read(stream: &mut BitReadStream<BigEndian>) -> Result<Self> {
Ok(<$type>::new(stream.read()?))
}
#[inline]
unsafe fn read_unchecked(
stream: &mut BitReadStream<BigEndian>,
end: bool,
) -> Result<Self> {
Ok(<$type>::new(
stream.read_int_unchecked(size_of::<$type>() * 8, end),
))
}
#[inline]
fn bit_size() -> Option<usize> {
Some(size_of::<$type>() * 8)
}
}
};
}
impl_read_int!(u8);
impl_read_int!(u16);
impl_read_int!(u32);
impl_read_int!(u64);
impl_read_int!(u128);
impl_read_int!(i8);
impl_read_int!(i16);
impl_read_int!(i32);
impl_read_int!(i64);
impl_read_int!(i128);
impl_read_int_nonzero!(std::num::NonZeroU8);
impl_read_int_nonzero!(std::num::NonZeroU16);
impl_read_int_nonzero!(std::num::NonZeroU32);
impl_read_int_nonzero!(std::num::NonZeroU64);
impl_read_int_nonzero!(std::num::NonZeroU128);
impl<E: Endianness> BitRead<'_, E> for f32 {
#[inline]
fn read(stream: &mut BitReadStream<E>) -> Result<f32> {
stream.read_float::<f32>()
}
#[inline]
unsafe fn read_unchecked(stream: &mut BitReadStream<E>, end: bool) -> Result<f32> {
Ok(stream.read_float_unchecked::<f32>(end))
}
#[inline]
fn bit_size() -> Option<usize> {
Some(32)
}
}
impl<E: Endianness> BitRead<'_, E> for f64 {
#[inline]
fn read(stream: &mut BitReadStream<E>) -> Result<f64> {
stream.read_float::<f64>()
}
#[inline]
unsafe fn read_unchecked(stream: &mut BitReadStream<E>, end: bool) -> Result<f64> {
Ok(stream.read_float_unchecked::<f64>(end))
}
#[inline]
fn bit_size() -> Option<usize> {
Some(64)
}
}
impl<E: Endianness> BitRead<'_, E> for bool {
#[inline]
fn read(stream: &mut BitReadStream<E>) -> Result<bool> {
stream.read_bool()
}
#[inline]
unsafe fn read_unchecked(stream: &mut BitReadStream<E>, _end: bool) -> Result<bool> {
Ok(stream.read_bool_unchecked())
}
#[inline]
fn bit_size() -> Option<usize> {
Some(1)
}
}
impl<E: Endianness> BitRead<'_, E> for String {
#[inline]
fn read(stream: &mut BitReadStream<E>) -> Result<String> {
Ok(stream.read_string(None)?.into_owned())
}
}
impl<'a, E: Endianness> BitRead<'a, E> for Cow<'a, str> {
#[inline]
fn read(stream: &mut BitReadStream<'a, E>) -> Result<Cow<'a, str>> {
stream.read_string(None)
}
}
impl<'a, E: Endianness, T: BitRead<'a, E>> BitRead<'a, E> for Rc<T> {
#[inline]
fn read(stream: &mut BitReadStream<'a, E>) -> Result<Self> {
Ok(Rc::new(T::read(stream)?))
}
#[inline]
unsafe fn read_unchecked(stream: &mut BitReadStream<'a, E>, end: bool) -> Result<Self> {
Ok(Rc::new(T::read_unchecked(stream, end)?))
}
#[inline]
fn bit_size() -> Option<usize> {
T::bit_size()
}
}
impl<'a, E: Endianness, T: BitRead<'a, E>> BitRead<'a, E> for Arc<T> {
#[inline]
fn read(stream: &mut BitReadStream<'a, E>) -> Result<Self> {
Ok(Arc::new(T::read(stream)?))
}
#[inline]
unsafe fn read_unchecked(stream: &mut BitReadStream<'a, E>, end: bool) -> Result<Self> {
Ok(Arc::new(T::read_unchecked(stream, end)?))
}
#[inline]
fn bit_size() -> Option<usize> {
T::bit_size()
}
}
impl<'a, E: Endianness, T: BitRead<'a, E>> BitRead<'a, E> for Box<T> {
#[inline]
fn read(stream: &mut BitReadStream<'a, E>) -> Result<Self> {
Ok(Box::new(T::read(stream)?))
}
#[inline]
unsafe fn read_unchecked(stream: &mut BitReadStream<'a, E>, end: bool) -> Result<Self> {
Ok(Box::new(T::read_unchecked(stream, end)?))
}
#[inline]
fn bit_size() -> Option<usize> {
T::bit_size()
}
}
macro_rules! impl_read_tuple {
($($type:ident),*) => {
impl<'a, E: Endianness, $($type: BitRead<'a, E>),*> BitRead<'a, E> for ($($type),*) {
#[inline]
fn read(stream: &mut BitReadStream<'a, E>) -> Result<Self> {
Ok(($(<$type>::read(stream)?),*))
}
#[inline]
unsafe fn read_unchecked(stream: &mut BitReadStream<'a, E>, end: bool) -> Result<Self> {
Ok(($(<$type>::read_unchecked(stream, end)?),*))
}
#[inline]
fn bit_size() -> Option<usize> {
Some(0)$(.and_then(|sum| <$type>::bit_size().map(|size| sum + size)))*
}
}
};
}
impl_read_tuple!(T1, T2);
impl_read_tuple!(T1, T2, T3);
impl_read_tuple!(T1, T2, T3, T4);
impl<'a, E: Endianness, T: BitRead<'a, E>, const N: usize> BitRead<'a, E> for [T; N] {
#[inline]
fn read(stream: &mut BitReadStream<'a, E>) -> Result<Self> {
match T::bit_size() {
Some(bit_size) => {
let end = stream.check_read(bit_size * N)?;
unsafe { Self::read_unchecked(stream, end) }
}
None => {
let mut array =
unsafe { MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init() };
for item in array.iter_mut() {
unsafe {
let val = stream.read()?;
item.as_mut_ptr().write(val)
}
}
unsafe { Ok((&array as *const _ as *const [T; N]).read()) }
}
}
}
#[inline]
unsafe fn read_unchecked(stream: &mut BitReadStream<'a, E>, end: bool) -> Result<Self> {
let mut array = MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init();
for item in array.iter_mut() {
let val = stream.read_unchecked(end)?;
item.as_mut_ptr().write(val);
}
Ok((&array as *const _ as *const [T; N]).read())
}
#[inline]
fn bit_size() -> Option<usize> {
T::bit_size().map(|size| size * N)
}
}
pub trait BitReadSized<'a, E: Endianness>: Sized {
fn read(stream: &mut BitReadStream<'a, E>, size: usize) -> Result<Self>;
#[doc(hidden)]
#[inline]
unsafe fn read_unchecked(
stream: &mut BitReadStream<'a, E>,
size: usize,
_end: bool,
) -> Result<Self> {
Self::read(stream, size)
}
#[inline]
fn skip(stream: &mut BitReadStream<'a, E>, size: usize) -> Result<()> {
match Self::bit_size_sized(size) {
Some(size) => stream.skip_bits(size),
None => Self::read(stream, size).map(|_| ()),
}
}
#[inline]
fn bit_size_sized(_size: usize) -> Option<usize> {
None
}
}
macro_rules! impl_read_int_sized {
( $ type: ty) => {
impl<E: Endianness> BitReadSized<'_, E> for $type {
#[inline]
fn read(stream: &mut BitReadStream<E>, size: usize) -> Result<$type> {
stream.read_int::<$type>(size)
}
#[inline]
unsafe fn read_unchecked(
stream: &mut BitReadStream<E>,
size: usize,
end: bool,
) -> Result<$type> {
Ok(stream.read_int_unchecked::<$type>(size, end))
}
#[inline]
fn bit_size_sized(size: usize) -> Option<usize> {
Some(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 BitReadStream<E>, size: usize) -> Result<String> {
Ok(stream.read_string(Some(size))?.into_owned())
}
#[inline]
fn bit_size_sized(size: usize) -> Option<usize> {
Some(8 * size)
}
}
impl<'a, E: Endianness> BitReadSized<'a, E> for Cow<'a, str> {
#[inline]
fn read(stream: &mut BitReadStream<'a, E>, size: usize) -> Result<Cow<'a, str>> {
stream.read_string(Some(size))
}
#[inline]
fn bit_size_sized(size: usize) -> Option<usize> {
Some(8 * size)
}
}
impl<'a, E: Endianness> BitReadSized<'a, E> for Cow<'a, [u8]> {
#[inline]
fn read(stream: &mut BitReadStream<'a, E>, size: usize) -> Result<Cow<'a, [u8]>> {
stream.read_bytes(size)
}
#[inline]
fn bit_size_sized(size: usize) -> Option<usize> {
Some(8 * size)
}
}
impl<'a, E: Endianness, T: BitRead<'a, E>> BitRead<'a, E> for Option<T> {
fn read(stream: &mut BitReadStream<'a, E>) -> Result<Self> {
if stream.read()? {
Ok(Some(stream.read()?))
} else {
Ok(None)
}
}
}
impl<'a, E: Endianness, T: BitReadSized<'a, E>> BitReadSized<'a, E> for Option<T> {
fn read(stream: &mut BitReadStream<'a, E>, size: usize) -> Result<Self> {
if stream.read()? {
Ok(Some(stream.read_sized(size)?))
} else {
Ok(None)
}
}
}
impl<'a, E: Endianness> BitReadSized<'a, E> for BitReadStream<'a, E> {
#[inline]
fn read(stream: &mut BitReadStream<'a, E>, size: usize) -> Result<Self> {
stream.read_bits(size)
}
#[inline]
fn bit_size_sized(size: usize) -> Option<usize> {
Some(size)
}
}
impl<'a, E: Endianness, T: BitRead<'a, E>> BitReadSized<'a, E> for Vec<T> {
fn read(stream: &mut BitReadStream<'a, E>, size: usize) -> Result<Self> {
let mut vec = Vec::with_capacity(min(size, 128));
match T::bit_size() {
Some(bit_size) => {
if stream.check_read(bit_size * size)? {
for _ in 0..size {
vec.push(unsafe { stream.read_unchecked(true) }?)
}
} else {
for _ in 0..size {
vec.push(unsafe { stream.read_unchecked(false) }?)
}
}
}
_ => {
for _ in 0..size {
vec.push(stream.read()?)
}
}
}
Ok(vec)
}
#[inline]
unsafe fn read_unchecked(
stream: &mut BitReadStream<'a, E>,
size: usize,
end: bool,
) -> Result<Self> {
let mut vec = Vec::with_capacity(min(size, 128));
for _ in 0..size {
vec.push(stream.read_unchecked(end)?)
}
Ok(vec)
}
#[inline]
fn bit_size_sized(size: usize) -> Option<usize> {
T::bit_size().map(|element_size| size * element_size)
}
}
#[allow(clippy::implicit_hasher)]
impl<'a, E: Endianness, K: BitRead<'a, E> + Eq + Hash, T: BitRead<'a, E>> BitReadSized<'a, E>
for HashMap<K, T>
{
fn read(stream: &mut BitReadStream<'a, E>, size: usize) -> Result<Self> {
let mut map = HashMap::with_capacity(min(size, 128));
for _ in 0..size {
let key = stream.read()?;
let value = stream.read()?;
map.insert(key, value);
}
Ok(map)
}
#[inline]
unsafe fn read_unchecked(
stream: &mut BitReadStream<'a, E>,
size: usize,
end: bool,
) -> Result<Self> {
let mut map = HashMap::with_capacity(min(size, 128));
for _ in 0..size {
let key = stream.read_unchecked(end)?;
let value = stream.read_unchecked(end)?;
map.insert(key, value);
}
Ok(map)
}
#[inline]
fn bit_size_sized(size: usize) -> Option<usize> {
if let (Some(key_size), Some(value_size)) = (K::bit_size(), T::bit_size()) {
Some(size * (key_size + value_size))
} else {
None
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct LazyBitRead<'a, T: BitRead<'a, E>, E: Endianness> {
source: BitReadStream<'a, E>,
inner_type: PhantomData<T>,
}
impl<'a, T: BitRead<'a, E>, E: Endianness> LazyBitRead<'a, T, E> {
#[inline]
pub fn read(&self) -> Result<T> {
self.source.clone().read::<T>()
}
}
impl<'a, T: BitRead<'a, E>, E: Endianness> BitRead<'a, E> for LazyBitRead<'a, T, E> {
#[inline]
fn read(stream: &mut BitReadStream<'a, E>) -> Result<Self> {
match T::bit_size() {
Some(bit_size) => Ok(LazyBitRead {
source: stream.read_bits(bit_size)?,
inner_type: PhantomData,
}),
None => panic!(),
}
}
#[inline]
fn bit_size() -> Option<usize> {
T::bit_size()
}
}
#[derive(Clone, Debug)]
pub struct LazyBitReadSized<'a, T: BitReadSized<'a, E>, E: Endianness> {
source: RefCell<BitReadStream<'a, E>>,
size: usize,
inner_type: PhantomData<T>,
}
impl<'a, T: BitReadSized<'a, E>, E: Endianness> LazyBitReadSized<'a, T, E> {
#[inline]
pub fn value(self) -> Result<T> {
self.source.borrow_mut().read_sized::<T>(self.size)
}
}
impl<'a, T: BitReadSized<'a, E>, E: Endianness> BitReadSized<'a, E> for LazyBitReadSized<'a, T, E> {
#[inline]
fn read(stream: &mut BitReadStream<'a, E>, size: usize) -> Result<Self> {
match T::bit_size_sized(size) {
Some(bit_size) => Ok(LazyBitReadSized {
source: RefCell::new(stream.read_bits(bit_size)?),
inner_type: PhantomData,
size,
}),
None => panic!(),
}
}
#[inline]
fn bit_size_sized(size: usize) -> Option<usize> {
T::bit_size_sized(size)
}
}
impl<'a, E: Endianness, T: BitReadSized<'a, E>, const N: usize> BitReadSized<'a, E> for [T; N] {
#[inline]
fn read(stream: &mut BitReadStream<'a, E>, size: usize) -> Result<Self> {
match T::bit_size_sized(size) {
Some(bit_size) => {
let end = stream.check_read(bit_size * N)?;
unsafe { Self::read_unchecked(stream, size, end) }
}
None => {
let mut array =
unsafe { MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init() };
for item in array.iter_mut() {
unsafe {
let val = stream.read_sized(size)?;
item.as_mut_ptr().write(val)
}
}
unsafe { Ok((&array as *const _ as *const [T; N]).read()) }
}
}
}
#[inline]
unsafe fn read_unchecked(
stream: &mut BitReadStream<'a, E>,
size: usize,
end: bool,
) -> Result<Self> {
let mut array = MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init();
for item in array.iter_mut() {
let val = stream.read_sized_unchecked(size, end)?;
item.as_mut_ptr().write(val);
}
Ok((&array as *const _ as *const [T; N]).read())
}
#[inline]
fn bit_size_sized(size: usize) -> Option<usize> {
T::bit_size_sized(size).map(|size| size * N)
}
}