rustic_rs/commands/tui/
tree.rs1#[derive(PartialEq, Eq)]
2pub struct TreeNode<Data, LeafData> {
3 pub data: Data,
4 pub open: bool,
5 pub children: Vec<Tree<Data, LeafData>>,
6}
7
8#[derive(PartialEq, Eq)]
9pub enum Tree<Data, LeafData> {
10 Node(TreeNode<Data, LeafData>),
11 Leaf(LeafData),
12}
13
14impl<Data, LeafData> Tree<Data, LeafData> {
15 pub fn leaf(data: LeafData) -> Self {
16 Self::Leaf(data)
17 }
18 pub fn node(data: Data, open: bool, children: Vec<Self>) -> Self {
19 Self::Node(TreeNode {
20 data,
21 open,
22 children,
23 })
24 }
25
26 pub fn child_count(&self) -> usize {
27 match self {
28 Self::Leaf(_) => 0,
29 Self::Node(TreeNode { children, .. }) => {
30 children.len() + children.iter().map(Self::child_count).sum::<usize>()
31 }
32 }
33 }
34
35 pub fn leaf_data(&self) -> Option<&LeafData> {
36 match self {
37 Self::Node(_) => None,
38 Self::Leaf(data) => Some(data),
39 }
40 }
41
42 pub fn openable(&self) -> bool {
43 matches!(self, Self::Node(node) if !node.open)
44 }
45
46 pub fn open(&mut self) {
47 if let Self::Node(node) = self {
48 node.open = true;
49 }
50 }
51 pub fn close(&mut self) {
52 if let Self::Node(node) = self {
53 node.open = false;
54 }
55 }
56
57 pub fn iter(&self) -> impl Iterator<Item = TreeIterItem<'_, Data, LeafData>> {
58 TreeIter {
59 tree: Some(self),
60 iter_stack: Vec::new(),
61 only_open: false,
62 }
63 }
64
65 pub fn iter_open(&self) -> impl Iterator<Item = TreeIterItem<'_, Data, LeafData>> {
68 TreeIter {
69 tree: Some(self),
70 iter_stack: Vec::new(),
71 only_open: true,
72 }
73 .skip(1)
74 }
75
76 pub fn nth_mut(&mut self, n: usize) -> Option<&mut Self> {
77 let mut count = 0;
78 let mut tree = Some(self);
79 let mut iter_stack = Vec::new();
80 loop {
81 if count == n + 1 {
82 return tree;
83 }
84 let item = tree?;
85 if let Self::Node(node) = item {
86 if node.open {
87 iter_stack.push(node.children.iter_mut());
88 }
89 }
90 tree = next_from_iter_stack(&mut iter_stack);
91 count += 1;
92 }
93 }
94}
95
96pub struct TreeIterItem<'a, Data, LeadData> {
97 pub depth: usize,
98 pub tree: &'a Tree<Data, LeadData>,
99}
100
101impl<Data, LeafData> TreeIterItem<'_, Data, LeafData> {
102 pub fn leaf_data(&self) -> Option<&LeafData> {
103 self.tree.leaf_data()
104 }
105}
106
107pub struct TreeIter<'a, Data, LeafData> {
108 tree: Option<&'a Tree<Data, LeafData>>,
109 iter_stack: Vec<std::slice::Iter<'a, Tree<Data, LeafData>>>,
110 only_open: bool,
111}
112
113impl<'a, Data, LeafData> Iterator for TreeIter<'a, Data, LeafData> {
114 type Item = TreeIterItem<'a, Data, LeafData>;
115 fn next(&mut self) -> Option<Self::Item> {
116 let item = self.tree?;
117 let depth = self.iter_stack.len();
118 if let Tree::Node(node) = item {
119 if !self.only_open || node.open {
120 self.iter_stack.push(node.children.iter());
121 }
122 }
123
124 self.tree = next_from_iter_stack(&mut self.iter_stack);
125 Some(TreeIterItem { depth, tree: item })
126 }
127}
128
129fn next_from_iter_stack<T>(stack: &mut Vec<impl Iterator<Item = T>>) -> Option<T> {
131 loop {
132 match stack.pop() {
133 None => {
134 break None;
135 }
136 Some(mut iter) => {
137 if let Some(next) = iter.next() {
138 stack.push(iter);
139 break Some(next);
140 }
141 }
142 }
143 }
144}