use std::borrow::Borrow;
use cid::Cid;
use fvm_ipld_blockstore::Blockstore;
use fvm_ipld_hamt::Error;
use fvm_shared3::clock::ChainEpoch;
use fvm_shared3::deal::DealID;
use fvm_shared3::HAMT_BIT_WIDTH;
use super::Set;
use crate::v11::{make_empty_map, make_map_with_root, parse_uint_key, u64_key, Map};
pub struct SetMultimap<'a, BS>(pub Map<'a, BS, Cid>);
impl<'a, BS> SetMultimap<'a, BS>
where
BS: Blockstore,
{
pub fn new(bs: &'a BS) -> Self {
Self(make_empty_map(bs, HAMT_BIT_WIDTH))
}
pub fn from_root(bs: &'a BS, cid: &Cid) -> Result<Self, Error> {
Ok(Self(make_map_with_root(cid, bs)?))
}
#[inline]
pub fn root(&mut self) -> Result<Cid, Error> {
self.0.flush()
}
pub fn put(&mut self, key: ChainEpoch, value: DealID) -> Result<(), Error> {
let mut set = self.get(key)?.unwrap_or_else(|| Set::new(self.0.store()));
set.put(u64_key(value))?;
let new_root = set.root()?;
self.0.set(u64_key(key as u64), new_root)?;
Ok(())
}
pub fn put_many(&mut self, key: ChainEpoch, values: &[DealID]) -> Result<(), Error> {
let mut set = self.get(key)?.unwrap_or_else(|| Set::new(self.0.store()));
for &v in values {
set.put(u64_key(v))?;
}
let new_root = set.root()?;
self.0.set(u64_key(key as u64), new_root)?;
Ok(())
}
#[inline]
pub fn get(&self, key: ChainEpoch) -> Result<Option<Set<'a, BS>>, Error> {
match self.0.get(&u64_key(key as u64))? {
Some(cid) => Ok(Some(Set::from_root(*self.0.store(), cid)?)),
None => Ok(None),
}
}
#[inline]
pub fn remove(&mut self, key: ChainEpoch, v: DealID) -> Result<(), Error> {
let mut set = match self.get(key)? {
Some(s) => s,
None => return Ok(()),
};
set.delete(u64_key(v).borrow())?;
let new_root = set.root()?;
self.0.set(u64_key(key as u64), new_root)?;
Ok(())
}
#[inline]
pub fn remove_all(&mut self, key: ChainEpoch) -> Result<(), Error> {
self.0.delete(&u64_key(key as u64))?;
Ok(())
}
pub fn for_each<F>(&self, key: ChainEpoch, mut f: F) -> Result<(), Error>
where
F: FnMut(DealID) -> Result<(), Error>,
{
let set = match self.get(key)? {
Some(s) => s,
None => return Ok(()),
};
set.for_each(|k| {
let v = parse_uint_key(k)
.map_err(|e| anyhow::anyhow!("Could not parse key: {:?}, ({})", &k.0, e))?;
Ok(f(v)?)
})
}
}