use ::alloc::{
collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque},
vec::Vec,
};
use crate::{
format::Format,
helpers::{take_byte, take_byte_iter, take_num, take_num_iter},
Error, Unpackable, UnpackableBorrowed,
};
pub fn unpack_array_len(mut buf: &[u8]) -> Result<(usize, usize), Error> {
let format = take_byte(&mut buf)?;
let (n, len) = match format {
0x90..=0x9f => (1, (format & 0x0f) as usize),
Format::ARRAY16 => (
3,
take_num(&mut buf, u16::from_be_bytes).map(|v| v as usize)?,
),
Format::ARRAY32 => (
5,
take_num(&mut buf, u32::from_be_bytes).map(|v| v as usize)?,
),
_ => return Err(Error::UnexpectedFormatTag),
};
Ok((n, len))
}
pub fn unpack_array<V, C>(mut buf: &[u8]) -> Result<(usize, C), <V as Unpackable>::Error>
where
V: Unpackable,
C: FromIterator<V>,
{
let (mut n, len) = unpack_array_len(buf)?;
buf = &buf[n..];
let array: C = (0..len)
.map(|_| {
let (count, v) = V::unpack_with_ofs(buf)?;
buf = &buf[count..];
n += count;
Ok(v)
})
.collect::<Result<_, <V as Unpackable>::Error>>()?;
Ok((n, array))
}
pub fn unpack_array_iter<I, V, C>(iter: I) -> Result<(usize, C), <V as Unpackable>::Error>
where
I: IntoIterator<Item = u8>,
V: Unpackable,
C: FromIterator<V>,
{
let mut bytes = iter.into_iter();
let format = take_byte_iter(bytes.by_ref())?;
let (mut n, len) = match format {
0x90..=0x9f => (1, (format & 0x0f) as usize),
Format::ARRAY16 => (
3,
take_num_iter(bytes.by_ref(), u16::from_be_bytes).map(|v| v as usize)?,
),
Format::ARRAY32 => (
5,
take_num_iter(bytes.by_ref(), u32::from_be_bytes).map(|v| v as usize)?,
),
_ => return Err(Error::UnexpectedFormatTag.into()),
};
let array: C = (0..len)
.map(|_| {
let (count, v) = V::unpack_iter(bytes.by_ref())?;
n += count;
Ok(v)
})
.collect::<Result<_, <V as Unpackable>::Error>>()?;
Ok((n, array))
}
pub fn unpack_array_borrowed<'a, V, C>(
buf: &'a [u8],
) -> Result<(usize, C), <V as UnpackableBorrowed<'a>>::Error>
where
V: UnpackableBorrowed<'a>,
C: FromIterator<V>,
{
let (mut n, len) = unpack_array_len(buf)?;
let mut remaining: &'a [u8] = &buf[n..];
let array: C = (0..len)
.map(|_| {
let (count, v) = V::unpack_with_ofs(remaining)?;
remaining = &remaining[count..];
n += count;
Ok(v)
})
.collect::<Result<_, <V as UnpackableBorrowed<'a>>::Error>>()?;
Ok((n, array))
}
pub fn unpack_map_len(mut buf: &[u8]) -> Result<(usize, usize), Error> {
let format = take_byte(&mut buf)?;
let (n, len) = match format {
0x80..=0x8f => (1, (format & 0x0f) as usize),
Format::MAP16 => (
3,
take_num(&mut buf, u16::from_be_bytes).map(|v| v as usize)?,
),
Format::MAP32 => (
5,
take_num(&mut buf, u32::from_be_bytes).map(|v| v as usize)?,
),
_ => return Err(Error::UnexpectedFormatTag),
};
Ok((n, len))
}
pub fn unpack_map<K, V, C>(mut buf: &[u8]) -> Result<(usize, C), <V as Unpackable>::Error>
where
K: Unpackable,
V: Unpackable,
<V as Unpackable>::Error: From<<K as Unpackable>::Error>,
C: FromIterator<(K, V)>,
{
let (mut n, len) = unpack_map_len(buf)?;
buf = &buf[n..];
let map: C = (0..len)
.map(|_| {
let (count, k) = K::unpack_with_ofs(buf)?;
buf = &buf[count..];
n += count;
let (count, v) = V::unpack_with_ofs(buf)?;
buf = &buf[count..];
n += count;
Ok((k, v))
})
.collect::<Result<_, <V as Unpackable>::Error>>()?;
Ok((n, map))
}
pub fn unpack_map_iter<I, K, V, C>(iter: I) -> Result<(usize, C), <V as Unpackable>::Error>
where
I: IntoIterator<Item = u8>,
K: Unpackable,
V: Unpackable,
<V as Unpackable>::Error: From<<K as Unpackable>::Error>,
C: FromIterator<(K, V)>,
{
let mut bytes = iter.into_iter();
let format = take_byte_iter(bytes.by_ref())?;
let (mut n, len) = match format {
0x80..=0x8f => (1, (format & 0x0f) as usize),
Format::MAP16 => (
3,
take_num_iter(bytes.by_ref(), u16::from_be_bytes).map(|v| v as usize)?,
),
Format::MAP32 => (
5,
take_num_iter(bytes.by_ref(), u32::from_be_bytes).map(|v| v as usize)?,
),
_ => return Err(Error::UnexpectedFormatTag.into()),
};
let map: C = (0..len)
.map(|_| {
let (count, k) = K::unpack_iter(bytes.by_ref())?;
n += count;
let (count, v) = V::unpack_iter(bytes.by_ref())?;
n += count;
Ok((k, v))
})
.collect::<Result<_, <V as Unpackable>::Error>>()?;
Ok((n, map))
}
impl<X> Unpackable for BTreeSet<X>
where
X: Unpackable + Ord,
{
type Error = <X as Unpackable>::Error;
fn unpack_with_ofs(buf: &[u8]) -> Result<(usize, Self), Self::Error> {
unpack_array(buf)
}
fn unpack_iter<I>(bytes: I) -> Result<(usize, Self), Self::Error>
where
I: IntoIterator<Item = u8>,
{
unpack_array_iter(bytes)
}
}
impl<X> Unpackable for BinaryHeap<X>
where
X: Unpackable + Ord,
{
type Error = <X as Unpackable>::Error;
fn unpack_with_ofs(buf: &[u8]) -> Result<(usize, Self), Self::Error> {
unpack_array(buf)
}
fn unpack_iter<I>(bytes: I) -> Result<(usize, Self), Self::Error>
where
I: IntoIterator<Item = u8>,
{
unpack_array_iter(bytes)
}
}
impl<X> Unpackable for LinkedList<X>
where
X: Unpackable,
{
type Error = <X as Unpackable>::Error;
fn unpack_with_ofs(buf: &[u8]) -> Result<(usize, Self), Self::Error> {
unpack_array(buf)
}
fn unpack_iter<I>(bytes: I) -> Result<(usize, Self), Self::Error>
where
I: IntoIterator<Item = u8>,
{
unpack_array_iter(bytes)
}
}
impl<X> Unpackable for Vec<X>
where
X: Unpackable,
{
type Error = <X as Unpackable>::Error;
fn unpack_with_ofs(buf: &[u8]) -> Result<(usize, Self), Self::Error> {
unpack_array(buf)
}
fn unpack_iter<I>(bytes: I) -> Result<(usize, Self), Self::Error>
where
I: IntoIterator<Item = u8>,
{
unpack_array_iter(bytes)
}
}
impl<X> Unpackable for VecDeque<X>
where
X: Unpackable,
{
type Error = <X as Unpackable>::Error;
fn unpack_with_ofs(buf: &[u8]) -> Result<(usize, Self), Self::Error> {
unpack_array(buf)
}
fn unpack_iter<I>(bytes: I) -> Result<(usize, Self), Self::Error>
where
I: IntoIterator<Item = u8>,
{
unpack_array_iter(bytes)
}
}
impl<K, V> Unpackable for BTreeMap<K, V>
where
K: Unpackable + Ord,
V: Unpackable,
<V as Unpackable>::Error: From<<K as Unpackable>::Error>,
{
type Error = <V as Unpackable>::Error;
fn unpack_with_ofs(buf: &[u8]) -> Result<(usize, Self), Self::Error> {
unpack_map(buf)
}
fn unpack_iter<I>(bytes: I) -> Result<(usize, Self), Self::Error>
where
I: IntoIterator<Item = u8>,
{
unpack_map_iter(bytes)
}
}
#[cfg(feature = "std")]
mod std {
use super::*;
use ::std::{
collections::{HashMap, HashSet},
hash::Hash,
};
impl<X> Unpackable for HashSet<X>
where
X: Unpackable + Hash + Eq,
{
type Error = <X as Unpackable>::Error;
fn unpack_with_ofs(buf: &[u8]) -> Result<(usize, Self), Self::Error> {
unpack_array(buf)
}
fn unpack_iter<I>(bytes: I) -> Result<(usize, Self), Self::Error>
where
I: IntoIterator<Item = u8>,
{
unpack_array_iter(bytes)
}
}
impl<K, V> Unpackable for HashMap<K, V>
where
K: Unpackable + Hash + Eq,
V: Unpackable,
<V as Unpackable>::Error: From<<K as Unpackable>::Error>,
{
type Error = <V as Unpackable>::Error;
fn unpack_with_ofs(buf: &[u8]) -> Result<(usize, Self), Self::Error> {
unpack_map(buf)
}
fn unpack_iter<I>(bytes: I) -> Result<(usize, Self), Self::Error>
where
I: IntoIterator<Item = u8>,
{
unpack_map_iter(bytes)
}
}
}