1use crate::infallible::Xap;
2use crate::infallible::XapIter;
3use crate::infallible::par_core::ParCore;
4use crate::infallible::par_runner::ParRunnerInfallible;
5use crate::infallible::xap::{FilMapOf, FilOf, FlatMapOf, FlattenOf, InsOf, MapOf};
6use crate::parameters::{ChunkSize, IterationOrder, NumThreads, Params};
7use crate::runner::{DefaultRunner, ParRunner};
8use crate::sizes::Size;
9use crate::{Par, ParExtend};
10use orx_concurrent_iter::ConcurrentIter;
11
12pub struct ParIter<I, X, R = DefaultRunner>
14where
15 I: ConcurrentIter,
16 X: Xap<I = I::Item>,
17 R: ParRunner,
18{
19 iter: I,
20 xap: X,
21 exe: R,
22 params: Params,
23}
24
25impl<I, X, R> ParIter<I, X, R>
26where
27 I: ConcurrentIter,
28 X: Xap<I = I::Item>,
29 R: ParRunner,
30{
31 pub(crate) fn new(iter: I, xap: X, exe: R, params: Params) -> Self {
32 Self {
33 iter,
34 xap,
35 exe,
36 params,
37 }
38 }
39
40 pub(super) fn with_xap<Y: Xap<I = I::Item>>(self, xap: Y) -> ParIter<I, Y, R> {
41 ParIter::new(self.iter, xap, self.exe, self.params)
42 }
43}
44
45impl<I, X, R> IntoIterator for ParIter<I, X, R>
46where
47 I: ConcurrentIter,
48 X: Xap<I = I::Item>,
49 R: ParRunner,
50{
51 type Item = X::O;
52
53 type IntoIter = XapIter<I::SequentialIter, X>;
54
55 fn into_iter(self) -> Self::IntoIter {
56 XapIter::new(self.iter.into_seq_iter(), self.xap)
57 }
58}
59
60impl<I, X, R> ParCore for ParIter<I, X, R>
61where
62 I: ConcurrentIter,
63 X: Xap<I = I::Item>,
64 R: ParRunner,
65{
66 type Runner = R;
67
68 type Input = I;
69
70 type Xap = X;
71
72 fn destruct(self) -> (Self::Input, Self::Xap, Self::Runner, Params) {
73 (self.iter, self.xap, self.exe, self.params)
74 }
75}
76
77impl<I, X, R> Par for ParIter<I, X, R>
78where
79 I: ConcurrentIter,
80 X: Xap<I = I::Item>,
81 R: ParRunner,
82{
83 fn runner<Q: ParRunner>(
86 self,
87 runner: Q,
88 ) -> impl Par<Item = Self::Item, Xap = Self::Xap, Input = Self::Input> {
89 let (iter, xap, _, params) = self.destruct();
90 ParIter::new(iter, xap, runner, params)
91 }
92
93 #[cfg(feature = "std")]
94 fn runner_with_diagnostics(
95 self,
96 ) -> impl Par<Item = Self::Item, Xap = Self::Xap, Input = Self::Input> {
97 let (iter, xap, exe, params) = self.destruct();
98 ParIter::new(iter, xap, exe.with_diagnostics(), params)
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 Par<Item = Q, Xap = MapOf<Self::Xap, Q, H>, Input = Self::Input>
122 where
123 H: Fn(X::O) -> 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 Par<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 Par<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 Par<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 Par<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 Par<
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 size_hint(&self) -> (usize, Option<usize>) {
191 <X::Size as Size>::transformed_size_hint(self.iter.size_hint())
192 }
193
194 fn first(self) -> Option<X::O>
197 where
198 X::O: Send,
199 {
200 let (iter, x, mut exe, params) = self.destruct();
201 match params.iteration_order {
202 IterationOrder::Ordered => exe.next(params, iter, x).map(|x| x.val),
203 IterationOrder::Arbitrary => exe.next_any(params, iter, x),
204 }
205 }
206
207 fn reduce<F>(self, f: F) -> Option<X::O>
208 where
209 F: Fn(X::O, X::O) -> X::O + Send + Copy,
210 X::O: Send,
211 {
212 let (iter, x, mut exe, params) = self.destruct();
213 exe.reduce(params, iter, x, f)
214 }
215
216 fn collect_into<P>(self, dst: &mut P)
217 where
218 P: ParExtend<X::O>,
219 X::O: Send,
220 {
221 let (iter, x, mut exe, params) = self.destruct();
222 match params.iteration_order {
223 IterationOrder::Ordered => exe.collect(params, iter, x, dst),
224 IterationOrder::Arbitrary => exe.collect_arb(params, iter, x, dst),
225 }
226 }
227}