bm-le 0.11.0

Little endian 256-bit layer for binary merkle trie with ssz compatibility and extensions
Documentation
use bm::{ReadBackend, WriteBackend, Construct, Error, Index, DanglingRaw, Leak};
use primitive_types::{H256, U256};
use alloc::boxed::Box;

use crate::{IntoTree, FromTree, Value, CompatibleConstruct};
use crate::utils::{mix_in_type, decode_with_type};

impl IntoTree for bool {
    fn into_tree<DB: WriteBackend>(&self, db: &mut DB) -> Result<<DB::Construct as Construct>::Value, Error<DB::Error>> where
        DB::Construct: CompatibleConstruct,
    {
        match self {
            true => 1u8.into_tree(db),
            false => 0u8.into_tree(db),
        }
    }
}

impl FromTree for bool {
    fn from_tree<DB: ReadBackend>(root: &<DB::Construct as Construct>::Value, db: &mut DB) -> Result<Self, Error<DB::Error>> where
        DB::Construct: CompatibleConstruct,
    {
        Ok(u8::from_tree(root, db)? != 0)
    }
}

macro_rules! impl_builtin_uint {
    ( $( $t:ty ),* ) => { $(
        impl IntoTree for $t {
            fn into_tree<DB: WriteBackend>(&self, _db: &mut DB) -> Result<<DB::Construct as Construct>::Value, Error<DB::Error>> where
                DB::Construct: CompatibleConstruct,
            {
                let mut ret = [0u8; 32];
                let bytes = self.to_le_bytes();
                ret[..bytes.len()].copy_from_slice(&bytes);

                Ok(Value(H256::from(ret)))
            }
        }

        impl FromTree for $t {
            fn from_tree<DB: ReadBackend>(root: &<DB::Construct as Construct>::Value, db: &mut DB) -> Result<Self, Error<DB::Error>> where
                DB::Construct: CompatibleConstruct,
            {
                let raw = DanglingRaw::from_leaked(root.clone());

                match raw.get(db, Index::root())? {
                    None => Err(Error::CorruptedDatabase),
                    Some(value) => {
                        let mut bytes = Self::default().to_le_bytes();
                        let bytes_len = bytes.len();
                        bytes.copy_from_slice(&value.0[..bytes_len]);

                        Ok(Self::from_le_bytes(bytes))
                    },
                }
            }
        }
    )* }
}

impl_builtin_uint!(u8, u16, u32, u64, u128);

impl IntoTree for U256 {
    fn into_tree<DB: WriteBackend>(&self, _db: &mut DB) -> Result<<DB::Construct as Construct>::Value, Error<DB::Error>> where
        DB::Construct: CompatibleConstruct,
    {
        let mut ret = [0u8; 32];
        self.to_little_endian(&mut ret);

        Ok(Value(H256::from(ret)))
    }
}

impl FromTree for U256 {
    fn from_tree<DB: ReadBackend>(root: &<DB::Construct as Construct>::Value, db: &mut DB) -> Result<Self, Error<DB::Error>> where
        DB::Construct: CompatibleConstruct,
    {
        let raw = DanglingRaw::from_leaked(root.clone());

        match raw.get(db, Index::root())? {
            None => Err(Error::CorruptedDatabase),
            Some(value) => {
                Ok(U256::from_little_endian(&value.as_ref()))
            },
        }
    }
}

impl IntoTree for Value {
    fn into_tree<DB: WriteBackend>(&self, _db: &mut DB) -> Result<<DB::Construct as Construct>::Value, Error<DB::Error>> where
        DB::Construct: CompatibleConstruct,
    {
        Ok(self.clone())
    }
}

impl FromTree for Value {
    fn from_tree<DB: ReadBackend>(root: &<DB::Construct as Construct>::Value, _db: &mut DB) -> Result<Self, Error<DB::Error>> where
        DB::Construct: CompatibleConstruct,
    {
        Ok(root.clone())
    }
}

impl IntoTree for bm::CompactValue<Value> {
    fn into_tree<DB: WriteBackend>(
        &self, db: &mut DB
    ) -> Result<<DB::Construct as Construct>::Value, Error<DB::Error>> where
        DB::Construct: CompatibleConstruct,
    {
        match self {
            bm::CompactValue::Single(value) => Ok(value.clone()),
            bm::CompactValue::Combined(boxed) => {
                let left = boxed.as_ref().0.into_tree(db)?;
                let right = boxed.as_ref().1.into_tree(db)?;
                let key = DB::Construct::intermediate_of(&left, &right);
                db.insert(key.clone(), (left, right))?;
                Ok(key)
            },
        }
    }
}

impl<T> FromTree for Option<T> where
    T: FromTree,
{
    fn from_tree<DB: ReadBackend>(root: &<DB::Construct as Construct>::Value, db: &mut DB) -> Result<Self, Error<DB::Error>> where
        DB::Construct: CompatibleConstruct,
    {
        decode_with_type(root, db, |inner, db, ty| {
            match ty {
                0 => {
                    <()>::from_tree(inner, db)?;
                    Ok(None)
                },
                1 => Ok(Some(T::from_tree(inner, db)?)),
                _ => Err(Error::CorruptedDatabase),
            }
        })
    }
}

impl<T> IntoTree for Option<T> where
    T: IntoTree,
{
    fn into_tree<DB: WriteBackend>(&self, db: &mut DB) -> Result<<DB::Construct as Construct>::Value, Error<DB::Error>> where
        DB::Construct: CompatibleConstruct,
    {
        match self {
            None => mix_in_type(&(), db, 0),
            Some(value) => mix_in_type(value, db, 1),
        }
    }
}

impl<T> FromTree for Box<T> where
    T: FromTree,
{
    fn from_tree<DB: ReadBackend>(root: &<DB::Construct as Construct>::Value, db: &mut DB) -> Result<Self, Error<DB::Error>> where
        DB::Construct: CompatibleConstruct,
    {
        Ok(Box::new(T::from_tree(root, db)?))
    }
}

impl<T> IntoTree for Box<T> where
    T: IntoTree,
{
    fn into_tree<DB: WriteBackend>(&self, db: &mut DB) -> Result<<DB::Construct as Construct>::Value, Error<DB::Error>> where
        DB::Construct: CompatibleConstruct,
    {
        self.as_ref().into_tree(db)
    }
}