Skip to main content

luct_core/store/
memory.rs

1use crate::store::{
2    AppendableStore, AsyncStoreRead, AsyncStoreWrite, OrderedStoreRead, SearchableStoreRead,
3    StoreBase, StoreRead, StoreWrite,
4};
5use std::{
6    collections::BTreeMap,
7    sync::{Arc, RwLock},
8};
9
10/// A non-persistent implementation of [`Store`](crate::store::Store)
11///
12/// This can be useful for testing, or in settings, in which the data should not be stored,
13/// for example when running as a command line tool in CI
14#[derive(Debug, Clone)]
15pub struct MemoryStore<K, V>(Arc<RwLock<BTreeMap<K, V>>>);
16
17impl<K, V> Default for MemoryStore<K, V> {
18    fn default() -> Self {
19        Self(Arc::new(RwLock::new(BTreeMap::new())))
20    }
21}
22
23impl<K, V> StoreBase for MemoryStore<K, V> {
24    type Key = K;
25    type Value = V;
26}
27
28impl<K: Ord, V: Clone> StoreRead for MemoryStore<K, V> {
29    fn get(&self, key: &K) -> Option<V> {
30        self.0.read().unwrap().get(key).cloned()
31    }
32
33    fn len(&self) -> usize {
34        self.0.read().unwrap().len()
35    }
36}
37
38impl<K: Ord, V: Clone> StoreWrite for MemoryStore<K, V> {
39    fn insert(&self, key: K, value: V) {
40        self.0.write().unwrap().insert(key, value);
41    }
42
43    fn delete(&self, key: &K) -> bool {
44        self.0.write().unwrap().remove(key).is_some()
45    }
46}
47
48impl<K: Ord + Clone, V: Clone> OrderedStoreRead for MemoryStore<K, V> {
49    fn last(&self) -> Option<(K, V)> {
50        self.0
51            .read()
52            .unwrap()
53            .iter()
54            .next_back()
55            .map(|(k, v)| (k.clone(), v.clone()))
56    }
57}
58
59impl<V: Clone> AppendableStore for MemoryStore<u64, V> {
60    fn append(&self, value: V) -> u64 {
61        let mut store = self.0.write().unwrap();
62
63        let len = store.len() as u64;
64        let old = store.insert(len, value);
65
66        assert!(
67            old.is_none(),
68            "IndexedStore already contained a value at {len}"
69        );
70
71        len
72    }
73}
74
75impl<K: Ord, V: Clone> AsyncStoreRead for MemoryStore<K, V> {
76    async fn get(&self, key: K) -> Option<V> {
77        self.0.read().unwrap().get(&key).cloned()
78    }
79
80    async fn len(&self) -> usize {
81        self.0.read().unwrap().len()
82    }
83}
84
85impl<K: Ord, V: Clone> AsyncStoreWrite for MemoryStore<K, V> {
86    async fn insert(&self, key: K, value: V) {
87        self.0.write().unwrap().insert(key, value);
88    }
89}
90
91impl<K: Ord + Clone, V: Clone> SearchableStoreRead for MemoryStore<K, V> {
92    fn filter(&self, mut pred: impl FnMut(&K, &V) -> bool) -> Vec<(K, V)> {
93        self.0
94            .read()
95            .unwrap()
96            .iter()
97            .filter(|(key, val)| pred(key, val))
98            .map(|(key, val)| (key.clone(), val.clone()))
99            .collect()
100    }
101}