aboutsummaryrefslogtreecommitdiff
path: root/src/iter.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/iter.rs')
-rw-r--r--src/iter.rs65
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)));
+ }
+}