tui_tree_widget/
flatten.rs1use std::collections::HashSet;
2
3use crate::tree_item::TreeItem;
4
5#[must_use]
9pub struct Flattened<'text, Identifier> {
10 pub identifier: Vec<Identifier>,
11 pub item: &'text TreeItem<'text, Identifier>,
12}
13
14impl<Identifier> Flattened<'_, Identifier> {
15 #[must_use]
17 pub fn depth(&self) -> usize {
18 self.identifier.len() - 1
19 }
20}
21
22#[must_use]
26pub fn flatten<'text, Identifier>(
27 open_identifiers: &HashSet<Vec<Identifier>>,
28 items: &'text [TreeItem<'text, Identifier>],
29 current: &[Identifier],
30) -> Vec<Flattened<'text, Identifier>>
31where
32 Identifier: Clone + PartialEq + Eq + core::hash::Hash,
33{
34 let mut result = Vec::new();
35 for item in items {
36 let mut child_identifier = current.to_vec();
37 child_identifier.push(item.identifier.clone());
38
39 let child_result = open_identifiers
40 .contains(&child_identifier)
41 .then(|| flatten(open_identifiers, &item.children, &child_identifier));
42
43 result.push(Flattened {
44 identifier: child_identifier,
45 item,
46 });
47
48 if let Some(mut child_result) = child_result {
49 result.append(&mut child_result);
50 }
51 }
52 result
53}
54
55#[test]
56fn depth_works() {
57 let mut open = HashSet::new();
58 open.insert(vec!["b"]);
59 open.insert(vec!["b", "d"]);
60 let depths = flatten(&open, &TreeItem::example(), &[])
61 .into_iter()
62 .map(|flattened| flattened.depth())
63 .collect::<Vec<_>>();
64 assert_eq!(depths, [0, 0, 1, 1, 2, 2, 1, 0]);
65}
66
67#[cfg(test)]
68fn flatten_works(open: &HashSet<Vec<&'static str>>, expected: &[&str]) {
69 let items = TreeItem::example();
70 let result = flatten(open, &items, &[]);
71 let actual = result
72 .into_iter()
73 .map(|flattened| flattened.identifier.into_iter().next_back().unwrap())
74 .collect::<Vec<_>>();
75 assert_eq!(actual, expected);
76}
77
78#[test]
79fn flatten_nothing_open_is_top_level() {
80 let open = HashSet::new();
81 flatten_works(&open, &["a", "b", "h"]);
82}
83
84#[test]
85fn flatten_wrong_open_is_only_top_level() {
86 let mut open = HashSet::new();
87 open.insert(vec!["a"]);
88 open.insert(vec!["b", "d"]);
89 flatten_works(&open, &["a", "b", "h"]);
90}
91
92#[test]
93fn flatten_one_is_open() {
94 let mut open = HashSet::new();
95 open.insert(vec!["b"]);
96 flatten_works(&open, &["a", "b", "c", "d", "g", "h"]);
97}
98
99#[test]
100fn flatten_all_open() {
101 let mut open = HashSet::new();
102 open.insert(vec!["b"]);
103 open.insert(vec!["b", "d"]);
104 flatten_works(&open, &["a", "b", "c", "d", "e", "f", "g", "h"]);
105}