]>
git.proxmox.com Git - rustc.git/blob - vendor/rustc-rayon/src/iter/interleave.rs
1 use super::plumbing
::*;
6 /// `Interleave` is an iterator that interleaves elements of iterators
7 /// `i` and `j` in one continuous iterator. This struct is created by
8 /// the [`interleave()`] method on [`IndexedParallelIterator`]
10 /// [`interleave()`]: trait.IndexedParallelIterator.html#method.interleave
11 /// [`IndexedParallelIterator`]: trait.IndexedParallelIterator.html
12 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
13 #[derive(Debug, Clone)]
14 pub struct Interleave
<I
, J
>
16 I
: IndexedParallelIterator
,
17 J
: IndexedParallelIterator
<Item
= I
::Item
>,
23 impl<I
, J
> Interleave
<I
, J
>
25 I
: IndexedParallelIterator
,
26 J
: IndexedParallelIterator
<Item
= I
::Item
>,
28 /// Creates a new `Interleave` iterator
29 pub(super) fn new(i
: I
, j
: J
) -> Self {
34 impl<I
, J
> ParallelIterator
for Interleave
<I
, J
>
36 I
: IndexedParallelIterator
,
37 J
: IndexedParallelIterator
<Item
= I
::Item
>,
41 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
45 bridge(self, consumer
)
48 fn opt_len(&self) -> Option
<usize> {
53 impl<I
, J
> IndexedParallelIterator
for Interleave
<I
, J
>
55 I
: IndexedParallelIterator
,
56 J
: IndexedParallelIterator
<Item
= I
::Item
>,
58 fn drive
<C
>(self, consumer
: C
) -> C
::Result
60 C
: Consumer
<Self::Item
>,
62 bridge(self, consumer
)
65 fn len(&self) -> usize {
66 self.i
.len().checked_add(self.j
.len()).expect("overflow")
69 fn with_producer
<CB
>(self, callback
: CB
) -> CB
::Output
71 CB
: ProducerCallback
<Self::Item
>,
73 let (i_len
, j_len
) = (self.i
.len(), self.j
.len());
74 return self.i
.with_producer(CallbackI
{
82 struct CallbackI
<CB
, J
> {
90 impl<CB
, J
> ProducerCallback
<J
::Item
> for CallbackI
<CB
, J
>
92 J
: IndexedParallelIterator
,
93 CB
: ProducerCallback
<J
::Item
>,
95 type Output
= CB
::Output
;
97 fn callback
<I
>(self, i_producer
: I
) -> Self::Output
99 I
: Producer
<Item
= J
::Item
>,
101 self.j
.with_producer(CallbackJ
{
106 callback
: self.callback
,
111 struct CallbackJ
<CB
, I
> {
119 impl<CB
, I
> ProducerCallback
<I
::Item
> for CallbackJ
<CB
, I
>
122 CB
: ProducerCallback
<I
::Item
>,
124 type Output
= CB
::Output
;
126 fn callback
<J
>(self, j_producer
: J
) -> Self::Output
128 J
: Producer
<Item
= I
::Item
>,
130 let producer
= InterleaveProducer
::new(
137 self.callback
.callback(producer
)
143 struct InterleaveProducer
<I
, J
>
146 J
: Producer
<Item
= I
::Item
>,
155 impl<I
, J
> InterleaveProducer
<I
, J
>
158 J
: Producer
<Item
= I
::Item
>,
160 fn new(i
: I
, j
: J
, i_len
: usize, j_len
: usize, i_next
: bool
) -> InterleaveProducer
<I
, J
> {
171 impl<I
, J
> Producer
for InterleaveProducer
<I
, J
>
174 J
: Producer
<Item
= I
::Item
>,
177 type IntoIter
= InterleaveSeq
<I
::IntoIter
, J
::IntoIter
>;
179 fn into_iter(self) -> Self::IntoIter
{
181 i
: self.i
.into_iter().fuse(),
182 j
: self.j
.into_iter().fuse(),
187 fn min_len(&self) -> usize {
188 cmp
::max(self.i
.min_len(), self.j
.min_len())
191 fn max_len(&self) -> usize {
192 cmp
::min(self.i
.max_len(), self.j
.max_len())
195 /// We know 0 < index <= self.i_len + self.j_len
197 /// Find a, b satisfying:
199 /// (1) 0 < a <= self.i_len
200 /// (2) 0 < b <= self.j_len
201 /// (3) a + b == index
203 /// For even splits, set a = b = index/2.
204 /// For odd splits, set a = (index/2)+1, b = index/2, if `i`
205 /// should yield the next element, otherwise, if `j` should yield
206 /// the next element, set a = index/2 and b = (index/2)+1
207 fn split_at(self, index
: usize) -> (Self, Self) {
209 fn odd_offset(flag
: bool
) -> usize {
213 let even
= index
% 2 == 0;
214 let idx
= index
>> 1;
217 let (i_idx
, j_idx
) = (
218 idx
+ odd_offset(even
|| self.i_next
),
219 idx
+ odd_offset(even
|| !self.i_next
),
222 let (i_split
, j_split
) = if self.i_len
>= i_idx
&& self.j_len
>= j_idx
{
224 } else if self.i_len
>= i_idx
{
226 (index
- self.j_len
, self.j_len
)
229 (self.i_len
, index
- self.i_len
)
232 let trailing_i_next
= even
== self.i_next
;
233 let (i_left
, i_right
) = self.i
.split_at(i_split
);
234 let (j_left
, j_right
) = self.j
.split_at(j_split
);
237 InterleaveProducer
::new(i_left
, j_left
, i_split
, j_split
, self.i_next
),
238 InterleaveProducer
::new(
241 self.i_len
- i_split
,
242 self.j_len
- j_split
,
249 /// Wrapper for Interleave to implement DoubleEndedIterator and
250 /// ExactSizeIterator.
252 /// This iterator is fused.
253 struct InterleaveSeq
<I
, J
> {
257 /// Flag to control which iterator should provide the next element. When
258 /// `false` then `i` produces the next element, otherwise `j` produces the
263 /// Iterator implementation for InterleaveSeq. This implementation is
264 /// taken more or less verbatim from itertools. It is replicated here
265 /// (instead of calling itertools directly), because we also need to
266 /// implement `DoubledEndedIterator` and `ExactSizeIterator`.
267 impl<I
, J
> Iterator
for InterleaveSeq
<I
, J
>
270 J
: Iterator
<Item
= I
::Item
>,
275 fn next(&mut self) -> Option
<Self::Item
> {
276 self.i_next
= !self.i_next
;
278 match self.i
.next() {
279 None
=> self.j
.next(),
283 match self.j
.next() {
284 None
=> self.i
.next(),
290 fn size_hint(&self) -> (usize, Option
<usize>) {
291 let (ih
, jh
) = (self.i
.size_hint(), self.j
.size_hint());
292 let min
= ih
.0.saturating_add(jh
.0);
293 let max
= match (ih
.1, jh
.1) {
294 (Some(x
), Some(y
)) => x
.checked_add(y
),
301 // The implementation for DoubleEndedIterator requires
302 // ExactSizeIterator to provide `next_back()`. The last element will
303 // come from the iterator that runs out last (ie has the most elements
304 // in it). If the iterators have the same number of elements, then the
305 // last iterator will provide the last element.
306 impl<I
, J
> DoubleEndedIterator
for InterleaveSeq
<I
, J
>
308 I
: DoubleEndedIterator
+ ExactSizeIterator
,
309 J
: DoubleEndedIterator
<Item
= I
::Item
> + ExactSizeIterator
<Item
= I
::Item
>,
312 fn next_back(&mut self) -> Option
<I
::Item
> {
313 if self.i
.len() == self.j
.len() {
319 } else if self.i
.len() < self.j
.len() {
327 impl<I
, J
> ExactSizeIterator
for InterleaveSeq
<I
, J
>
329 I
: ExactSizeIterator
,
330 J
: ExactSizeIterator
<Item
= I
::Item
>,
333 fn len(&self) -> usize {
334 self.i
.len() + self.j
.len()