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