prune_lang/utils/
env_map.rs1use std::borrow::Borrow;
2use std::collections::{HashMap, hash_map};
3use std::fmt::Debug;
4use std::hash::Hash;
5
6#[derive(Clone, Debug, PartialEq)]
10enum EnvOpr<K, V> {
11 Update(K, V),
15 Insert(K),
19 Delete(K, V),
23 Nothing,
27}
28
29#[derive(Clone, Debug)]
31pub struct EnvMap<K, V> {
32 base_map: HashMap<K, V>,
34 history: Vec<EnvOpr<K, V>>,
36 scopes: Vec<usize>,
38}
39
40impl<K, V> Default for EnvMap<K, V>
42where
43 K: Eq + Hash + Clone,
44{
45 fn default() -> Self {
46 Self::new()
47 }
48}
49
50impl<K, V> EnvMap<K, V>
51where
52 K: Eq + Hash + Clone,
53{
54 pub fn new() -> EnvMap<K, V> {
56 EnvMap {
57 base_map: HashMap::new(),
58 history: Vec::new(),
59 scopes: Vec::new(),
60 }
61 }
62
63 pub fn with_capacity(capacity: usize) -> EnvMap<K, V> {
65 EnvMap {
66 base_map: HashMap::with_capacity(capacity),
67 history: Vec::new(),
68 scopes: Vec::new(),
69 }
70 }
71
72 pub fn capacity(&self) -> usize {
74 self.base_map.capacity()
75 }
76
77 pub fn keys(&self) -> hash_map::Keys<'_, K, V> {
79 self.base_map.keys()
80 }
81
82 pub fn values(&self) -> hash_map::Values<'_, K, V> {
84 self.base_map.values()
85 }
86
87 pub fn iter(&self) -> hash_map::Iter<'_, K, V> {
89 self.base_map.iter()
90 }
91
92 pub fn is_empty(&self) -> bool {
94 self.base_map.is_empty()
95 }
96
97 pub fn is_scope_empty(&self) -> bool {
99 self.scopes.is_empty()
100 }
101
102 pub fn clear(&mut self) {
105 self.base_map.clear();
106 self.history.clear();
107 self.scopes.clear();
108 }
109
110 pub fn get<Q>(&self, k: &Q) -> Option<&V>
112 where
113 K: Borrow<Q>,
114 Q: ?Sized + Hash + Eq,
115 {
116 self.base_map.get(k)
117 }
118
119 pub fn get_key_value<Q>(&self, k: &Q) -> Option<(&K, &V)>
121 where
122 K: Borrow<Q>,
123 Q: ?Sized + Hash + Eq,
124 {
125 self.base_map.get_key_value(k)
126 }
127
128 pub fn contains_key<Q>(&self, k: &Q) -> bool
130 where
131 K: Borrow<Q>,
132 Q: ?Sized + Hash + Eq,
133 {
134 self.base_map.contains_key(k)
135 }
136
137 pub fn insert(&mut self, k: K, v: V) -> bool {
139 if let Some(old) = self.base_map.insert(k.clone(), v) {
140 self.history.push(EnvOpr::Update(k, old));
141 true
142 } else {
143 self.history.push(EnvOpr::Insert(k));
144 false
145 }
146 }
147
148 pub fn remove(&mut self, k: &K) -> bool {
150 if let Some(old) = self.base_map.remove(k) {
151 self.history.push(EnvOpr::Delete(k.clone(), old));
152 true
153 } else {
154 self.history.push(EnvOpr::Nothing);
155 false
156 }
157 }
158
159 pub fn enter_scope(&mut self) {
161 self.scopes.push(self.history.len())
162 }
163
164 pub fn leave_scope(&mut self) {
166 let n = self.scopes.pop().unwrap();
167 for _ in n..self.history.len() {
168 match self.history.pop().unwrap() {
169 EnvOpr::Update(k, v) => {
170 let r = self.base_map.insert(k, v);
172 assert!(r.is_some());
173 }
174 EnvOpr::Insert(k) => {
175 let r = self.base_map.remove(&k);
177 assert!(r.is_some());
178 }
179 EnvOpr::Delete(k, v) => {
180 let r = self.base_map.insert(k, v);
182 assert!(r.is_none());
183 }
184 EnvOpr::Nothing => {
185 }
187 }
188 }
189 }
190}
191
192impl<K, V> std::ops::Index<&K> for EnvMap<K, V>
193where
194 K: Hash + Eq,
195{
196 type Output = V;
197
198 fn index(&self, index: &K) -> &Self::Output {
199 &self.base_map[index]
200 }
201}
202
203#[test]
204fn env_map_test() {
205 let mut env = EnvMap::new();
206 env.insert(&1, 'a');
207 env.enter_scope();
208 env.insert(&1, 'd');
209 env.insert(&2, 'b');
210 env.insert(&3, 'c');
211 assert_eq!(env.get(&1), Some(&'d'));
212 assert_eq!(env.get(&2), Some(&'b'));
213 assert_eq!(env.get(&3), Some(&'c'));
214 env.leave_scope();
215 assert_eq!(env.get(&1), Some(&'a'));
216 assert_eq!(env.get(&2), None);
217 assert_eq!(env.get(&3), None);
218}