#[allow(unused)]
macro_rules! impl_read_map {
(
$ty:ident<K: $kbound0:ident $(+ $kbound1:ident)?, V
$(, $h:ident : $hbound0:ident + $hbound1:ident)?>,
$new:expr
) => {
impl<Tag, Ctx, K, V, $($h)?> $crate::BitDecode<Ctx, $crate::Tag<Tag>> for $ty<K, V, $($h)?>
where
K: $crate::BitDecode<Ctx> + $kbound0 + $($kbound1)?,
V: $crate::BitDecode<Ctx>,
Tag: ::core::convert::TryInto<usize>,
$($h: $hbound0 + $hbound1)?
{
fn decode<R, E>(
read: &mut R,
ctx: &mut Ctx,
tag: $crate::Tag<Tag>,
) -> $crate::Result<Self>
where
R: ::bitstream_io::BitRead,
E: ::bitstream_io::Endianness,
{
let item_count = ::core::convert::TryInto::try_into(tag.0)
.map_err(|_| $crate::Error::TagConvert)?;
let mut this = ($new)(item_count);
for _ in 0..item_count {
this.insert(
$crate::BitDecode::<_, _>::decode::<_, E>(read, ctx, ())?,
$crate::BitDecode::<_, _>::decode::<_, E>(read, ctx, ())?
);
}
::core::result::Result::Ok(this)
}
}
impl<Ctx, K, V, $($h)?> $crate::BitDecode<Ctx, $crate::Untagged> for $ty<K, V, $($h)?>
where
K: $crate::BitDecode<Ctx> + $kbound0 $(+ $kbound1)?,
V: $crate::BitDecode<Ctx>,
$($h: $hbound0 + $hbound1)?
{
fn decode<R, E>(
read: &mut R,
ctx: &mut Ctx,
_: $crate::Untagged,
) -> $crate::Result<Self>
where
R: ::bitstream_io::BitRead,
E: ::bitstream_io::Endianness,
{
$crate::util::decode_items_to_eof::<_, E, _, _>(read, ctx).collect()
}
}
#[cfg(feature = "prepend-tags")]
impl<Ctx, K, V, $($h)?> $crate::BitDecode<Ctx> for $ty<K, V, $($h)?>
where
K: $crate::BitDecode<Ctx> + $kbound0 $(+ $kbound1)?,
V: $crate::BitDecode<Ctx>,
$($h: $hbound0 + $hbound1)?
{
fn decode<R, E>(
read: &mut R,
ctx: &mut Ctx,
(): (),
) -> $crate::Result<Self>
where
R: ::bitstream_io::BitRead,
E: ::bitstream_io::Endianness,
{
let tag: usize = $crate::BitDecode::decode::<_, E>(read, ctx, ())?;
$crate::BitDecode::decode::<_, E>(read, ctx, $crate::Tag(tag))
}
}
};
}
#[allow(unused)]
macro_rules! impl_write_map {
( $ty:ident<K: $kbound0:ident $(+ $kbound1:ident)?, V $(, $h:ident)?> ) => {
impl<Ctx, K, V, $($h)?> $crate::BitEncode<Ctx, $crate::Untagged> for $ty<K, V, $($h)?>
where
K: $crate::BitEncode<Ctx> + $kbound0 $(+ $kbound1)?,
V: $crate::BitEncode<Ctx>
{
fn encode<W, E>(
&self,
write: &mut W,
ctx: &mut Ctx,
_: $crate::Untagged,
) -> $crate::Result<()>
where
W: ::bitstream_io::BitWrite,
E: ::bitstream_io::Endianness,
{
for (key, value) in self.iter() {
$crate::BitEncode::encode::<_, E>(key, write, ctx, ())?;
$crate::BitEncode::encode::<_, E>(value, write, ctx, ())?;
}
Ok(())
}
}
#[cfg(feature = "prepend-tags")]
impl<Ctx, K, V, $($h)?> $crate::BitEncode<Ctx> for $ty<K, V, $($h)?>
where
K: $crate::BitEncode<Ctx> + $kbound0 $(+ $kbound1)?,
V: $crate::BitEncode<Ctx>
{
fn encode<W, E>(
&self,
write: &mut W,
ctx: &mut Ctx,
(): (),
) -> $crate::Result<()>
where
W: ::bitstream_io::BitWrite,
E: ::bitstream_io::Endianness,
{
$crate::BitEncode::encode::<_, E>(&self.len(), write, ctx, ())?;
$crate::BitEncode::encode::<_, E>(self, write, ctx, $crate::Untagged)
}
}
}
}
#[cfg(feature = "std")]
mod hash_map {
use core::hash::{BuildHasher, Hash};
use std::collections::HashMap;
impl_write_map!(HashMap<K: Eq + Hash, V, H>);
impl_read_map!(HashMap<K: Eq + Hash, V, H: BuildHasher + Default>, |n| Self::with_capacity_and_hasher(n, H::default()));
#[cfg(test)]
mod tests {
use crate::{Tag, Untagged};
use super::*;
test_untagged_and_codec!(
HashMap<u8, u8>| Untagged, Tag(1); [(1, 2)].into() => [0x01, 0x02]
);
#[cfg(feature = "prepend-tags")]
test_roundtrip!(HashMap::<i32, i64>);
}
}
#[cfg(feature = "alloc")]
mod b_tree_map {
use alloc::collections::btree_map::BTreeMap;
impl_write_map!(BTreeMap<K: Ord, V>);
impl_read_map!(BTreeMap<K: Ord, V>, |_| Self::new());
#[cfg(test)]
mod tests {
use crate::{Tag, Untagged};
use super::*;
test_untagged_and_codec!(
BTreeMap<u8, u8>| Untagged, Tag(3);
[(1, 2), (3, 4), (5, 6)].into() => [0x01, 0x02, 0x03, 0x04, 0x05, 0x06]
);
#[cfg(feature = "prepend-tags")]
test_roundtrip!(BTreeMap::<i32, i64>);
}
}