display_node/
lib.rs

1use std::vec;
2
3pub mod implementations;
4
5/// simple trait to provide an easy way to display hierarchy trees
6pub trait DisplayableNode: Sized {
7    fn label(&self) -> Option<String>;
8    fn children(&self) -> Vec<&Self>;
9
10    fn display(&self) -> String {
11        NodeDisplayBlock::from_displayable_node(self, 0).extract()
12    }
13}
14
15///
16struct NodeDisplayBlock {
17    lines: Vec<String>,
18}
19
20impl NodeDisplayBlock {
21    fn extract(self) -> String {
22        self.lines.join("\n")
23    }
24
25    fn from_displayable_node<N: DisplayableNode>(node: &N, index: usize) -> Self {
26        let mut result = Self::from_label(node, index);
27        let children = node.children();
28        result.append_children::<N>(children);
29
30        result
31    }
32
33    fn from_label<N: DisplayableNode>(node: &N, index: usize) -> Self {
34        let mut lines = Vec::new();
35        let label = node.label().unwrap_or_else(|| format!("[{index}]"));
36
37        for line in label.lines() {
38            lines.push(line.to_string());
39        }
40
41        Self { lines }
42    }
43
44    fn append_children<N: DisplayableNode>(&mut self, children: Vec<&N>) {
45        if children.is_empty() {
46            return;
47        }
48        let last_child_index = children.len() - 1;
49        let mut children_iterator = children.into_iter();
50        self.append_middle_children_nodes(&mut children_iterator, last_child_index);
51        let last_child_node = children_iterator.next().unwrap();
52        self.append_last_child_node(last_child_node, last_child_index);
53    }
54
55    fn append_middle_children_nodes<N: DisplayableNode>(
56        &mut self,
57        children_iterator: &mut vec::IntoIter<&N>,
58        last_child_index: usize,
59    ) {
60        for middle_child_index in 0..last_child_index {
61            let middle_child_node = children_iterator.next().unwrap();
62            let middle_child_block =
63                Self::from_displayable_node(middle_child_node, middle_child_index);
64            self.append_middle_child_block(&middle_child_block);
65        }
66    }
67
68    fn append_last_child_node<N: DisplayableNode>(
69        &mut self,
70        last_child_node: &N,
71        last_child_index: usize,
72    ) {
73        let last_child_block = Self::from_displayable_node(last_child_node, last_child_index);
74        self.append_last_child_block(&last_child_block);
75    }
76
77    fn append_middle_child_block(&mut self, middle_child: &NodeDisplayBlock) {
78        let own_lines = &mut self.lines;
79        let mut child_lines_iterator = middle_child.lines.iter();
80        let child_label_line = child_lines_iterator.next().unwrap();
81        own_lines.push(format!("├─ {child_label_line}"));
82        for child_line in child_lines_iterator {
83            own_lines.push(format!("│  {child_line}"));
84        }
85    }
86
87    fn append_last_child_block(&mut self, last_child: &NodeDisplayBlock) {
88        let own_lines = &mut self.lines;
89        let mut child_lines_iterator = last_child.lines.iter();
90        let child_label_line = child_lines_iterator.next().unwrap();
91        own_lines.push(format!("└─ {child_label_line}"));
92        for child_line in child_lines_iterator {
93            own_lines.push(format!("   {child_line}"));
94        }
95    }
96}