use std::ops::Range;
pub trait HasRestLen {
fn rest_len(&self) -> usize;
}
pub struct IterWithRange<I> {
original_len: usize,
inner: I,
}
impl<I> IterWithRange<I> {
pub fn original_len(&self) -> usize {
self.original_len
}
pub fn inner(&self) -> &I {
&self.inner
}
pub fn inner_mut(&mut self) -> &mut I {
&mut self.inner
}
#[inline(always)]
pub fn pos(&self) -> usize
where
I: HasRestLen,
{
self.original_len - self.inner.rest_len()
}
}
impl<I: Iterator> Iterator for IterWithRange<I>
where
I: HasRestLen,
{
type Item = (Range<usize>, I::Item);
fn next(&mut self) -> Option<Self::Item> {
let pos_before = self.pos();
let item = self.inner.next()?;
let pos_after = self.pos();
Some((pos_before..pos_after, item))
}
}
pub trait IteratorWithRangesExt: Sized {
fn with_ranges(self) -> IterWithRange<Self>;
}
impl<I> IteratorWithRangesExt for I
where
I: Iterator + HasRestLen,
{
fn with_ranges(self) -> IterWithRange<Self> {
IterWithRange {
original_len: self.rest_len(),
inner: self,
}
}
}