Skip to main content

luct_store/
last.rs

1use luct_core::store::{
2    AppendableStore, AsyncAppendableStore, AsyncOrderedStoreRead, AsyncSearchableStoreRead,
3    AsyncStoreRead, AsyncStoreWrite, OrderedStoreRead, SearchableStoreRead, StoreBase, StoreRead,
4    StoreWrite,
5};
6use std::{
7    cell::RefCell,
8    ops::{Deref, DerefMut},
9};
10
11/// A [`OrderedStore`](luct_core::store::OrderedStore) that caches the `last` value in memory
12///
13/// If you need to call [`OrderedStoreRead::last`] as lot, this will speed up access
14pub struct LastValCacheStore<S>
15where
16    S: StoreBase,
17{
18    last: RefCell<Option<(S::Key, S::Value)>>,
19    inner: S,
20}
21
22impl<S> Deref for LastValCacheStore<S>
23where
24    S: StoreBase,
25{
26    type Target = S;
27
28    fn deref(&self) -> &Self::Target {
29        &self.inner
30    }
31}
32
33impl<S> DerefMut for LastValCacheStore<S>
34where
35    S: StoreBase,
36{
37    fn deref_mut(&mut self) -> &mut Self::Target {
38        &mut self.inner
39    }
40}
41
42impl<S> LastValCacheStore<S>
43where
44    S: StoreBase,
45{
46    pub fn new(store: S) -> Self {
47        Self {
48            last: RefCell::new(None),
49            inner: store,
50        }
51    }
52}
53
54impl<S> StoreBase for LastValCacheStore<S>
55where
56    S: StoreBase,
57{
58    type Key = S::Key;
59    type Value = S::Value;
60}
61
62impl<S> StoreRead for LastValCacheStore<S>
63where
64    S: StoreRead,
65{
66    fn get(&self, key: &Self::Key) -> Option<Self::Value> {
67        self.inner.get(key)
68    }
69
70    fn len(&self) -> usize {
71        self.inner.len()
72    }
73}
74
75impl<S> StoreWrite for LastValCacheStore<S>
76where
77    S: StoreWrite,
78{
79    fn insert(&self, key: Self::Key, value: Self::Value) {
80        *self.last.borrow_mut() = None;
81        self.inner.insert(key, value);
82    }
83
84    fn delete(&self, key: &Self::Key) -> bool {
85        *self.last.borrow_mut() = None;
86        self.inner.delete(key)
87    }
88}
89
90impl<S> OrderedStoreRead for LastValCacheStore<S>
91where
92    S: OrderedStoreRead<Key: Clone, Value: Clone>,
93{
94    fn last(&self) -> Option<(Self::Key, Self::Value)> {
95        let mut last_borrow = self.last.borrow_mut();
96        match last_borrow.as_ref() {
97            Some(last) => Some(last.clone()),
98            None => {
99                let last = self.inner.last();
100                *last_borrow = last.clone();
101                last
102            }
103        }
104    }
105}
106
107impl<S> AppendableStore for LastValCacheStore<S>
108where
109    S: AppendableStore<Key: Clone, Value: Clone>,
110{
111    fn append(&self, value: Self::Value) -> Self::Key {
112        *self.last.borrow_mut() = None;
113        self.inner.append(value)
114    }
115}
116
117impl<S> SearchableStoreRead for LastValCacheStore<S>
118where
119    S: SearchableStoreRead<Key: Clone, Value: Clone>,
120{
121    fn filter(
122        &self,
123        pred: impl FnMut(&Self::Key, &Self::Value) -> bool,
124    ) -> Vec<(Self::Key, Self::Value)> {
125        self.inner.filter(pred)
126    }
127
128    fn find(
129        &self,
130        pred: impl FnMut(&Self::Key, &Self::Value) -> bool,
131    ) -> Option<(Self::Key, Self::Value)> {
132        self.inner.find(pred)
133    }
134}
135
136impl<S> AsyncStoreRead for LastValCacheStore<S>
137where
138    S: AsyncStoreRead<Key: Clone>,
139{
140    async fn get(&self, key: Self::Key) -> Option<Self::Value> {
141        self.inner.get(key.clone()).await
142    }
143
144    async fn len(&self) -> usize {
145        self.inner.len().await
146    }
147}
148
149impl<S> AsyncStoreWrite for LastValCacheStore<S>
150where
151    S: AsyncStoreWrite<Key: Clone>,
152{
153    async fn insert(&self, key: Self::Key, value: Self::Value) {
154        *self.last.borrow_mut() = None;
155        self.inner.insert(key, value).await
156    }
157
158    async fn delete(&self, key: Self::Key) -> bool {
159        *self.last.borrow_mut() = None;
160        self.inner.delete(key).await
161    }
162}
163
164impl<S> AsyncOrderedStoreRead for LastValCacheStore<S>
165where
166    S: AsyncOrderedStoreRead<Key: Clone, Value: Clone>,
167{
168    async fn last(&self) -> Option<(Self::Key, Self::Value)> {
169        let last = self.last.borrow().clone();
170
171        if let Some(last) = last {
172            Some(last)
173        } else {
174            let new_last = self.inner.last().await;
175            *self.last.borrow_mut() = new_last.clone();
176            new_last
177        }
178    }
179}
180
181impl<S> AsyncAppendableStore for LastValCacheStore<S>
182where
183    S: AsyncAppendableStore<Key: Clone, Value: Clone>,
184{
185    async fn append(&self, value: Self::Value) -> Self::Key {
186        *self.last.borrow_mut() = None;
187        self.inner.append(value).await
188    }
189}
190
191impl<S> AsyncSearchableStoreRead for LastValCacheStore<S>
192where
193    S: AsyncSearchableStoreRead<Key: Clone, Value: Clone>,
194{
195    async fn filter(
196        &self,
197        pred: impl FnMut(&Self::Key, &Self::Value) -> bool,
198    ) -> Vec<(Self::Key, Self::Value)> {
199        self.inner.filter(pred).await
200    }
201
202    async fn find(
203        &self,
204        pred: impl FnMut(&Self::Key, &Self::Value) -> bool,
205    ) -> Option<(Self::Key, Self::Value)> {
206        self.inner.find(pred).await
207    }
208}
209
210#[cfg(test)]
211mod tests {
212    use super::*;
213    use luct_core::store::{MemoryStore, async_adapter::AsyncAdapter};
214    use luct_test::{
215        async_store::{async_ordered_store_test, async_searchable_store_test, async_store_test},
216        store::{ordered_store_test, searchable_store_test, store_test},
217    };
218
219    #[test]
220    fn last_val_store() {
221        let store = LastValCacheStore::new(MemoryStore::<u64, String>::default());
222        store_test(store);
223    }
224
225    #[test]
226    fn last_val_ordered_store() {
227        let store = LastValCacheStore::new(MemoryStore::<u64, String>::default());
228        ordered_store_test(store);
229    }
230
231    #[test]
232    fn last_val_searchable_store() {
233        let store = LastValCacheStore::new(MemoryStore::<u64, String>::default());
234        searchable_store_test(store);
235    }
236
237    #[tokio::test]
238    async fn async_last_val_store() {
239        let store =
240            AsyncAdapter::new(LastValCacheStore::new(MemoryStore::<u64, String>::default()));
241        async_store_test(store).await;
242    }
243
244    #[tokio::test]
245    async fn async_last_val_ordered_store() {
246        let store =
247            AsyncAdapter::new(LastValCacheStore::new(MemoryStore::<u64, String>::default()));
248        async_ordered_store_test(store).await;
249    }
250
251    #[tokio::test]
252    async fn async_last_val_searchable_store() {
253        let store =
254            AsyncAdapter::new(LastValCacheStore::new(MemoryStore::<u64, String>::default()));
255        async_searchable_store_test(store).await;
256    }
257}