#[cfg(feature = "std")]
use std::collections::HashMap as Map;
#[cfg(not(feature = "std"))]
use alloc::collections::BTreeMap as Map;
use generic_array::GenericArray;
use digest::Digest;
use core::marker::PhantomData;
use core::hash::Hash;
use crate::{Construct, Backend, ReadBackend, WriteBackend};
pub trait EmptyStatus {
fn is_unit() -> bool { !Self::is_inherited() }
fn is_inherited() -> bool { !Self::is_unit() }
}
pub struct InheritedEmpty;
impl EmptyStatus for InheritedEmpty {
fn is_inherited() -> bool { true }
}
pub struct UnitEmpty;
impl EmptyStatus for UnitEmpty {
fn is_unit() -> bool { true }
}
pub struct UnitDigestConstruct<D: Digest, V=GenericArray<u8, <D as Digest>::OutputSize>>(PhantomData<(D, V)>);
impl<D: Digest, V> Construct for UnitDigestConstruct<D, V> where
V: From<GenericArray<u8, D::OutputSize>> + AsRef<[u8]> + Default + Clone,
{
type Value = V;
fn intermediate_of(left: &Self::Value, right: &Self::Value) -> Self::Value {
let mut digest = D::new();
digest.input(&left.as_ref()[..]);
digest.input(&right.as_ref()[..]);
digest.result().into()
}
fn empty_at<DB: WriteBackend<Construct=Self> + ?Sized>(
_db: &mut DB,
_depth_to_bottom: usize
) -> Result<Self::Value, DB::Error> {
Ok(Default::default())
}
}
pub struct InheritedDigestConstruct<D: Digest, V=GenericArray<u8, <D as Digest>::OutputSize>>(PhantomData<(D, V)>);
impl<D: Digest, V> Construct for InheritedDigestConstruct<D, V> where
V: From<GenericArray<u8, D::OutputSize>> + AsRef<[u8]> + Default + Clone,
{
type Value = V;
fn intermediate_of(left: &Self::Value, right: &Self::Value) -> Self::Value {
let mut digest = D::new();
digest.input(&left.as_ref()[..]);
digest.input(&right.as_ref()[..]);
digest.result().into()
}
fn empty_at<DB: WriteBackend<Construct=Self> + ?Sized>(
db: &mut DB,
depth_to_bottom: usize
) -> Result<Self::Value, DB::Error> {
let mut current = Self::Value::default();
for _ in 0..depth_to_bottom {
let value = (current.clone(), current);
let key = Self::intermediate_of(&value.0, &value.1);
db.insert(key.clone(), value)?;
current = key;
}
Ok(current)
}
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum NoopBackendError {
NotSupported,
}
pub struct NoopBackend<C: Construct>(
PhantomData<C>,
);
impl<C: Construct> Default for NoopBackend<C> where
C::Value: Eq + Hash + Ord
{
fn default() -> Self {
Self(Default::default())
}
}
impl<C: Construct> Clone for NoopBackend<C> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<C: Construct> Backend for NoopBackend<C> {
type Construct = C;
type Error = NoopBackendError;
}
impl<C: Construct> ReadBackend for NoopBackend<C> {
fn get(
&mut self,
_key: &C::Value,
) -> Result<Option<(C::Value, C::Value)>, Self::Error> {
Err(NoopBackendError::NotSupported)
}
}
impl<C: Construct> WriteBackend for NoopBackend<C> {
fn rootify(&mut self, _key: &C::Value) -> Result<(), Self::Error> {
Ok(())
}
fn unrootify(&mut self, _key: &C::Value) -> Result<(), Self::Error> {
Ok(())
}
fn insert(
&mut self,
_key: C::Value,
_value: (C::Value, C::Value)
) -> Result<(), Self::Error> {
Ok(())
}
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum InMemoryBackendError {
FetchingKeyNotExist,
RootifyKeyNotExist,
SetIntermediateNotExist
}
#[cfg(feature = "std")]
impl std::fmt::Display for InMemoryBackendError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
#[cfg(feature = "std")]
impl std::error::Error for InMemoryBackendError { }
pub struct InMemoryBackend<C: Construct>(
Map<C::Value, (Option<(C::Value, C::Value)>, Option<usize>)>,
);
impl<C: Construct> Default for InMemoryBackend<C> where
C::Value: Eq + Hash + Ord
{
fn default() -> Self {
let mut map = Map::default();
map.insert(Default::default(), (None, None));
Self(map)
}
}
impl<C: Construct> Clone for InMemoryBackend<C> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<C: Construct> InMemoryBackend<C> where
C::Value: Eq + Hash + Ord,
{
fn remove(&mut self, old_key: &C::Value) -> Result<(), InMemoryBackendError> {
let (old_value, to_remove) = {
let value = match self.0.get_mut(old_key) {
Some(value) => value,
None => return Ok(()),
};
value.1.as_mut().map(|v| *v -= 1);
(value.0.clone(), value.1.map(|v| v == 0).unwrap_or(false))
};
if to_remove {
if let Some(old_value) = old_value {
self.remove(&old_value.0)?;
self.remove(&old_value.1)?;
}
self.0.remove(old_key);
}
Ok(())
}
pub fn populate(&mut self, proofs: Map<C::Value, (C::Value, C::Value)>) {
for (key, (left, right)) in proofs {
self.0.insert(key, (Some((left.clone(), right.clone())), None));
self.0.entry(left).or_insert((None, None));
self.0.entry(right).or_insert((None, None));
}
}
}
impl<C: Construct> AsRef<Map<C::Value, (Option<(C::Value, C::Value)>, Option<usize>)>> for InMemoryBackend<C> {
fn as_ref(&self) -> &Map<C::Value, (Option<(C::Value, C::Value)>, Option<usize>)> {
&self.0
}
}
impl<C: Construct> Backend for InMemoryBackend<C> {
type Construct = C;
type Error = InMemoryBackendError;
}
impl<C: Construct> ReadBackend for InMemoryBackend<C> where
C::Value: Eq + Hash + Ord,
{
fn get(&mut self, key: &C::Value) -> Result<Option<(C::Value, C::Value)>, Self::Error> {
Ok(self.0.get(key).map(|v| v.0.clone()).unwrap_or(None))
}
}
impl<C: Construct> WriteBackend for InMemoryBackend<C> where
C::Value: Eq + Hash + Ord,
{
fn rootify(&mut self, key: &C::Value) -> Result<(), Self::Error> {
self.0.entry(key.clone()).or_insert((None, Some(0))).1
.as_mut().map(|v| *v += 1);
Ok(())
}
fn unrootify(&mut self, key: &C::Value) -> Result<(), Self::Error> {
self.remove(key)?;
Ok(())
}
fn insert(
&mut self,
key: C::Value,
value: (C::Value, C::Value)
) -> Result<(), Self::Error> {
if self.0.contains_key(&key) {
return Ok(())
}
let (left, right) = value;
self.0.entry(left.clone()).or_insert((None, Some(0))).1
.as_mut().map(|v| *v += 1);
self.0.entry(right.clone()).or_insert((None, Some(0))).1
.as_mut().map(|v| *v += 1);
self.0.insert(key, (Some((left, right)), Some(0)));
Ok(())
}
}