#![cfg_attr(not(feature = "std"), no_std)]
use core::fmt;
use arrayvec::ArrayVec;
pub const fn new<T, const N: usize>() -> ArrayBuilder<T, N> {
ArrayBuilder::new()
}
#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ArrayBuilder<T, const N: usize> {
inner: arrayvec::ArrayVec<T, N>,
excess: usize,
}
impl<T, const N: usize> ArrayBuilder<T, N> {
pub const fn new() -> Self {
Self {
inner: ArrayVec::new_const(),
excess: 0,
}
}
pub fn push(&mut self, item: T) -> &mut Self {
if self.inner.try_push(item).is_err() {
self.excess += 1
};
self
}
fn pad_with(&mut self, mut f: impl FnMut() -> T) {
for _ in 0..self.inner.remaining_capacity() {
self.inner.push(f())
}
}
fn error(&self) -> Error {
Error {
expected: N,
actual: self.inner.len() + self.excess,
}
}
pub fn build_pad(&mut self, item: T) -> Result<[T; N], Error>
where
T: Clone,
{
if self.excess > 0 {
return Err(self.error());
}
self.pad_with(|| item.clone());
match self.inner.take().into_inner() {
Ok(it) => Ok(it),
Err(_) => unreachable!("we've just padded"),
}
}
pub fn build_pad_truncate(&mut self, item: T) -> [T; N]
where
T: Clone,
{
self.pad_with(|| item.clone());
self.excess = 0;
match self.inner.take().into_inner() {
Ok(it) => it,
Err(_) => unreachable!("we've just padded"),
}
}
pub fn build_truncate(&mut self) -> Result<[T; N], Error> {
match self.inner.remaining_capacity() == 0 {
true => match self.inner.take().into_inner() {
Ok(it) => Ok(it),
Err(_) => unreachable!("we've just checked the capacity"),
},
false => Err(self.error()),
}
}
pub fn build_exact(&mut self) -> Result<[T; N], Error> {
if self.inner.remaining_capacity() == 0 && self.excess == 0 {
match self.inner.take().into_inner() {
Ok(it) => Ok(it),
Err(_) => unreachable!("remaining capacity is zero"),
}
} else {
Err(self.error())
}
}
pub fn as_slice(&self) -> &[T] {
self.inner.as_slice()
}
pub fn as_mut_slice(&mut self) -> &mut [T] {
self.inner.as_mut_slice()
}
}
impl<T, const N: usize> Extend<T> for ArrayBuilder<T, N> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
for it in iter {
self.push(it);
}
}
}
impl<T, const N: usize> FromIterator<T> for ArrayBuilder<T, N> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let mut this = Self::new();
this.extend(iter);
this
}
}
#[derive(Debug, Clone)]
pub struct Error {
expected: usize,
actual: usize,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { expected, actual } = self;
let snip = match actual < expected {
true => "few",
false => "many",
};
f.write_fmt(format_args!(
"too {} elements for array, needed {} but got {}",
snip, expected, actual
))
}
}
#[cfg(feature = "std")]
impl std::error::Error for Error {}