Coverage Report

Created: 2025-07-18 06:49

/rust/registry/src/index.crates.io-6f17d22bba15001f/rayon-1.10.0/src/iter/fold.rs
Line
Count
Source (jump to first uncovered line)
1
use super::plumbing::*;
2
use super::*;
3
4
use std::fmt::{self, Debug};
5
6
impl<U, I, ID, F> Fold<I, ID, F>
7
where
8
    I: ParallelIterator,
9
    F: Fn(U, I::Item) -> U + Sync + Send,
10
    ID: Fn() -> U + Sync + Send,
11
    U: Send,
12
{
13
0
    pub(super) fn new(base: I, identity: ID, fold_op: F) -> Self {
14
0
        Fold {
15
0
            base,
16
0
            identity,
17
0
            fold_op,
18
0
        }
19
0
    }
20
}
21
22
/// `Fold` is an iterator that applies a function over an iterator producing a single value.
23
/// This struct is created by the [`fold()`] method on [`ParallelIterator`]
24
///
25
/// [`fold()`]: trait.ParallelIterator.html#method.fold
26
/// [`ParallelIterator`]: trait.ParallelIterator.html
27
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
28
#[derive(Clone)]
29
pub struct Fold<I, ID, F> {
30
    base: I,
31
    identity: ID,
32
    fold_op: F,
33
}
34
35
impl<I: ParallelIterator + Debug, ID, F> Debug for Fold<I, ID, F> {
36
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37
0
        f.debug_struct("Fold").field("base", &self.base).finish()
38
0
    }
39
}
40
41
impl<U, I, ID, F> ParallelIterator for Fold<I, ID, F>
42
where
43
    I: ParallelIterator,
44
    F: Fn(U, I::Item) -> U + Sync + Send,
45
    ID: Fn() -> U + Sync + Send,
46
    U: Send,
47
{
48
    type Item = U;
49
50
0
    fn drive_unindexed<C>(self, consumer: C) -> C::Result
51
0
    where
52
0
        C: UnindexedConsumer<Self::Item>,
53
0
    {
54
0
        let consumer1 = FoldConsumer {
55
0
            base: consumer,
56
0
            fold_op: &self.fold_op,
57
0
            identity: &self.identity,
58
0
        };
59
0
        self.base.drive_unindexed(consumer1)
60
0
    }
61
}
62
63
struct FoldConsumer<'c, C, ID, F> {
64
    base: C,
65
    fold_op: &'c F,
66
    identity: &'c ID,
67
}
68
69
impl<'r, U, T, C, ID, F> Consumer<T> for FoldConsumer<'r, C, ID, F>
70
where
71
    C: Consumer<U>,
72
    F: Fn(U, T) -> U + Sync,
73
    ID: Fn() -> U + Sync,
74
    U: Send,
75
{
76
    type Folder = FoldFolder<'r, C::Folder, U, F>;
77
    type Reducer = C::Reducer;
78
    type Result = C::Result;
79
80
0
    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
81
0
        let (left, right, reducer) = self.base.split_at(index);
82
0
        (
83
0
            FoldConsumer { base: left, ..self },
84
0
            FoldConsumer {
85
0
                base: right,
86
0
                ..self
87
0
            },
88
0
            reducer,
89
0
        )
90
0
    }
91
92
0
    fn into_folder(self) -> Self::Folder {
93
0
        FoldFolder {
94
0
            base: self.base.into_folder(),
95
0
            item: (self.identity)(),
96
0
            fold_op: self.fold_op,
97
0
        }
98
0
    }
99
100
0
    fn full(&self) -> bool {
101
0
        self.base.full()
102
0
    }
103
}
104
105
impl<'r, U, T, C, ID, F> UnindexedConsumer<T> for FoldConsumer<'r, C, ID, F>
106
where
107
    C: UnindexedConsumer<U>,
108
    F: Fn(U, T) -> U + Sync,
109
    ID: Fn() -> U + Sync,
110
    U: Send,
111
{
112
0
    fn split_off_left(&self) -> Self {
113
0
        FoldConsumer {
114
0
            base: self.base.split_off_left(),
115
0
            ..*self
116
0
        }
117
0
    }
118
119
0
    fn to_reducer(&self) -> Self::Reducer {
120
0
        self.base.to_reducer()
121
0
    }
122
}
123
124
struct FoldFolder<'r, C, ID, F> {
125
    base: C,
126
    fold_op: &'r F,
127
    item: ID,
128
}
129
130
impl<'r, C, ID, F, T> Folder<T> for FoldFolder<'r, C, ID, F>
131
where
132
    C: Folder<ID>,
133
    F: Fn(ID, T) -> ID + Sync,
134
{
135
    type Result = C::Result;
136
137
0
    fn consume(self, item: T) -> Self {
138
0
        let item = (self.fold_op)(self.item, item);
139
0
        FoldFolder {
140
0
            base: self.base,
141
0
            fold_op: self.fold_op,
142
0
            item,
143
0
        }
144
0
    }
145
146
0
    fn consume_iter<I>(self, iter: I) -> Self
147
0
    where
148
0
        I: IntoIterator<Item = T>,
149
0
    {
150
0
        fn not_full<C, ID, T>(base: &C) -> impl Fn(&T) -> bool + '_
151
0
        where
152
0
            C: Folder<ID>,
153
0
        {
154
0
            move |_| !base.full()
155
0
        }
156
157
0
        let base = self.base;
158
0
        let item = iter
159
0
            .into_iter()
160
0
            // stop iterating if another thread has finished
161
0
            .take_while(not_full(&base))
162
0
            .fold(self.item, self.fold_op);
163
0
164
0
        FoldFolder {
165
0
            base,
166
0
            item,
167
0
            fold_op: self.fold_op,
168
0
        }
169
0
    }
170
171
0
    fn complete(self) -> C::Result {
172
0
        self.base.consume(self.item).complete()
173
0
    }
174
175
0
    fn full(&self) -> bool {
176
0
        self.base.full()
177
0
    }
178
}
179
180
// ///////////////////////////////////////////////////////////////////////////
181
182
impl<U, I, F> FoldWith<I, U, F>
183
where
184
    I: ParallelIterator,
185
    F: Fn(U, I::Item) -> U + Sync + Send,
186
    U: Send + Clone,
187
{
188
0
    pub(super) fn new(base: I, item: U, fold_op: F) -> Self {
189
0
        FoldWith {
190
0
            base,
191
0
            item,
192
0
            fold_op,
193
0
        }
194
0
    }
195
}
196
197
/// `FoldWith` is an iterator that applies a function over an iterator producing a single value.
198
/// This struct is created by the [`fold_with()`] method on [`ParallelIterator`]
199
///
200
/// [`fold_with()`]: trait.ParallelIterator.html#method.fold_with
201
/// [`ParallelIterator`]: trait.ParallelIterator.html
202
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
203
#[derive(Clone)]
204
pub struct FoldWith<I, U, F> {
205
    base: I,
206
    item: U,
207
    fold_op: F,
208
}
209
210
impl<I: ParallelIterator + Debug, U: Debug, F> Debug for FoldWith<I, U, F> {
211
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
212
0
        f.debug_struct("FoldWith")
213
0
            .field("base", &self.base)
214
0
            .field("item", &self.item)
215
0
            .finish()
216
0
    }
217
}
218
219
impl<U, I, F> ParallelIterator for FoldWith<I, U, F>
220
where
221
    I: ParallelIterator,
222
    F: Fn(U, I::Item) -> U + Sync + Send,
223
    U: Send + Clone,
224
{
225
    type Item = U;
226
227
0
    fn drive_unindexed<C>(self, consumer: C) -> C::Result
228
0
    where
229
0
        C: UnindexedConsumer<Self::Item>,
230
0
    {
231
0
        let consumer1 = FoldWithConsumer {
232
0
            base: consumer,
233
0
            item: self.item,
234
0
            fold_op: &self.fold_op,
235
0
        };
236
0
        self.base.drive_unindexed(consumer1)
237
0
    }
238
}
239
240
struct FoldWithConsumer<'c, C, U, F> {
241
    base: C,
242
    item: U,
243
    fold_op: &'c F,
244
}
245
246
impl<'r, U, T, C, F> Consumer<T> for FoldWithConsumer<'r, C, U, F>
247
where
248
    C: Consumer<U>,
249
    F: Fn(U, T) -> U + Sync,
250
    U: Send + Clone,
251
{
252
    type Folder = FoldFolder<'r, C::Folder, U, F>;
253
    type Reducer = C::Reducer;
254
    type Result = C::Result;
255
256
0
    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
257
0
        let (left, right, reducer) = self.base.split_at(index);
258
0
        (
259
0
            FoldWithConsumer {
260
0
                base: left,
261
0
                item: self.item.clone(),
262
0
                ..self
263
0
            },
264
0
            FoldWithConsumer {
265
0
                base: right,
266
0
                ..self
267
0
            },
268
0
            reducer,
269
0
        )
270
0
    }
271
272
0
    fn into_folder(self) -> Self::Folder {
273
0
        FoldFolder {
274
0
            base: self.base.into_folder(),
275
0
            item: self.item,
276
0
            fold_op: self.fold_op,
277
0
        }
278
0
    }
279
280
0
    fn full(&self) -> bool {
281
0
        self.base.full()
282
0
    }
283
}
284
285
impl<'r, U, T, C, F> UnindexedConsumer<T> for FoldWithConsumer<'r, C, U, F>
286
where
287
    C: UnindexedConsumer<U>,
288
    F: Fn(U, T) -> U + Sync,
289
    U: Send + Clone,
290
{
291
0
    fn split_off_left(&self) -> Self {
292
0
        FoldWithConsumer {
293
0
            base: self.base.split_off_left(),
294
0
            item: self.item.clone(),
295
0
            ..*self
296
0
        }
297
0
    }
298
299
0
    fn to_reducer(&self) -> Self::Reducer {
300
0
        self.base.to_reducer()
301
0
    }
302
}