use crate::Result;
use std::fmt::Debug;
use std::future::Future;
use std::pin::Pin;
#[cfg(not(target_arch = "wasm32"))]
pub type StorageFuture<'a, T> = Pin<Box<dyn Future<Output = Result<T>> + Send + 'a>>;
#[cfg(target_arch = "wasm32")]
pub type StorageFuture<'a, T> = Pin<Box<dyn Future<Output = Result<T>> + 'a>>;
pub trait Storage: Send + Sync + Debug {
fn get<'a>(&'a self, namespace: &'a str, key: &'a str) -> StorageFuture<'a, Option<Vec<u8>>>;
fn put<'a>(&'a self, namespace: &'a str, key: &'a str, value: Vec<u8>)
-> StorageFuture<'a, ()>;
fn delete<'a>(&'a self, namespace: &'a str, key: &'a str) -> StorageFuture<'a, ()>;
fn list_keys<'a>(
&'a self,
namespace: &'a str,
prefix: &'a str,
) -> StorageFuture<'a, Vec<String>>;
}
#[cfg(feature = "test-utils")]
pub mod memory {
use super::*;
use parking_lot::RwLock;
use std::collections::BTreeMap;
#[derive(Debug, Default)]
pub struct MemStorage {
inner: RwLock<BTreeMap<(String, String), Vec<u8>>>,
}
impl Storage for MemStorage {
fn get<'a>(&'a self, ns: &'a str, k: &'a str) -> StorageFuture<'a, Option<Vec<u8>>> {
Box::pin(async move { Ok(self.inner.read().get(&(ns.into(), k.into())).cloned()) })
}
fn put<'a>(&'a self, ns: &'a str, k: &'a str, v: Vec<u8>) -> StorageFuture<'a, ()> {
Box::pin(async move {
self.inner.write().insert((ns.into(), k.into()), v);
Ok(())
})
}
fn delete<'a>(&'a self, ns: &'a str, k: &'a str) -> StorageFuture<'a, ()> {
Box::pin(async move {
self.inner.write().remove(&(ns.into(), k.into()));
Ok(())
})
}
fn list_keys<'a>(&'a self, ns: &'a str, prefix: &'a str) -> StorageFuture<'a, Vec<String>> {
Box::pin(async move {
let g = self.inner.read();
Ok(g.keys()
.filter(|(n, k)| n == ns && k.starts_with(prefix))
.map(|(_, k)| k.clone())
.collect())
})
}
}
}