]> git.proxmox.com Git - rustc.git/blobdiff - vendor/itertools-0.8.2/src/ziptuple.rs
Update upstream source from tag 'upstream/1.52.1+dfsg1'
[rustc.git] / vendor / itertools-0.8.2 / src / ziptuple.rs
diff --git a/vendor/itertools-0.8.2/src/ziptuple.rs b/vendor/itertools-0.8.2/src/ziptuple.rs
new file mode 100644 (file)
index 0000000..2dc3ea5
--- /dev/null
@@ -0,0 +1,111 @@
+use super::size_hint;
+
+/// See [`multizip`](../fn.multizip.html) for more information.
+#[derive(Clone, Debug)]
+#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+pub struct Zip<T> {
+    t: T,
+}
+
+/// An iterator that generalizes *.zip()* and allows running multiple iterators in lockstep.
+///
+/// The iterator `Zip<(I, J, ..., M)>` is formed from a tuple of iterators (or values that
+/// implement `IntoIterator`) and yields elements
+/// until any of the subiterators yields `None`.
+///
+/// The iterator element type is a tuple like like `(A, B, ..., E)` where `A` to `E` are the
+/// element types of the subiterator.
+///
+/// **Note:** The result of this macro is a value of a named type (`Zip<(I, J,
+/// ..)>` of each component iterator `I, J, ...`) if each component iterator is
+/// nameable.
+///
+/// Prefer [`izip!()`] over `multizip` for the performance benefits of using the
+/// standard library `.zip()`. Prefer `multizip` if a nameable type is needed.
+///
+/// [`izip!()`]: macro.izip.html
+///
+/// ```
+/// use itertools::multizip;
+///
+/// // iterate over three sequences side-by-side
+/// let mut results = [0, 0, 0, 0];
+/// let inputs = [3, 7, 9, 6];
+///
+/// for (r, index, input) in multizip((&mut results, 0..10, &inputs)) {
+///     *r = index * 10 + input;
+/// }
+///
+/// assert_eq!(results, [0 + 3, 10 + 7, 29, 36]);
+/// ```
+pub fn multizip<T, U>(t: U) -> Zip<T>
+    where Zip<T>: From<U>,
+          Zip<T>: Iterator,
+{
+    Zip::from(t)
+}
+
+macro_rules! impl_zip_iter {
+    ($($B:ident),*) => (
+        #[allow(non_snake_case)]
+        impl<$($B: IntoIterator),*> From<($($B,)*)> for Zip<($($B::IntoIter,)*)> {
+            fn from(t: ($($B,)*)) -> Self {
+                let ($($B,)*) = t;
+                Zip { t: ($($B.into_iter(),)*) }
+            }
+        }
+
+        #[allow(non_snake_case)]
+        #[allow(unused_assignments)]
+        impl<$($B),*> Iterator for Zip<($($B,)*)>
+            where
+            $(
+                $B: Iterator,
+            )*
+        {
+            type Item = ($($B::Item,)*);
+
+            fn next(&mut self) -> Option<Self::Item>
+            {
+                let ($(ref mut $B,)*) = self.t;
+
+                // NOTE: Just like iter::Zip, we check the iterators
+                // for None in order. We may finish unevenly (some
+                // iterators gave n + 1 elements, some only n).
+                $(
+                    let $B = match $B.next() {
+                        None => return None,
+                        Some(elt) => elt
+                    };
+                )*
+                Some(($($B,)*))
+            }
+
+            fn size_hint(&self) -> (usize, Option<usize>)
+            {
+                let sh = (::std::usize::MAX, None);
+                let ($(ref $B,)*) = self.t;
+                $(
+                    let sh = size_hint::min($B.size_hint(), sh);
+                )*
+                sh
+            }
+        }
+
+        #[allow(non_snake_case)]
+        impl<$($B),*> ExactSizeIterator for Zip<($($B,)*)> where
+            $(
+                $B: ExactSizeIterator,
+            )*
+        { }
+    );
+}
+
+impl_zip_iter!(A);
+impl_zip_iter!(A, B);
+impl_zip_iter!(A, B, C);
+impl_zip_iter!(A, B, C, D);
+impl_zip_iter!(A, B, C, D, E);
+impl_zip_iter!(A, B, C, D, E, F);
+impl_zip_iter!(A, B, C, D, E, F, G);
+impl_zip_iter!(A, B, C, D, E, F, G, H);