Skip to main content

macroonz_compiler/bounded/
type_guard.rs

1//! The bounded home's invariant nucleus: every road that reaches a private field.
2//!
3//! Declared inside `types.rs` as its own child, which is what makes this home's claims structural.
4//! A list longer than its ceiling and a non-empty list with nothing in it are values nobody can build, rather than shapes something downstream has to check for.
5
6use super::{
7    Bounded, Capped, Capping, DuplicateKey, Empty, ForeignRosterReference, KeyedRoster,
8    KeyedRosterAssignment, KeyedRosterAssignmentError, KeyedRosterError, NonEmpty, NonEmptyError,
9    Overflow, UnassignedRosterMember,
10};
11use core::borrow::Borrow;
12
13impl<T, const N: usize> Bounded<T, N> {
14    /// An empty collection under this ceiling.
15    #[must_use]
16    pub const fn empty() -> Self {
17        Self(Vec::new())
18    }
19
20    /// Admits one complete ordered offering under this ceiling.
21    ///
22    /// # Errors
23    ///
24    /// Returns [`Overflow`] when more than `N` items are offered.
25    pub fn new(items: Vec<T>) -> Result<Self, Overflow> {
26        if items.len() <= N {
27            Ok(Self(items))
28        } else {
29            Err(Overflow {
30                capacity: N,
31                offered: items.len(),
32            })
33        }
34    }
35
36    /// Admits a fixed-arity offering whose fit is settled at compile time.
37    #[must_use]
38    pub fn from_array<const M: usize>(items: [T; M]) -> Self {
39        const {
40            assert!(
41                M <= N,
42                "a fixed list longer than the ceiling it is declared under"
43            );
44        }
45        Self(Vec::from(items))
46    }
47
48    /// The held items.
49    #[must_use]
50    pub fn as_slice(&self) -> &[T] {
51        self.0.as_slice()
52    }
53
54    /// Reads the held items in order.
55    pub fn iter(&self) -> impl Iterator<Item = &T> {
56        self.0.iter()
57    }
58
59    /// How many items are held.
60    #[must_use]
61    pub fn len(&self) -> usize {
62        self.0.len()
63    }
64
65    /// Whether nothing is held.
66    #[must_use]
67    pub fn is_empty(&self) -> bool {
68        self.0.is_empty()
69    }
70
71    pub(crate) fn into_vec(self) -> Vec<T> {
72        self.0
73    }
74
75    pub(crate) fn mapped<U>(&self, operation: impl FnMut(&T) -> U) -> Bounded<U, N> {
76        Bounded(self.iter().map(operation).collect())
77    }
78
79    /// Appends one item where the resulting collection fits under this ceiling.
80    ///
81    /// # Errors
82    ///
83    /// Returns [`Overflow`] without changing the list where the appended item would exceed `N`.
84    pub fn try_push(&mut self, item: T) -> Result<(), Overflow> {
85        let offered = self.0.len().saturating_add(1);
86        if offered > N {
87            return Err(Overflow {
88                capacity: N,
89                offered,
90            });
91        }
92        self.0.push(item);
93        Ok(())
94    }
95}
96
97impl<T, const N: usize> NonEmpty<T, N> {
98    /// A non-empty collection holding exactly one item.
99    #[must_use]
100    pub const fn one(value: T) -> Self {
101        const {
102            assert!(
103                N >= 1,
104                "a non-empty list under a ceiling that admits no item"
105            );
106        }
107        Self {
108            head: value,
109            tail: Vec::new(),
110        }
111    }
112
113    /// Admits one complete ordered offering that is non-empty and under this ceiling.
114    ///
115    /// # Errors
116    ///
117    /// Returns [`Empty`] when nothing is offered, and [`Overflow`] when more than `N` items are.
118    pub fn new(items: Vec<T>) -> Result<Self, NonEmptyError> {
119        let offered = items.len();
120        let mut rest = items.into_iter();
121        let Some(head) = rest.next() else {
122            return Err(NonEmptyError::Empty(Empty));
123        };
124        if offered <= N {
125            Ok(Self {
126                head,
127                tail: rest.collect(),
128            })
129        } else {
130            Err(NonEmptyError::Overflow(Overflow {
131                capacity: N,
132                offered,
133            }))
134        }
135    }
136
137    pub(crate) fn from_bounded(items: Bounded<T, N>) -> Result<Self, Empty> {
138        let mut items = items.into_vec().into_iter();
139        let Some(head) = items.next() else {
140            return Err(Empty);
141        };
142        Ok(Self {
143            head,
144            tail: items.collect(),
145        })
146    }
147
148    /// The first item, which this list always has.
149    #[must_use]
150    pub const fn first(&self) -> &T {
151        &self.head
152    }
153
154    /// The first item and the rest, in order.
155    #[must_use]
156    pub fn split(&self) -> (&T, &[T]) {
157        (&self.head, self.tail.as_slice())
158    }
159
160    /// Reads the held items in order.
161    pub fn iter(&self) -> impl Iterator<Item = &T> {
162        self.into_iter()
163    }
164
165    /// How many items are held, which is never zero.
166    #[must_use]
167    pub fn count(&self) -> usize {
168        self.tail.len().saturating_add(1)
169    }
170
171    pub(crate) fn mapped<U>(self, mut operation: impl FnMut(T) -> U) -> NonEmpty<U, N> {
172        NonEmpty {
173            head: operation(self.head),
174            tail: self.tail.into_iter().map(operation).collect(),
175        }
176    }
177}
178
179impl<'held, T, const N: usize> IntoIterator for &'held NonEmpty<T, N> {
180    type Item = &'held T;
181    type IntoIter = core::iter::Chain<core::iter::Once<&'held T>, core::slice::Iter<'held, T>>;
182
183    fn into_iter(self) -> Self::IntoIter {
184        core::iter::once(&self.head).chain(self.tail.iter())
185    }
186}
187
188impl<T, K, const N: usize> KeyedRoster<T, K, N> {
189    /// A roster containing one member under its caller-declared key.
190    #[must_use]
191    pub const fn one(member: T, key: K) -> Self {
192        Self {
193            members: NonEmpty::one(member),
194            keys: NonEmpty::one(key),
195        }
196    }
197
198    /// The first member, which this roster always has.
199    #[must_use]
200    pub const fn first(&self) -> &T {
201        self.members.first()
202    }
203
204    /// The key retained for the first member.
205    #[must_use]
206    pub const fn first_key(&self) -> &K {
207        self.keys.first()
208    }
209
210    /// How many members are held, which is never zero.
211    #[must_use]
212    pub fn count(&self) -> usize {
213        self.members.count()
214    }
215
216    pub(crate) fn positions_where(
217        &self,
218        mut predicate: impl FnMut(usize, &K, &T) -> bool,
219    ) -> Bounded<usize, N> {
220        Bounded(
221            self.indexed()
222                .filter_map(|(index, key, member)| predicate(index, key, member).then_some(index))
223                .collect(),
224        )
225    }
226
227    /// Reads the members in declaration order.
228    pub fn members(&self) -> impl Iterator<Item = &T> {
229        self.members.iter()
230    }
231
232    /// Reads the retained keys in declaration order.
233    pub fn keys(&self) -> impl Iterator<Item = &K> {
234        self.keys.iter()
235    }
236
237    /// Reads every declaration index, retained key, and member together.
238    pub fn indexed(&self) -> impl Iterator<Item = (usize, &K, &T)> {
239        self.keys()
240            .zip(self.members())
241            .enumerate()
242            .map(|(index, (key, member))| (index, key, member))
243    }
244
245    /// Reads the key and member at one checked declaration index.
246    #[must_use]
247    pub fn at(&self, index: usize) -> Option<(&K, &T)> {
248        self.keys().zip(self.members()).nth(index)
249    }
250
251    /// Finds the declaration index of one borrowed key.
252    #[must_use]
253    pub fn index_of<Q>(&self, sought: &Q) -> Option<usize>
254    where
255        K: Borrow<Q>,
256        Q: Eq + ?Sized,
257    {
258        self.keys().position(|key| key.borrow() == sought)
259    }
260
261    /// Finds the member held under one borrowed key.
262    #[must_use]
263    pub fn get<Q>(&self, sought: &Q) -> Option<&T>
264    where
265        K: Borrow<Q>,
266        Q: Eq + ?Sized,
267    {
268        self.keys()
269            .zip(self.members())
270            .find_map(|(key, member)| (key.borrow() == sought).then_some(member))
271    }
272
273    /// Finds the declaration position, retained key, and member under one borrowed key.
274    #[must_use]
275    pub fn indexed_get<Q>(&self, sought: &Q) -> Option<(usize, &K, &T)>
276    where
277        K: Borrow<Q>,
278        Q: Eq + ?Sized,
279    {
280        self.indexed()
281            .find(|(_index, key, _member)| (*key).borrow() == sought)
282    }
283}
284
285impl<T, K: Eq, const N: usize> KeyedRoster<T, K, N> {
286    /// Admits one complete ordered offering under caller-declared unique keys.
287    ///
288    /// The offering's nonempty bounded magnitude is settled before the key projection runs.
289    ///
290    /// # Errors
291    ///
292    /// Returns [`Empty`] when nothing is offered, [`Overflow`] when more than `N` items are offered, and [`DuplicateKey`] coordinates for every distinct key that occurs more than once.
293    pub fn new(
294        members: Vec<T>,
295        key_of: impl FnMut(&T) -> K,
296    ) -> Result<Self, KeyedRosterError<K, N>> {
297        let members = NonEmpty::new(members).map_err(keyed_magnitude_refusal)?;
298        let keys = project_keys(&members, key_of);
299        match admit_keys(keys) {
300            KeyAdmission::Unique(keys) => Ok(Self { members, keys }),
301            KeyAdmission::Duplicated(duplicates) => {
302                Err(KeyedRosterError::DuplicateKeys(duplicates))
303            }
304        }
305    }
306}
307
308impl<K: Eq, const N: usize> NonEmpty<K, N> {
309    pub(crate) fn duplicate_keys(self) -> Option<NonEmpty<DuplicateKey<K, N>, N>> {
310        match admit_keys(self) {
311            KeyAdmission::Unique(_) => None,
312            KeyAdmission::Duplicated(duplicates) => Some(duplicates),
313        }
314    }
315}
316
317impl<K, const N: usize> DuplicateKey<K, N> {
318    /// The caller-declared key that occurred more than once.
319    #[must_use]
320    pub const fn key(&self) -> &K {
321        &self.key
322    }
323
324    /// The zero-based declaration position of the first occurrence.
325    #[must_use]
326    pub const fn first_position(&self) -> usize {
327        self.first
328    }
329
330    /// The zero-based declaration positions of every later occurrence.
331    #[must_use]
332    pub const fn repeated_positions(&self) -> &NonEmpty<usize, N> {
333        &self.repeated
334    }
335}
336
337pub(crate) fn first_duplicate_position<T>(
338    items: &[T],
339    equivalent: impl Fn(&T, &T) -> bool,
340) -> Option<usize> {
341    items.iter().enumerate().find_map(|(position, item)| {
342        items
343            .iter()
344            .take(position)
345            .any(|earlier| equivalent(earlier, item))
346            .then_some(position)
347    })
348}
349
350fn keyed_magnitude_refusal<K, const N: usize>(error: NonEmptyError) -> KeyedRosterError<K, N> {
351    match error {
352        NonEmptyError::Empty(empty) => KeyedRosterError::Empty(empty),
353        NonEmptyError::Overflow(overflow) => KeyedRosterError::Overflow(overflow),
354    }
355}
356
357fn project_keys<T, K, const N: usize>(
358    members: &NonEmpty<T, N>,
359    mut key_of: impl FnMut(&T) -> K,
360) -> NonEmpty<K, N> {
361    let (head, tail) = members.split();
362    NonEmpty {
363        head: key_of(head),
364        tail: tail.iter().map(key_of).collect(),
365    }
366}
367
368fn admit_keys<K: Eq, const N: usize>(keys: NonEmpty<K, N>) -> KeyAdmission<K, N> {
369    let NonEmpty { head, tail } = keys;
370    let mut groups = KeyGroups {
371        head: KeyGroup {
372            key: head,
373            first: 0,
374            repeated: Vec::new(),
375        },
376        tail: Vec::new(),
377    };
378    for (index, key) in tail.into_iter().enumerate() {
379        groups.insert(key, index.saturating_add(1));
380    }
381    groups.admit()
382}
383
384struct KeyGroup<K> {
385    key: K,
386    first: usize,
387    repeated: Vec<usize>,
388}
389
390struct KeyGroups<K> {
391    head: KeyGroup<K>,
392    tail: Vec<KeyGroup<K>>,
393}
394
395enum KeyAdmission<K, const N: usize> {
396    Unique(NonEmpty<K, N>),
397    Duplicated(NonEmpty<DuplicateKey<K, N>, N>),
398}
399
400impl<K: Eq> KeyGroups<K> {
401    fn insert(&mut self, key: K, index: usize) {
402        if self.head.key == key {
403            self.head.repeated.push(index);
404            return;
405        }
406        if let Some(group) = self.tail.iter_mut().find(|group| group.key == key) {
407            group.repeated.push(index);
408            return;
409        }
410        self.tail.push(KeyGroup {
411            key,
412            first: index,
413            repeated: Vec::new(),
414        });
415    }
416
417    fn admit<const N: usize>(self) -> KeyAdmission<K, N> {
418        let mut tail = self.tail.into_iter();
419        let head = match admitted_group(self.head) {
420            Ok(key) => key,
421            Err(duplicate) => {
422                return KeyAdmission::Duplicated(NonEmpty {
423                    head: duplicate,
424                    tail: tail
425                        .filter_map(|group| admitted_group(group).err())
426                        .collect(),
427                });
428            }
429        };
430        let mut unique = Vec::new();
431        while let Some(group) = tail.next() {
432            match admitted_group(group) {
433                Ok(key) => unique.push(key),
434                Err(duplicate) => {
435                    return KeyAdmission::Duplicated(NonEmpty {
436                        head: duplicate,
437                        tail: tail
438                            .filter_map(|remaining| admitted_group(remaining).err())
439                            .collect(),
440                    });
441                }
442            }
443        }
444        KeyAdmission::Unique(NonEmpty { head, tail: unique })
445    }
446}
447
448fn admitted_group<K, const N: usize>(group: KeyGroup<K>) -> Result<K, DuplicateKey<K, N>> {
449    let KeyGroup {
450        key,
451        first,
452        repeated,
453    } = group;
454    let mut repeated = repeated.into_iter();
455    if let Some(repeated_head) = repeated.next() {
456        return Err(DuplicateKey {
457            key,
458            first,
459            repeated: NonEmpty {
460                head: repeated_head,
461                tail: repeated.collect(),
462            },
463        });
464    }
465    Ok(key)
466}
467
468impl<D, K, P, S, const N: usize> KeyedRosterAssignment<D, K, P, S, N> {
469    /// The complete caller-keyed denominator retained by this assignment.
470    #[must_use]
471    pub const fn denominator(&self) -> &KeyedRoster<D, K, N> {
472        &self.denominator
473    }
474
475    /// The payload roster aligned with the denominator and keyed by caller-declared seats.
476    #[must_use]
477    pub const fn payloads(&self) -> &KeyedRoster<P, S, N> {
478        &self.payloads
479    }
480
481    /// How many denominator members and aligned payloads are held.
482    #[must_use]
483    pub fn count(&self) -> usize {
484        self.denominator.count()
485    }
486
487    /// The first denominator member and its assigned payload.
488    #[must_use]
489    pub const fn first(&self) -> (&K, &D, &S, &P) {
490        (
491            self.denominator.first_key(),
492            self.denominator.first(),
493            self.payloads.first_key(),
494            self.payloads.first(),
495        )
496    }
497
498    /// Reads every denominator member and aligned payload in denominator order.
499    pub fn indexed(&self) -> impl Iterator<Item = (usize, &K, &D, &S, &P)> {
500        self.denominator
501            .indexed()
502            .zip(self.payloads.keys().zip(self.payloads.members()))
503            .map(|((index, key, member), (seat, payload))| (index, key, member, seat, payload))
504    }
505
506    /// Reads one denominator member and aligned payload at a checked index.
507    #[must_use]
508    pub fn at(&self, index: usize) -> Option<(&K, &D, &S, &P)> {
509        self.denominator
510            .at(index)
511            .zip(self.payloads.at(index))
512            .map(|((key, member), (seat, payload))| (key, member, seat, payload))
513    }
514
515    /// Finds one denominator member and aligned payload through a borrowed key.
516    #[must_use]
517    pub fn get<Q>(&self, sought: &Q) -> Option<(&D, &S, &P)>
518    where
519        K: Borrow<Q>,
520        Q: Eq + ?Sized,
521    {
522        let index = self.denominator.index_of(sought)?;
523        self.at(index)
524            .map(|(_key, member, seat, payload)| (member, seat, payload))
525    }
526}
527
528impl<D, K: Eq, P, S: Eq, const N: usize> KeyedRosterAssignment<D, K, P, S, N> {
529    /// Completes one payload assignment over an existing caller-keyed denominator.
530    ///
531    /// Payload magnitude is settled before either key projection runs.
532    /// Reference membership and uniqueness are settled before payload-seat keys are projected.
533    ///
534    /// # Errors
535    ///
536    /// Returns [`KeyedRosterAssignmentError`] with the first structural refusal class reached by the declared construction order.
537    pub fn complete(
538        denominator: KeyedRoster<D, K, N>,
539        payloads: Vec<P>,
540        reference_of: impl FnMut(&P) -> K,
541        seat_of: impl FnMut(&P) -> S,
542    ) -> Result<Self, KeyedRosterAssignmentError<K, S, N>> {
543        let payloads = NonEmpty::new(payloads).map_err(assignment_magnitude_refusal::<K, S, N>)?;
544        let references = project_keys(&payloads, reference_of);
545        let (references, positions) = match admit_references(&denominator, references) {
546            ReferenceAdmission::Lawful { keys, positions } => (keys, positions),
547            ReferenceAdmission::Foreign(foreign) => {
548                return Err(KeyedRosterAssignmentError::ForeignReferences(foreign));
549            }
550        };
551        if let KeyAdmission::Duplicated(duplicates) = admit_keys(references) {
552            return Err(KeyedRosterAssignmentError::DuplicateReferences(duplicates));
553        }
554        let seats = project_keys(&payloads, seat_of);
555        let seats = match admit_keys(seats) {
556            KeyAdmission::Unique(seats) => seats,
557            KeyAdmission::Duplicated(duplicates) => {
558                return Err(KeyedRosterAssignmentError::ReusedPayloadSeats(duplicates));
559            }
560        };
561        let denominator = match settle_completeness(denominator, &positions) {
562            AssignmentCompleteness::Complete(denominator) => denominator,
563            AssignmentCompleteness::Missing(missing) => {
564                return Err(KeyedRosterAssignmentError::MissingMembers(missing));
565            }
566        };
567        let payloads = align_payloads(payloads, seats, positions);
568        Ok(Self {
569            denominator,
570            payloads,
571        })
572    }
573}
574
575impl<K> ForeignRosterReference<K> {
576    pub(crate) const fn at(key: K, offered_position: usize) -> Self {
577        Self {
578            key,
579            offered_position,
580        }
581    }
582
583    /// The foreign roster key named by the offered item.
584    #[must_use]
585    pub const fn key(&self) -> &K {
586        &self.key
587    }
588
589    /// The zero-based offered-item position carrying the foreign reference.
590    #[must_use]
591    pub const fn offered_position(&self) -> usize {
592        self.offered_position
593    }
594}
595
596impl<K> UnassignedRosterMember<K> {
597    /// The denominator key for which no payload was offered.
598    #[must_use]
599    pub const fn key(&self) -> &K {
600        &self.key
601    }
602
603    /// The zero-based denominator position for which no payload was offered.
604    #[must_use]
605    pub const fn denominator_position(&self) -> usize {
606        self.denominator_position
607    }
608}
609
610enum ReferenceAdmission<K, const N: usize> {
611    Lawful {
612        keys: NonEmpty<K, N>,
613        positions: NonEmpty<usize, N>,
614    },
615    Foreign(NonEmpty<ForeignRosterReference<K>, N>),
616}
617
618fn admit_references<D, K: Eq, const N: usize>(
619    denominator: &KeyedRoster<D, K, N>,
620    references: NonEmpty<K, N>,
621) -> ReferenceAdmission<K, N> {
622    let NonEmpty { head, tail } = references;
623    let Some(head_position) = denominator.index_of(&head) else {
624        let foreign_tail = tail
625            .into_iter()
626            .enumerate()
627            .filter_map(|(offset, key)| {
628                denominator
629                    .index_of(&key)
630                    .is_none()
631                    .then_some(ForeignRosterReference {
632                        key,
633                        offered_position: offset.saturating_add(1),
634                    })
635            })
636            .collect();
637        return ReferenceAdmission::Foreign(NonEmpty {
638            head: ForeignRosterReference {
639                key: head,
640                offered_position: 0,
641            },
642            tail: foreign_tail,
643        });
644    };
645    admit_references_after_lawful_head(denominator, head, head_position, tail)
646}
647
648fn admit_references_after_lawful_head<D, K: Eq, const N: usize>(
649    denominator: &KeyedRoster<D, K, N>,
650    head: K,
651    head_position: usize,
652    tail: Vec<K>,
653) -> ReferenceAdmission<K, N> {
654    let mut lawful_keys = Vec::new();
655    let mut lawful_positions = Vec::new();
656    let mut foreign_head = None;
657    let mut foreign_tail = Vec::new();
658    for (offset, key) in tail.into_iter().enumerate() {
659        let offered_position = offset.saturating_add(1);
660        if let Some(position) = denominator.index_of(&key) {
661            lawful_keys.push(key);
662            lawful_positions.push(position);
663        } else {
664            let foreign = ForeignRosterReference {
665                key,
666                offered_position,
667            };
668            if foreign_head.is_none() {
669                foreign_head = Some(foreign);
670            } else {
671                foreign_tail.push(foreign);
672            }
673        }
674    }
675    if let Some(foreign) = foreign_head {
676        ReferenceAdmission::Foreign(NonEmpty {
677            head: foreign,
678            tail: foreign_tail,
679        })
680    } else {
681        ReferenceAdmission::Lawful {
682            keys: NonEmpty {
683                head,
684                tail: lawful_keys,
685            },
686            positions: NonEmpty {
687                head: head_position,
688                tail: lawful_positions,
689            },
690        }
691    }
692}
693
694enum AssignmentCompleteness<D, K, const N: usize> {
695    Complete(KeyedRoster<D, K, N>),
696    Missing(NonEmpty<UnassignedRosterMember<K>, N>),
697}
698
699enum KeyCompleteness<K, const N: usize> {
700    Complete(NonEmpty<K, N>),
701    Missing(NonEmpty<UnassignedRosterMember<K>, N>),
702}
703
704enum AssignmentStanding {
705    Assigned,
706    Missing,
707}
708
709fn settle_completeness<D, K, const N: usize>(
710    denominator: KeyedRoster<D, K, N>,
711    positions: &NonEmpty<usize, N>,
712) -> AssignmentCompleteness<D, K, N> {
713    let KeyedRoster { members, keys } = denominator;
714    let NonEmpty { head, tail } = keys;
715    let first_assigned = positions.iter().any(|position| *position == 0);
716    let mut completeness = if first_assigned {
717        KeyCompleteness::Complete(NonEmpty {
718            head,
719            tail: Vec::new(),
720        })
721    } else {
722        KeyCompleteness::Missing(NonEmpty {
723            head: UnassignedRosterMember {
724                key: head,
725                denominator_position: 0,
726            },
727            tail: Vec::new(),
728        })
729    };
730    for (offset, key) in tail.into_iter().enumerate() {
731        let denominator_position = offset.saturating_add(1);
732        let standing = if positions
733            .iter()
734            .any(|position| *position == denominator_position)
735        {
736            AssignmentStanding::Assigned
737        } else {
738            AssignmentStanding::Missing
739        };
740        completeness = completeness.push(key, denominator_position, standing);
741    }
742    match completeness {
743        KeyCompleteness::Complete(complete_keys) => AssignmentCompleteness::Complete(KeyedRoster {
744            members,
745            keys: complete_keys,
746        }),
747        KeyCompleteness::Missing(missing) => AssignmentCompleteness::Missing(missing),
748    }
749}
750
751impl<K, const N: usize> KeyCompleteness<K, N> {
752    fn push(self, key: K, denominator_position: usize, standing: AssignmentStanding) -> Self {
753        match (self, standing) {
754            (Self::Complete(mut keys), AssignmentStanding::Assigned) => {
755                keys.tail.push(key);
756                Self::Complete(keys)
757            }
758            (Self::Complete(_keys), AssignmentStanding::Missing) => Self::Missing(NonEmpty {
759                head: UnassignedRosterMember {
760                    key,
761                    denominator_position,
762                },
763                tail: Vec::new(),
764            }),
765            (Self::Missing(missing), AssignmentStanding::Assigned) => Self::Missing(missing),
766            (Self::Missing(mut missing), AssignmentStanding::Missing) => {
767                missing.tail.push(UnassignedRosterMember {
768                    key,
769                    denominator_position,
770                });
771                Self::Missing(missing)
772            }
773        }
774    }
775}
776
777struct PendingAssignment<P, S> {
778    denominator_position: usize,
779    payload: P,
780    seat: S,
781}
782
783fn align_payloads<P, S, const N: usize>(
784    payloads: NonEmpty<P, N>,
785    seats: NonEmpty<S, N>,
786    positions: NonEmpty<usize, N>,
787) -> KeyedRoster<P, S, N> {
788    let NonEmpty {
789        head: payload_head,
790        tail: payload_tail,
791    } = payloads;
792    let NonEmpty {
793        head: seat_head,
794        tail: seat_tail,
795    } = seats;
796    let NonEmpty {
797        head: position_head,
798        tail: position_tail,
799    } = positions;
800    let mut head = PendingAssignment {
801        denominator_position: position_head,
802        payload: payload_head,
803        seat: seat_head,
804    };
805    let mut tail = position_tail
806        .into_iter()
807        .zip(payload_tail)
808        .zip(seat_tail)
809        .map(
810            |((denominator_position, payload), seat)| PendingAssignment {
811                denominator_position,
812                payload,
813                seat,
814            },
815        )
816        .collect::<Vec<_>>();
817    for assignment in &mut tail {
818        if assignment.denominator_position < head.denominator_position {
819            core::mem::swap(&mut head, assignment);
820        }
821    }
822    tail.sort_by_key(|assignment| assignment.denominator_position);
823    let mut ordered_payload_tail = Vec::with_capacity(tail.len());
824    let mut ordered_seat_tail = Vec::with_capacity(tail.len());
825    for assignment in tail {
826        ordered_payload_tail.push(assignment.payload);
827        ordered_seat_tail.push(assignment.seat);
828    }
829    KeyedRoster {
830        members: NonEmpty {
831            head: head.payload,
832            tail: ordered_payload_tail,
833        },
834        keys: NonEmpty {
835            head: head.seat,
836            tail: ordered_seat_tail,
837        },
838    }
839}
840
841fn assignment_magnitude_refusal<K, S, const N: usize>(
842    error: NonEmptyError,
843) -> KeyedRosterAssignmentError<K, S, N> {
844    match error {
845        NonEmptyError::Empty(empty) => KeyedRosterAssignmentError::Empty(empty),
846        NonEmptyError::Overflow(overflow) => KeyedRosterAssignmentError::Overflow(overflow),
847    }
848}
849
850impl<T, const N: usize> Capped<T, N> {
851    /// A capped collection that kept its complete lawful offering.
852    #[must_use]
853    pub const fn all(items: NonEmpty<T, N>) -> Self {
854        Self {
855            items,
856            capping: Capping::Complete,
857        }
858    }
859
860    /// Keeps the first item and the ordered prefix of the rest that fits, then records the exact omitted count.
861    #[must_use]
862    pub fn first_n(first: T, rest: impl Iterator<Item = T>) -> Self {
863        const {
864            assert!(N >= 1, "a capped list under a ceiling that admits no item");
865        }
866        let mut tail = Vec::new();
867        let mut omitted = 0_usize;
868        for item in rest {
869            if tail.len() < N.saturating_sub(1) {
870                tail.push(item);
871            } else {
872                omitted = omitted.saturating_add(1);
873            }
874        }
875        Self {
876            items: NonEmpty { head: first, tail },
877            capping: capping_over(omitted),
878        }
879    }
880
881    /// The items the list kept.
882    #[must_use]
883    pub const fn items(&self) -> &NonEmpty<T, N> {
884        &self.items
885    }
886
887    /// Whether the list kept everything offered to it.
888    #[must_use]
889    pub const fn capping(&self) -> Capping {
890        self.capping
891    }
892}
893
894/// Reads the capping off the exact count of what was dropped.
895const fn capping_over(omitted: usize) -> Capping {
896    if omitted == 0 {
897        Capping::Complete
898    } else {
899        Capping::Truncated { omitted }
900    }
901}