use std::collections::BTreeSet;
pub(crate) fn effective_hidden<K: Ord + Clone>(
manual: &BTreeSet<K>,
isolate: Option<&BTreeSet<K>>,
all: impl IntoIterator<Item = K>,
) -> BTreeSet<K> {
let mut hidden = manual.clone();
if let Some(keep) = isolate {
hidden.extend(all.into_iter().filter(|k| !keep.contains(k)));
}
hidden
}
pub(crate) fn is_hidden<K: Ord>(
key: &K,
manual: &BTreeSet<K>,
isolate: Option<&BTreeSet<K>>,
) -> bool {
manual.contains(key) || isolate.is_some_and(|keep| !keep.contains(key))
}
#[cfg(test)]
mod tests {
use super::*;
fn set(names: &[&'static str]) -> BTreeSet<&'static str> {
names.iter().copied().collect()
}
#[test]
fn no_isolate_is_just_the_manual_set() {
let manual = set(&["a"]);
let hidden = effective_hidden(&manual, None, ["a", "b", "c"]);
assert_eq!(hidden, set(&["a"]));
}
#[test]
fn isolate_hides_everything_outside_the_kept_set() {
let manual = BTreeSet::new();
let keep = set(&["b"]);
let hidden = effective_hidden(&manual, Some(&keep), ["a", "b", "c"]);
assert_eq!(hidden, set(&["a", "c"]));
}
#[test]
fn manual_wins_inside_the_kept_set() {
let manual = set(&["b"]);
let keep = set(&["a", "b"]);
let hidden = effective_hidden(&manual, Some(&keep), ["a", "b", "c"]);
assert_eq!(hidden, set(&["b", "c"]));
assert!(is_hidden(&"b", &manual, Some(&keep)));
assert!(!is_hidden(&"a", &manual, Some(&keep)));
}
#[test]
fn leaving_isolate_restores_the_manual_state() {
let manual = set(&["a"]);
let keep = set(&["b"]);
let during = effective_hidden(&manual, Some(&keep), ["a", "b", "c"]);
assert_eq!(during, set(&["a", "c"]));
let after = effective_hidden(&manual, None, ["a", "b", "c"]);
assert_eq!(after, set(&["a"]));
}
#[test]
fn per_name_check_matches_the_set() {
let manual = set(&["a"]);
let keep = set(&["b"]);
for n in ["a", "b", "c"] {
let in_set = effective_hidden(&manual, Some(&keep), ["a", "b", "c"]).contains(n);
assert_eq!(is_hidden(&n, &manual, Some(&keep)), in_set, "{n}");
}
}
}