1use std::collections::BTreeMap;
2use std::io::{self, Write};
3
4#[derive(Default, Debug, PartialEq, Clone)]
5pub struct Tree(pub BTreeMap<String, Box<Tree>>);
6
7impl Drop for Tree {
13 fn drop(&mut self) {
14 let mut pending = vec![std::mem::take(&mut self.0)];
15 while let Some(map) = pending.pop() {
16 for (_, mut child) in map {
17 pending.push(std::mem::take(&mut child.0));
18 }
19 }
20 }
21}
22
23pub fn insert_path(tree: &mut BTreeMap<String, Box<Tree>>, parts: &[&str]) {
36 if let Some((key, rest)) = parts.split_first() {
37 let subtree = tree
38 .entry((*key).to_string())
39 .or_insert_with(|| Box::new(Tree::default()));
40 if !rest.is_empty() {
41 insert_path(&mut subtree.0, rest);
42 }
43 }
44}
45
46pub fn insert_path_iterative(tree: &mut BTreeMap<String, Box<Tree>>, parts: &[&str]) {
62 let mut current_tree = tree;
63
64 for key in parts {
65 let subtree = current_tree
66 .entry((*key).to_string())
67 .or_insert_with(|| Box::new(Tree::default()));
68 current_tree = &mut subtree.0;
69 }
70}
71
72pub fn insert_path_iterative_with_stack(tree: &mut BTreeMap<String, Box<Tree>>, parts: &[&str]) {
81 let mut stack = vec![parts];
83 let mut tree_stack: Vec<*mut BTreeMap<String, Box<Tree>>> = vec![tree];
84
85 while let Some(current_parts) = stack.pop() {
86 if let Some(current_tree_ptr) = tree_stack.pop() {
87 if let Some((key, rest)) = current_parts.split_first() {
88 let subtree = unsafe {
89 (*current_tree_ptr)
90 .entry((*key).to_string())
91 .or_insert_with(|| Box::new(Tree::default()))
92 };
93
94 if !rest.is_empty() {
95 tree_stack.push(&mut subtree.0);
97 stack.push(rest);
98 }
99 }
100 }
101 }
102}
103
104pub fn write_tree<W: Write>(out: &mut W, tree: &BTreeMap<String, Box<Tree>>, depth: usize) -> io::Result<()> {
114 for (key, subtree) in tree {
115 writeln!(out, "{}{}", " ".repeat(depth), key)?;
116 write_tree(out, &subtree.0, depth + 1)?;
117 }
118 Ok(())
119}
120
121pub fn write_tree_iterative<W: Write>(
131 out: &mut W,
132 tree: &BTreeMap<String, Box<Tree>>,
133 initial_depth: usize,
134) -> io::Result<()> {
135 let mut stack = vec![(tree.iter(), initial_depth)];
136 loop {
137 let next = match stack.last_mut() {
138 Some((children, depth)) => children.next().map(|(key, subtree)| (key, subtree, *depth)),
139 None => break,
140 };
141 match next {
142 Some((key, subtree, depth)) => {
143 writeln!(out, "{}{}", " ".repeat(depth), key)?;
144 stack.push((subtree.0.iter(), depth + 1));
145 }
146 None => {
147 stack.pop();
148 }
149 }
150 }
151 Ok(())
152}
153
154pub fn write_tree_safe<W: Write>(
166 out: &mut W,
167 tree: &BTreeMap<String, Box<Tree>>,
168 depth: usize,
169 max_depth: usize,
170) -> io::Result<()> {
171 if depth > max_depth {
172 return Err(io::Error::new(
173 io::ErrorKind::InvalidInput,
174 format!("Maximum tree depth {} exceeded (current depth: {})", max_depth, depth),
175 ));
176 }
177 for (key, subtree) in tree {
178 writeln!(out, "{}{}", " ".repeat(depth), key)?;
179 write_tree_safe(out, &subtree.0, depth + 1, max_depth)?;
180 }
181 Ok(())
182}
183
184pub fn print_tree(tree: &BTreeMap<String, Box<Tree>>, depth: usize) {
190 write_tree(&mut io::stdout().lock(), tree, depth).expect("failed printing to stdout");
191}
192
193pub fn print_tree_iterative(tree: &BTreeMap<String, Box<Tree>>, initial_depth: usize) {
201 write_tree_iterative(&mut io::stdout().lock(), tree, initial_depth).expect("failed printing to stdout");
202}
203
204pub fn print_tree_safe(
229 tree: &BTreeMap<String, Box<Tree>>,
230 depth: usize,
231 max_depth: usize,
232) -> Result<(), String> {
233 write_tree_safe(&mut io::stdout().lock(), tree, depth, max_depth).map_err(|e| e.to_string())
234}
235
236#[cfg(test)]
237mod tests {
238 use super::*;
239
240 #[test]
241 fn test_insert_single_path() {
242 let mut tree = Tree::default();
243 insert_path(&mut tree.0, &["a", "b", "c"]);
244
245 assert!(tree.0.contains_key("a"));
246 assert!(tree.0["a"].0.contains_key("b"));
247 assert!(tree.0["a"].0["b"].0.contains_key("c"));
248 assert!(tree.0["a"].0["b"].0["c"].0.is_empty());
249 }
250
251 #[test]
252 fn test_insert_multiple_paths() {
253 let mut tree = Tree::default();
254 insert_path(&mut tree.0, &["a", "b", "c"]);
255 insert_path(&mut tree.0, &["a", "b", "d"]);
256 insert_path(&mut tree.0, &["a", "e"]);
257
258 assert!(tree.0.contains_key("a"));
259 let a_subtree = &tree.0["a"].0;
260
261 assert!(a_subtree.contains_key("b"));
262 assert!(a_subtree.contains_key("e"));
263
264 let b_subtree = &a_subtree["b"].0;
265 assert!(b_subtree.contains_key("c"));
266 assert!(b_subtree.contains_key("d"));
267 }
268
269 #[test]
270 fn test_insert_single_element() {
271 let mut tree = Tree::default();
272 insert_path(&mut tree.0, &["single"]);
273
274 assert!(tree.0.contains_key("single"));
275 assert!(tree.0["single"].0.is_empty());
276 }
277
278 #[test]
279 fn test_insert_empty_parts() {
280 let mut tree = Tree::default();
281 let original = tree.clone();
282 insert_path(&mut tree.0, &[]);
283
284 assert_eq!(tree, original);
285 }
286
287 #[test]
288 fn test_tree_structure_is_sorted() {
289 let mut tree = Tree::default();
290 insert_path(&mut tree.0, &["z"]);
291 insert_path(&mut tree.0, &["a"]);
292 insert_path(&mut tree.0, &["m"]);
293
294 let keys: Vec<_> = tree.0.keys().collect();
295 assert_eq!(keys, vec![&"a".to_string(), &"m".to_string(), &"z".to_string()]);
296 }
297
298 #[test]
299 fn test_complex_tree_structure() {
300 let mut tree = Tree::default();
301 insert_path(&mut tree.0, &["config", "database", "host"]);
302 insert_path(&mut tree.0, &["config", "database", "port"]);
303 insert_path(&mut tree.0, &["config", "app", "name"]);
304 insert_path(&mut tree.0, &["logs", "error"]);
305
306 assert_eq!(tree.0.len(), 2);
307 assert!(tree.0.contains_key("config"));
308 assert!(tree.0.contains_key("logs"));
309
310 let config = &tree.0["config"].0;
311 assert_eq!(config.len(), 2);
312 assert!(config.contains_key("database"));
313 assert!(config.contains_key("app"));
314
315 let database = &config["database"].0;
316 assert_eq!(database.len(), 2);
317 }
318
319 #[test]
320 fn test_insert_overlapping_paths() {
321 let mut tree = Tree::default();
322 insert_path(&mut tree.0, &["a", "b"]);
323 insert_path(&mut tree.0, &["a", "b", "c"]);
324
325 assert!(tree.0["a"].0["b"].0.contains_key("c"));
326 }
327}