use crate::node::Node;
use crate::{Error, Hash, HashAlgorithm, Sha256, DEFAULT_BIT_WIDTH};
use cid::{Cid, Code::Blake2b256};
use forest_hash_utils::BytesKey;
use ipld_blockstore::BlockStore;
use serde::{de::DeserializeOwned, Serialize, Serializer};
use std::borrow::Borrow;
use std::error::Error as StdError;
use std::marker::PhantomData;
#[derive(Debug)]
pub struct Hamt<'a, BS, V, K = BytesKey, H = Sha256> {
root: Node<K, V, H>,
store: &'a BS,
bit_width: u32,
hash: PhantomData<H>,
}
impl<BS, V, K, H> Serialize for Hamt<'_, BS, V, K, H>
where
K: Serialize,
V: Serialize,
H: HashAlgorithm,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.root.serialize(serializer)
}
}
impl<'a, K: PartialEq, V: PartialEq, S: BlockStore, H: HashAlgorithm> PartialEq
for Hamt<'a, S, V, K, H>
{
fn eq(&self, other: &Self) -> bool {
self.root == other.root
}
}
impl<'a, BS, V, K, H> Hamt<'a, BS, V, K, H>
where
K: Hash + Eq + PartialOrd + Serialize + DeserializeOwned,
V: Serialize + DeserializeOwned,
BS: BlockStore,
H: HashAlgorithm,
{
pub fn new(store: &'a BS) -> Self {
Self::new_with_bit_width(store, DEFAULT_BIT_WIDTH)
}
pub fn new_with_bit_width(store: &'a BS, bit_width: u32) -> Self {
Self {
root: Node::default(),
store,
bit_width,
hash: Default::default(),
}
}
pub fn load(cid: &Cid, store: &'a BS) -> Result<Self, Error> {
Self::load_with_bit_width(cid, store, DEFAULT_BIT_WIDTH)
}
pub fn load_with_bit_width(cid: &Cid, store: &'a BS, bit_width: u32) -> Result<Self, Error> {
match store.get(cid)? {
Some(root) => Ok(Self {
root,
store,
bit_width,
hash: Default::default(),
}),
None => Err(Error::CidNotFound(cid.to_string())),
}
}
pub fn set_root(&mut self, cid: &Cid) -> Result<(), Error> {
match self.store.get(cid)? {
Some(root) => self.root = root,
None => return Err(Error::CidNotFound(cid.to_string())),
}
Ok(())
}
pub fn store(&self) -> &'a BS {
self.store
}
pub fn set(&mut self, key: K, value: V) -> Result<Option<V>, Error>
where
V: PartialEq,
{
self.root
.set(key, value, self.store, self.bit_width, true)
.map(|(r, _)| r)
}
pub fn set_if_absent(&mut self, key: K, value: V) -> Result<bool, Error>
where
V: PartialEq,
{
self.root
.set(key, value, self.store, self.bit_width, false)
.map(|(_, set)| set)
}
#[inline]
pub fn get<Q: ?Sized>(&self, k: &Q) -> Result<Option<&V>, Error>
where
K: Borrow<Q>,
Q: Hash + Eq,
V: DeserializeOwned,
{
match self.root.get(k, self.store, self.bit_width)? {
Some(v) => Ok(Some(v)),
None => Ok(None),
}
}
#[inline]
pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> Result<bool, Error>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
Ok(self.root.get(k, self.store, self.bit_width)?.is_some())
}
pub fn delete<Q: ?Sized>(&mut self, k: &Q) -> Result<Option<(K, V)>, Error>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
self.root.remove_entry(k, self.store, self.bit_width)
}
pub fn flush(&mut self) -> Result<Cid, Error> {
self.root.flush(self.store)?;
Ok(self.store.put(&self.root, Blake2b256)?)
}
pub fn is_empty(&self) -> bool {
self.root.is_empty()
}
#[inline]
pub fn for_each<F>(&self, mut f: F) -> Result<(), Box<dyn StdError>>
where
V: DeserializeOwned,
F: FnMut(&K, &V) -> Result<(), Box<dyn StdError>>,
{
self.root.for_each(self.store, &mut f)
}
}