use arrayvec::ArrayVec;
use fluent_result::into::IntoResult;
use tap::Pipe;
use crate::TryExtendOne;
use crate::errors::capacity::{FixedCap, RemainingCap};
use crate::errors::types::SizeHint;
use crate::errors::{CapacityError, CollectError, ExtendError};
use crate::impls::ensure_empty::{EnsureEmpty, NotEmpty};
use crate::{TryExtend, TryExtendSafe, TryFromIterator};
impl<T, const N: usize> RemainingCap for ArrayVec<T, N> {
fn remaining_cap(&self) -> SizeHint {
self.remaining_capacity().pipe(SizeHint::at_most)
}
}
impl<T, const N: usize> FixedCap for ArrayVec<T, N> {
const CAP: SizeHint = SizeHint::at_most(N);
}
impl<T, I, const N: usize> TryFromIterator<I> for ArrayVec<T, N>
where
I: IntoIterator<Item = T>,
{
type Error = CollectError<I::IntoIter, Self, CapacityError<T>>;
fn try_from_iter(into_iter: I) -> Result<Self, Self::Error> {
let iter = into_iter.into_iter();
CollectError::ensure_fits_in::<Self>(iter).and_then(|mut iter| {
let array_vec = iter.by_ref().take(N).collect::<Self>();
match iter.ensure_empty() {
Ok(()) => Ok(array_vec),
Err(NotEmpty { iter, item }) => CollectError::collect_overflow::<Self>(iter, array_vec, item).into_err(),
}
})
}
}
impl<T, const N: usize, I> TryExtend<I> for ArrayVec<T, N>
where
I: IntoIterator<Item = T>,
{
type Error = ExtendError<I::IntoIter, CapacityError<T>>;
fn try_extend(&mut self, iter: I) -> Result<(), Self::Error> {
let iter = iter.into_iter();
ExtendError::ensure_fits_into(iter, self)
.and_then(|mut iter| iter.try_for_each(|item| self.try_extend_one(item)).map_err(|err| ExtendError::new(iter, err)))
}
}
impl<T, const N: usize, I> TryExtendSafe<I> for ArrayVec<T, N>
where
I: IntoIterator<Item = T>,
{
type Error = CollectError<I::IntoIter, Self, CapacityError<T>>;
fn try_extend_safe(&mut self, iter: I) -> Result<(), Self::Error> {
let iter = iter.into_iter();
CollectError::ensure_fits_into(iter, self).and_then(|mut iter| {
let len = self.len();
iter.try_for_each(|item| self.try_push(item))
.map_err(|err| CollectError::overflow_remaining_cap(iter, self.drain(len..).collect(), err.element(), self))
})
}
}
impl<T, const N: usize> crate::TryExtendOne for ArrayVec<T, N> {
type Item = T;
type Error = CapacityError<T>;
fn try_extend_one(&mut self, item: Self::Item) -> Result<(), Self::Error> {
self.try_push(item).map_err(Into::into)
}
}