1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use std::vec;

pub mod implementations;

/// simple trait to provide an easy way to display hierarchy trees
pub trait DisplayableNode: Sized {
    fn label(&self) -> Option<String>;
    fn children(&self) -> Vec<&Self>;

    fn display(&self) -> String {
        NodeDisplayBlock::from_displayable_node(self, 0).extract()
    }
}

///
struct NodeDisplayBlock {
    lines: Vec<String>,
}

impl NodeDisplayBlock {
    fn extract(self) -> String {
        self.lines.join("\n")
    }

    fn from_displayable_node<N: DisplayableNode>(node: &N, index: usize) -> Self {
        let mut result = Self::from_label(node, index);
        let children = node.children();
        result.append_children::<N>(children);

        result
    }

    fn from_label<N: DisplayableNode>(node: &N, index: usize) -> Self {
        let mut lines = Vec::new();
        let label = node.label().unwrap_or_else(|| format!("[{index}]"));

        for line in label.lines() {
            lines.push(line.to_string());
        }

        Self { lines }
    }

    fn append_children<N: DisplayableNode>(&mut self, children: Vec<&N>) {
        if children.is_empty() {
            return;
        }
        let last_child_index = children.len() - 1;
        let mut children_iterator = children.into_iter();
        self.append_middle_children_nodes(&mut children_iterator, last_child_index);
        let last_child_node = children_iterator.next().unwrap();
        self.append_last_child_node(last_child_node, last_child_index);
    }

    fn append_middle_children_nodes<N: DisplayableNode>(
        &mut self,
        children_iterator: &mut vec::IntoIter<&N>,
        last_child_index: usize,
    ) {
        for middle_child_index in 0..last_child_index {
            let middle_child_node = children_iterator.next().unwrap();
            let middle_child_block =
                Self::from_displayable_node(middle_child_node, middle_child_index);
            self.append_middle_child_block(&middle_child_block);
        }
    }

    fn append_last_child_node<N: DisplayableNode>(
        &mut self,
        last_child_node: &N,
        last_child_index: usize,
    ) {
        let last_child_block = Self::from_displayable_node(last_child_node, last_child_index);
        self.append_last_child_block(&last_child_block);
    }

    fn append_middle_child_block(&mut self, middle_child: &NodeDisplayBlock) {
        let own_lines = &mut self.lines;
        let mut child_lines_iterator = middle_child.lines.iter();
        let child_label_line = child_lines_iterator.next().unwrap();
        own_lines.push(format!("├─ {child_label_line}"));
        for child_line in child_lines_iterator {
            own_lines.push(format!("│  {child_line}"));
        }
    }

    fn append_last_child_block(&mut self, last_child: &NodeDisplayBlock) {
        let own_lines = &mut self.lines;
        let mut child_lines_iterator = last_child.lines.iter();
        let child_label_line = child_lines_iterator.next().unwrap();
        own_lines.push(format!("└─ {child_label_line}"));
        for child_line in child_lines_iterator {
            own_lines.push(format!("   {child_line}"));
        }
    }
}