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