1use crate::{normalize_key, normalize_prefix, BlobStore, BoxFuture, PutOpts, StorageError};
4use bytes::Bytes;
5use std::collections::HashMap;
6use std::sync::{Arc, Mutex};
7
8#[derive(Clone, Default)]
9pub struct MemoryStore {
10 inner: Arc<Mutex<HashMap<String, Bytes>>>,
11}
12
13impl MemoryStore {
14 pub fn new() -> Self {
15 Self::default()
16 }
17}
18
19impl BlobStore for MemoryStore {
20 fn put<'a>(
21 &'a self,
22 key: &'a str,
23 data: Bytes,
24 _opts: PutOpts,
25 ) -> BoxFuture<'a, Result<(), StorageError>> {
26 Box::pin(async move {
27 let key = normalize_key(key)?;
28 self.inner.lock().unwrap().insert(key, data);
29 Ok(())
30 })
31 }
32
33 fn get<'a>(&'a self, key: &'a str) -> BoxFuture<'a, Result<Option<Bytes>, StorageError>> {
34 Box::pin(async move {
35 let key = normalize_key(key)?;
36 Ok(self.inner.lock().unwrap().get(&key).cloned())
37 })
38 }
39
40 fn delete<'a>(&'a self, key: &'a str) -> BoxFuture<'a, Result<(), StorageError>> {
41 Box::pin(async move {
42 let key = normalize_key(key)?;
43 self.inner.lock().unwrap().remove(&key);
44 Ok(())
45 })
46 }
47
48 fn exists<'a>(&'a self, key: &'a str) -> BoxFuture<'a, Result<bool, StorageError>> {
49 Box::pin(async move {
50 let key = normalize_key(key)?;
51 Ok(self.inner.lock().unwrap().contains_key(&key))
52 })
53 }
54
55 fn list<'a>(&'a self, prefix: &'a str) -> BoxFuture<'a, Result<Vec<String>, StorageError>> {
56 Box::pin(async move {
57 let prefix = normalize_prefix(prefix)?;
58 let map = self.inner.lock().unwrap();
59 let mut keys: Vec<String> = map
60 .keys()
61 .filter(|k| {
62 if prefix.is_empty() {
63 true
64 } else if prefix.ends_with('/') {
65 k.starts_with(&prefix)
66 } else {
67 *k == &prefix || k.starts_with(&format!("{prefix}/"))
68 }
69 })
70 .cloned()
71 .collect();
72 keys.sort();
73 Ok(keys)
74 })
75 }
76}