Skip to main content

jscpd_rs/detector/
store.rs

1use std::{collections::HashMap, error::Error, fmt};
2
3#[derive(Clone, Debug, Eq, PartialEq)]
4pub struct MemoryStoreError {
5    namespace: String,
6    key: String,
7}
8
9impl MemoryStoreError {
10    pub fn new(namespace: impl Into<String>, key: impl Into<String>) -> Self {
11        Self {
12            namespace: namespace.into(),
13            key: key.into(),
14        }
15    }
16
17    pub fn namespace(&self) -> &str {
18        &self.namespace
19    }
20
21    pub fn key(&self) -> &str {
22        &self.key
23    }
24}
25
26impl fmt::Display for MemoryStoreError {
27    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
28        write!(
29            formatter,
30            "key '{}' not found in namespace '{}'",
31            self.key, self.namespace
32        )
33    }
34}
35
36impl Error for MemoryStoreError {}
37
38#[derive(Clone, Debug)]
39pub struct MemoryStore<T> {
40    namespace: String,
41    values: HashMap<String, HashMap<String, T>>,
42}
43
44impl<T> Default for MemoryStore<T> {
45    fn default() -> Self {
46        Self::new()
47    }
48}
49
50impl<T> MemoryStore<T> {
51    pub fn new() -> Self {
52        Self {
53            namespace: String::new(),
54            values: HashMap::new(),
55        }
56    }
57
58    pub fn namespace(&mut self, namespace: impl Into<String>) {
59        self.namespace = namespace.into();
60        self.values.entry(self.namespace.clone()).or_default();
61    }
62
63    pub fn current_namespace(&self) -> &str {
64        &self.namespace
65    }
66
67    pub fn get(&self, key: impl AsRef<str>) -> Result<&T, MemoryStoreError> {
68        let key = key.as_ref();
69        self.values
70            .get(&self.namespace)
71            .and_then(|namespace| namespace.get(key))
72            .ok_or_else(|| MemoryStoreError::new(self.namespace.clone(), key))
73    }
74
75    pub fn set(&mut self, key: impl Into<String>, value: T) -> &T {
76        let key = key.into();
77        self.values
78            .entry(self.namespace.clone())
79            .or_default()
80            .entry(key)
81            .insert_entry(value)
82            .into_mut()
83    }
84
85    pub fn close(&mut self) {
86        self.values.clear();
87    }
88
89    pub fn is_empty(&self) -> bool {
90        self.values.values().all(HashMap::is_empty)
91    }
92
93    pub fn len(&self) -> usize {
94        self.values.values().map(HashMap::len).sum()
95    }
96}