use bm::{Error, ReadBackend, WriteBackend, Construct};
use primitive_types::U256;
use alloc::vec::Vec;
use crate::{ElementalFixedVec, FromCompactVectorTree, FromCompositeVectorTree,
ElementalFixedVecRef, IntoCompactVectorTree,
IntoCompositeVectorTree, CompatibleConstruct};
use crate::utils::{mix_in_length, decode_with_length};
pub trait IntoCompositeListTree {
fn into_composite_list_tree<DB: WriteBackend>(
&self,
db: &mut DB,
max_len: Option<u64>
) -> Result<<DB::Construct as Construct>::Value, Error<DB::Error>> where
DB::Construct: CompatibleConstruct;
}
pub trait IntoCompactListTree {
fn into_compact_list_tree<DB: WriteBackend>(
&self,
db: &mut DB,
max_len: Option<u64>
) -> Result<<DB::Construct as Construct>::Value, Error<DB::Error>> where
DB::Construct: CompatibleConstruct;
}
pub trait FromCompositeListTree: Sized {
fn from_composite_list_tree<DB: ReadBackend>(
root: &<DB::Construct as Construct>::Value,
db: &mut DB,
max_len: Option<u64>,
) -> Result<Self, Error<DB::Error>> where
DB::Construct: CompatibleConstruct;
}
pub trait FromCompactListTree: Sized {
fn from_compact_list_tree<DB: ReadBackend>(
root: &<DB::Construct as Construct>::Value,
db: &mut DB,
max_len: Option<u64>,
) -> Result<Self, Error<DB::Error>> where
DB::Construct: CompatibleConstruct;
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ElementalVariableVecRef<'a, T>(pub &'a [T]);
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ElementalVariableVec<T>(pub Vec<T>);
macro_rules! impl_packed {
( $t:ty ) => {
impl<'a> IntoCompactListTree for ElementalVariableVecRef<'a, $t> {
fn into_compact_list_tree<DB: WriteBackend>(
&self,
db: &mut DB,
max_len: Option<u64>
) -> Result<<DB::Construct as Construct>::Value, Error<DB::Error>> where
DB::Construct: CompatibleConstruct,
{
let len = self.0.len();
mix_in_length(&ElementalFixedVecRef(&self.0).into_compact_vector_tree(db, max_len)?,
db, len)
}
}
}
}
impl_packed!(bool);
impl_packed!(u8);
impl_packed!(u16);
impl_packed!(u32);
impl_packed!(u64);
impl_packed!(u128);
impl_packed!(U256);
impl<'a, T> IntoCompositeListTree for ElementalVariableVecRef<'a, T> where
for<'b> ElementalFixedVecRef<'b, T>: IntoCompositeVectorTree,
{
fn into_composite_list_tree<DB: WriteBackend>(
&self,
db: &mut DB,
max_len: Option<u64>
) -> Result<<DB::Construct as Construct>::Value, Error<DB::Error>> where
DB::Construct: CompatibleConstruct,
{
let len = self.0.len();
mix_in_length(&ElementalFixedVecRef(&self.0).into_composite_vector_tree(db, max_len)?,
db, len)
}
}
fn from_list_tree<T, F, DB: ReadBackend>(
root: &<DB::Construct as Construct>::Value,
db: &mut DB,
max_len: Option<u64>,
f: F
) -> Result<ElementalVariableVec<T>, Error<DB::Error>> where
DB::Construct: CompatibleConstruct,
F: FnOnce(&<DB::Construct as Construct>::Value, &mut DB, usize, Option<u64>) -> Result<ElementalFixedVec<T>, Error<DB::Error>>
{
let (vector_root, len) = decode_with_length::<<DB::Construct as Construct>::Value, _>(root, db)?;
let vector = f(
&vector_root, db, len, max_len
)?;
Ok(ElementalVariableVec(vector.0))
}
impl<T> FromCompactListTree for ElementalVariableVec<T> where
ElementalFixedVec<T>: FromCompactVectorTree,
{
fn from_compact_list_tree<DB: ReadBackend>(
root: &<DB::Construct as Construct>::Value,
db: &mut DB,
max_len: Option<u64>,
) -> Result<Self, Error<DB::Error>> where
DB::Construct: CompatibleConstruct,
{
from_list_tree(root, db, max_len, |vector_root, db, len, max_len| {
ElementalFixedVec::<T>::from_compact_vector_tree(
vector_root, db, len, max_len
)
})
}
}
impl<T> FromCompositeListTree for ElementalVariableVec<T> where
ElementalFixedVec<T>: FromCompositeVectorTree,
{
fn from_composite_list_tree<DB: ReadBackend>(
root: &<DB::Construct as Construct>::Value,
db: &mut DB,
max_len: Option<u64>,
) -> Result<Self, Error<DB::Error>> where
DB::Construct: CompatibleConstruct,
{
from_list_tree(root, db, max_len, |vector_root, db, len, max_len| {
ElementalFixedVec::<T>::from_composite_vector_tree(
vector_root, db, len, max_len
)
})
}
}
impl<T> IntoCompactListTree for ElementalVariableVec<T> where
for<'a> ElementalVariableVecRef<'a, T>: IntoCompactListTree,
{
fn into_compact_list_tree<DB: WriteBackend>(
&self,
db: &mut DB,
max_len: Option<u64>
) -> Result<<DB::Construct as Construct>::Value, Error<DB::Error>> where
DB::Construct: CompatibleConstruct,
{
ElementalVariableVecRef(&self.0).into_compact_list_tree(db, max_len)
}
}
impl<T> IntoCompositeListTree for ElementalVariableVec<T> where
for<'a> ElementalVariableVecRef<'a, T>: IntoCompositeListTree,
{
fn into_composite_list_tree<DB: WriteBackend>(
&self,
db: &mut DB,
max_len: Option<u64>
) -> Result<<DB::Construct as Construct>::Value, Error<DB::Error>> where
DB::Construct: CompatibleConstruct,
{
ElementalVariableVecRef(&self.0).into_composite_list_tree(db, max_len)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{IntoTree, FromTree, DigestConstruct};
use bm::InMemoryBackend;
use sha2::Sha256;
#[test]
fn test_plain() {
let data = {
let mut ret = Vec::new();
for i in 0..17u16 {
ret.push(i);
}
ret
};
let mut db = InMemoryBackend::<DigestConstruct<Sha256>>::default();
let encoded = data.into_tree(&mut db).unwrap();
let decoded = Vec::<u16>::from_tree(&encoded, &mut db).unwrap();
assert_eq!(data, decoded);
}
}