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