]>
Commit | Line | Data |
---|---|---|
2c00a5a8 XL |
1 | use super::plumbing::*; |
2 | use super::*; | |
3 | use std::cmp; | |
4 | use std::iter; | |
5 | ||
6 | /// `Zip` is an iterator that zips up `a` and `b` into a single iterator | |
7 | /// of pairs. This struct is created by the [`zip()`] method on | |
8 | /// [`IndexedParallelIterator`] | |
9 | /// | |
10 | /// [`zip()`]: trait.IndexedParallelIterator.html#method.zip | |
11 | /// [`IndexedParallelIterator`]: trait.IndexedParallelIterator.html | |
12 | #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] | |
13 | #[derive(Debug, Clone)] | |
14 | pub struct Zip<A: IndexedParallelIterator, B: IndexedParallelIterator> { | |
15 | a: A, | |
16 | b: B, | |
17 | } | |
18 | ||
e74abb32 | 19 | impl<A, B> Zip<A, B> |
532ac7d7 XL |
20 | where |
21 | A: IndexedParallelIterator, | |
22 | B: IndexedParallelIterator, | |
2c00a5a8 | 23 | { |
923072b8 | 24 | /// Creates a new `Zip` iterator. |
e74abb32 XL |
25 | pub(super) fn new(a: A, b: B) -> Self { |
26 | Zip { a, b } | |
27 | } | |
2c00a5a8 XL |
28 | } |
29 | ||
30 | impl<A, B> ParallelIterator for Zip<A, B> | |
532ac7d7 XL |
31 | where |
32 | A: IndexedParallelIterator, | |
33 | B: IndexedParallelIterator, | |
2c00a5a8 XL |
34 | { |
35 | type Item = (A::Item, B::Item); | |
36 | ||
37 | fn drive_unindexed<C>(self, consumer: C) -> C::Result | |
532ac7d7 XL |
38 | where |
39 | C: UnindexedConsumer<Self::Item>, | |
2c00a5a8 XL |
40 | { |
41 | bridge(self, consumer) | |
42 | } | |
43 | ||
44 | fn opt_len(&self) -> Option<usize> { | |
45 | Some(self.len()) | |
46 | } | |
47 | } | |
48 | ||
49 | impl<A, B> IndexedParallelIterator for Zip<A, B> | |
532ac7d7 XL |
50 | where |
51 | A: IndexedParallelIterator, | |
52 | B: IndexedParallelIterator, | |
2c00a5a8 XL |
53 | { |
54 | fn drive<C>(self, consumer: C) -> C::Result | |
532ac7d7 XL |
55 | where |
56 | C: Consumer<Self::Item>, | |
2c00a5a8 XL |
57 | { |
58 | bridge(self, consumer) | |
59 | } | |
60 | ||
61 | fn len(&self) -> usize { | |
62 | cmp::min(self.a.len(), self.b.len()) | |
63 | } | |
64 | ||
65 | fn with_producer<CB>(self, callback: CB) -> CB::Output | |
532ac7d7 XL |
66 | where |
67 | CB: ProducerCallback<Self::Item>, | |
2c00a5a8 XL |
68 | { |
69 | return self.a.with_producer(CallbackA { | |
e74abb32 | 70 | callback, |
532ac7d7 XL |
71 | b: self.b, |
72 | }); | |
2c00a5a8 XL |
73 | |
74 | struct CallbackA<CB, B> { | |
75 | callback: CB, | |
76 | b: B, | |
77 | } | |
78 | ||
79 | impl<CB, ITEM, B> ProducerCallback<ITEM> for CallbackA<CB, B> | |
532ac7d7 XL |
80 | where |
81 | B: IndexedParallelIterator, | |
82 | CB: ProducerCallback<(ITEM, B::Item)>, | |
2c00a5a8 XL |
83 | { |
84 | type Output = CB::Output; | |
85 | ||
86 | fn callback<A>(self, a_producer: A) -> Self::Output | |
532ac7d7 XL |
87 | where |
88 | A: Producer<Item = ITEM>, | |
2c00a5a8 | 89 | { |
e74abb32 XL |
90 | self.b.with_producer(CallbackB { |
91 | a_producer, | |
532ac7d7 | 92 | callback: self.callback, |
e74abb32 | 93 | }) |
2c00a5a8 XL |
94 | } |
95 | } | |
96 | ||
97 | struct CallbackB<CB, A> { | |
98 | a_producer: A, | |
99 | callback: CB, | |
100 | } | |
101 | ||
102 | impl<CB, A, ITEM> ProducerCallback<ITEM> for CallbackB<CB, A> | |
532ac7d7 XL |
103 | where |
104 | A: Producer, | |
105 | CB: ProducerCallback<(A::Item, ITEM)>, | |
2c00a5a8 XL |
106 | { |
107 | type Output = CB::Output; | |
108 | ||
109 | fn callback<B>(self, b_producer: B) -> Self::Output | |
532ac7d7 XL |
110 | where |
111 | B: Producer<Item = ITEM>, | |
2c00a5a8 XL |
112 | { |
113 | self.callback.callback(ZipProducer { | |
532ac7d7 XL |
114 | a: self.a_producer, |
115 | b: b_producer, | |
116 | }) | |
2c00a5a8 XL |
117 | } |
118 | } | |
2c00a5a8 XL |
119 | } |
120 | } | |
121 | ||
122 | /// //////////////////////////////////////////////////////////////////////// | |
123 | ||
124 | struct ZipProducer<A: Producer, B: Producer> { | |
125 | a: A, | |
126 | b: B, | |
127 | } | |
128 | ||
129 | impl<A: Producer, B: Producer> Producer for ZipProducer<A, B> { | |
130 | type Item = (A::Item, B::Item); | |
131 | type IntoIter = iter::Zip<A::IntoIter, B::IntoIter>; | |
132 | ||
133 | fn into_iter(self) -> Self::IntoIter { | |
134 | self.a.into_iter().zip(self.b.into_iter()) | |
135 | } | |
136 | ||
137 | fn min_len(&self) -> usize { | |
138 | cmp::max(self.a.min_len(), self.b.min_len()) | |
139 | } | |
140 | ||
141 | fn max_len(&self) -> usize { | |
142 | cmp::min(self.a.max_len(), self.b.max_len()) | |
143 | } | |
144 | ||
145 | fn split_at(self, index: usize) -> (Self, Self) { | |
146 | let (a_left, a_right) = self.a.split_at(index); | |
147 | let (b_left, b_right) = self.b.split_at(index); | |
532ac7d7 XL |
148 | ( |
149 | ZipProducer { | |
150 | a: a_left, | |
151 | b: b_left, | |
152 | }, | |
153 | ZipProducer { | |
154 | a: a_right, | |
155 | b: b_right, | |
156 | }, | |
157 | ) | |
2c00a5a8 XL |
158 | } |
159 | } |