Coverage Report

Created: 2025-10-10 07:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rayon-1.11.0/src/iter/interleave.rs
Line
Count
Source
1
use super::plumbing::*;
2
use super::*;
3
use std::iter::Fuse;
4
5
/// `Interleave` is an iterator that interleaves elements of iterators
6
/// `i` and `j` in one continuous iterator. This struct is created by
7
/// the [`interleave()`] method on [`IndexedParallelIterator`]
8
///
9
/// [`interleave()`]: IndexedParallelIterator::interleave()
10
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
11
#[derive(Debug, Clone)]
12
pub struct Interleave<I, J> {
13
    i: I,
14
    j: J,
15
}
16
17
impl<I, J> Interleave<I, J> {
18
    /// Creates a new `Interleave` iterator
19
0
    pub(super) fn new(i: I, j: J) -> Self {
20
0
        Interleave { i, j }
21
0
    }
22
}
23
24
impl<I, J> ParallelIterator for Interleave<I, J>
25
where
26
    I: IndexedParallelIterator,
27
    J: IndexedParallelIterator<Item = I::Item>,
28
{
29
    type Item = I::Item;
30
31
0
    fn drive_unindexed<C>(self, consumer: C) -> C::Result
32
0
    where
33
0
        C: Consumer<I::Item>,
34
    {
35
0
        bridge(self, consumer)
36
0
    }
37
38
0
    fn opt_len(&self) -> Option<usize> {
39
0
        Some(self.len())
40
0
    }
41
}
42
43
impl<I, J> IndexedParallelIterator for Interleave<I, J>
44
where
45
    I: IndexedParallelIterator,
46
    J: IndexedParallelIterator<Item = I::Item>,
47
{
48
0
    fn drive<C>(self, consumer: C) -> C::Result
49
0
    where
50
0
        C: Consumer<Self::Item>,
51
    {
52
0
        bridge(self, consumer)
53
0
    }
54
55
0
    fn len(&self) -> usize {
56
0
        self.i.len().checked_add(self.j.len()).expect("overflow")
57
0
    }
58
59
0
    fn with_producer<CB>(self, callback: CB) -> CB::Output
60
0
    where
61
0
        CB: ProducerCallback<Self::Item>,
62
    {
63
0
        let (i_len, j_len) = (self.i.len(), self.j.len());
64
0
        return self.i.with_producer(CallbackI {
65
0
            callback,
66
0
            i_len,
67
0
            j_len,
68
0
            i_next: false,
69
0
            j: self.j,
70
0
        });
71
72
        struct CallbackI<CB, J> {
73
            callback: CB,
74
            i_len: usize,
75
            j_len: usize,
76
            i_next: bool,
77
            j: J,
78
        }
79
80
        impl<CB, J> ProducerCallback<J::Item> for CallbackI<CB, J>
81
        where
82
            J: IndexedParallelIterator,
83
            CB: ProducerCallback<J::Item>,
84
        {
85
            type Output = CB::Output;
86
87
0
            fn callback<I>(self, i_producer: I) -> Self::Output
88
0
            where
89
0
                I: Producer<Item = J::Item>,
90
            {
91
0
                self.j.with_producer(CallbackJ {
92
0
                    i_producer,
93
0
                    i_len: self.i_len,
94
0
                    j_len: self.j_len,
95
0
                    i_next: self.i_next,
96
0
                    callback: self.callback,
97
0
                })
98
0
            }
99
        }
100
101
        struct CallbackJ<CB, I> {
102
            callback: CB,
103
            i_len: usize,
104
            j_len: usize,
105
            i_next: bool,
106
            i_producer: I,
107
        }
108
109
        impl<CB, I> ProducerCallback<I::Item> for CallbackJ<CB, I>
110
        where
111
            I: Producer,
112
            CB: ProducerCallback<I::Item>,
113
        {
114
            type Output = CB::Output;
115
116
0
            fn callback<J>(self, j_producer: J) -> Self::Output
117
0
            where
118
0
                J: Producer<Item = I::Item>,
119
            {
120
0
                let producer = InterleaveProducer::new(
121
0
                    self.i_producer,
122
0
                    j_producer,
123
0
                    self.i_len,
124
0
                    self.j_len,
125
0
                    self.i_next,
126
                );
127
0
                self.callback.callback(producer)
128
0
            }
129
        }
130
0
    }
131
}
132
133
struct InterleaveProducer<I, J>
134
where
135
    I: Producer,
136
    J: Producer<Item = I::Item>,
137
{
138
    i: I,
139
    j: J,
140
    i_len: usize,
141
    j_len: usize,
142
    i_next: bool,
143
}
144
145
impl<I, J> InterleaveProducer<I, J>
146
where
147
    I: Producer,
148
    J: Producer<Item = I::Item>,
149
{
150
0
    fn new(i: I, j: J, i_len: usize, j_len: usize, i_next: bool) -> InterleaveProducer<I, J> {
151
0
        InterleaveProducer {
152
0
            i,
153
0
            j,
154
0
            i_len,
155
0
            j_len,
156
0
            i_next,
157
0
        }
158
0
    }
159
}
160
161
impl<I, J> Producer for InterleaveProducer<I, J>
162
where
163
    I: Producer,
164
    J: Producer<Item = I::Item>,
165
{
166
    type Item = I::Item;
167
    type IntoIter = InterleaveSeq<I::IntoIter, J::IntoIter>;
168
169
0
    fn into_iter(self) -> Self::IntoIter {
170
0
        InterleaveSeq {
171
0
            i: self.i.into_iter().fuse(),
172
0
            j: self.j.into_iter().fuse(),
173
0
            i_next: self.i_next,
174
0
        }
175
0
    }
176
177
0
    fn min_len(&self) -> usize {
178
0
        Ord::max(self.i.min_len(), self.j.min_len())
179
0
    }
180
181
0
    fn max_len(&self) -> usize {
182
0
        Ord::min(self.i.max_len(), self.j.max_len())
183
0
    }
184
185
    /// We know 0 < index <= self.i_len + self.j_len
186
    ///
187
    /// Find a, b satisfying:
188
    ///
189
    ///  (1) 0 < a <= self.i_len
190
    ///  (2) 0 < b <= self.j_len
191
    ///  (3) a + b == index
192
    ///
193
    /// For even splits, set a = b = index/2.
194
    /// For odd splits, set a = (index/2)+1, b = index/2, if `i`
195
    /// should yield the next element, otherwise, if `j` should yield
196
    /// the next element, set a = index/2 and b = (index/2)+1
197
0
    fn split_at(self, index: usize) -> (Self, Self) {
198
        #[inline]
199
0
        fn odd_offset(flag: bool) -> usize {
200
0
            (!flag) as usize
201
0
        }
202
203
0
        let even = index % 2 == 0;
204
0
        let idx = index >> 1;
205
206
        // desired split
207
0
        let (i_idx, j_idx) = (
208
0
            idx + odd_offset(even || self.i_next),
209
0
            idx + odd_offset(even || !self.i_next),
210
        );
211
212
0
        let (i_split, j_split) = if self.i_len >= i_idx && self.j_len >= j_idx {
213
0
            (i_idx, j_idx)
214
0
        } else if self.i_len >= i_idx {
215
            // j too short
216
0
            (index - self.j_len, self.j_len)
217
        } else {
218
            // i too short
219
0
            (self.i_len, index - self.i_len)
220
        };
221
222
0
        let trailing_i_next = even == self.i_next;
223
0
        let (i_left, i_right) = self.i.split_at(i_split);
224
0
        let (j_left, j_right) = self.j.split_at(j_split);
225
226
0
        (
227
0
            InterleaveProducer::new(i_left, j_left, i_split, j_split, self.i_next),
228
0
            InterleaveProducer::new(
229
0
                i_right,
230
0
                j_right,
231
0
                self.i_len - i_split,
232
0
                self.j_len - j_split,
233
0
                trailing_i_next,
234
0
            ),
235
0
        )
236
0
    }
237
}
238
239
/// Wrapper for Interleave to implement DoubleEndedIterator and
240
/// ExactSizeIterator.
241
///
242
/// This iterator is fused.
243
struct InterleaveSeq<I, J> {
244
    i: Fuse<I>,
245
    j: Fuse<J>,
246
247
    /// Flag to control which iterator should provide the next element. When
248
    /// `false` then `i` produces the next element, otherwise `j` produces the
249
    /// next element.
250
    i_next: bool,
251
}
252
253
/// Iterator implementation for InterleaveSeq. This implementation is
254
/// taken more or less verbatim from itertools. It is replicated here
255
/// (instead of calling itertools directly), because we also need to
256
/// implement `DoubledEndedIterator` and `ExactSizeIterator`.
257
impl<I, J> Iterator for InterleaveSeq<I, J>
258
where
259
    I: Iterator,
260
    J: Iterator<Item = I::Item>,
261
{
262
    type Item = I::Item;
263
264
    #[inline]
265
0
    fn next(&mut self) -> Option<Self::Item> {
266
0
        self.i_next = !self.i_next;
267
0
        if self.i_next {
268
0
            match self.i.next() {
269
0
                None => self.j.next(),
270
0
                r => r,
271
            }
272
        } else {
273
0
            match self.j.next() {
274
0
                None => self.i.next(),
275
0
                r => r,
276
            }
277
        }
278
0
    }
279
280
0
    fn size_hint(&self) -> (usize, Option<usize>) {
281
0
        let (ih, jh) = (self.i.size_hint(), self.j.size_hint());
282
0
        let min = ih.0.saturating_add(jh.0);
283
0
        let max = match (ih.1, jh.1) {
284
0
            (Some(x), Some(y)) => x.checked_add(y),
285
0
            _ => None,
286
        };
287
0
        (min, max)
288
0
    }
289
}
290
291
// The implementation for DoubleEndedIterator requires
292
// ExactSizeIterator to provide `next_back()`. The last element will
293
// come from the iterator that runs out last (ie has the most elements
294
// in it). If the iterators have the same number of elements, then the
295
// last iterator will provide the last element.
296
impl<I, J> DoubleEndedIterator for InterleaveSeq<I, J>
297
where
298
    I: DoubleEndedIterator + ExactSizeIterator,
299
    J: DoubleEndedIterator<Item = I::Item> + ExactSizeIterator<Item = I::Item>,
300
{
301
    #[inline]
302
0
    fn next_back(&mut self) -> Option<I::Item> {
303
0
        match self.i.len().cmp(&self.j.len()) {
304
0
            Ordering::Less => self.j.next_back(),
305
            Ordering::Equal => {
306
0
                if self.i_next {
307
0
                    self.i.next_back()
308
                } else {
309
0
                    self.j.next_back()
310
                }
311
            }
312
0
            Ordering::Greater => self.i.next_back(),
313
        }
314
0
    }
315
}
316
317
impl<I, J> ExactSizeIterator for InterleaveSeq<I, J>
318
where
319
    I: ExactSizeIterator,
320
    J: ExactSizeIterator<Item = I::Item>,
321
{
322
    #[inline]
323
0
    fn len(&self) -> usize {
324
0
        self.i.len() + self.j.len()
325
0
    }
326
}