Iterators
Implementing Custom Iterators
To create a custom iterator in Rust, define a struct that holds the iteration state and implement std::iter::Iterator by specifying type Item and fn next(&mut self) -> Option<Self::Item>.
Step-by-Step Implementation of a Stateful Iterator
struct StepRange {
current: i64,
end: i64,
step: i64,
}
impl StepRange {
fn new(start: i64, end: i64, step: i64) -> Self {
assert!(step > 0, "step must be positive");
Self {
current: start,
end,
step,
}
}
}
impl Iterator for StepRange {
type Item = i64;
fn next(&mut self) -> Option<Self::Item> {
if self.current >= self.end {
return None;
}
let value = self.current;
self.current += self.step;
Some(value)
}
fn size_hint(&self) -> (usize, Option<usize>) {
if self.current >= self.end {
(0, Some(0))
} else {
let remaining = ((self.end - self.current + self.step - 1) / self.step) as usize;
(remaining, Some(remaining))
}
}
}
impl ExactSizeIterator for StepRange {}
fn main() {
let iter = StepRange::new(0, 15, 4);
println!("Exact length: {}", iter.len());
let collected: Vec<i64> = iter.collect();
println!("Values: {collected:?}");
}
Exact length: 4
Values: [0, 4, 8, 12]
Implementing DoubleEndedIterator
If your custom iterator can also yield items from the back without colliding with the front cursor, implement DoubleEndedIterator by defining next_back(&mut self):
struct IndexWindow {
front: usize,
back: usize, // Exclusive upper bound
}
impl Iterator for IndexWindow {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
if self.front >= self.back {
None
} else {
let idx = self.front;
self.front += 1;
Some(idx)
}
}
}
impl DoubleEndedIterator for IndexWindow {
fn next_back(&mut self) -> Option<Self::Item> {
if self.front >= self.back {
None
} else {
self.back -= 1;
Some(self.back)
}
}
}
fn main() {
let mut win = IndexWindow { front: 10, back: 14 };
println!("front: {:?}", win.next());
println!("back: {:?}", win.next_back());
let rest_reversed: Vec<usize> = win.rev().collect();
println!("rest (rev): {rest_reversed:?}");
}
front: Some(10)
back: Some(13)
rest (rev): [12, 11]
Quick One-Off Iterators with std::iter::from_fn and successors
When you do not need a named iterator type in a public API, the standard library provides two generator functions in std::iter that build an Iterator directly from a closure:
std::iter::from_fn(f: impl FnMut() -> Option<T>): Calls the stateful closure on each.next()until it returnsNone.std::iter::successors(first: Option<T>, succ: impl FnMut(&T) -> Option<T>): Generates each subsequent element from a reference to the previous element.