1use crate::ParExtend;
2use crate::infallible::Xap;
3use crate::infallible::recursive::execution;
4use crate::infallible::recursive::par::ParRec;
5use crate::infallible::recursive::par_core::ParRecCore;
6use crate::infallible::xap::{FilMapOf, FilOf, FlatMapOf, FlattenOf, InsOf, MapOf};
7use crate::parameters::{ChunkSize, IterationOrder, NumThreads, Params};
8use crate::runner::{DefaultRunner, ParRunner};
9use alloc::vec::Vec;
10
11pub struct ParRecIter<I, X, Ix, Ex, R = DefaultRunner>
13where
14 I: IntoIterator,
15 X: Xap<I = I::Item>,
16 R: ParRunner,
17 Ix: IntoIterator<Item = X::I>,
18 Ex: Fn(&I::Item) -> Ix + Send + Copy,
19{
20 iter: I,
21 xap: X,
22 exe: R,
23 params: Params,
24 extend: Ex,
25}
26
27impl<I, X, Ix, Ex, R> ParRecIter<I, X, Ix, Ex, R>
28where
29 I: IntoIterator,
30 X: Xap<I = I::Item>,
31 R: ParRunner,
32 Ix: IntoIterator<Item = X::I>,
33 Ex: Fn(&I::Item) -> Ix + Send + Copy,
34{
35 pub(crate) fn new(iter: I, xap: X, exe: R, params: Params, extend: Ex) -> Self {
36 Self {
37 iter,
38 xap,
39 exe,
40 params,
41 extend,
42 }
43 }
44
45 pub(super) fn with_xap<Y: Xap<I = I::Item>>(self, xap: Y) -> ParRecIter<I, Y, Ix, Ex, R> {
46 ParRecIter::new(self.iter, xap, self.exe, self.params, self.extend)
47 }
48
49 fn destruct_x(self) -> (I, X, R, Params, Ex) {
50 (self.iter, self.xap, self.exe, self.params, self.extend)
51 }
52}
53
54impl<I, X, Ix, Ex, R> ParRecCore for ParRecIter<I, X, Ix, Ex, R>
55where
56 I: IntoIterator,
57 X: Xap<I = I::Item>,
58 R: ParRunner,
59 Ix: IntoIterator<Item = X::I>,
60 Ex: Fn(&I::Item) -> Ix + Send + Copy,
61{
62 type Item = X::O;
63
64 type Runner = R;
65
66 type Input = I;
67
68 type Xap = X;
69
70 fn destruct(self) -> (Self::Input, Self::Xap, Self::Runner, Params) {
71 (self.iter, self.xap, self.exe, self.params)
72 }
73}
74
75impl<I, X, Ix, Ex, R> ParRec for ParRecIter<I, X, Ix, Ex, R>
76where
77 I: IntoIterator,
78 X: Xap<I = I::Item>,
79 R: ParRunner,
80 Ix: IntoIterator<Item = X::I>,
81 Ex: Fn(&I::Item) -> Ix + Send + Copy,
82{
83 fn runner<Q: ParRunner>(
86 self,
87 runner: Q,
88 ) -> impl ParRec<Item = Self::Item, Xap = Self::Xap, Input = Self::Input> {
89 let (iter, xap, _, params, extend) = self.destruct_x();
90 ParRecIter::new(iter, xap, runner, params, extend)
91 }
92
93 #[cfg(feature = "std")]
94 fn runner_with_diagnostics(
95 self,
96 ) -> impl ParRec<Item = Self::Item, Xap = Self::Xap, Input = Self::Input> {
97 let (iter, xap, exe, params, extend) = self.destruct_x();
98 ParRecIter::new(iter, xap, exe.with_diagnostics(), params, extend)
99 }
100
101 fn num_threads(mut self, num_threads: impl Into<NumThreads>) -> Self {
102 self.params = self.params.with_num_threads(num_threads);
103 self
104 }
105
106 fn chunk_size(mut self, chunk_size: impl Into<ChunkSize>) -> Self {
107 self.params = self.params.with_chunk_size(chunk_size);
108 self
109 }
110
111 fn iteration_order(mut self, collect: IterationOrder) -> Self {
112 self.params = self.params.with_collect_ordering(collect);
113 self
114 }
115
116 fn map<Q, H>(
119 self,
120 h: H,
121 ) -> impl ParRec<Item = Q, Xap = MapOf<Self::Xap, Q, H>, Input = Self::Input>
122 where
123 H: Fn(Self::Item) -> Q + Copy + Send,
124 {
125 let xap = self.xap.map(h);
126 self.with_xap(xap)
127 }
128
129 fn inspect<H>(
130 self,
131 h: H,
132 ) -> impl ParRec<Item = Self::Item, Xap = InsOf<Self::Xap, H>, Input = Self::Input>
133 where
134 H: Fn(&Self::Item) + Copy + Send,
135 {
136 let xap = self.xap.inspect(h);
137 self.with_xap(xap)
138 }
139
140 fn filter<H>(
141 self,
142 h: H,
143 ) -> impl ParRec<Item = Self::Item, Xap = FilOf<Self::Xap, H>, Input = Self::Input>
144 where
145 H: Fn(&Self::Item) -> bool + Copy + Send,
146 {
147 let xap = self.xap.filter(h);
148 self.with_xap(xap)
149 }
150
151 fn filter_map<Q, H>(
152 self,
153 h: H,
154 ) -> impl ParRec<Item = Q, Xap = FilMapOf<Self::Xap, Q, H>, Input = Self::Input>
155 where
156 H: Fn(Self::Item) -> Option<Q> + Copy + Send,
157 {
158 let xap = self.xap.filter_map(h);
159 self.with_xap(xap)
160 }
161
162 fn flat_map<V, H>(
163 self,
164 h: H,
165 ) -> impl ParRec<Item = V::Item, Xap = FlatMapOf<Self::Xap, V, H>, Input = Self::Input>
166 where
167 V: IntoIterator,
168 H: Fn(Self::Item) -> V + Copy + Send,
169 {
170 let xap = self.xap.flat_map(h);
171 self.with_xap(xap)
172 }
173
174 fn flatten(
175 self,
176 ) -> impl ParRec<
177 Item = <Self::Item as IntoIterator>::Item,
178 Xap = FlattenOf<Self::Xap>,
179 Input = Self::Input,
180 >
181 where
182 Self::Item: IntoIterator,
183 {
184 let xap = self.xap.flatten();
185 self.with_xap(xap)
186 }
187
188 fn first(self) -> Option<Self::Item>
191 where
192 Self::Item: Send,
193 <Self::Input as IntoIterator>::Item: Send,
194 {
195 let (iter, x, exe, params, extend) = self.destruct_x();
196
197 match params.iteration_order {
198 IterationOrder::Ordered => execution::next(exe, params, iter, x, extend),
199 IterationOrder::Arbitrary => execution::next_any(exe, params, iter, x, extend),
200 }
201 }
202
203 fn reduce<F>(self, f: F) -> Option<Self::Item>
204 where
205 F: Fn(Self::Item, Self::Item) -> Self::Item + Send + Copy,
206 Self::Item: Send,
207 <Self::Input as IntoIterator>::Item: Send,
208 {
209 let (iter, x, exe, params, extend) = self.destruct_x();
210 execution::reduce(exe, params, iter, x, extend, f)
211 }
212
213 fn fold<B, Id, F>(self, init: Id, f: F) -> Vec<B>
214 where
215 B: Send,
216 Id: Fn() -> B,
217 F: Fn(&mut B, Self::Item) + Copy + Send,
218 <Self::Input as IntoIterator>::Item: Send,
219 {
220 let (iter, x, exe, params, extend) = self.destruct_x();
221 execution::fold(exe, params, iter, x, extend, init, f)
222 }
223
224 fn collect_into<C>(self, dst: &mut C)
225 where
226 C: ParExtend<Self::Item>,
227 Self::Item: Send,
228 <Self::Input as IntoIterator>::Item: Send,
229 {
230 let (iter, x, exe, params, extend) = self.destruct_x();
231 match params.iteration_order {
232 IterationOrder::Ordered => execution::collect(exe, params, iter, x, extend, dst),
233 IterationOrder::Arbitrary => execution::collect_arb(exe, params, iter, x, extend, dst),
234 }
235 }
236}