use crate::collections::BTreeMap;
use crate::merge::Merge;
use crate::mmr_store::{MMRStoreReadOps, MMRStoreWriteOps};
use crate::vec::Vec;
use crate::{Arc, RwLock};
use core::convert::Infallible;
cfg_if::cfg_if! {
if #[cfg(feature = "std")] {
macro_rules! read_guard {
($lock:expr) => { $lock.read().unwrap() }
}
macro_rules! write_guard {
($lock:expr) => { $lock.write().unwrap() }
}
} else {
macro_rules! read_guard {
($lock:expr) => { $lock.read() }
}
macro_rules! write_guard {
($lock:expr) => { $lock.write() }
}
}
}
#[derive(Clone)]
pub struct MemStore<T>(Arc<RwLock<BTreeMap<u64, T>>>);
impl<T> Default for MemStore<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> MemStore<T> {
#[must_use]
pub fn new() -> Self {
MemStore(Arc::new(RwLock::new(Default::default())))
}
}
impl<T: Clone + Send + Sync> MMRStoreReadOps<T> for MemStore<T> {
type Error = Infallible;
async fn get_elem(&self, pos: u64) -> Result<Option<T>, Self::Error> {
Ok(read_guard!(self.0).get(&pos).cloned())
}
async fn get_elems(
&self,
positions: impl Iterator<Item = u64> + Send,
) -> Result<Vec<Option<T>>, Self::Error> {
let store = read_guard!(self.0);
Ok(positions.map(|pos| store.get(&pos).cloned()).collect())
}
}
impl<T: Send + Sync> MMRStoreWriteOps<T> for MemStore<T> {
type Error = Infallible;
async fn append(
&mut self,
pos: u64,
elems: Vec<T>,
) -> Result<(), Self::Error> {
let mut store = write_guard!(self.0);
for (i, elem) in elems.into_iter().enumerate() {
store.insert(pos + i as u64, elem);
}
Ok(())
}
}
pub type MemMMR<M> = crate::MMR<M, MemStore<<M as Merge>::Item>>;
pub type MemMMRIVER<M> = crate::MMRIVER<M, MemStore<<M as Merge>::Item>>;