1 use super::plumbing
::*;
7 /// `Chain` is an iterator that joins `b` after `a` in one continuous iterator.
8 /// This struct is created by the [`chain()`] method on [`ParallelIterator`]
10 /// [`chain()`]: trait.ParallelIterator.html#method.chain
11 /// [`ParallelIterator`]: trait.ParallelIterator.html
12 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
13 #[derive(Debug, Clone)]
14 pub struct Chain
<A
, B
>
15 where A
: ParallelIterator
,
16 B
: ParallelIterator
<Item
= A
::Item
>
22 /// Create a new `Chain` iterator.
24 /// NB: a free fn because it is NOT part of the end-user API.
25 pub fn new
<A
, B
>(a
: A
, b
: B
) -> Chain
<A
, B
>
26 where A
: ParallelIterator
,
27 B
: ParallelIterator
<Item
= A
::Item
>
32 impl<A
, B
> ParallelIterator
for Chain
<A
, B
>
33 where A
: ParallelIterator
,
34 B
: ParallelIterator
<Item
= A
::Item
>
38 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
39 where C
: UnindexedConsumer
<Self::Item
>
41 let Chain { a, b }
= self;
43 // If we returned a value from our own `opt_len`, then the collect consumer in particular
44 // will balk at being treated like an actual `UnindexedConsumer`. But when we do know the
45 // length, we can use `Consumer::split_at` instead, and this is still harmless for other
46 // truly-unindexed consumers too.
47 let (left
, right
, reducer
) = if let Some(len
) = a
.opt_len() {
48 consumer
.split_at(len
)
50 let reducer
= consumer
.to_reducer();
51 (consumer
.split_off_left(), consumer
, reducer
)
54 let (a
, b
) = join(|| a
.drive_unindexed(left
), || b
.drive_unindexed(right
));
58 fn opt_len(&self) -> Option
<usize> {
59 match (self.a
.opt_len(), self.b
.opt_len()) {
60 (Some(a_len
), Some(b_len
)) => a_len
.checked_add(b_len
),
66 impl<A
, B
> IndexedParallelIterator
for Chain
<A
, B
>
67 where A
: IndexedParallelIterator
,
68 B
: IndexedParallelIterator
<Item
= A
::Item
>
70 fn drive
<C
>(self, consumer
: C
) -> C
::Result
71 where C
: Consumer
<Self::Item
>
73 let Chain { a, b }
= self;
74 let (left
, right
, reducer
) = consumer
.split_at(a
.len());
75 let (a
, b
) = join(|| a
.drive(left
), || b
.drive(right
));
79 fn len(&self) -> usize {
82 .checked_add(self.b
.len())
86 fn with_producer
<CB
>(self, callback
: CB
) -> CB
::Output
87 where CB
: ProducerCallback
<Self::Item
>
89 let a_len
= self.a
.len();
90 return self.a
.with_producer(CallbackA
{
96 struct CallbackA
<CB
, B
> {
102 impl<CB
, B
> ProducerCallback
<B
::Item
> for CallbackA
<CB
, B
>
103 where B
: IndexedParallelIterator
,
104 CB
: ProducerCallback
<B
::Item
>
106 type Output
= CB
::Output
;
108 fn callback
<A
>(self, a_producer
: A
) -> Self::Output
109 where A
: Producer
<Item
= B
::Item
>
111 return self.b
.with_producer(CallbackB
{
112 callback
: self.callback
,
114 a_producer
: a_producer
,
119 struct CallbackB
<CB
, A
> {
125 impl<CB
, A
> ProducerCallback
<A
::Item
> for CallbackB
<CB
, A
>
127 CB
: ProducerCallback
<A
::Item
>
129 type Output
= CB
::Output
;
131 fn callback
<B
>(self, b_producer
: B
) -> Self::Output
132 where B
: Producer
<Item
= A
::Item
>
134 let producer
= ChainProducer
::new(self.a_len
, self.a_producer
, b_producer
);
135 self.callback
.callback(producer
)
142 /// ////////////////////////////////////////////////////////////////////////
144 struct ChainProducer
<A
, B
>
146 B
: Producer
<Item
= A
::Item
>
153 impl<A
, B
> ChainProducer
<A
, B
>
155 B
: Producer
<Item
= A
::Item
>
157 fn new(a_len
: usize, a
: A
, b
: B
) -> Self {
166 impl<A
, B
> Producer
for ChainProducer
<A
, B
>
168 B
: Producer
<Item
= A
::Item
>
171 type IntoIter
= ChainSeq
<A
::IntoIter
, B
::IntoIter
>;
173 fn into_iter(self) -> Self::IntoIter
{
174 ChainSeq
::new(self.a
.into_iter(), self.b
.into_iter())
177 fn min_len(&self) -> usize {
178 cmp
::max(self.a
.min_len(), self.b
.min_len())
181 fn max_len(&self) -> usize {
182 cmp
::min(self.a
.max_len(), self.b
.max_len())
185 fn split_at(self, index
: usize) -> (Self, Self) {
186 if index
<= self.a_len
{
187 let a_rem
= self.a_len
- index
;
188 let (a_left
, a_right
) = self.a
.split_at(index
);
189 let (b_left
, b_right
) = self.b
.split_at(0);
190 (ChainProducer
::new(index
, a_left
, b_left
), ChainProducer
::new(a_rem
, a_right
, b_right
))
192 let (a_left
, a_right
) = self.a
.split_at(self.a_len
);
193 let (b_left
, b_right
) = self.b
.split_at(index
- self.a_len
);
194 (ChainProducer
::new(self.a_len
, a_left
, b_left
),
195 ChainProducer
::new(0, a_right
, b_right
))
199 fn fold_with
<F
>(self, mut folder
: F
) -> F
200 where F
: Folder
<A
::Item
>
202 folder
= self.a
.fold_with(folder
);
206 self.b
.fold_with(folder
)
211 /// ////////////////////////////////////////////////////////////////////////
212 /// Wrapper for Chain to implement ExactSizeIterator
214 struct ChainSeq
<A
, B
> {
215 chain
: iter
::Chain
<A
, B
>,
218 impl<A
, B
> ChainSeq
<A
, B
> {
219 fn new(a
: A
, b
: B
) -> ChainSeq
<A
, B
>
220 where A
: ExactSizeIterator
,
221 B
: ExactSizeIterator
<Item
= A
::Item
>
223 ChainSeq { chain: a.chain(b) }
227 impl<A
, B
> Iterator
for ChainSeq
<A
, B
>
229 B
: Iterator
<Item
= A
::Item
>
233 fn next(&mut self) -> Option
<Self::Item
> {
237 fn size_hint(&self) -> (usize, Option
<usize>) {
238 self.chain
.size_hint()
242 impl<A
, B
> ExactSizeIterator
for ChainSeq
<A
, B
>
243 where A
: ExactSizeIterator
,
244 B
: ExactSizeIterator
<Item
= A
::Item
>
248 impl<A
, B
> DoubleEndedIterator
for ChainSeq
<A
, B
>
249 where A
: DoubleEndedIterator
,
250 B
: DoubleEndedIterator
<Item
= A
::Item
>
252 fn next_back(&mut self) -> Option
<Self::Item
> {
253 self.chain
.next_back()