perf(flatten): fewer clones
This commit is contained in:
+23
-42
@@ -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
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user