1#![allow(dead_code)]
2use async_trait::async_trait;
4use std::{collections::HashMap, sync::RwLock};
5
6use crate::err::TribResult;
7
8#[derive(Debug, Clone)]
9
10pub struct KeyValue {
12 pub key: String,
14 pub value: String,
16}
17
18impl KeyValue {
19 pub fn new(key: &str, value: &str) -> KeyValue {
21 KeyValue {
22 key: key.to_string(),
23 value: value.to_string(),
24 }
25 }
26}
27
28#[derive(Debug, Clone, Default)]
29pub struct Pattern {
31 pub prefix: String,
33 pub suffix: String,
35}
36
37impl Pattern {
38 pub fn matches(&self, k: &str) -> bool {
41 k.starts_with(&self.prefix) && k.ends_with(&self.suffix)
42 }
43}
44
45#[derive(Debug, Clone)]
46pub struct List(pub Vec<String>);
48
49#[async_trait]
50pub trait KeyString {
53 async fn get(&self, key: &str) -> TribResult<Option<String>>;
55
56 async fn set(&self, kv: &KeyValue) -> TribResult<bool>;
58
59 async fn keys(&self, p: &Pattern) -> TribResult<List>;
62}
63
64#[async_trait]
65pub trait KeyList {
67 async fn list_get(&self, key: &str) -> TribResult<List>;
69
70 async fn list_append(&self, kv: &KeyValue) -> TribResult<bool>;
72
73 async fn list_remove(&self, kv: &KeyValue) -> TribResult<u32>;
76
77 async fn list_keys(&self, p: &Pattern) -> TribResult<List>;
80}
81
82#[async_trait]
83pub trait Storage: KeyString + KeyList + Send + Sync {
88 async fn clock(&self, at_least: u64) -> TribResult<u64>;
92}
93
94#[derive(Debug, Default)]
99pub struct MemStorage {
100 kvs: RwLock<HashMap<String, String>>,
101 kv_list: RwLock<HashMap<String, List>>,
102 clock: RwLock<u64>,
103}
104
105impl MemStorage {
106 pub fn new() -> MemStorage {
108 MemStorage::default()
109 }
110}
111
112#[async_trait]
113impl KeyString for MemStorage {
114 async fn get(&self, key: &str) -> TribResult<Option<String>> {
115 match self.kvs.read().map_err(|e| e.to_string())?.get(key) {
116 Some(v) => Ok(Some(v.to_string())),
117 None => Ok(None),
118 }
119 }
120
121 async fn set(&self, kv: &KeyValue) -> TribResult<bool> {
122 let mut entry = self.kvs.write().map_err(|e| e.to_string())?;
123 if kv.value.is_empty() {
124 entry.remove(&kv.key);
125 } else {
126 entry.insert(kv.key.clone(), kv.value.clone());
127 }
128 Ok(true)
129 }
130
131 async fn keys(&self, p: &Pattern) -> TribResult<List> {
132 let result = self
133 .kvs
134 .read()
135 .map_err(|e| e.to_string())?
136 .iter()
137 .filter(|(k, _)| p.matches(*k))
138 .map(|(k, _)| k.to_string())
139 .collect::<Vec<String>>();
140 Ok(List(result))
141 }
142}
143
144#[async_trait]
145impl KeyList for MemStorage {
146 async fn list_get(&self, key: &str) -> TribResult<List> {
147 match self.kv_list.read().map_err(|e| e.to_string())?.get(key) {
148 Some(l) => Ok(l.clone()),
149 None => Ok(List(vec![])),
150 }
151 }
152
153 async fn list_append(&self, kv: &KeyValue) -> TribResult<bool> {
154 let mut kvl = self.kv_list.write().map_err(|e| e.to_string())?;
155 match kvl.get_mut(&kv.key) {
156 Some(list) => {
157 list.0.push(kv.value.clone());
158 Ok(true)
159 }
160 None => {
161 let list = vec![kv.value.clone()];
162 kvl.insert(kv.key.clone(), List(list));
163 Ok(true)
164 }
165 }
166 }
167
168 async fn list_remove(&self, kv: &KeyValue) -> TribResult<u32> {
169 let mut removed = 0;
170 let mut kvl = self.kv_list.write().map_err(|e| e.to_string())?;
171 kvl.entry(kv.key.clone()).and_modify(|list| {
172 let begin_size = list.0.len();
173 *list = List(
174 list.0
175 .iter()
176 .filter(|val| **val != kv.value)
177 .map(String::from)
178 .collect::<Vec<String>>(),
179 );
180 let end_size = list.0.len();
181 removed = begin_size - end_size;
182 });
183 if let Some(x) = kvl.get(&kv.key) {
184 if x.0.is_empty() {
185 kvl.remove(&kv.key);
186 }
187 };
188
189 Ok(removed as u32)
190 }
191
192 async fn list_keys(&self, p: &Pattern) -> TribResult<List> {
193 let mut result = vec![];
194 self.kv_list
195 .read()
196 .map_err(|e| e.to_string())?
197 .iter()
198 .filter(|(k, _)| p.matches(*k))
199 .for_each(|(v, _)| result.push((*v).clone()));
200 result.sort();
201 Ok(List(result))
202 }
203}
204
205#[async_trait]
206impl Storage for MemStorage {
207 async fn clock(&self, at_least: u64) -> TribResult<u64> {
208 let mut clk = self.clock.write().map_err(|e| e.to_string())?;
209 if *clk < at_least {
210 *clk = at_least
211 }
212
213 let ret = *clk;
214
215 if *clk < u64::MAX {
216 *clk += 1;
217 }
218 Ok(ret)
219 }
220}
221
222#[async_trait]
223pub trait BinStorage: Send + Sync {
225 async fn bin(&self, name: &str) -> TribResult<Box<dyn Storage>>;
227}
228
229#[cfg(test)]
230mod test {
231 use crate::{
232 err::TribResult,
233 storage::{KeyValue, Pattern, Storage},
234 };
235
236 use super::{KeyList, KeyString, MemStorage};
237
238 async fn setup_test_storage() -> MemStorage {
239 let storage = MemStorage::new();
240 storage
241 .set(&KeyValue {
242 key: "test".to_string(),
243 value: "test-value".to_string(),
244 })
245 .await
246 .unwrap();
247 storage
248 .list_append(&KeyValue {
249 key: "test".to_string(),
250 value: "test-value".to_string(),
251 })
252 .await
253 .unwrap();
254 storage
255 }
256
257 #[tokio::test]
258 async fn storage_get_set() -> TribResult<()> {
259 let storage = MemStorage::new();
260 assert_eq!(
261 true,
262 storage
263 .set(&KeyValue {
264 key: "test".to_string(),
265 value: "test-value".to_string()
266 })
267 .await?
268 );
269 assert_eq!(Some("test-value".to_string()), storage.get("test").await?);
270 Ok(())
271 }
272
273 #[tokio::test]
274 async fn storage_get_empty() -> TribResult<()> {
275 let storage = setup_test_storage().await;
276 assert_eq!(None, storage.get("test2").await?);
277 Ok(())
278 }
279
280 #[tokio::test]
281 async fn storage_keys() {
282 let storage = setup_test_storage().await;
283 let p1 = Pattern {
284 prefix: "test".to_string(),
285 suffix: "test".to_string(),
286 };
287 let p2 = Pattern {
288 prefix: "".to_string(),
289 suffix: "test".to_string(),
290 };
291 let p3 = Pattern {
292 prefix: "test".to_string(),
293 suffix: "".to_string(),
294 };
295 let p4 = Pattern {
296 prefix: "wrong".to_string(),
297 suffix: "right".to_string(),
298 };
299 let p5 = Pattern {
300 prefix: "".to_string(),
301 suffix: "".to_string(),
302 };
303 assert_eq!(1, storage.keys(&p1).await.unwrap().0.len());
304 assert_eq!(1, storage.keys(&p2).await.unwrap().0.len());
305 assert_eq!(1, storage.keys(&p3).await.unwrap().0.len());
306 assert_eq!(0, storage.keys(&p4).await.unwrap().0.len());
307 assert_eq!(1, storage.keys(&p5).await.unwrap().0.len());
308 }
309
310 #[tokio::test]
311 async fn storage_keys_unset() {
312 let s = setup_test_storage().await;
313 assert_eq!(1, s.keys(&Pattern::default()).await.unwrap().0.len());
314 let _ = s.set(&KeyValue::new("test", "")).await.unwrap();
315 assert_eq!(0, s.keys(&Pattern::default()).await.unwrap().0.len())
316 }
317
318 #[tokio::test]
319 async fn storage_list_keys_unset() {
320 let s = setup_test_storage().await;
321 assert_eq!(1, s.list_keys(&Pattern::default()).await.unwrap().0.len());
322 let _ = s
323 .list_remove(&KeyValue::new("test", "test-value"))
324 .await
325 .unwrap();
326 assert_eq!(0, s.list_keys(&Pattern::default()).await.unwrap().0.len())
327 }
328
329 #[tokio::test]
330 async fn storage_get_list() {
331 let storage = setup_test_storage().await;
332 assert_eq!("test-value", storage.list_get("test").await.unwrap().0[0]);
333 }
334
335 #[tokio::test]
336 async fn storage_get_list_empty() {
337 let storage = setup_test_storage().await;
338 assert_eq!(0, storage.list_get("test2").await.unwrap().0.len());
339 }
340
341 #[tokio::test]
342 async fn storage_get_list_append() -> TribResult<()> {
343 let storage = setup_test_storage().await;
344 let res = storage
345 .list_append(&KeyValue {
346 key: "test".to_string(),
347 value: "val2".to_string(),
348 })
349 .await?;
350 assert_eq!(true, res);
351 assert_eq!(2, storage.list_get("test").await.unwrap().0.len());
352 Ok(())
353 }
354
355 #[tokio::test]
356 async fn storage_get_list_remove() {
357 let storage = setup_test_storage().await;
358 let kv = KeyValue {
359 key: "test".to_string(),
360 value: "val2".to_string(),
361 };
362 assert_eq!(true, storage.list_append(&kv).await.unwrap());
363 assert_eq!(true, storage.list_append(&kv).await.unwrap());
364 assert_eq!(true, storage.list_append(&kv).await.unwrap());
365 assert_eq!(3, storage.list_remove(&kv).await.unwrap());
366 println!("{:?}", storage.list_get("test").await.unwrap().0);
367 assert_eq!("test-value", storage.list_get("test").await.unwrap().0[0]);
368 }
369
370 #[tokio::test]
371 async fn storage_list_keys() {
372 let storage = setup_test_storage().await;
373 let p1 = Pattern {
374 prefix: "test".to_string(),
375 suffix: "test".to_string(),
376 };
377 let p2 = Pattern {
378 prefix: "".to_string(),
379 suffix: "test".to_string(),
380 };
381 let p3 = Pattern {
382 prefix: "test".to_string(),
383 suffix: "".to_string(),
384 };
385 let p4 = Pattern {
386 prefix: "wrong".to_string(),
387 suffix: "right".to_string(),
388 };
389 let p5 = Pattern {
390 prefix: "".to_string(),
391 suffix: "".to_string(),
392 };
393 assert_eq!(1, storage.list_keys(&p1).await.unwrap().0.len());
394 assert_eq!(1, storage.list_keys(&p2).await.unwrap().0.len());
395 assert_eq!(1, storage.list_keys(&p3).await.unwrap().0.len());
396 assert_eq!(0, storage.list_keys(&p4).await.unwrap().0.len());
397 assert_eq!(1, storage.list_keys(&p5).await.unwrap().0.len());
398 }
399
400 #[tokio::test]
401 async fn clock_at_least() {
402 let storage = setup_test_storage().await;
403 assert_eq!(1234, storage.clock(1234).await.unwrap());
404 }
405
406 #[tokio::test]
407 async fn clock_ge() {
408 let storage = setup_test_storage().await;
409 let c1 = storage.clock(1234).await.unwrap();
410 let c2 = storage.clock(0).await.unwrap();
411 assert_eq!(true, c2 > c1);
412 }
413}