mod r#as;
mod reader;
pub use self::{r#as::*, reader::*};
use std::{
borrow::Cow,
collections::{BTreeMap, BTreeSet, HashMap, HashSet, LinkedList, VecDeque},
hash::Hash,
rc::Rc,
sync::Arc,
};
use bitvec::{array::BitArray, order::Msb0, slice::BitSlice, vec::BitVec, view::BitViewSized};
use either::Either;
use crate::{
Context, Error, StringError,
r#as::{BorrowCow, FromInto, Same},
};
pub trait BitUnpack<'de>: Sized {
type Args;
fn unpack<R>(reader: &mut R, args: Self::Args) -> Result<Self, R::Error>
where
R: BitReader<'de> + ?Sized;
}
#[inline]
pub fn unpack<'de, T>(mut bits: &'de BitSlice<u8, Msb0>, args: T::Args) -> Result<T, StringError>
where
T: BitUnpack<'de>,
{
bits.unpack(args)
}
#[inline]
pub fn unpack_bytes<'de, T>(bytes: &'de [u8], args: T::Args) -> Result<T, StringError>
where
T: BitUnpack<'de>,
{
unpack(BitSlice::from_slice(bytes), args)
}
#[inline]
pub fn unpack_fully<'de, T>(
mut bits: &'de BitSlice<u8, Msb0>,
args: T::Args,
) -> Result<T, StringError>
where
T: BitUnpack<'de>,
{
let v = bits.unpack(args)?;
if !bits.is_empty() {
return Err(Error::custom("more data left"));
}
Ok(v)
}
#[inline]
pub fn unpack_bytes_fully<'de, T>(bytes: &'de [u8], args: T::Args) -> Result<T, StringError>
where
T: BitUnpack<'de>,
{
unpack_fully(BitSlice::from_slice(bytes), args)
}
macro_rules! impl_bit_unpack_for_tuple {
($($t:ident:$n:tt),*) => {
impl<'de, $($t),*> BitUnpack<'de> for ($($t,)*)
where $(
$t: BitUnpack<'de>,
)*
{
type Args = ($($t::Args,)*);
#[inline]
#[allow(unused_variables)]
fn unpack<R>(reader: &mut R, args: Self::Args) -> Result<Self, R::Error>
where
R: BitReader<'de> + ?Sized,
{
Ok(($(
$t::unpack(reader, args.$n).context(concat!(".", stringify!($n)))?,
)*))
}
}
};
}
impl_bit_unpack_for_tuple!();
impl_bit_unpack_for_tuple!(T0:0);
impl_bit_unpack_for_tuple!(T0:0,T1:1);
impl_bit_unpack_for_tuple!(T0:0,T1:1,T2:2);
impl_bit_unpack_for_tuple!(T0:0,T1:1,T2:2,T3:3);
impl_bit_unpack_for_tuple!(T0:0,T1:1,T2:2,T3:3,T4:4);
impl_bit_unpack_for_tuple!(T0:0,T1:1,T2:2,T3:3,T4:4,T5:5);
impl_bit_unpack_for_tuple!(T0:0,T1:1,T2:2,T3:3,T4:4,T5:5,T6:6);
impl_bit_unpack_for_tuple!(T0:0,T1:1,T2:2,T3:3,T4:4,T5:5,T6:6,T7:7);
impl_bit_unpack_for_tuple!(T0:0,T1:1,T2:2,T3:3,T4:4,T5:5,T6:6,T7:7,T8:8);
impl_bit_unpack_for_tuple!(T0:0,T1:1,T2:2,T3:3,T4:4,T5:5,T6:6,T7:7,T8:8,T9:9);
impl<'de> BitUnpack<'de> for bool {
type Args = ();
#[inline]
fn unpack<R>(reader: &mut R, _: Self::Args) -> Result<Self, R::Error>
where
R: BitReader<'de> + ?Sized,
{
reader.read_bit()?.ok_or_else(|| Error::custom("EOF"))
}
}
impl<'de, T, const N: usize> BitUnpack<'de> for [T; N]
where
T: BitUnpack<'de>,
T::Args: Clone,
{
type Args = T::Args;
#[inline]
fn unpack<R>(reader: &mut R, args: Self::Args) -> Result<Self, R::Error>
where
R: BitReader<'de> + ?Sized,
{
array_util::try_from_fn(|i| {
T::unpack(reader, args.clone()).with_context(|| format!("[{i}]"))
})
}
}
impl<'de, T> BitUnpack<'de> for Box<T>
where
T: BitUnpack<'de>,
{
type Args = T::Args;
#[inline]
fn unpack<R>(reader: &mut R, args: Self::Args) -> Result<Self, R::Error>
where
R: BitReader<'de> + ?Sized,
{
reader.unpack_as::<_, FromInto<T>>(args)
}
}
impl<'de, T> BitUnpack<'de> for Rc<T>
where
T: BitUnpack<'de>,
{
type Args = T::Args;
#[inline]
fn unpack<R>(reader: &mut R, args: Self::Args) -> Result<Self, R::Error>
where
R: BitReader<'de> + ?Sized,
{
reader.unpack_as::<_, FromInto<T>>(args)
}
}
impl<'de, T> BitUnpack<'de> for Arc<T>
where
T: BitUnpack<'de>,
{
type Args = T::Args;
#[inline]
fn unpack<R>(reader: &mut R, args: Self::Args) -> Result<Self, R::Error>
where
R: BitReader<'de> + ?Sized,
{
reader.unpack_as::<_, FromInto<T>>(args)
}
}
impl<'de, T> BitUnpack<'de> for Cow<'_, T>
where
T: ToOwned + ?Sized,
T::Owned: BitUnpack<'de>,
{
type Args = <T::Owned as BitUnpack<'de>>::Args;
#[inline]
fn unpack<R>(reader: &mut R, args: Self::Args) -> Result<Self, R::Error>
where
R: BitReader<'de> + ?Sized,
{
reader.unpack::<T::Owned>(args).map(Self::Owned)
}
}
impl<'de, Left, Right> BitUnpack<'de> for Either<Left, Right>
where
Left: BitUnpack<'de>,
Right: BitUnpack<'de>,
{
type Args = (Left::Args, Right::Args);
#[inline]
fn unpack<R>(reader: &mut R, (la, ra): Self::Args) -> Result<Self, R::Error>
where
R: BitReader<'de> + ?Sized,
{
match reader.unpack(()).context("tag")? {
false => reader.unpack(la).map(Either::Left).context("left"),
true => reader.unpack(ra).map(Either::Right).context("right"),
}
}
}
impl<'de, T> BitUnpack<'de> for Option<T>
where
T: BitUnpack<'de>,
{
type Args = T::Args;
#[inline]
fn unpack<R>(reader: &mut R, args: Self::Args) -> Result<Self, R::Error>
where
R: BitReader<'de> + ?Sized,
{
reader.unpack_as::<_, Either<(), Same>>(args)
}
}
impl<'de, A> BitUnpack<'de> for BitArray<A, Msb0>
where
A: BitViewSized<Store = u8>,
{
type Args = ();
fn unpack<R>(reader: &mut R, _: Self::Args) -> Result<Self, R::Error>
where
R: BitReader<'de> + ?Sized,
{
let mut arr = Self::ZERO;
reader.read_bits_into(arr.as_mut_bitslice())?;
Ok(arr)
}
}
impl<'de> BitUnpack<'de> for BitVec<u8, Msb0> {
type Args = usize;
#[inline]
fn unpack<R>(reader: &mut R, len: Self::Args) -> Result<Self, R::Error>
where
R: BitReader<'de> + ?Sized,
{
reader
.unpack_as::<Cow<BitSlice<u8, Msb0>>, BorrowCow>(len)
.map(Cow::into_owned)
}
}
impl<'de, T> BitUnpack<'de> for Vec<T>
where
T: BitUnpack<'de>,
T::Args: Clone,
{
type Args = (usize, T::Args);
fn unpack<R>(reader: &mut R, (len, item_args): Self::Args) -> Result<Self, R::Error>
where
R: BitReader<'de> + ?Sized,
{
reader.unpack_iter(item_args).take(len).collect()
}
}
impl<'de, T> BitUnpack<'de> for VecDeque<T>
where
T: BitUnpack<'de>,
T::Args: Clone,
{
type Args = (usize, T::Args);
fn unpack<R>(reader: &mut R, args: Self::Args) -> Result<Self, R::Error>
where
R: BitReader<'de> + ?Sized,
{
reader.unpack::<Vec<_>>(args).map(Into::into)
}
}
impl<'de, T> BitUnpack<'de> for LinkedList<T>
where
T: BitUnpack<'de>,
T::Args: Clone,
{
type Args = (usize, T::Args);
fn unpack<R>(reader: &mut R, (len, item_args): Self::Args) -> Result<Self, R::Error>
where
R: BitReader<'de> + ?Sized,
{
reader.unpack_iter(item_args).take(len).collect()
}
}
impl<'de, T> BitUnpack<'de> for BTreeSet<T>
where
T: BitUnpack<'de> + Ord + Eq,
T::Args: Clone,
{
type Args = (usize, T::Args);
fn unpack<R>(reader: &mut R, (len, item_args): Self::Args) -> Result<Self, R::Error>
where
R: BitReader<'de> + ?Sized,
{
reader.unpack_iter(item_args).take(len).collect()
}
}
impl<'de, K, V> BitUnpack<'de> for BTreeMap<K, V>
where
K: BitUnpack<'de> + Ord + Eq,
K::Args: Clone,
V: BitUnpack<'de>,
V::Args: Clone,
{
type Args = (usize, (K::Args, V::Args));
fn unpack<R>(reader: &mut R, (len, kv): Self::Args) -> Result<Self, R::Error>
where
R: BitReader<'de> + ?Sized,
{
reader.unpack_iter(kv).take(len).collect()
}
}
impl<'de, T> BitUnpack<'de> for HashSet<T>
where
T: BitUnpack<'de> + Hash + Eq,
T::Args: Clone,
{
type Args = (usize, T::Args);
fn unpack<R>(reader: &mut R, (len, item_args): Self::Args) -> Result<Self, R::Error>
where
R: BitReader<'de> + ?Sized,
{
reader.unpack_iter(item_args).take(len).collect()
}
}
impl<'de, K, V> BitUnpack<'de> for HashMap<K, V>
where
K: BitUnpack<'de> + Hash + Eq,
K::Args: Clone,
V: BitUnpack<'de>,
V::Args: Clone,
{
type Args = (usize, (K::Args, V::Args));
fn unpack<R>(reader: &mut R, (len, kv): Self::Args) -> Result<Self, R::Error>
where
R: BitReader<'de> + ?Sized,
{
reader.unpack_iter(kv).take(len).collect()
}
}