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