perf(flatten): fewer clones

This commit is contained in:
EdJoPaTo
2024-05-01 16:39:39 +02:00
parent fdd2c5436a
commit 537dc8021e
2 changed files with 24 additions and 43 deletions
+23 -42
View File
@@ -18,21 +18,12 @@ impl<'a, Identifier> Flattened<'a, Identifier> {
} }
/// Get a flat list of all visible [`TreeItem`]s. /// Get a flat list of all visible [`TreeItem`]s.
///
/// `current` starts empty: `&[]`
#[must_use] #[must_use]
pub fn flatten<'a, Identifier>( pub fn flatten<'a, Identifier>(
opened: &HashSet<Vec<Identifier>>, opened: &HashSet<Vec<Identifier>>,
items: &'a [TreeItem<'a, Identifier>], items: &'a [TreeItem<'a, Identifier>],
) -> Vec<Flattened<'a, Identifier>>
where
Identifier: Clone + PartialEq + Eq + core::hash::Hash,
{
internal(opened, items, &[])
}
#[must_use]
fn internal<'a, Identifier>(
opened: &HashSet<Vec<Identifier>>,
items: &'a [TreeItem<'a, Identifier>],
current: &[Identifier], current: &[Identifier],
) -> Vec<Flattened<'a, Identifier>> ) -> Vec<Flattened<'a, Identifier>>
where where
@@ -43,68 +34,58 @@ where
let mut child_identifier = current.to_vec(); let mut child_identifier = current.to_vec();
child_identifier.push(item.identifier.clone()); child_identifier.push(item.identifier.clone());
let child_result = opened
.contains(&child_identifier)
.then(|| flatten(opened, &item.children, &child_identifier));
result.push(Flattened { result.push(Flattened {
identifier: child_identifier,
item, item,
identifier: child_identifier.clone(),
}); });
if opened.contains(&child_identifier) { if let Some(mut child_result) = child_result {
let mut child_result = internal(opened, &item.children, &child_identifier);
result.append(&mut child_result); result.append(&mut child_result);
} }
} }
result result
} }
#[cfg(test)]
fn flatten_works(opened: &HashSet<Vec<&'static str>>, expected: &[&str]) {
let items = TreeItem::example();
let result = flatten(opened, &items, &[]);
let actual = result
.into_iter()
.map(|flattened| flattened.identifier.into_iter().last().unwrap())
.collect::<Vec<_>>();
assert_eq!(actual, expected);
}
#[test] #[test]
fn get_opened_nothing_opened_is_top_level() { fn get_opened_nothing_opened_is_top_level() {
let items = TreeItem::example();
let opened = HashSet::new(); let opened = HashSet::new();
let result = flatten(&opened, &items); flatten_works(&opened, &["a", "b", "h"]);
let result_text = result
.into_iter()
.map(|flattened| flattened.item.identifier)
.collect::<Vec<_>>();
assert_eq!(result_text, ["a", "b", "h"]);
} }
#[test] #[test]
fn get_opened_wrong_opened_is_only_top_level() { fn get_opened_wrong_opened_is_only_top_level() {
let items = TreeItem::example();
let mut opened = HashSet::new(); let mut opened = HashSet::new();
opened.insert(vec!["a"]); opened.insert(vec!["a"]);
opened.insert(vec!["b", "d"]); opened.insert(vec!["b", "d"]);
let result = flatten(&opened, &items); flatten_works(&opened, &["a", "b", "h"]);
let result_text = result
.into_iter()
.map(|flattened| flattened.item.identifier)
.collect::<Vec<_>>();
assert_eq!(result_text, ["a", "b", "h"]);
} }
#[test] #[test]
fn get_opened_one_is_opened() { fn get_opened_one_is_opened() {
let items = TreeItem::example();
let mut opened = HashSet::new(); let mut opened = HashSet::new();
opened.insert(vec!["b"]); opened.insert(vec!["b"]);
let result = flatten(&opened, &items); flatten_works(&opened, &["a", "b", "c", "d", "g", "h"]);
let result_text = result
.into_iter()
.map(|flattened| flattened.item.identifier)
.collect::<Vec<_>>();
assert_eq!(result_text, ["a", "b", "c", "d", "g", "h"]);
} }
#[test] #[test]
fn get_opened_all_opened() { fn get_opened_all_opened() {
let items = TreeItem::example();
let mut opened = HashSet::new(); let mut opened = HashSet::new();
opened.insert(vec!["b"]); opened.insert(vec!["b"]);
opened.insert(vec!["b", "d"]); opened.insert(vec!["b", "d"]);
let result = flatten(&opened, &items); flatten_works(&opened, &["a", "b", "c", "d", "e", "f", "g", "h"]);
let result_text = result
.into_iter()
.map(|flattened| flattened.item.identifier)
.collect::<Vec<_>>();
assert_eq!(result_text, ["a", "b", "c", "d", "e", "f", "g", "h"]);
} }
+1 -1
View File
@@ -51,7 +51,7 @@ where
&self, &self,
items: &'a [TreeItem<'a, Identifier>], items: &'a [TreeItem<'a, Identifier>],
) -> Vec<Flattened<'a, Identifier>> { ) -> Vec<Flattened<'a, Identifier>> {
flatten(&self.opened, items) flatten(&self.opened, items, &[])
} }
/// Selects the given identifier. /// Selects the given identifier.