use rpds::VectorSync;
#[must_use]
pub(crate) fn swapped<T: Clone>(sequence: &VectorSync<T>, a: usize, b: usize) -> VectorSync<T> {
let (Some(at_a), Some(at_b)) = (sequence.get(a).cloned(), sequence.get(b).cloned()) else {
return sequence.clone();
};
sequence
.set(a, at_b)
.and_then(|sequence| sequence.set(b, at_a))
.unwrap_or_else(|| sequence.clone())
}
#[must_use]
pub(crate) fn without<T: Clone + PartialEq>(sequence: &VectorSync<T>, value: &T) -> VectorSync<T> {
sequence
.iter()
.filter(|held| *held != value)
.cloned()
.collect()
}
#[cfg(test)]
mod tests {
use rpds::VectorSync;
use super::{swapped, without};
fn sequence_of(numbers: &[u16]) -> VectorSync<u16> {
numbers
.iter()
.fold(VectorSync::new_sync(), |sequence, number| {
sequence.push_back(*number)
})
}
fn elements(sequence: &VectorSync<u16>) -> Vec<u16> {
sequence.iter().copied().collect()
}
#[test]
fn swapping_two_places_exchanges_them_and_leaves_every_other_place_alone() {
let sequence = sequence_of(&[1, 2, 3, 4]);
let swapped = swapped(&sequence, 0, 3);
assert_eq!(elements(&swapped), vec![4, 2, 3, 1]);
}
#[test]
fn swapping_does_not_disturb_the_sequence_it_was_given() {
let sequence = sequence_of(&[1, 2, 3, 4]);
let swapped = swapped(&sequence, 0, 3);
assert_eq!(
elements(&sequence),
vec![1, 2, 3, 4],
"the sequence it was given"
);
assert_eq!(
elements(&swapped),
vec![4, 2, 3, 1],
"the sequence it handed back"
);
}
#[test]
fn swapping_places_that_do_not_stand_changes_nothing() {
let sequence = sequence_of(&[1, 2, 3]);
assert_eq!(
elements(&swapped(&sequence, 1, 7)),
vec![1, 2, 3],
"one place missing"
);
assert_eq!(
elements(&swapped(&sequence, 7, 8)),
vec![1, 2, 3],
"both missing"
);
}
#[test]
fn without_drops_the_place_the_value_stood_in() {
let sequence = sequence_of(&[1, 2, 3, 4]);
let left = without(&sequence, &2);
assert_eq!(elements(&left), vec![1, 3, 4]);
}
#[test]
fn without_a_value_the_sequence_never_held_changes_nothing() {
let sequence = sequence_of(&[1, 2, 3]);
assert_eq!(elements(&without(&sequence, &9)), vec![1, 2, 3]);
assert!(
without(&VectorSync::new_sync(), &1).is_empty(),
"a sequence holding nothing has nothing to drop"
);
}
#[test]
fn without_the_only_element_leaves_an_empty_sequence_rather_than_nothing() {
let sequence = sequence_of(&[1]);
let left = without(&sequence, &1);
assert!(left.is_empty());
assert_eq!(left.len(), 0);
}
}