use super::Set;
use crate::{make_map, make_map_with_root, parse_uint_key, u64_key, DealID, Map};
use cid::Cid;
use clock::ChainEpoch;
use ipld_blockstore::BlockStore;
use ipld_hamt::Error;
use std::borrow::Borrow;
use std::error::Error as StdError;
pub struct SetMultimap<'a, BS>(Map<'a, BS, Cid>);
impl<'a, BS> SetMultimap<'a, BS>
where
BS: BlockStore,
{
pub fn new(bs: &'a BS) -> Self {
Self(make_map(bs))
}
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<(), Box<dyn StdError>> {
let mut set = self.get(key)?.unwrap_or_else(|| Set::new(self.0.store()));
set.put(u64_key(value))?;
let new_root = set.root()?;
Ok(self.0.set(u64_key(key as u64), new_root)?)
}
pub fn put_many(
&mut self,
key: ChainEpoch,
values: &[DealID],
) -> Result<(), Box<dyn StdError>> {
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()?;
Ok(self.0.set(u64_key(key as u64), new_root)?)
}
#[inline]
pub fn get(&self, key: ChainEpoch) -> Result<Option<Set<'a, BS>>, Box<dyn StdError>> {
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<(), Box<dyn StdError>> {
let mut set = match self.get(key)? {
Some(s) => s,
None => return Ok(()),
};
set.delete(u64_key(v).borrow())?;
let new_root = set.root()?;
Ok(self.0.set(u64_key(key as u64), new_root)?)
}
#[inline]
pub fn remove_all(&mut self, key: ChainEpoch) -> Result<(), Box<dyn StdError>> {
self.0.delete(&u64_key(key as u64))?;
Ok(())
}
pub fn for_each<F>(&self, key: ChainEpoch, mut f: F) -> Result<(), Box<dyn StdError>>
where
F: FnMut(DealID) -> Result<(), Box<dyn StdError>>,
{
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| format!("Could not parse key: {:?}, ({})", &k.0, e))?;
f(v)
})
}
}