1#[cfg(test)]
10mod tests;
11mod tree;
12
13use std::{borrow::Borrow, cmp::Ordering, ops::Bound, sync::Arc};
14
15use super::{Budgeted, MemoryBudget, MemoryError, MAX_HEIGHT};
16
17type Entry<K, V> = Arc<Budgeted<(K, V)>>;
18type SharedNode<K, V> = Arc<Budgeted<Node<K, V>>>;
19type Link<K, V> = Option<SharedNode<K, V>>;
20
21struct Node<K, V> {
22 entry: Entry<K, V>,
23 left: Link<K, V>,
24 right: Link<K, V>,
25 height: u8,
26}
27
28pub struct BudgetedSharedMap<K, V> {
30 root: Link<K, V>,
31 len: usize,
32 memory: MemoryBudget,
33}
34
35pub struct BudgetedSharedMapSnapshot<K, V> {
37 root: Link<K, V>,
38 len: usize,
39}
40
41impl<K, V> Clone for BudgetedSharedMapSnapshot<K, V> {
42 fn clone(&self) -> Self {
43 Self {
44 root: self.root.clone(),
45 len: self.len,
46 }
47 }
48}
49
50impl<K, V> BudgetedSharedMapSnapshot<K, V> {
51 pub fn len(&self) -> usize {
52 self.len
53 }
54
55 pub fn is_empty(&self) -> bool {
56 self.len == 0
57 }
58}
59
60impl<K: Ord, V> BudgetedSharedMapSnapshot<K, V> {
61 pub fn get<Q: Ord + ?Sized>(&self, key: &Q) -> Option<&V>
62 where
63 K: Borrow<Q>,
64 {
65 lookup(&self.root, key)
66 }
67}
68
69impl<K, V> Clone for BudgetedSharedMap<K, V> {
70 fn clone(&self) -> Self {
71 Self {
72 root: self.root.clone(),
73 len: self.len,
74 memory: self.memory.clone(),
75 }
76 }
77}
78
79impl<K, V> BudgetedSharedMap<K, V> {
80 pub fn new(memory: &MemoryBudget) -> Self {
81 Self {
82 root: None,
83 len: 0,
84 memory: memory.clone(),
85 }
86 }
87
88 pub fn len(&self) -> usize {
89 self.len
90 }
91
92 pub fn is_empty(&self) -> bool {
93 self.len == 0
94 }
95
96 pub fn budget(&self) -> &MemoryBudget {
97 &self.memory
98 }
99
100 pub fn snapshot(&self) -> BudgetedSharedMapSnapshot<K, V> {
102 BudgetedSharedMapSnapshot {
103 root: self.root.clone(),
104 len: self.len,
105 }
106 }
107
108 pub fn restore(&mut self, snapshot: &BudgetedSharedMapSnapshot<K, V>) {
110 if let Some(root) = &snapshot.root {
111 assert!(
112 self.memory.shares_allowance(root.budget()),
113 "different memory allowances"
114 );
115 }
116 self.root.clone_from(&snapshot.root);
117 self.len = snapshot.len;
118 }
119
120 pub fn iter(&self) -> BudgetedSharedMapIter<'_, K, V> {
121 let mut iter = BudgetedSharedMapIter::empty();
122 iter.push_left(self.root.as_ref().map(|node| &***node));
123 iter
124 }
125}
126
127impl<K: Ord, V> BudgetedSharedMap<K, V> {
128 pub fn last_before<Q: Ord + ?Sized>(&self, end: Bound<&Q>) -> Option<(&K, &V)>
130 where
131 K: Borrow<Q>,
132 {
133 let mut link = &self.root;
134 let mut found = None;
135 while let Some(node) = link {
136 let included = match end {
137 Bound::Unbounded => true,
138 Bound::Included(key) => node.entry.0.borrow() <= key,
139 Bound::Excluded(key) => node.entry.0.borrow() < key,
140 };
141 if included {
142 found = Some((&node.entry.0, &node.entry.1));
143 link = &node.right;
144 } else {
145 link = &node.left;
146 }
147 }
148 found
149 }
150
151 pub fn get<Q: Ord + ?Sized>(&self, key: &Q) -> Option<&V>
152 where
153 K: Borrow<Q>,
154 {
155 lookup(&self.root, key)
156 }
157
158 pub fn with_insert(&self, key: K, value: V) -> Result<Self, MemoryError> {
160 let mut candidate = self.clone();
161 candidate.try_insert(key, value)?;
162 Ok(candidate)
163 }
164
165 pub fn try_insert(&mut self, key: K, value: V) -> Result<(), MemoryError> {
167 let added = tree::insert(&mut self.root, key, value, &self.memory)?;
168 self.len += usize::from(added);
169 Ok(())
170 }
171
172 pub fn range_from<Q: Ord + ?Sized>(&self, start: Bound<&Q>) -> BudgetedSharedMapIter<'_, K, V>
174 where
175 K: Borrow<Q>,
176 {
177 let mut iter = BudgetedSharedMapIter::empty();
178 let mut link = &self.root;
179 while let Some(node) = link {
180 let included = match start {
181 Bound::Unbounded => true,
182 Bound::Included(key) => node.entry.0.borrow() >= key,
183 Bound::Excluded(key) => node.entry.0.borrow() > key,
184 };
185 if included {
186 iter.stack[iter.depth] = Some(node);
187 iter.depth += 1;
188 link = &node.left;
189 } else {
190 link = &node.right;
191 }
192 }
193 iter
194 }
195}
196
197fn lookup<'a, K: Borrow<Q>, V, Q: Ord + ?Sized>(
198 mut link: &'a Link<K, V>,
199 key: &Q,
200) -> Option<&'a V> {
201 while let Some(node) = link {
202 match key.cmp(node.entry.0.borrow()) {
203 Ordering::Less => link = &node.left,
204 Ordering::Greater => link = &node.right,
205 Ordering::Equal => return Some(&node.entry.1),
206 }
207 }
208 None
209}
210
211pub struct BudgetedSharedMapIter<'a, K, V> {
212 stack: [Option<&'a Node<K, V>>; MAX_HEIGHT],
213 depth: usize,
214}
215
216impl<'a, K, V> BudgetedSharedMapIter<'a, K, V> {
217 fn empty() -> Self {
218 Self {
219 stack: [None; MAX_HEIGHT],
220 depth: 0,
221 }
222 }
223
224 fn push_left(&mut self, mut node: Option<&'a Node<K, V>>) {
225 while let Some(current) = node {
226 self.stack[self.depth] = Some(current);
227 self.depth += 1;
228 node = current.left.as_ref().map(|node| &***node);
229 }
230 }
231}
232
233impl<'a, K, V> Iterator for BudgetedSharedMapIter<'a, K, V> {
234 type Item = (&'a K, &'a V);
235
236 fn next(&mut self) -> Option<Self::Item> {
237 self.depth = self.depth.checked_sub(1)?;
238 let node = self.stack[self.depth].take().expect("retained map node");
239 self.push_left(node.right.as_ref().map(|node| &***node));
240 Some((&node.entry.0, &node.entry.1))
241 }
242}
243
244impl<K, V> std::iter::FusedIterator for BudgetedSharedMapIter<'_, K, V> {}
245
246impl<'a, K, V> IntoIterator for &'a BudgetedSharedMap<K, V> {
247 type Item = (&'a K, &'a V);
248 type IntoIter = BudgetedSharedMapIter<'a, K, V>;
249
250 fn into_iter(self) -> Self::IntoIter {
251 self.iter()
252 }
253}