actix_storage_hashmap/
basic.rs1use std::collections::HashMap;
2use std::sync::{Arc, RwLock};
3
4use actix_storage::{dev::Store, Result, StorageError};
5use thiserror::Error;
6
7#[derive(Debug, Error)]
8#[error("A proccess obtaining the lock has failed while keeping it.")]
9pub struct PoisionLockStorageError;
10
11type ScopeMap = HashMap<Arc<[u8]>, Arc<[u8]>>;
12type InternalMap = HashMap<Arc<[u8]>, ScopeMap>;
13
14#[derive(Debug, Default)]
36pub struct HashMapStore {
37 map: RwLock<InternalMap>,
38}
39
40impl HashMapStore {
41 pub fn new() -> Self {
43 Self::default()
44 }
45
46 pub fn with_capacity(capacity: usize) -> Self {
48 Self {
49 map: RwLock::new(HashMap::with_capacity(capacity)),
50 }
51 }
52
53 pub fn from_hashmap(map: InternalMap) -> Self {
55 Self {
56 map: RwLock::new(map),
57 }
58 }
59}
60
61#[async_trait::async_trait]
62impl Store for HashMapStore {
63 async fn set(&self, scope: Arc<[u8]>, key: Arc<[u8]>, value: Arc<[u8]>) -> Result<()> {
64 match self.map.write() {
65 Ok(mut h) => {
66 h.entry(scope).or_default().insert(key, value);
67 Ok(())
68 }
69 Err(_) => Err(StorageError::custom(PoisionLockStorageError)),
70 }
71 }
72
73 async fn get(&self, scope: Arc<[u8]>, key: Arc<[u8]>) -> Result<Option<Arc<[u8]>>> {
74 match self.map.read() {
75 Ok(h) => Ok(h
76 .get(&scope)
77 .and_then(|scope_map| scope_map.get(&key))
78 .cloned()),
79 Err(_) => Err(StorageError::custom(PoisionLockStorageError)),
80 }
81 }
82
83 async fn delete(&self, scope: Arc<[u8]>, key: Arc<[u8]>) -> Result<()> {
84 match self.map.write() {
85 Ok(mut h) => {
86 h.get_mut(&scope)
87 .and_then(|scope_map| scope_map.remove(&key));
88 Ok(())
89 }
90 Err(_) => Err(StorageError::custom(PoisionLockStorageError)),
91 }
92 }
93
94 async fn contains_key(&self, scope: Arc<[u8]>, key: Arc<[u8]>) -> Result<bool> {
95 match self.map.read() {
96 Ok(h) => Ok(h
97 .get(&scope)
98 .map(|scope_map| scope_map.contains_key(&key))
99 .unwrap_or(false)),
100 Err(_) => Err(StorageError::custom(PoisionLockStorageError)),
101 }
102 }
103}
104
105#[cfg(test)]
106mod test {
107 use super::*;
108 use actix_storage::tests::*;
109
110 #[test]
111 fn test_hashmap_basic_store() {
112 test_store(Box::pin(async { HashMapStore::default() }));
113 }
114
115 #[test]
116 fn test_hashmap_basic_formats() {
117 impl Clone for HashMapStore {
118 fn clone(&self) -> Self {
119 Self::default()
120 }
121 }
122 test_all_formats(Box::pin(async { HashMapStore::default() }));
123 }
124}