use core::marker::PhantomData;
use tlb::{
bits::{
bitvec::{order::Msb0, vec::BitVec},
de::BitReaderExt,
ser::BitWriterExt,
},
de::{args::r#as::CellDeserializeAsWithArgs, CellParser, CellParserError},
r#as::{ParseFully, Ref, Same},
ser::{args::r#as::CellSerializeAsWithArgs, CellBuilder, CellBuilderError},
Error, ResultExt,
};
use super::{aug::HashmapAugNode, hm_label::HmLabel, Hashmap, HashmapE, HashmapNode};
pub struct PfxHashmapE<As: ?Sized = Same>(PhantomData<As>);
impl<T, As> CellSerializeAsWithArgs<HashmapE<T>> for PfxHashmapE<As>
where
As: CellSerializeAsWithArgs<T>,
As::Args: Clone,
{
type Args = (u32, As::Args);
#[inline]
fn store_as_with(
source: &HashmapE<T>,
builder: &mut tlb::ser::CellBuilder,
args: Self::Args,
) -> Result<(), tlb::ser::CellBuilderError> {
match source {
HashmapE::Empty => builder
.pack(false)?,
HashmapE::Root(root) => builder
.pack(true)?
.store_as_with::<_, Ref<&PfxHashmap<As>>>(root, args)?,
};
Ok(())
}
}
impl<'de, T, As> CellDeserializeAsWithArgs<'de, HashmapE<T>> for PfxHashmapE<As>
where
As: CellDeserializeAsWithArgs<'de, T>,
As::Args: Clone,
{
type Args = (u32, As::Args);
#[inline]
fn parse_as_with(
parser: &mut tlb::de::CellParser<'de>,
(n, args): Self::Args,
) -> Result<HashmapE<T>, tlb::de::CellParserError<'de>> {
Ok(match parser.unpack()? {
false => HashmapE::Empty,
true => parser
.parse_as_with::<_, Ref<ParseFully<PfxHashmap<As>>>>((n, args))
.map(HashmapE::Root)?,
})
}
}
pub struct PfxHashmap<As: ?Sized = Same>(PhantomData<As>);
impl<T, As> CellSerializeAsWithArgs<Hashmap<T>> for PfxHashmap<As>
where
As: CellSerializeAsWithArgs<T>,
As::Args: Clone,
{
type Args = (u32, As::Args);
fn store_as_with(
source: &Hashmap<T>,
builder: &mut CellBuilder,
(n, args): Self::Args,
) -> Result<(), CellBuilderError> {
builder
.pack_as_with::<_, &HmLabel>(source.prefix.as_bitslice(), n)
.context("label")?
.store_as_with::<_, &PfxHashmapNode<As>>(
&source.node,
(
n - source.prefix.len() as u32,
args,
),
)
.context("node")?;
Ok(())
}
}
impl<'de, T, As> CellDeserializeAsWithArgs<'de, Hashmap<T>> for PfxHashmap<As>
where
As: CellDeserializeAsWithArgs<'de, T>,
As::Args: Clone,
{
type Args = (u32, As::Args);
#[inline]
fn parse_as_with(
parser: &mut CellParser<'de>,
(n, args): Self::Args,
) -> Result<Hashmap<T>, CellParserError<'de>> {
let prefix: BitVec<u8, Msb0> = parser.unpack_as_with::<_, HmLabel>(n).context("label")?;
let m = n - prefix.len() as u32;
Ok(Hashmap {
prefix,
node: HashmapAugNode::new(
parser
.parse_as_with::<_, ParseFully<PfxHashmapNode<As>>>((m, args))
.context("node")?,
(),
),
})
}
}
pub struct PfxHashmapNode<As: ?Sized = Same>(PhantomData<As>);
impl<T, As> CellSerializeAsWithArgs<HashmapNode<T>> for PfxHashmapNode<As>
where
As: CellSerializeAsWithArgs<T>,
As::Args: Clone,
{
type Args = (u32, As::Args);
fn store_as_with(
source: &HashmapNode<T>,
builder: &mut CellBuilder,
(n, args): Self::Args,
) -> Result<(), CellBuilderError> {
match source {
HashmapNode::Leaf(value) => {
builder
.pack(false)?
.store_as_with::<_, &As>(value, args)?
}
HashmapNode::Fork(fork) => {
if n == 0 {
return Err(Error::custom("key is too long"));
}
builder
.pack(true)?
.store_as_with::<_, &[Box<Ref<PfxHashmap<As>>>; 2]>(fork, (n - 1, args))?
}
};
Ok(())
}
}
impl<'de, T, As> CellDeserializeAsWithArgs<'de, HashmapNode<T>> for PfxHashmapNode<As>
where
As: CellDeserializeAsWithArgs<'de, T>,
As::Args: Clone,
{
type Args = (u32, As::Args);
fn parse_as_with(
parser: &mut CellParser<'de>,
(n, args): Self::Args,
) -> Result<HashmapNode<T>, CellParserError<'de>> {
match parser.unpack()? {
false => {
parser.parse_as_with::<_, As>(args).map(HashmapNode::Leaf)
}
true => {
Ok(HashmapNode::Fork(
parser
.parse_as_with::<_, [Box<Ref<ParseFully<PfxHashmap<As>>>>; 2]>((
n - 1,
args,
))?,
))
}
}
}
}