use core::iter::FusedIterator;
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct ShuntingMap<I, F> {
iter: I,
f: F,
}
pub enum Direction {
Forwards,
Backwards,
}
#[allow(clippy::module_name_repetitions)]
pub(crate) trait ShuntingMapExt: Sized + Iterator {
fn shunting_map<F: FnMut(Self::Item, Direction) -> U, U>(self, f: F) -> ShuntingMap<Self, F> {
ShuntingMap { iter: self, f }
}
}
impl<I: Iterator> ShuntingMapExt for I {}
impl<I: Iterator, F, U> Iterator for ShuntingMap<I, F>
where
F: FnMut(I::Item, Direction) -> U,
{
type Item = U;
fn next(&mut self) -> Option<Self::Item> {
self.iter
.next()
.map(|item| (self.f)(item, Direction::Forwards))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<I: DoubleEndedIterator, F, U> DoubleEndedIterator for ShuntingMap<I, F>
where
F: FnMut(I::Item, Direction) -> U,
{
fn next_back(&mut self) -> Option<Self::Item> {
self.iter
.next_back()
.map(|item| (self.f)(item, Direction::Backwards))
}
}
impl<I: ExactSizeIterator, F, U> ExactSizeIterator for ShuntingMap<I, F> where
F: FnMut(I::Item, Direction) -> U
{
}
impl<I: FusedIterator, F, U> FusedIterator for ShuntingMap<I, F> where
F: FnMut(I::Item, Direction) -> U
{
}