Skip to main content

terminals_core/primitives/
registry.rs

1use std::collections::{HashMap, VecDeque};
2use std::hash::Hash;
3
4pub struct BasicRegistry<K, V> {
5    map: HashMap<K, V>,
6}
7
8impl<K: Hash + Eq, V> Default for BasicRegistry<K, V> {
9    fn default() -> Self {
10        Self {
11            map: HashMap::new(),
12        }
13    }
14}
15
16impl<K: Hash + Eq, V> BasicRegistry<K, V> {
17    pub fn new() -> Self {
18        Self::default()
19    }
20    pub fn get(&self, key: &K) -> Option<&V> {
21        self.map.get(key)
22    }
23    pub fn insert(&mut self, key: K, value: V) -> Option<V> {
24        self.map.insert(key, value)
25    }
26    pub fn remove(&mut self, key: &K) -> Option<V> {
27        self.map.remove(key)
28    }
29    pub fn len(&self) -> usize {
30        self.map.len()
31    }
32    pub fn is_empty(&self) -> bool {
33        self.map.is_empty()
34    }
35    pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
36        self.map.iter()
37    }
38}
39
40pub struct LruRegistry<K, V> {
41    map: HashMap<K, V>,
42    order: VecDeque<K>,
43    capacity: usize,
44}
45
46impl<K: Hash + Eq + Clone, V> LruRegistry<K, V> {
47    pub fn new(capacity: usize) -> Self {
48        Self {
49            map: HashMap::with_capacity(capacity),
50            order: VecDeque::with_capacity(capacity),
51            capacity,
52        }
53    }
54
55    pub fn get(&mut self, key: &K) -> Option<&V> {
56        if self.map.contains_key(key) {
57            self.order.retain(|k| k != key);
58            self.order.push_back(key.clone());
59            self.map.get(key)
60        } else {
61            None
62        }
63    }
64
65    pub fn insert(&mut self, key: K, value: V) -> Option<V> {
66        if self.map.contains_key(&key) {
67            self.order.retain(|k| k != &key);
68        } else if self.map.len() >= self.capacity {
69            if let Some(evicted) = self.order.pop_front() {
70                self.map.remove(&evicted);
71            }
72        }
73        self.order.push_back(key.clone());
74        self.map.insert(key, value)
75    }
76
77    pub fn remove(&mut self, key: &K) -> Option<V> {
78        self.order.retain(|k| k != key);
79        self.map.remove(key)
80    }
81
82    pub fn len(&self) -> usize {
83        self.map.len()
84    }
85    pub fn is_empty(&self) -> bool {
86        self.map.is_empty()
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93
94    #[test]
95    fn test_basic_registry() {
96        let mut reg = BasicRegistry::new();
97        reg.insert("key1", 42);
98        assert_eq!(reg.get(&"key1"), Some(&42));
99        assert_eq!(reg.len(), 1);
100    }
101
102    #[test]
103    fn test_lru_registry_eviction() {
104        let mut reg = LruRegistry::new(2);
105        reg.insert("a", 1);
106        reg.insert("b", 2);
107        reg.insert("c", 3); // should evict "a"
108        assert_eq!(reg.get(&"a"), None);
109        assert_eq!(reg.get(&"c"), Some(&3));
110    }
111
112    #[test]
113    fn test_lru_access_refreshes() {
114        let mut reg = LruRegistry::new(2);
115        reg.insert("a", 1);
116        reg.insert("b", 2);
117        reg.get(&"a"); // refresh "a"
118        reg.insert("c", 3); // should evict "b" (LRU), not "a"
119        assert_eq!(reg.get(&"a"), Some(&1));
120        assert_eq!(reg.get(&"b"), None);
121    }
122
123    #[test]
124    fn test_registry_remove() {
125        let mut reg = BasicRegistry::new();
126        reg.insert("key", 42);
127        assert_eq!(reg.remove(&"key"), Some(42));
128        assert_eq!(reg.get(&"key"), None);
129    }
130}