xref: /aosp_15_r20/external/cronet/third_party/rust/chromium_crates_io/vendor/itertools-0.11.0/src/ziptuple.rs (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 use super::size_hint;
2 
3 /// See [`multizip`] for more information.
4 #[derive(Clone, Debug)]
5 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
6 pub struct Zip<T> {
7     t: T,
8 }
9 
10 /// An iterator that generalizes *.zip()* and allows running multiple iterators in lockstep.
11 ///
12 /// The iterator `Zip<(I, J, ..., M)>` is formed from a tuple of iterators (or values that
13 /// implement [`IntoIterator`]) and yields elements
14 /// until any of the subiterators yields `None`.
15 ///
16 /// The iterator element type is a tuple like like `(A, B, ..., E)` where `A` to `E` are the
17 /// element types of the subiterator.
18 ///
19 /// **Note:** The result of this macro is a value of a named type (`Zip<(I, J,
20 /// ..)>` of each component iterator `I, J, ...`) if each component iterator is
21 /// nameable.
22 ///
23 /// Prefer [`izip!()`] over `multizip` for the performance benefits of using the
24 /// standard library `.zip()`. Prefer `multizip` if a nameable type is needed.
25 ///
26 /// ```
27 /// use itertools::multizip;
28 ///
29 /// // iterate over three sequences side-by-side
30 /// let mut results = [0, 0, 0, 0];
31 /// let inputs = [3, 7, 9, 6];
32 ///
33 /// for (r, index, input) in multizip((&mut results, 0..10, &inputs)) {
34 ///     *r = index * 10 + input;
35 /// }
36 ///
37 /// assert_eq!(results, [0 + 3, 10 + 7, 29, 36]);
38 /// ```
39 /// [`izip!()`]: crate::izip
multizip<T, U>(t: U) -> Zip<T> where Zip<T>: From<U>, Zip<T>: Iterator,40 pub fn multizip<T, U>(t: U) -> Zip<T>
41     where Zip<T>: From<U>,
42           Zip<T>: Iterator,
43 {
44     Zip::from(t)
45 }
46 
47 macro_rules! impl_zip_iter {
48     ($($B:ident),*) => (
49         #[allow(non_snake_case)]
50         impl<$($B: IntoIterator),*> From<($($B,)*)> for Zip<($($B::IntoIter,)*)> {
51             fn from(t: ($($B,)*)) -> Self {
52                 let ($($B,)*) = t;
53                 Zip { t: ($($B.into_iter(),)*) }
54             }
55         }
56 
57         #[allow(non_snake_case)]
58         #[allow(unused_assignments)]
59         impl<$($B),*> Iterator for Zip<($($B,)*)>
60             where
61             $(
62                 $B: Iterator,
63             )*
64         {
65             type Item = ($($B::Item,)*);
66 
67             fn next(&mut self) -> Option<Self::Item>
68             {
69                 let ($(ref mut $B,)*) = self.t;
70 
71                 // NOTE: Just like iter::Zip, we check the iterators
72                 // for None in order. We may finish unevenly (some
73                 // iterators gave n + 1 elements, some only n).
74                 $(
75                     let $B = match $B.next() {
76                         None => return None,
77                         Some(elt) => elt
78                     };
79                 )*
80                 Some(($($B,)*))
81             }
82 
83             fn size_hint(&self) -> (usize, Option<usize>)
84             {
85                 let sh = (::std::usize::MAX, None);
86                 let ($(ref $B,)*) = self.t;
87                 $(
88                     let sh = size_hint::min($B.size_hint(), sh);
89                 )*
90                 sh
91             }
92         }
93 
94         #[allow(non_snake_case)]
95         impl<$($B),*> ExactSizeIterator for Zip<($($B,)*)> where
96             $(
97                 $B: ExactSizeIterator,
98             )*
99         { }
100 
101         #[allow(non_snake_case)]
102         impl<$($B),*> DoubleEndedIterator for Zip<($($B,)*)> where
103             $(
104                 $B: DoubleEndedIterator + ExactSizeIterator,
105             )*
106         {
107             #[inline]
108             fn next_back(&mut self) -> Option<Self::Item> {
109                 let ($(ref mut $B,)*) = self.t;
110                 let size = *[$( $B.len(), )*].iter().min().unwrap();
111 
112                 $(
113                     if $B.len() != size {
114                         for _ in 0..$B.len() - size { $B.next_back(); }
115                     }
116                 )*
117 
118                 match ($($B.next_back(),)*) {
119                     ($(Some($B),)*) => Some(($($B,)*)),
120                     _ => None,
121                 }
122             }
123         }
124     );
125 }
126 
127 impl_zip_iter!(A);
128 impl_zip_iter!(A, B);
129 impl_zip_iter!(A, B, C);
130 impl_zip_iter!(A, B, C, D);
131 impl_zip_iter!(A, B, C, D, E);
132 impl_zip_iter!(A, B, C, D, E, F);
133 impl_zip_iter!(A, B, C, D, E, F, G);
134 impl_zip_iter!(A, B, C, D, E, F, G, H);
135 impl_zip_iter!(A, B, C, D, E, F, G, H, I);
136 impl_zip_iter!(A, B, C, D, E, F, G, H, I, J);
137 impl_zip_iter!(A, B, C, D, E, F, G, H, I, J, K);
138 impl_zip_iter!(A, B, C, D, E, F, G, H, I, J, K, L);
139