use super::{Bounded, Capped, Capping, Empty, NonEmpty, NonEmptyError, Overflow};
impl<T, const N: usize> Bounded<T, N> {
#[must_use]
pub const fn empty() -> Self {
Self(Vec::new())
}
pub fn new(items: Vec<T>) -> Result<Self, Overflow> {
if items.len() <= N {
Ok(Self(items))
} else {
Err(Overflow {
capacity: N,
offered: items.len(),
})
}
}
#[must_use]
pub fn from_array<const M: usize>(items: [T; M]) -> Self {
const {
assert!(
M <= N,
"a fixed list longer than the ceiling it is declared under"
);
}
Self(Vec::from(items))
}
#[must_use]
pub fn as_slice(&self) -> &[T] {
self.0.as_slice()
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.0.iter()
}
#[must_use]
pub fn len(&self) -> usize {
self.0.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn try_push(&mut self, item: T) -> Result<(), Overflow> {
let offered = self.0.len().saturating_add(1);
if offered > N {
return Err(Overflow {
capacity: N,
offered,
});
}
self.0.push(item);
Ok(())
}
}
impl<T, const N: usize> NonEmpty<T, N> {
#[must_use]
pub const fn one(value: T) -> Self {
const {
assert!(
N >= 1,
"a non-empty list under a ceiling that admits no item"
);
}
Self {
head: value,
tail: Vec::new(),
}
}
pub fn new(items: Vec<T>) -> Result<Self, NonEmptyError> {
let offered = items.len();
let mut rest = items.into_iter();
let Some(head) = rest.next() else {
return Err(NonEmptyError::Empty(Empty));
};
if offered <= N {
Ok(Self {
head,
tail: rest.collect(),
})
} else {
Err(NonEmptyError::Overflow(Overflow {
capacity: N,
offered,
}))
}
}
#[must_use]
pub const fn first(&self) -> &T {
&self.head
}
#[must_use]
pub fn split(&self) -> (&T, &[T]) {
(&self.head, self.tail.as_slice())
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.into_iter()
}
#[must_use]
pub fn count(&self) -> usize {
self.tail.len().saturating_add(1)
}
}
impl<'held, T, const N: usize> IntoIterator for &'held NonEmpty<T, N> {
type Item = &'held T;
type IntoIter = core::iter::Chain<core::iter::Once<&'held T>, core::slice::Iter<'held, T>>;
fn into_iter(self) -> Self::IntoIter {
core::iter::once(&self.head).chain(self.tail.iter())
}
}
impl<T, const N: usize> Capped<T, N> {
#[must_use]
pub const fn all(items: NonEmpty<T, N>) -> Self {
Self {
items,
capping: Capping::Complete,
}
}
#[must_use]
pub fn first_n(first: T, rest: impl Iterator<Item = T>) -> Self {
const {
assert!(N >= 1, "a capped list under a ceiling that admits no item");
}
let mut tail = Vec::new();
let mut omitted = 0_usize;
for item in rest {
if tail.len() < N.saturating_sub(1) {
tail.push(item);
} else {
omitted = omitted.saturating_add(1);
}
}
Self {
items: NonEmpty { head: first, tail },
capping: capping_over(omitted),
}
}
#[must_use]
pub const fn items(&self) -> &NonEmpty<T, N> {
&self.items
}
#[must_use]
pub const fn capping(&self) -> Capping {
self.capping
}
}
const fn capping_over(omitted: usize) -> Capping {
if omitted == 0 {
Capping::Complete
} else {
Capping::Truncated { omitted }
}
}