]> git.proxmox.com Git - rustc.git/blobdiff - vendor/itertools-0.8.2/src/zip_longest.rs
New upstream version 1.52.1+dfsg1
[rustc.git] / vendor / itertools-0.8.2 / src / zip_longest.rs
diff --git a/vendor/itertools-0.8.2/src/zip_longest.rs b/vendor/itertools-0.8.2/src/zip_longest.rs
new file mode 100644 (file)
index 0000000..68a381a
--- /dev/null
@@ -0,0 +1,78 @@
+use std::cmp::Ordering::{Equal, Greater, Less};
+use super::size_hint;
+use std::iter::Fuse;
+
+use either_or_both::EitherOrBoth;
+
+// ZipLongest originally written by SimonSapin,
+// and dedicated to itertools https://github.com/rust-lang/rust/pull/19283
+
+/// An iterator which iterates two other iterators simultaneously
+///
+/// This iterator is *fused*.
+///
+/// See [`.zip_longest()`](../trait.Itertools.html#method.zip_longest) for more information.
+#[derive(Clone, Debug)]
+#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+pub struct ZipLongest<T, U> {
+    a: Fuse<T>,
+    b: Fuse<U>,
+}
+
+/// Create a new `ZipLongest` iterator.
+pub fn zip_longest<T, U>(a: T, b: U) -> ZipLongest<T, U> 
+    where T: Iterator,
+          U: Iterator
+{
+    ZipLongest {
+        a: a.fuse(),
+        b: b.fuse(),
+    }
+}
+
+impl<T, U> Iterator for ZipLongest<T, U>
+    where T: Iterator,
+          U: Iterator
+{
+    type Item = EitherOrBoth<T::Item, U::Item>;
+
+    #[inline]
+    fn next(&mut self) -> Option<Self::Item> {
+        match (self.a.next(), self.b.next()) {
+            (None, None) => None,
+            (Some(a), None) => Some(EitherOrBoth::Left(a)),
+            (None, Some(b)) => Some(EitherOrBoth::Right(b)),
+            (Some(a), Some(b)) => Some(EitherOrBoth::Both(a, b)),
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        size_hint::max(self.a.size_hint(), self.b.size_hint())
+    }
+}
+
+impl<T, U> DoubleEndedIterator for ZipLongest<T, U>
+    where T: DoubleEndedIterator + ExactSizeIterator,
+          U: DoubleEndedIterator + ExactSizeIterator
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<Self::Item> {
+        match self.a.len().cmp(&self.b.len()) {
+            Equal => match (self.a.next_back(), self.b.next_back()) {
+                (None, None) => None,
+                (Some(a), Some(b)) => Some(EitherOrBoth::Both(a, b)),
+                // These can only happen if .len() is inconsistent with .next_back()
+                (Some(a), None) => Some(EitherOrBoth::Left(a)),
+                (None, Some(b)) => Some(EitherOrBoth::Right(b)),
+            },
+            Greater => self.a.next_back().map(EitherOrBoth::Left),
+            Less => self.b.next_back().map(EitherOrBoth::Right),
+        }
+    }
+}
+
+impl<T, U> ExactSizeIterator for ZipLongest<T, U>
+    where T: ExactSizeIterator,
+          U: ExactSizeIterator
+{}