oxihuman_core/
persistent_hash_map.rs1#![allow(dead_code)]
4
5use std::collections::HashMap;
10use std::hash::Hash;
11
12pub type PmapVersion = usize;
14
15pub struct PersistentHashMap<K, V> {
17 versions: Vec<HashMap<K, V>>,
18}
19
20impl<K, V> PersistentHashMap<K, V>
21where
22 K: Eq + Hash + Clone,
23 V: Clone,
24{
25 pub fn new() -> Self {
27 Self {
28 versions: vec![HashMap::new()],
29 }
30 }
31
32 pub fn current_version(&self) -> PmapVersion {
34 self.versions.len() - 1
35 }
36
37 pub fn insert(&mut self, key: K, value: V) -> PmapVersion {
39 let mut next = self.versions.last().cloned().unwrap_or_default();
40 next.insert(key, value);
41 self.versions.push(next);
42 self.current_version()
43 }
44
45 pub fn remove(&mut self, key: &K) -> PmapVersion {
47 let mut next = self.versions.last().cloned().unwrap_or_default();
48 next.remove(key);
49 self.versions.push(next);
50 self.current_version()
51 }
52
53 pub fn get_at(&self, version: PmapVersion, key: &K) -> Option<&V> {
55 self.versions.get(version)?.get(key)
56 }
57
58 pub fn get(&self, key: &K) -> Option<&V> {
60 self.get_at(self.current_version(), key)
61 }
62
63 pub fn len(&self) -> usize {
65 self.versions.last().map(|m| m.len()).unwrap_or(0)
66 }
67
68 pub fn is_empty(&self) -> bool {
70 self.len() == 0
71 }
72
73 pub fn version_count(&self) -> usize {
75 self.versions.len()
76 }
77}
78
79impl<K, V> Default for PersistentHashMap<K, V>
80where
81 K: Eq + Hash + Clone,
82 V: Clone,
83{
84 fn default() -> Self {
85 Self::new()
86 }
87}
88
89pub fn new_persistent_hash_map<K, V>() -> PersistentHashMap<K, V>
91where
92 K: Eq + Hash + Clone,
93 V: Clone,
94{
95 PersistentHashMap::new()
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
103 fn test_insert_and_get() {
104 let mut m: PersistentHashMap<&str, i32> = PersistentHashMap::new();
105 m.insert("a", 1);
106 assert_eq!(m.get(&"a"), Some(&1)); }
108
109 #[test]
110 fn test_old_version_preserved() {
111 let mut m: PersistentHashMap<&str, i32> = PersistentHashMap::new();
112 m.insert("a", 1);
113 let v1 = m.insert("b", 2);
114 assert_eq!(m.get_at(1, &"a"), Some(&1));
116 assert_eq!(m.get_at(1, &"b"), None);
117 assert_eq!(m.get_at(v1, &"b"), Some(&2));
119 }
120
121 #[test]
122 fn test_remove_creates_version() {
123 let mut m: PersistentHashMap<&str, i32> = PersistentHashMap::new();
124 let v0 = m.insert("x", 10);
125 let v1 = m.remove(&"x");
126 assert!(m.get_at(v1, &"x").is_none()); assert!(m.get_at(v0, &"x").is_some()); }
129
130 #[test]
131 fn test_len() {
132 let mut m: PersistentHashMap<i32, i32> = PersistentHashMap::new();
133 m.insert(1, 1);
134 m.insert(2, 2);
135 assert_eq!(m.len(), 2); }
137
138 #[test]
139 fn test_is_empty_initially() {
140 let m: PersistentHashMap<i32, i32> = PersistentHashMap::new();
141 assert!(m.is_empty()); }
143
144 #[test]
145 fn test_version_count() {
146 let mut m: PersistentHashMap<i32, i32> = PersistentHashMap::new();
147 m.insert(1, 1);
148 m.insert(2, 2);
149 assert_eq!(m.version_count(), 3); }
151
152 #[test]
153 fn test_current_version() {
154 let mut m: PersistentHashMap<i32, i32> = PersistentHashMap::new();
155 assert_eq!(m.current_version(), 0);
156 m.insert(1, 1);
157 assert_eq!(m.current_version(), 1);
158 }
159
160 #[test]
161 fn test_default() {
162 let m: PersistentHashMap<i32, i32> = PersistentHashMap::default();
163 assert!(m.is_empty()); }
165
166 #[test]
167 fn test_new_helper() {
168 let m = new_persistent_hash_map::<i32, i32>();
169 assert!(m.is_empty()); }
171
172 #[test]
173 fn test_overwrite_key() {
174 let mut m: PersistentHashMap<&str, i32> = PersistentHashMap::new();
175 m.insert("k", 1);
176 m.insert("k", 2);
177 assert_eq!(m.get(&"k"), Some(&2)); }
179}