use std::collections::BTreeMap;
pub(crate) fn sorted_values<T: Ord>(mut values: Vec<T>) -> Vec<T> {
values.sort();
values
}
pub(crate) fn sorted_copied_values<T: Copy + Ord>(values: impl IntoIterator<Item = T>) -> Vec<T> {
let mut values: Vec<_> = values.into_iter().collect();
values.sort_unstable();
values
}
pub(crate) fn sorted_unique_strings(mut values: Vec<String>) -> Vec<String> {
values = sorted_values(values);
values.dedup();
values
}
pub(crate) fn sorted_unique_non_empty_strings(
values: impl IntoIterator<Item = String>,
) -> Vec<String> {
sorted_unique_strings(
values
.into_iter()
.filter(|value| !value.is_empty())
.collect(),
)
}
pub(crate) fn sorted_unique_strings_with_optional(
mut values: Vec<String>,
optional: Option<&String>,
) -> Vec<String> {
if let Some(value) = optional {
values.push(value.clone());
}
sorted_unique_strings(values)
}
pub(crate) fn sorted_ref_deltas(
previous_refs: &[String],
updated_refs: &[String],
) -> (Vec<String>, Vec<String>) {
let mut removed_refs = Vec::with_capacity(previous_refs.len());
let mut added_refs = Vec::with_capacity(updated_refs.len());
let mut previous = previous_refs.iter();
let mut updated = updated_refs.iter();
let mut previous_id = previous.next();
let mut updated_id = updated.next();
loop {
match (previous_id, updated_id) {
(Some(previous_value), Some(updated_value)) => {
match previous_value.cmp(updated_value) {
std::cmp::Ordering::Less => {
removed_refs.push(previous_value.clone());
previous_id = previous.next();
}
std::cmp::Ordering::Equal => {
previous_id = previous.next();
updated_id = updated.next();
}
std::cmp::Ordering::Greater => {
added_refs.push(updated_value.clone());
updated_id = updated.next();
}
}
}
(Some(previous_value), None) => {
removed_refs.push(previous_value.clone());
removed_refs.extend(previous.cloned());
break;
}
(None, Some(updated_value)) => {
added_refs.push(updated_value.clone());
added_refs.extend(updated.cloned());
break;
}
(None, None) => break,
}
}
(removed_refs, added_refs)
}
pub(crate) fn remove_matching_values<T>(
values: &mut BTreeMap<String, T>,
mut predicate: impl FnMut(&T) -> bool,
) -> Vec<T> {
let removed_ids: Vec<_> = values
.iter()
.filter_map(|(id, value)| predicate(value).then_some(id.clone()))
.collect();
let mut removed_values = Vec::with_capacity(removed_ids.len());
for id in removed_ids {
if let Some(value) = values.remove(&id) {
removed_values.push(value);
}
}
removed_values
}
#[cfg(test)]
#[path = "tests/collection_tests.rs"]
mod collection_tests;