pub trait IntoIteratorExt: IntoIterator + Sized {
fn chain_if<C>(self, cond: bool, iter: C) -> ChainIf<Self, C>
where
C: IntoIterator<Item = Self::Item>,
{
self.chain_if_with(cond, || iter)
}
fn chain_if_else<I, E>(self, cond: bool, iter_if: I, iter_else: E) -> ChainIfElse<Self, I, E>
where
I: IntoIterator<Item = Self::Item>,
E: IntoIterator<Item = Self::Item>,
{
self.chain_if_else_with(cond, || iter_if, || iter_else)
}
fn chain_if_with<F, C>(self, cond: bool, fun: F) -> ChainIf<Self, C>
where
F: FnOnce() -> C,
C: IntoIterator<Item = Self::Item>;
fn chain_if_else_with<FI, I, FE, E>(
self,
cond: bool,
fun_if: FI,
fun_else: FE,
) -> ChainIfElse<Self, I, E>
where
FI: FnOnce() -> I,
I: IntoIterator<Item = Self::Item>,
FE: FnOnce() -> E,
E: IntoIterator<Item = Self::Item>;
}
impl<T> IntoIteratorExt for T
where
T: IntoIterator + Sized,
{
fn chain_if_with<F, C>(self, cond: bool, fun: F) -> ChainIf<Self, C>
where
F: FnOnce() -> C,
C: IntoIterator<Item = Self::Item>,
{
if cond {
ChainIf::Chained(self.into_iter(), fun().into_iter())
} else {
ChainIf::Original(self.into_iter())
}
}
fn chain_if_else_with<FI, I, FE, E>(
self,
cond: bool,
fun_if: FI,
fun_else: FE,
) -> ChainIfElse<Self, I, E>
where
FI: FnOnce() -> I,
I: IntoIterator<Item = Self::Item>,
FE: FnOnce() -> E,
E: IntoIterator<Item = Self::Item>,
{
if cond {
ChainIfElse::If(self.into_iter(), fun_if().into_iter())
} else {
ChainIfElse::Else(self.into_iter(), fun_else().into_iter())
}
}
}
pub enum ChainIf<O, C>
where
O: IntoIterator,
C: IntoIterator<Item = O::Item>,
{
Chained(O::IntoIter, C::IntoIter),
Original(O::IntoIter),
}
impl<O, C> Iterator for ChainIf<O, C>
where
O: IntoIterator,
C: IntoIterator<Item = O::Item>,
{
type Item = O::Item;
fn next(&mut self) -> Option<Self::Item> {
match self {
ChainIf::Chained(original, chained) => original.next().or_else(|| chained.next()),
ChainIf::Original(original) => original.next(),
}
}
}
pub enum ChainIfElse<O, I, E>
where
O: IntoIterator,
I: IntoIterator<Item = O::Item>,
E: IntoIterator<Item = O::Item>,
{
If(O::IntoIter, I::IntoIter),
Else(O::IntoIter, E::IntoIter),
}
impl<O, I, E> Iterator for ChainIfElse<O, I, E>
where
O: IntoIterator,
I: IntoIterator<Item = O::Item>,
E: IntoIterator<Item = O::Item>,
{
type Item = O::Item;
fn next(&mut self) -> Option<Self::Item> {
match self {
ChainIfElse::If(original, other) => original.next().or_else(|| other.next()),
ChainIfElse::Else(original, other) => original.next().or_else(|| other.next()),
}
}
}