jscpd_rs/detector/
store.rs1use 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}