use std::fmt::Debug; use std::iter::Peekable; pub trait IteratorExt: Sized + Iterator { /// Returns an iterator over overlapping item tuples. fn windows(self) -> Windows; } impl IteratorExt for Iter where Iter::Item: Clone, { fn windows(self) -> Windows { Windows { iter: self.peekable(), } } } pub struct Windows { iter: Peekable, } impl Iterator for Windows where Iter::Item: Clone + Debug, { type Item = (Iter::Item, Option); fn next(&mut self) -> Option { let opt_first = self.iter.next(); let opt_second = self.iter.peek(); let Some(first) = opt_first else { return None; }; Some((first, opt_second.cloned())) } } #[cfg(test)] mod tests { use pretty_assertions::assert_eq; use super::*; #[test] fn windows_works() { let mut windows = (0..6).windows(); assert_eq!(windows.next(), Some((0, Some(1)))); assert_eq!(windows.next(), Some((1, Some(2)))); assert_eq!(windows.next(), Some((2, Some(3)))); assert_eq!(windows.next(), Some((3, Some(4)))); assert_eq!(windows.next(), Some((4, Some(5)))); assert_eq!(windows.next(), Some((5, None))); } }