use std::marker::PhantomData;
#[derive(Debug)]
pub enum Finite {}
#[derive(Debug)]
pub enum Infinite {}
#[derive(Debug)]
pub enum Unknown {}
pub type FiniteIterator<I> = TrackedIterator<I, Finite>;
#[expect(unused)]
pub type InfiniteIterator<I> = TrackedIterator<I, Infinite>;
#[expect(unused)]
pub type UnknownIterator<I> = TrackedIterator<I, Unknown>;
#[derive(Debug)]
pub struct TrackedIterator<I: Iterator, F> {
pub(crate) inner: I,
pub(crate) _marker: PhantomData<F>,
}
impl<I: Iterator, F> Iterator for TrackedIterator<I, F> {
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
}
pub trait IntoTrackedIterator: Iterator + Sized {
fn into_tracked(self) -> TrackedIterator<Self, Unknown> {
TrackedIterator {
inner: self,
_marker: PhantomData,
}
}
}
impl<I: Iterator> IntoTrackedIterator for I {}
impl<I: Iterator, F> TrackedIterator<I, F> {
pub fn take(self, n: usize) -> TrackedIterator<std::iter::Take<I>, Finite> {
TrackedIterator {
inner: self.inner.take(n),
_marker: PhantomData,
}
}
pub fn map<B, Func>(self, f: Func) -> TrackedIterator<std::iter::Map<I, Func>, F>
where
Func: FnMut(I::Item) -> B,
{
TrackedIterator {
inner: self.inner.map(f),
_marker: PhantomData,
}
}
pub fn filter<Pred>(self, predicate: Pred) -> TrackedIterator<std::iter::Filter<I, Pred>, F>
where
Pred: FnMut(&I::Item) -> bool,
{
TrackedIterator {
inner: self.inner.filter(predicate),
_marker: PhantomData,
}
}
}
impl<T> From<Vec<T>> for TrackedIterator<std::vec::IntoIter<T>, Finite> {
fn from(vec: Vec<T>) -> Self {
TrackedIterator {
inner: vec.into_iter(),
_marker: PhantomData,
}
}
}
impl<'a, T> From<&'a [T]> for TrackedIterator<std::slice::Iter<'a, T>, Finite> {
fn from(slice: &'a [T]) -> Self {
TrackedIterator {
inner: slice.iter(),
_marker: PhantomData,
}
}
}