use crate::actor_error;
use std::any::type_name;
use std::marker::PhantomData;
use super::{make_empty_map, make_map_with_root_and_bitwidth};
use crate::tcid_ops;
use anyhow::{anyhow, Result};
use fvm_ipld_blockstore::{Blockstore, MemoryBlockstore};
use fvm_ipld_hamt::Error as HamtError;
use fvm_ipld_hamt::Hamt;
use fvm_shared::HAMT_BIT_WIDTH;
use serde::de::DeserializeOwned;
use serde::ser::Serialize;
use super::{TCid, TCidContent};
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct THamt<K, V, const W: u32 = HAMT_BIT_WIDTH> {
_phantom_k: PhantomData<K>,
_phantom_v: PhantomData<V>,
}
impl<K, V, const W: u32> TCidContent for THamt<K, V, W> {}
impl<K, V, const W: u32> TCid<THamt<K, V, W>>
where
V: Serialize + DeserializeOwned,
{
pub fn new_hamt<S: Blockstore>(store: &S) -> Result<Self> {
let cid = make_empty_map::<_, V>(store, W)
.flush()
.map_err(|e| anyhow!("Failed to create empty map: {:?}", e))?;
Ok(Self::from(cid))
}
pub fn maybe_load<'s, S: Blockstore>(&self, store: &'s S) -> Result<Option<Hamt<&'s S, V>>> {
match make_map_with_root_and_bitwidth::<S, V>(&self.cid, store, W) {
Ok(content) => Ok(Some(content)),
Err(HamtError::CidNotFound(_)) => Ok(None),
Err(other) => Err(anyhow!(other)),
}
}
pub fn flush<'s, S: Blockstore>(
&mut self,
mut value: Hamt<&'s S, V>,
) -> Result<Hamt<&'s S, V>> {
let cid = value
.flush()
.map_err(|e| anyhow!("error flushing {}: {:?}", type_name::<Self>(), e))?;
self.cid = cid;
Ok(value)
}
}
tcid_ops!(THamt<K, V : Serialize + DeserializeOwned, W const: u32> => Hamt<&'s S, V>);
impl<K, V, const W: u32> Default for TCid<THamt<K, V, W>>
where
V: Serialize + DeserializeOwned,
{
fn default() -> Self {
Self::new_hamt(&MemoryBlockstore::new()).unwrap()
}
}