]>
Commit | Line | Data |
---|---|---|
abe05a73 XL |
1 | use super::size_hint; |
2 | ||
3 | /// See [`multizip`](../fn.multizip.html) for more information. | |
4 | #[derive(Clone)] | |
5 | pub struct Zip<T> { | |
6 | t: T, | |
7 | } | |
8 | ||
9 | impl<T> Zip<T> { | |
10 | /// Deprecated: renamed to multizip | |
11 | #[deprecated(note = "Renamed to multizip")] | |
12 | pub fn new<U>(t: U) -> Zip<T> | |
13 | where Zip<T>: From<U>, | |
14 | Zip<T>: Iterator, | |
15 | { | |
16 | multizip(t) | |
17 | } | |
18 | } | |
19 | ||
20 | /// An iterator that generalizes *.zip()* and allows running multiple iterators in lockstep. | |
21 | /// | |
22 | /// The iterator `Zip<(I, J, ..., M)>` is formed from a tuple of iterators (or values that | |
23 | /// implement `IntoIterator`) and yields elements | |
24 | /// until any of the subiterators yields `None`. | |
25 | /// | |
26 | /// The iterator element type is a tuple like like `(A, B, ..., E)` where `A` to `E` are the | |
27 | /// element types of the subiterator. | |
28 | /// | |
29 | /// ``` | |
30 | /// use itertools::multizip; | |
31 | /// | |
32 | /// // Iterate over three sequences side-by-side | |
33 | /// let mut xs = [0, 0, 0]; | |
34 | /// let ys = [69, 107, 101]; | |
35 | /// | |
36 | /// for (i, a, b) in multizip((0..100, &mut xs, &ys)) { | |
37 | /// *a = i ^ *b; | |
38 | /// } | |
39 | /// | |
40 | /// assert_eq!(xs, [69, 106, 103]); | |
41 | /// ``` | |
42 | pub fn multizip<T, U>(t: U) -> Zip<T> | |
43 | where Zip<T>: From<U>, | |
44 | Zip<T>: Iterator, | |
45 | { | |
46 | Zip::from(t) | |
47 | } | |
48 | ||
49 | macro_rules! impl_zip_iter { | |
50 | ($($B:ident),*) => ( | |
51 | #[allow(non_snake_case)] | |
52 | impl<$($B: IntoIterator),*> From<($($B,)*)> for Zip<($($B::IntoIter,)*)> { | |
53 | fn from(t: ($($B,)*)) -> Self { | |
54 | let ($($B,)*) = t; | |
55 | Zip { t: ($($B.into_iter(),)*) } | |
56 | } | |
57 | } | |
58 | ||
59 | #[allow(non_snake_case)] | |
60 | #[allow(unused_assignments)] | |
61 | impl<$($B),*> Iterator for Zip<($($B,)*)> | |
62 | where | |
63 | $( | |
64 | $B: Iterator, | |
65 | )* | |
66 | { | |
67 | type Item = ($($B::Item,)*); | |
68 | ||
69 | fn next(&mut self) -> Option<Self::Item> | |
70 | { | |
71 | let ($(ref mut $B,)*) = self.t; | |
72 | ||
73 | // NOTE: Just like iter::Zip, we check the iterators | |
74 | // for None in order. We may finish unevenly (some | |
75 | // iterators gave n + 1 elements, some only n). | |
76 | $( | |
77 | let $B = match $B.next() { | |
78 | None => return None, | |
79 | Some(elt) => elt | |
80 | }; | |
81 | )* | |
82 | Some(($($B,)*)) | |
83 | } | |
84 | ||
85 | fn size_hint(&self) -> (usize, Option<usize>) | |
86 | { | |
87 | let sh = (::std::usize::MAX, None); | |
88 | let ($(ref $B,)*) = self.t; | |
89 | $( | |
90 | let sh = size_hint::min($B.size_hint(), sh); | |
91 | )* | |
92 | sh | |
93 | } | |
94 | } | |
95 | ||
96 | #[allow(non_snake_case)] | |
97 | impl<$($B),*> ExactSizeIterator for Zip<($($B,)*)> where | |
98 | $( | |
99 | $B: ExactSizeIterator, | |
100 | )* | |
101 | { } | |
102 | ); | |
103 | } | |
104 | ||
105 | impl_zip_iter!(A); | |
106 | impl_zip_iter!(A, B); | |
107 | impl_zip_iter!(A, B, C); | |
108 | impl_zip_iter!(A, B, C, D); | |
109 | impl_zip_iter!(A, B, C, D, E); | |
110 | impl_zip_iter!(A, B, C, D, E, F); | |
111 | impl_zip_iter!(A, B, C, D, E, F, G); | |
112 | impl_zip_iter!(A, B, C, D, E, F, G, H); |