use crate::TryExtendOne;
pub fn try_extend_basic<T, C, I>(map: &mut C, iter: &mut I) -> Result<(), C::Error>
where
I: Iterator<Item = T>,
C: TryExtendOne<Item = T>,
{
iter.try_for_each(|item| map.try_extend_one(item))
}
macro_rules! impl_try_from_iter_via_try_extend_one {
(
type: $type:ty where [$($generics:tt)*] of $item:ty;
ctor: $ctor:expr
) => {
impl<$($generics)*, I> $crate::TryFromIterator<I> for $type
where
I: IntoIterator<Item = $item>,
{
type Error = $crate::errors::CollectError<I::IntoIter, Self, <Self as $crate::TryExtendOne>::Error>;
fn try_from_iter(into_iter: I) -> Result<Self, Self::Error>
where
Self: Sized,
{
let mut iter = into_iter.into_iter();
let mut collection = $crate::impls::macros::infer_ctor::<I, Self, _>($ctor)(&iter);
match $crate::impls::macros::try_extend_basic(&mut collection, &mut iter) {
Ok(()) => Ok(collection),
Err(err) => Err($crate::errors::CollectError::new(iter, collection, err)),
}
}
}
};
}
pub const fn infer_ctor<I: IntoIterator, C, F: Fn(&I::IntoIter) -> C>(f: F) -> F {
f
}
macro_rules! impl_try_extend_via_try_extend_one {
(
type: $type:ty where [$($generics:tt)*] of $item:ty;
reserve: $reserve:expr
) => {
impl<$($generics)*, I> $crate::TryExtend<I> for $type
where
I: IntoIterator<Item = $item>,
{
type Error = $crate::errors::ExtendError<I::IntoIter, <Self as $crate::TryExtendOne>::Error>;
fn try_extend(&mut self, into_iter: I) -> Result<(), Self::Error>
where
Self: Sized,
{
let mut iter = into_iter.into_iter();
$crate::impls::macros::infer_reserve::<I, Self, _>($reserve)(self, &mut iter);
$crate::impls::macros::try_extend_basic(self, &mut iter)
.map_err(|err| $crate::errors::ExtendError::new(iter, err))
}
}
};
}
pub const fn infer_reserve<I: IntoIterator, C, F: Fn(&mut C, &I::IntoIter)>(f: F) -> F {
f
}
macro_rules! impl_try_extend_safe_for_colliding_type {
(
type: $type:ty where [$($generics:tt)*] of $item:ty;
build_staging: $build_staging:expr;
contains: $contains:expr
) => {
impl<$($generics)*, I> $crate::TryExtendSafe<I> for $type
where
I: IntoIterator<Item = $item>,
{
type Error = $crate::errors::CollectError<I::IntoIter, Self, <Self as $crate::TryExtendOne>::Error>;
fn try_extend_safe(&mut self, iter: I) -> Result<(), Self::Error> {
let mut iter = iter.into_iter();
let staging = $crate::impls::macros::infer_build_staging::<Self, I, _>($build_staging)(&iter, self);
let contains = $crate::impls::macros::infer_contains::<Self, $item, _>($contains);
iter.try_fold(staging, |mut staging, item| {
match contains(self, &item) {
true => Err((staging, $crate::errors::collision::Collision::new(item))),
false => match $crate::TryExtendOne::try_extend_one(&mut staging, item) {
Ok(()) => Ok(staging),
Err(err) => Err((staging, err)),
},
}
})
.map(|staging| ::core::iter::Extend::extend(self, staging))
.map_err(|(staging, err)| $crate::errors::CollectError::new(iter, staging, err))
}
}
};
}
pub const fn infer_build_staging<C, I: IntoIterator, F: Fn(&I::IntoIter, &mut C) -> C>(f: F) -> F {
f
}
pub const fn infer_contains<C, T, F: Fn(&C, &T) -> bool>(f: F) -> F {
f
}
macro_rules! impl_try_extend_one_for_colliding_type {
(
type: $type:ty where [$($generics:tt)*] of $item:ty;
contains: $contains:expr;
insert: $insert:expr
) => {
impl<$($generics)*> $crate::TryExtendOne for $type {
type Item = $item;
type Error = $crate::errors::Collision<$item>;
fn try_extend_one(&mut self, item: Self::Item) -> Result<(), Self::Error> {
match $crate::impls::macros::infer_contains::<Self, $item, _>($contains)(self, &item) {
true => Err($crate::errors::Collision::new(item)),
false => {
$crate::impls::macros::infer_insert::<Self, $item, _>($insert)(self, item);
Ok(())
}
}
}
}
};
}
pub const fn infer_insert<C, T, F: Fn(&mut C, T)>(f: F) -> F {
f
}
pub(crate) use impl_try_extend_one_for_colliding_type;
pub(crate) use impl_try_extend_safe_for_colliding_type;
pub(crate) use impl_try_extend_via_try_extend_one;
pub(crate) use impl_try_from_iter_via_try_extend_one;