#![doc = include_str!("README.md")]
#![no_std]
use core::marker::PhantomData;
use replace_with::replace_with_or_abort_and_return;
type IdFn<X> = fn(X) -> X;
type DupFn<X> = fn(X) -> (X, X);
type Tpl2<X> = (X, X);
pub trait IterScan: Iterator + Sized {
fn scan_clone<Compute, State>(
self,
initial: State,
compute: Compute,
) -> Scan<Self, DupFn<State>, Compute, State>
where
State: Clone,
Compute: FnMut(State, Self::Item) -> State,
{
Scan {
compute,
iter: self,
state: initial,
duplicate: |x| (x.clone(), x),
_phantom: Default::default(),
}
}
fn scan_copy<Compute, State>(
self,
initial: State,
compute: Compute,
) -> Scan<Self, DupFn<State>, Compute, State>
where
State: Copy,
Compute: FnMut(State, Self::Item) -> State,
{
Scan {
compute,
iter: self,
state: initial,
duplicate: |x| (x, x),
_phantom: Default::default(),
}
}
fn scan_with_tuple<Compute, State>(
self,
initial: State,
compute: Compute,
) -> Scan<Self, IdFn<Tpl2<State>>, Compute, State>
where
Compute: FnMut(State, Self::Item) -> Tpl2<State>,
{
Scan {
compute,
iter: self,
state: initial,
duplicate: |x| x,
_phantom: Default::default(),
}
}
}
impl<X: Iterator + Sized> IterScan for X {}
#[derive(Clone)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct Scan<Iter, Duplicate, Compute, State> {
iter: Iter,
state: State,
duplicate: Duplicate,
compute: Compute,
_phantom: PhantomData<State>,
}
impl<Iter, Duplicate, Compute, State, Intermediate> Iterator
for Scan<Iter, Duplicate, Compute, State>
where
Iter: Iterator,
Duplicate: FnMut(Intermediate) -> Tpl2<State>,
Compute: FnMut(State, Iter::Item) -> Intermediate,
{
type Item = State;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let Scan {
iter,
state,
duplicate,
compute,
..
} = self;
let x = iter.next()?;
let f = |state| duplicate(compute(state, x));
let y = replace_with_or_abort_and_return(state, f);
Some(y)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (_, upper) = self.iter.size_hint();
(0, upper) }
}