I already wanted to skip some range. The best in my opinion is to create an iterator:
mod skip_range {
use std::ops::Range;
use std::iter::Skip;
/// Either the user provided iterator, or a `Skip` one.
enum Either<I: Iterator> {
Iter(I),
Skip(Skip<I>),
}
pub struct SkipRange<I: Iterator> {
it: Option<Either<I>>,
count: usize,
range: Range<usize>,
}
impl<I: Iterator> SkipRange<I> {
pub fn new(it: I, range: Range<usize>) -> Self {
SkipRange { it: Some(Either::Iter(it)), count: 0, range }
}
}
impl<I: Iterator> Iterator for SkipRange<I> {
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
// If we are in the part we must skip, change the iterator to `Skip`
if self.count == self.range.start {
self.count = self.range.end;
if let Some(Either::Iter(it)) = self.it.take() {
self.it = Some(Either::Skip(it.skip(self.range.end - self.range.start)));
}
} else {
self.count += 1;
}
match &mut self.it {
Some(Either::Iter(it)) => it.next(),
Some(Either::Skip(it)) => it.next(),
_ => unreachable!(),
}
}
}
}
use skip_range::SkipRange;
fn main() {
let v = vec![0, 1, 2, 3, 4, 5];
let it = SkipRange::new(v.into_iter(), 2..4);
let res: Vec<_> = it.collect();
assert_eq!(res, vec![0, 1, 4, 5]);
}
The principle is to use 2 different iterators: the first one is given by the user, the second one is a Skip
iterator, created from the first one.