1use crate::Result;
7use std::fmt::Debug;
8use std::future::Future;
9use std::pin::Pin;
10
11#[cfg(not(target_arch = "wasm32"))]
15pub type StorageFuture<'a, T> = Pin<Box<dyn Future<Output = Result<T>> + Send + 'a>>;
16#[cfg(target_arch = "wasm32")]
17pub type StorageFuture<'a, T> = Pin<Box<dyn Future<Output = Result<T>> + 'a>>;
18
19pub trait Storage: Send + Sync + Debug {
20 fn get<'a>(&'a self, namespace: &'a str, key: &'a str) -> StorageFuture<'a, Option<Vec<u8>>>;
21 fn put<'a>(&'a self, namespace: &'a str, key: &'a str, value: Vec<u8>)
22 -> StorageFuture<'a, ()>;
23 fn delete<'a>(&'a self, namespace: &'a str, key: &'a str) -> StorageFuture<'a, ()>;
24 fn list_keys<'a>(
25 &'a self,
26 namespace: &'a str,
27 prefix: &'a str,
28 ) -> StorageFuture<'a, Vec<String>>;
29}
30
31#[cfg(feature = "test-utils")]
32pub mod memory {
33 use super::*;
34 use parking_lot::RwLock;
35 use std::collections::BTreeMap;
36
37 #[derive(Debug, Default)]
38 pub struct MemStorage {
39 inner: RwLock<BTreeMap<(String, String), Vec<u8>>>,
40 }
41
42 impl Storage for MemStorage {
43 fn get<'a>(&'a self, ns: &'a str, k: &'a str) -> StorageFuture<'a, Option<Vec<u8>>> {
44 Box::pin(async move { Ok(self.inner.read().get(&(ns.into(), k.into())).cloned()) })
45 }
46 fn put<'a>(&'a self, ns: &'a str, k: &'a str, v: Vec<u8>) -> StorageFuture<'a, ()> {
47 Box::pin(async move {
48 self.inner.write().insert((ns.into(), k.into()), v);
49 Ok(())
50 })
51 }
52 fn delete<'a>(&'a self, ns: &'a str, k: &'a str) -> StorageFuture<'a, ()> {
53 Box::pin(async move {
54 self.inner.write().remove(&(ns.into(), k.into()));
55 Ok(())
56 })
57 }
58 fn list_keys<'a>(&'a self, ns: &'a str, prefix: &'a str) -> StorageFuture<'a, Vec<String>> {
59 Box::pin(async move {
60 let g = self.inner.read();
61 Ok(g.keys()
62 .filter(|(n, k)| n == ns && k.starts_with(prefix))
63 .map(|(_, k)| k.clone())
64 .collect())
65 })
66 }
67 }
68}