diff options
Diffstat (limited to 'src/iter.rs')
-rw-r--r-- | src/iter.rs | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/iter.rs b/src/iter.rs new file mode 100644 index 0000000..650dceb --- /dev/null +++ b/src/iter.rs @@ -0,0 +1,65 @@ +use std::fmt::Debug; +use std::iter::Peekable; + +pub trait IteratorExt: Sized + Iterator +{ + /// Returns an iterator over overlapping item tuples. + fn windows(self) -> Windows<Self>; +} + +impl<Iter: Iterator> IteratorExt for Iter +where + Iter::Item: Clone, +{ + fn windows(self) -> Windows<Self> + { + Windows { + iter: self.peekable(), + } + } +} + +pub struct Windows<Iter: Iterator> +{ + iter: Peekable<Iter>, +} + +impl<Iter: Iterator> Iterator for Windows<Iter> +where + Iter::Item: Clone + Debug, +{ + type Item = (Iter::Item, Option<Iter::Item>); + + fn next(&mut self) -> Option<Self::Item> + { + 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))); + } +} |