1use crate::arith::{mul, raise_by};
2use crate::clamp::clamp_upper;
3use crate::seq::{with, Keyed};
4use patterns_macros::because;
5
6pub fn dequeued<T: Clone>(items: &[T]) -> Option<(T, Vec<T>)> {
7 items
8 .split_first()
9 .map(|(head, rest)| (head.clone(), rest.to_vec()))
10}
11because!(dequeued, "taking the front of a queue and the remainder together, so a caller never indexes zero and the empty queue is a value rather than a panic");
12
13pub fn rotated<T: Clone>(items: &[T]) -> Vec<T> {
14 match items.split_first() {
15 Some((head, rest)) => with(rest, head.clone()),
16 None => Vec::new(),
17 }
18}
19because!(rotated, "one turn of a round robin, so a rota or a fair share of bays advances without a caller tracking an index that must wrap");
20
21pub fn moved<T: Keyed + Clone>(from: &[T], to: &[T], key: T::Key) -> (Vec<T>, Vec<T>) {
22 let mut left = Vec::new();
23 let mut arrived = to.to_vec();
24 for item in from {
25 if item.key() == key {
26 arrived.push(item.clone());
27 } else {
28 left.push(item.clone());
29 }
30 }
31 (left, arrived)
32}
33because!(moved, "a transfer between two shelves as one step, so the element cannot be dropped from one without arriving on the other, which without and with as separate calls allow; every element under the key moves, so two sharing a key arrive together rather than one being stranded");
34
35pub fn replaced<T: Keyed + Clone>(items: &[T], item: T) -> Vec<T> {
36 let mut out = Vec::new();
37 for held in items {
38 if held.key() == item.key() {
39 out.push(item.clone());
40 } else {
41 out.push(held.clone());
42 }
43 }
44 out
45}
46because!(replaced, "an update in place that keeps the position, because with after without sends a queued element to the back and silently changes its turn; every element under the key is replaced, so two sharing a key both become the new element and a duplicate is not silently kept");
47
48pub fn page<T: Clone>(items: &[T], size: usize, number: usize) -> Vec<T> {
49 let start = clamp_upper(mul(size, number), items.len());
50 let end = clamp_upper(raise_by(start, size), items.len());
51 items[start..end].to_vec()
52}
53because!(page, "one page of a listing, with the arithmetic that ends a list saturated and clamped here so a request past the end is an empty page rather than a panic");