Coverage Report

Created: 2025-11-24 07:30

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/chain.rs
Line
Count
Source
1
use super::plumbing::*;
2
use super::*;
3
use rayon_core::join;
4
use std::iter;
5
6
/// `Chain` is an iterator that joins `b` after `a` in one continuous iterator.
7
/// This struct is created by the [`chain()`] method on [`ParallelIterator`]
8
///
9
/// [`chain()`]: ParallelIterator::chain()
10
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
11
#[derive(Debug, Clone)]
12
pub struct Chain<A, B> {
13
    a: A,
14
    b: B,
15
}
16
17
impl<A, B> Chain<A, B> {
18
    /// Creates a new `Chain` iterator.
19
0
    pub(super) fn new(a: A, b: B) -> Self {
20
0
        Chain { a, b }
21
0
    }
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<i8>, rayon::iter::once::Once<i8>>>::new
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<u8>, rayon::iter::once::Once<u8>>>::new
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<isize>, rayon::iter::once::Once<isize>>>::new
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<usize>, rayon::iter::once::Once<usize>>>::new
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<i32>, rayon::iter::once::Once<i32>>>::new
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<u32>, rayon::iter::once::Once<u32>>>::new
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<i128>, rayon::iter::once::Once<i128>>>::new
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<u128>, rayon::iter::once::Once<u128>>>::new
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<i16>, rayon::iter::once::Once<i16>>>::new
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<u16>, rayon::iter::once::Once<u16>>>::new
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<i64>, rayon::iter::once::Once<i64>>>::new
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<u64>, rayon::iter::once::Once<u64>>>::new
22
}
23
24
impl<A, B> ParallelIterator for Chain<A, B>
25
where
26
    A: ParallelIterator,
27
    B: ParallelIterator<Item = A::Item>,
28
{
29
    type Item = A::Item;
30
31
0
    fn drive_unindexed<C>(self, consumer: C) -> C::Result
32
0
    where
33
0
        C: UnindexedConsumer<Self::Item>,
34
    {
35
0
        let Chain { a, b } = self;
36
37
        // If we returned a value from our own `opt_len`, then the collect consumer in particular
38
        // will balk at being treated like an actual `UnindexedConsumer`.  But when we do know the
39
        // length, we can use `Consumer::split_at` instead, and this is still harmless for other
40
        // truly-unindexed consumers too.
41
0
        let (left, right, reducer) = if let Some(len) = a.opt_len() {
42
0
            consumer.split_at(len)
43
        } else {
44
0
            let reducer = consumer.to_reducer();
45
0
            (consumer.split_off_left(), consumer, reducer)
46
        };
47
48
0
        let (a, b) = join(|| a.drive_unindexed(left), || b.drive_unindexed(right));
49
0
        reducer.reduce(a, b)
50
0
    }
51
52
0
    fn opt_len(&self) -> Option<usize> {
53
0
        self.a.opt_len()?.checked_add(self.b.opt_len()?)
54
0
    }
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<i8>, rayon::iter::once::Once<i8>> as rayon::iter::ParallelIterator>::opt_len
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<u8>, rayon::iter::once::Once<u8>> as rayon::iter::ParallelIterator>::opt_len
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<isize>, rayon::iter::once::Once<isize>> as rayon::iter::ParallelIterator>::opt_len
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<usize>, rayon::iter::once::Once<usize>> as rayon::iter::ParallelIterator>::opt_len
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<i32>, rayon::iter::once::Once<i32>> as rayon::iter::ParallelIterator>::opt_len
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<u32>, rayon::iter::once::Once<u32>> as rayon::iter::ParallelIterator>::opt_len
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<i128>, rayon::iter::once::Once<i128>> as rayon::iter::ParallelIterator>::opt_len
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<u128>, rayon::iter::once::Once<u128>> as rayon::iter::ParallelIterator>::opt_len
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<i16>, rayon::iter::once::Once<i16>> as rayon::iter::ParallelIterator>::opt_len
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<u16>, rayon::iter::once::Once<u16>> as rayon::iter::ParallelIterator>::opt_len
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<i64>, rayon::iter::once::Once<i64>> as rayon::iter::ParallelIterator>::opt_len
Unexecuted instantiation: <rayon::iter::chain::Chain<rayon::range::Iter<u64>, rayon::iter::once::Once<u64>> as rayon::iter::ParallelIterator>::opt_len
55
}
56
57
impl<A, B> IndexedParallelIterator for Chain<A, B>
58
where
59
    A: IndexedParallelIterator,
60
    B: IndexedParallelIterator<Item = A::Item>,
61
{
62
0
    fn drive<C>(self, consumer: C) -> C::Result
63
0
    where
64
0
        C: Consumer<Self::Item>,
65
    {
66
0
        let Chain { a, b } = self;
67
0
        let (left, right, reducer) = consumer.split_at(a.len());
68
0
        let (a, b) = join(|| a.drive(left), || b.drive(right));
69
0
        reducer.reduce(a, b)
70
0
    }
71
72
0
    fn len(&self) -> usize {
73
0
        self.a.len().checked_add(self.b.len()).expect("overflow")
74
0
    }
75
76
0
    fn with_producer<CB>(self, callback: CB) -> CB::Output
77
0
    where
78
0
        CB: ProducerCallback<Self::Item>,
79
    {
80
0
        let a_len = self.a.len();
81
0
        return self.a.with_producer(CallbackA {
82
0
            callback,
83
0
            a_len,
84
0
            b: self.b,
85
0
        });
86
87
        struct CallbackA<CB, B> {
88
            callback: CB,
89
            a_len: usize,
90
            b: B,
91
        }
92
93
        impl<CB, B> ProducerCallback<B::Item> for CallbackA<CB, B>
94
        where
95
            B: IndexedParallelIterator,
96
            CB: ProducerCallback<B::Item>,
97
        {
98
            type Output = CB::Output;
99
100
0
            fn callback<A>(self, a_producer: A) -> Self::Output
101
0
            where
102
0
                A: Producer<Item = B::Item>,
103
            {
104
0
                self.b.with_producer(CallbackB {
105
0
                    callback: self.callback,
106
0
                    a_len: self.a_len,
107
0
                    a_producer,
108
0
                })
109
0
            }
110
        }
111
112
        struct CallbackB<CB, A> {
113
            callback: CB,
114
            a_len: usize,
115
            a_producer: A,
116
        }
117
118
        impl<CB, A> ProducerCallback<A::Item> for CallbackB<CB, A>
119
        where
120
            A: Producer,
121
            CB: ProducerCallback<A::Item>,
122
        {
123
            type Output = CB::Output;
124
125
0
            fn callback<B>(self, b_producer: B) -> Self::Output
126
0
            where
127
0
                B: Producer<Item = A::Item>,
128
            {
129
0
                let producer = ChainProducer::new(self.a_len, self.a_producer, b_producer);
130
0
                self.callback.callback(producer)
131
0
            }
132
        }
133
0
    }
134
}
135
136
// ////////////////////////////////////////////////////////////////////////
137
138
struct ChainProducer<A, B>
139
where
140
    A: Producer,
141
    B: Producer<Item = A::Item>,
142
{
143
    a_len: usize,
144
    a: A,
145
    b: B,
146
}
147
148
impl<A, B> ChainProducer<A, B>
149
where
150
    A: Producer,
151
    B: Producer<Item = A::Item>,
152
{
153
0
    fn new(a_len: usize, a: A, b: B) -> Self {
154
0
        ChainProducer { a_len, a, b }
155
0
    }
156
}
157
158
impl<A, B> Producer for ChainProducer<A, B>
159
where
160
    A: Producer,
161
    B: Producer<Item = A::Item>,
162
{
163
    type Item = A::Item;
164
    type IntoIter = ChainSeq<A::IntoIter, B::IntoIter>;
165
166
0
    fn into_iter(self) -> Self::IntoIter {
167
0
        ChainSeq::new(self.a.into_iter(), self.b.into_iter())
168
0
    }
169
170
0
    fn min_len(&self) -> usize {
171
0
        Ord::max(self.a.min_len(), self.b.min_len())
172
0
    }
173
174
0
    fn max_len(&self) -> usize {
175
0
        Ord::min(self.a.max_len(), self.b.max_len())
176
0
    }
177
178
0
    fn split_at(self, index: usize) -> (Self, Self) {
179
0
        if index <= self.a_len {
180
0
            let a_rem = self.a_len - index;
181
0
            let (a_left, a_right) = self.a.split_at(index);
182
0
            let (b_left, b_right) = self.b.split_at(0);
183
0
            (
184
0
                ChainProducer::new(index, a_left, b_left),
185
0
                ChainProducer::new(a_rem, a_right, b_right),
186
0
            )
187
        } else {
188
0
            let (a_left, a_right) = self.a.split_at(self.a_len);
189
0
            let (b_left, b_right) = self.b.split_at(index - self.a_len);
190
0
            (
191
0
                ChainProducer::new(self.a_len, a_left, b_left),
192
0
                ChainProducer::new(0, a_right, b_right),
193
0
            )
194
        }
195
0
    }
196
197
0
    fn fold_with<F>(self, mut folder: F) -> F
198
0
    where
199
0
        F: Folder<A::Item>,
200
    {
201
0
        folder = self.a.fold_with(folder);
202
0
        if folder.full() {
203
0
            folder
204
        } else {
205
0
            self.b.fold_with(folder)
206
        }
207
0
    }
208
}
209
210
// ////////////////////////////////////////////////////////////////////////
211
212
/// Wrapper for `Chain` to implement `ExactSizeIterator`
213
struct ChainSeq<A, B> {
214
    chain: iter::Chain<A, B>,
215
}
216
217
impl<A, B> ChainSeq<A, B> {
218
0
    fn new(a: A, b: B) -> ChainSeq<A, B>
219
0
    where
220
0
        A: ExactSizeIterator,
221
0
        B: ExactSizeIterator<Item = A::Item>,
222
    {
223
0
        ChainSeq { chain: a.chain(b) }
224
0
    }
225
}
226
227
impl<A, B> Iterator for ChainSeq<A, B>
228
where
229
    A: Iterator,
230
    B: Iterator<Item = A::Item>,
231
{
232
    type Item = A::Item;
233
234
0
    fn next(&mut self) -> Option<Self::Item> {
235
0
        self.chain.next()
236
0
    }
237
238
0
    fn size_hint(&self) -> (usize, Option<usize>) {
239
0
        self.chain.size_hint()
240
0
    }
241
}
242
243
impl<A, B> ExactSizeIterator for ChainSeq<A, B>
244
where
245
    A: ExactSizeIterator,
246
    B: ExactSizeIterator<Item = A::Item>,
247
{
248
}
249
250
impl<A, B> DoubleEndedIterator for ChainSeq<A, B>
251
where
252
    A: DoubleEndedIterator,
253
    B: DoubleEndedIterator<Item = A::Item>,
254
{
255
0
    fn next_back(&mut self) -> Option<Self::Item> {
256
0
        self.chain.next_back()
257
0
    }
258
}