1use crate::NamespaceError;
6use cm_types::{BorrowedName, IterablePath, Name, NamespacePath};
7use std::collections::BTreeMap;
8
9#[derive(Debug)]
14pub struct Tree<T> {
15 root: Node<T>,
16}
17
18impl<T> Tree<T> {
19 pub fn new() -> Self {
20 Tree { root: Node::Internal(BTreeMap::new()) }
21 }
22
23 pub fn add(self: &mut Self, path: &NamespacePath, thing: T) -> Result<&mut T, NamespaceError> {
24 let names = path.split();
25 self.root.add(names.into_iter(), thing).map_err(|e| match e {
26 AddError::Shadow => NamespaceError::Shadow(path.clone()),
27 AddError::Duplicate => NamespaceError::Duplicate(path.clone()),
28 })
29 }
30
31 pub fn get_mut(&mut self, path: &NamespacePath) -> Option<&mut T> {
32 self.root.get_mut(path.iter_segments())
33 }
34
35 pub fn get(&self, path: &NamespacePath) -> Option<&T> {
36 self.root.get(path.iter_segments())
37 }
38
39 pub fn remove(&mut self, path: &NamespacePath) -> Option<T> {
40 self.root.remove(path.iter_segments().peekable())
41 }
42
43 pub fn flatten(self) -> Vec<(NamespacePath, T)> {
44 self.root
45 .flatten()
46 .into_iter()
47 .map(|(path, thing)| (NamespacePath::new(path).unwrap(), thing))
48 .collect()
49 }
50
51 pub fn map_ref<R>(&self, mut f: impl FnMut(&T) -> R) -> Tree<R> {
52 Tree { root: self.root.map_ref(&mut f) }
53 }
54}
55
56impl<T> Default for Tree<T> {
57 fn default() -> Self {
58 Self::new()
59 }
60}
61
62impl<T: Clone> Clone for Tree<T> {
63 fn clone(&self) -> Self {
64 Self { root: self.root.map_ref(&mut <T as Clone>::clone) }
65 }
66}
67
68#[derive(Debug)]
69enum Node<T> {
70 Internal(BTreeMap<Name, Node<T>>),
71 Leaf(T),
72}
73
74enum AddError {
75 Shadow,
76 Duplicate,
77}
78
79impl<T> Node<T> {
80 fn add(
81 &mut self,
82 mut path: std::vec::IntoIter<&BorrowedName>,
83 thing: T,
84 ) -> Result<&mut T, AddError> {
85 match path.next() {
86 Some(name) => match self {
87 Node::Leaf(_) => Err(AddError::Shadow),
88 Node::Internal(children) => {
89 let entry = children
90 .entry(name.into())
91 .or_insert_with(|| Node::Internal(BTreeMap::new()));
92 entry.add(path, thing)
93 }
94 },
95 None => {
96 match self {
97 Node::Internal(children) => {
98 if !children.is_empty() {
99 return Err(AddError::Shadow);
100 }
101 }
102 Node::Leaf(_) => {
103 return Err(AddError::Duplicate);
104 }
105 }
106 *self = Node::Leaf(thing);
107 match self {
108 Node::Internal(_) => unreachable!(),
109 Node::Leaf(ref mut t) => Ok(t),
110 }
111 }
112 }
113 }
114
115 fn get_mut<'a, 'b, I>(&'a mut self, mut path: I) -> Option<&'a mut T>
116 where
117 I: Iterator<Item = &'b BorrowedName>,
118 {
119 match path.next() {
120 Some(name) => match self {
121 Node::Leaf(_) => None,
122 Node::Internal(children) => match children.get_mut(name) {
123 Some(node) => node.get_mut(path),
124 None => None,
125 },
126 },
127 None => match self {
128 Node::Internal(_) => None,
129 Node::Leaf(ref mut n) => Some(n),
130 },
131 }
132 }
133
134 fn get<'a, 'b, I>(&'a self, mut path: I) -> Option<&'a T>
135 where
136 I: Iterator<Item = &'b BorrowedName>,
137 {
138 match path.next() {
139 Some(name) => match self {
140 Node::Leaf(_) => None,
141 Node::Internal(children) => match children.get(name) {
142 Some(node) => node.get(path),
143 None => None,
144 },
145 },
146 None => match self {
147 Node::Internal(_) => None,
148 Node::Leaf(ref n) => Some(n),
149 },
150 }
151 }
152
153 fn remove<'a, I>(&mut self, mut path: std::iter::Peekable<I>) -> Option<T>
154 where
155 I: Iterator<Item = &'a BorrowedName>,
156 {
157 match path.next() {
158 Some(name) => match self {
159 Node::Leaf(_) => None,
160 Node::Internal(children) => {
161 if path.peek().is_none() {
162 match children.remove(name) {
163 Some(Node::Leaf(n)) => Some(n),
164 Some(Node::Internal(c)) => {
165 children.insert(name.into(), Node::Internal(c));
166 return None;
167 }
168 None => None,
169 }
170 } else {
171 match children.get_mut(name) {
172 Some(node) => node.remove(path),
173 None => None,
174 }
175 }
176 }
177 },
178 None => None,
179 }
180 }
181
182 pub fn flatten(self) -> Vec<(String, T)> {
183 fn recurse<T>(path: &str, node: Node<T>, result: &mut Vec<(String, T)>) {
184 match node {
185 Node::Internal(map) => {
186 for (key, value) in map {
187 let path = format!("{}/{}", path, key);
188 recurse(&path, value, result);
189 }
190 }
191 Node::Leaf(leaf) => {
192 let path = if path.is_empty() { "/" } else { path };
197 result.push((path.to_string(), leaf));
198 }
199 }
200 }
201
202 let mut result = Vec::new();
203 recurse("", self, &mut result);
204 result
205 }
206
207 pub fn map_ref<R>(&self, f: &mut impl FnMut(&T) -> R) -> Node<R> {
208 match self {
209 Node::Internal(map) => Node::Internal(BTreeMap::from_iter(
210 map.iter().map(|(k, v)| (k.clone(), v.map_ref(f))),
211 )),
212 Node::Leaf(t) => Node::Leaf(f(t)),
213 }
214 }
215}
216
217#[cfg(test)]
218mod tests {
219 use super::*;
220 use assert_matches::assert_matches;
221
222 fn ns_path(str: &str) -> NamespacePath {
223 str.parse().unwrap()
224 }
225
226 #[test]
227 fn test_add() {
228 let mut tree = Tree::new();
229 tree.add(&ns_path("/foo"), 1).unwrap();
230 tree.add(&ns_path("/bar"), 2).unwrap();
231 tree.add(&ns_path("/x/y/z"), 3).unwrap();
232 tree.add(&ns_path("/x/x/z"), 4).unwrap();
233 tree.add(&ns_path("/x/y/w"), 5).unwrap();
234 assert_matches!(tree.add(&ns_path("/foo"), 6), Err(NamespaceError::Duplicate(_)));
235 assert_matches!(tree.add(&ns_path("/bar"), 7), Err(NamespaceError::Duplicate(_)));
236
237 tree.add(&ns_path("/a/b/c"), 0).unwrap();
238 assert_matches!(tree.add(&ns_path("/"), 0), Err(NamespaceError::Shadow(_)));
239 assert_matches!(tree.add(&ns_path("/a"), 0), Err(NamespaceError::Shadow(_)));
240 assert_matches!(tree.add(&ns_path("/a/b"), 0), Err(NamespaceError::Shadow(_)));
241 assert_matches!(tree.add(&ns_path("/a/b/c"), 0), Err(NamespaceError::Duplicate(_)));
242 assert_matches!(tree.add(&ns_path("/a/b/c/d"), 0), Err(NamespaceError::Shadow(_)));
243 assert_matches!(tree.add(&ns_path("/a/b/c/d/e"), 0), Err(NamespaceError::Shadow(_)));
244 }
245
246 #[test]
247 fn test_root() {
248 let mut tree = Tree::new();
249 tree.add(&ns_path("/"), 1).unwrap();
250 assert_matches!(
251 tree.add(&ns_path("/"), 2),
252 Err(NamespaceError::Duplicate(path)) if path.to_string() == "/"
253 );
254 assert_matches!(
255 tree.add(&ns_path("/a"), 3),
256 Err(NamespaceError::Shadow(path)) if path.to_string() == "/a"
257 );
258 }
259
260 #[test]
261 fn test_get_mut() {
262 let mut tree = Tree::new();
263 tree.add(&ns_path("/foo"), 1).unwrap();
264 assert_eq!(*tree.get_mut(&ns_path("/foo")).unwrap(), 1);
265 *tree.get_mut(&ns_path("/foo")).unwrap() = 2;
266 assert_eq!(*tree.get_mut(&ns_path("/foo")).unwrap(), 2);
267 assert_matches!(tree.get_mut(&ns_path("/bar")), None);
268
269 tree.add(&ns_path("/a/b"), 1).unwrap();
270 assert_matches!(tree.get_mut(&ns_path("/a")), None);
271 assert_matches!(tree.get_mut(&ns_path("/a/b/c")), None);
272 assert_eq!(*tree.get_mut(&ns_path("/a/b")).unwrap(), 1);
273 *tree.get_mut(&ns_path("/a/b")).unwrap() = 2;
274 assert_eq!(*tree.get_mut(&ns_path("/a/b")).unwrap(), 2);
275 }
276
277 #[test]
278 fn test_get() {
279 let mut tree = Tree::new();
280 assert_eq!(tree.get(&ns_path("/foo")), None);
281 tree.add(&ns_path("/foo"), 1).unwrap();
282 assert_eq!(*tree.get(&ns_path("/foo")).unwrap(), 1);
283
284 tree.add(&ns_path("/a/b"), 1).unwrap();
285 assert_matches!(tree.get_mut(&ns_path("/a")), None);
286 assert_eq!(*tree.get(&ns_path("/a/b")).unwrap(), 1);
287 assert_matches!(tree.get_mut(&ns_path("/a/b/c")), None);
288 }
289
290 #[test]
291 fn test_remove() {
292 let mut tree = Tree::new();
293 assert_matches!(tree.remove(&ns_path("/foo")), None);
294 tree.add(&ns_path("/foo"), 1).unwrap();
295 assert_matches!(tree.remove(&ns_path("/foo")), Some(1));
296 assert_matches!(tree.remove(&ns_path("/foo")), None);
297
298 tree.add(&ns_path("/foo/bar"), 1).unwrap();
299 assert_matches!(tree.remove(&ns_path("/foo")), None);
300 assert_matches!(tree.remove(&ns_path("/foo/bar/baz")), None);
301 assert_matches!(tree.remove(&ns_path("/foo/bar")), Some(1));
302 assert_matches!(tree.remove(&ns_path("/foo/bar")), None);
303 }
304
305 #[test]
306 fn test_flatten() {
307 let mut tree = Tree::new();
308 tree.add(&ns_path("/a/b/c"), 1).unwrap();
309 tree.add(&ns_path("/b/c/d/e"), 2).unwrap();
310 tree.add(&ns_path("/b/c/e/f"), 3).unwrap();
311 let mut entries = tree.flatten();
312 entries.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());
313 assert_eq!(entries.len(), 3);
314 assert_eq!(entries[0].0.to_string(), "/a/b/c");
315 assert_eq!(entries[0].1, 1);
316 assert_eq!(entries[1].0.to_string(), "/b/c/d/e");
317 assert_eq!(entries[1].1, 2);
318 assert_eq!(entries[2].0.to_string(), "/b/c/e/f");
319 assert_eq!(entries[2].1, 3);
320 }
321
322 #[test]
323 fn test_flatten_root() {
324 let mut tree = Tree::new();
325 tree.add(&ns_path("/"), 1).unwrap();
326 let entries = tree.flatten();
327 assert_eq!(entries.len(), 1);
328 assert_eq!(entries[0].0.to_string(), "/");
329 assert_eq!(entries[0].1, 1);
330 }
331
332 #[test]
333 fn test_clone() {
334 let mut tree = Tree::new();
335 tree.add(&ns_path("/foo"), 1).unwrap();
336 tree.add(&ns_path("/bar/baz"), 2).unwrap();
337
338 let tree_clone = tree.clone();
339
340 let mut entries = tree.flatten();
341 entries.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());
342
343 let mut entries_clone = tree_clone.flatten();
344 entries_clone.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());
345
346 assert_eq!(entries, entries_clone);
347 }
348}