Coverage Report

Created: 2026-01-13 06:28

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