13.3 Creating Custom Iterators
Although the standard library covers most common scenarios, you may occasionally need a custom iterator for specialized data structures. To create your own iterator:
- Define a struct to keep track of iteration state.
- Implement the
Iterator
trait, writing anext()
method that yields items until no more remain.
13.3.1 A Simple Range-Like Iterator
#![allow(unused)] fn main() { struct MyRange { current: u32, end: u32, } impl MyRange { fn new(start: u32, end: u32) -> Self { MyRange { current: start, end } } } }
13.3.2 Implementing the Iterator
Trait
#![allow(unused)] fn main() { impl Iterator for MyRange { type Item = u32; fn next(&mut self) -> Option<Self::Item> { if self.current < self.end { let result = self.current; self.current += 1; Some(result) } else { None } } } }
13.3.3 Using a Custom Iterator
struct MyRange { current: u32, end: u32, } impl MyRange { fn new(start: u32, end: u32) -> Self { MyRange { current: start, end } } } impl Iterator for MyRange { type Item = u32; fn next(&mut self) -> Option<Self::Item> { if self.current < self.end { let result = self.current; self.current += 1; Some(result) } else { None } } } fn main() { let range = MyRange::new(10, 15); for number in range { print!("{} ", number); } // 10 11 12 13 14 }
13.3.4 A Fibonacci Iterator
#![allow(unused)] fn main() { struct Fibonacci { current: u32, next: u32, max: u32, } impl Fibonacci { fn new(max: u32) -> Self { Fibonacci { current: 0, next: 1, max, } } } impl Iterator for Fibonacci { type Item = u32; fn next(&mut self) -> Option<Self::Item> { if self.current > self.max { None } else { let new_next = self.current + self.next; let result = self.current; self.current = self.next; self.next = new_next; Some(result) } } } }