]> git.proxmox.com Git - rustc.git/blob - vendor/rustc-rayon/src/iter/try_fold.rs
51f9881794b8fa3aa81b1c05d627426235c28927
[rustc.git] / vendor / rustc-rayon / src / iter / try_fold.rs
1 use super::plumbing::*;
2 use super::*;
3
4 use super::private::Try;
5 use std::fmt::{self, Debug};
6 use std::marker::PhantomData;
7
8 impl<U, I, ID, F> TryFold<I, U, ID, F>
9 where
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 /// `TryFold` is an iterator that applies a function over an iterator producing a single value.
26 /// This struct is created by the [`try_fold()`] method on [`ParallelIterator`]
27 ///
28 /// [`try_fold()`]: trait.ParallelIterator.html#method.try_fold
29 /// [`ParallelIterator`]: trait.ParallelIterator.html
30 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
31 #[derive(Clone)]
32 pub struct TryFold<I, U, ID, F> {
33 base: I,
34 identity: ID,
35 fold_op: F,
36 marker: PhantomData<U>,
37 }
38
39 impl<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
45 impl<U, I, ID, F> ParallelIterator for TryFold<I, U, ID, F>
46 where
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
68 struct TryFoldConsumer<'c, U, C, ID: 'c, F: 'c> {
69 base: C,
70 identity: &'c ID,
71 fold_op: &'c F,
72 marker: PhantomData<U>,
73 }
74
75 impl<'r, U, T, C, ID, F> Consumer<T> for TryFoldConsumer<'r, U, C, ID, F>
76 where
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
111 impl<'r, U, T, C, ID, F> UnindexedConsumer<T> for TryFoldConsumer<'r, U, C, ID, F>
112 where
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
130 struct TryFoldFolder<'r, C, U: Try, F: 'r> {
131 base: C,
132 fold_op: &'r F,
133 result: Result<U::Ok, U::Error>,
134 }
135
136 impl<'r, C, U, F, T> Folder<T> for TryFoldFolder<'r, C, U, F>
137 where
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
165 // ///////////////////////////////////////////////////////////////////////////
166
167 impl<U, I, F> TryFoldWith<I, U, F>
168 where
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 /// `TryFoldWith` is an iterator that applies a function over an iterator producing a single value.
184 /// This struct is created by the [`try_fold_with()`] method on [`ParallelIterator`]
185 ///
186 /// [`try_fold_with()`]: trait.ParallelIterator.html#method.try_fold_with
187 /// [`ParallelIterator`]: trait.ParallelIterator.html
188 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
189 #[derive(Clone)]
190 pub struct TryFoldWith<I, U: Try, F> {
191 base: I,
192 item: U::Ok,
193 fold_op: F,
194 }
195
196 impl<I: ParallelIterator + Debug, U: Try, F> Debug for TryFoldWith<I, U, F>
197 where
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
208 impl<U, I, F> ParallelIterator for TryFoldWith<I, U, F>
209 where
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
230 struct TryFoldWithConsumer<'c, C, U: Try, F: 'c> {
231 base: C,
232 item: U::Ok,
233 fold_op: &'c F,
234 }
235
236 impl<'r, U, T, C, F> Consumer<T> for TryFoldWithConsumer<'r, C, U, F>
237 where
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
276 impl<'r, U, T, C, F> UnindexedConsumer<T> for TryFoldWithConsumer<'r, C, U, F>
277 where
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 }