1use std::cmp::Ordering;
2
3pub trait IntoMaybeParallelIterator {
9 type Item;
10 #[cfg(not(feature = "rayon"))]
11 type Iter: Iterator<Item = Self::Item>;
12 #[cfg(feature = "rayon")]
13 type Iter: rayon::iter::ParallelIterator<Item = Self::Item>;
14
15 fn into_maybe_par_iter(self) -> MaybeParallelIterator<Self::Iter>;
16}
17
18pub trait IntoMaybeParallelRefIterator<'a> {
20 #[cfg(not(feature = "rayon"))]
21 type Iter: Iterator;
22 #[cfg(feature = "rayon")]
23 type Iter: rayon::iter::ParallelIterator;
24
25 fn maybe_par_iter(&'a self) -> MaybeParallelIterator<Self::Iter>;
26}
27
28pub trait IntoMaybeParallelRefMutIterator<'a> {
30 #[cfg(not(feature = "rayon"))]
31 type Iter: Iterator;
32 #[cfg(feature = "rayon")]
33 type Iter: rayon::iter::ParallelIterator;
34
35 fn maybe_par_iter_mut(&'a mut self) -> MaybeParallelIterator<Self::Iter>;
36}
37
38#[cfg(not(feature = "rayon"))]
40#[repr(transparent)]
41pub struct MaybeParallelIterator<IT: Iterator>(IT);
42
43#[cfg(not(feature = "rayon"))]
44impl<IIT: IntoIterator> IntoMaybeParallelIterator for IIT {
45 type Item = IIT::Item;
46 type Iter = IIT::IntoIter;
47
48 fn into_maybe_par_iter(self) -> MaybeParallelIterator<Self::Iter> {
49 MaybeParallelIterator(self.into_iter())
50 }
51}
52
53#[cfg(not(feature = "rayon"))]
54impl<'a, IIT: 'a + ?Sized> IntoMaybeParallelRefIterator<'a> for IIT
55where
56 &'a IIT: IntoIterator,
57{
58 type Iter = <&'a IIT as IntoIterator>::IntoIter;
59
60 fn maybe_par_iter(&'a self) -> MaybeParallelIterator<Self::Iter> {
61 MaybeParallelIterator(self.into_iter())
62 }
63}
64
65#[cfg(not(feature = "rayon"))]
66impl<'a, IIT: 'a + ?Sized> IntoMaybeParallelRefMutIterator<'a> for IIT
67where
68 &'a mut IIT: IntoIterator,
69{
70 type Iter = <&'a mut IIT as IntoIterator>::IntoIter;
71
72 fn maybe_par_iter_mut(&'a mut self) -> MaybeParallelIterator<Self::Iter> {
73 MaybeParallelIterator(self.into_iter())
74 }
75}
76
77#[cfg(not(feature = "rayon"))]
78impl<IT: Iterator> MaybeParallelIterator<IT> {
79 pub fn collect<B: FromIterator<IT::Item>>(self) -> B
80 where
81 Self: Sized,
82 {
83 FromIterator::from_iter(self)
84 }
85
86 pub fn for_each<O: Fn(IT::Item)>(self, op: O) {
88 self.0.for_each(op)
89 }
90
91 pub fn with_min_sequential(self, _: usize) -> Self {
98 self
99 }
100
101 pub fn enumerate(self) -> MaybeParallelIterator<std::iter::Enumerate<IT>> {
108 MaybeParallelIterator(self.0.enumerate())
109 }
110
111 pub fn map<O, M: Fn(IT::Item) -> O>(
113 self,
114 map: M,
115 ) -> MaybeParallelIterator<std::iter::Map<IT, M>> {
116 MaybeParallelIterator(self.0.map(map))
117 }
118
119 pub fn filter_map<O, M: Fn(IT::Item) -> Option<O>>(
121 self,
122 map: M,
123 ) -> MaybeParallelIterator<std::iter::FilterMap<IT, M>> {
124 MaybeParallelIterator(self.0.filter_map(map))
125 }
126
127 pub fn flat_map<O: IntoIterator, M: Fn(IT::Item) -> O>(
129 self,
130 map: M,
131 ) -> MaybeParallelIterator<std::iter::FlatMap<IT, O, M>> {
132 MaybeParallelIterator(self.0.flat_map(map))
133 }
134
135 pub fn find_any<F: Fn(&IT::Item) -> bool>(mut self, f: F) -> Option<IT::Item> {
137 self.0.find(f)
138 }
139
140 pub fn into_inner(self) -> IT {
142 self.0
143 }
144}
145
146#[cfg(not(feature = "rayon"))]
147impl<IT: Iterator> IntoIterator for MaybeParallelIterator<IT> {
148 type Item = IT::Item;
149 type IntoIter = IT;
150
151 fn into_iter(self) -> Self::IntoIter {
152 self.into_inner()
153 }
154}
155
156#[cfg(feature = "rayon")]
158#[repr(transparent)]
159pub struct MaybeParallelIterator<IT: rayon::iter::ParallelIterator>(IT);
160
161#[cfg(feature = "rayon")]
162impl<IIT> IntoMaybeParallelIterator for IIT
163where
164 IIT: rayon::iter::IntoParallelIterator,
165{
166 type Item = IIT::Item;
167 type Iter = IIT::Iter;
168
169 fn into_maybe_par_iter(self) -> MaybeParallelIterator<Self::Iter> {
170 MaybeParallelIterator(self.into_par_iter())
171 }
172}
173
174#[cfg(feature = "rayon")]
175impl<'a, IIT: 'a> IntoMaybeParallelRefIterator<'a> for IIT
176where
177 IIT: rayon::iter::IntoParallelRefIterator<'a> + ?Sized,
178{
179 type Iter = IIT::Iter;
180
181 fn maybe_par_iter(&'a self) -> MaybeParallelIterator<Self::Iter> {
182 MaybeParallelIterator(self.par_iter())
183 }
184}
185
186#[cfg(feature = "rayon")]
187impl<'a, IIT: 'a> IntoMaybeParallelRefMutIterator<'a> for IIT
188where
189 IIT: rayon::iter::IntoParallelRefMutIterator<'a> + ?Sized,
190{
191 type Iter = IIT::Iter;
192
193 fn maybe_par_iter_mut(&'a mut self) -> MaybeParallelIterator<Self::Iter> {
194 MaybeParallelIterator(self.par_iter_mut())
195 }
196}
197
198#[cfg(feature = "rayon")]
227impl<IT: rayon::iter::ParallelIterator> MaybeParallelIterator<IT> {
228 pub fn collect<C>(self) -> C
229 where
230 C: rayon::iter::FromParallelIterator<IT::Item>,
231 {
232 C::from_par_iter(self)
233 }
234
235 pub fn for_each<O: Fn(IT::Item) + Sync + Send>(self, op: O) {
237 self.0.for_each(op)
238 }
239
240 pub fn map<O: Send, M: Fn(IT::Item) -> O + Send + Sync>(
242 self,
243 map: M,
244 ) -> MaybeParallelIterator<rayon::iter::Map<IT, M>> {
245 MaybeParallelIterator(self.0.map(map))
246 }
247
248 pub fn filter_map<O: Send, M: Fn(IT::Item) -> Option<O> + Send + Sync>(
250 self,
251 map: M,
252 ) -> MaybeParallelIterator<rayon::iter::FilterMap<IT, M>> {
253 MaybeParallelIterator(self.0.filter_map(map))
254 }
255
256 pub fn flat_map<O: rayon::iter::IntoParallelIterator, M: Fn(IT::Item) -> O + Send + Sync>(
258 self,
259 map: M,
260 ) -> MaybeParallelIterator<rayon::iter::FlatMap<IT, M>> {
261 MaybeParallelIterator(self.0.flat_map(map))
262 }
263
264 pub fn find_any<F: Fn(&IT::Item) -> bool + Send + Sync>(self, f: F) -> Option<IT::Item> {
266 self.0.find_any(f)
267 }
268
269 pub fn into_inner(self) -> IT {
271 self.0
272 }
273}
274
275#[cfg(feature = "rayon")]
276impl<IT: rayon::iter::IndexedParallelIterator> MaybeParallelIterator<IT> {
277 pub fn enumerate(self) -> MaybeParallelIterator<rayon::iter::Enumerate<IT>> {
278 MaybeParallelIterator(self.0.enumerate())
279 }
280
281 pub fn with_min_sequential(
283 self,
284 min_sequential: usize,
285 ) -> MaybeParallelIterator<rayon::iter::MinLen<IT>> {
286 MaybeParallelIterator(self.0.with_min_len(min_sequential))
287 }
288}
289
290#[cfg(feature = "rayon")]
291impl<IT: rayon::iter::ParallelIterator> rayon::iter::ParallelIterator
292 for MaybeParallelIterator<IT>
293{
294 type Item = IT::Item;
295
296 fn drive_unindexed<C>(self, consumer: C) -> C::Result
297 where
298 C: rayon::iter::plumbing::UnindexedConsumer<Self::Item>,
299 {
300 self.0.drive_unindexed(consumer)
301 }
302
303 fn opt_len(&self) -> Option<usize> {
304 self.0.opt_len()
305 }
306}
307
308pub trait MaybeParallelSort<T: Send> {
309 fn maybe_par_sort(&mut self)
310 where
311 T: Ord;
312
313 fn maybe_par_sort_unstable(&mut self)
314 where
315 T: Ord;
316
317 fn maybe_par_sort_by<F>(&mut self, compare: F)
318 where
319 F: Fn(&T, &T) -> Ordering + Sync;
320
321 fn maybe_par_sort_unstable_by<F>(&mut self, compare: F)
322 where
323 F: Fn(&T, &T) -> Ordering + Sync;
324
325 fn maybe_par_sort_by_key<F, K: Ord>(&mut self, f: F)
326 where
327 F: Fn(&T) -> K + Sync;
328
329 fn maybe_par_sort_unstable_by_key<F, K: Ord>(&mut self, f: F)
330 where
331 F: Fn(&T) -> K + Sync;
332}
333
334#[cfg(not(feature = "rayon"))]
335impl<T: Send> MaybeParallelSort<T> for [T] {
336 fn maybe_par_sort(&mut self)
337 where
338 T: Ord,
339 {
340 self.sort()
341 }
342
343 fn maybe_par_sort_unstable(&mut self)
344 where
345 T: Ord,
346 {
347 self.sort_unstable()
348 }
349
350 fn maybe_par_sort_by<F>(&mut self, compare: F)
351 where
352 F: Fn(&T, &T) -> Ordering + Sync,
353 {
354 self.sort_by(compare)
355 }
356
357 fn maybe_par_sort_unstable_by<F>(&mut self, compare: F)
358 where
359 F: Fn(&T, &T) -> Ordering + Sync,
360 {
361 self.sort_unstable_by(compare)
362 }
363
364 fn maybe_par_sort_by_key<F, K: Ord>(&mut self, f: F)
365 where
366 F: Fn(&T) -> K + Sync,
367 {
368 self.sort_by_key(f)
369 }
370
371 fn maybe_par_sort_unstable_by_key<F, K: Ord>(&mut self, f: F)
372 where
373 F: Fn(&T) -> K + Sync,
374 {
375 self.sort_unstable_by_key(f)
376 }
377}
378
379#[cfg(feature = "rayon")]
380impl<T: Send, C> MaybeParallelSort<T> for C
381where
382 C: rayon::slice::ParallelSliceMut<T> + ?Sized,
383{
384 fn maybe_par_sort(&mut self)
385 where
386 T: Ord,
387 {
388 self.par_sort()
389 }
390
391 fn maybe_par_sort_unstable(&mut self)
392 where
393 T: Ord,
394 {
395 self.par_sort_unstable()
396 }
397
398 fn maybe_par_sort_by<F>(&mut self, compare: F)
399 where
400 F: Fn(&T, &T) -> Ordering + Sync,
401 {
402 self.par_sort_by(compare)
403 }
404
405 fn maybe_par_sort_unstable_by<F>(&mut self, compare: F)
406 where
407 F: Fn(&T, &T) -> Ordering + Sync,
408 {
409 self.par_sort_unstable_by(compare)
410 }
411
412 fn maybe_par_sort_by_key<F, K: Ord>(&mut self, f: F)
413 where
414 F: Fn(&T) -> K + Sync,
415 {
416 self.par_sort_by_key(f)
417 }
418
419 fn maybe_par_sort_unstable_by_key<F, K: Ord>(&mut self, f: F)
420 where
421 F: Fn(&T) -> K + Sync,
422 {
423 self.par_sort_unstable_by_key(f)
424 }
425}
426
427#[cfg(test)]
428mod tests {
429 use crate::{
430 IntoMaybeParallelIterator, IntoMaybeParallelRefIterator, IntoMaybeParallelRefMutIterator,
431 MaybeParallelSort,
432 };
433
434 #[test]
435 #[cfg(not(feature = "rayon"))]
436 fn test_sequential() {
437 let mut a: Vec<i32> = (0..100).collect();
438 a.maybe_par_iter().for_each(|item| println!("{}", item));
439 a.maybe_par_iter_mut().for_each(|item| *item -= 5);
440 println!("{:?}", a);
441 a.into_maybe_par_iter()
442 .with_min_sequential(2)
443 .map(|n| -n)
444 .enumerate()
445 .flat_map(|(e, n)| vec![e as i32, n, n + 1000].into_maybe_par_iter())
446 .for_each(|item| {
447 println!("seq: {:?}", item);
448 });
449
450 let mut to_sort: Vec<i32> = vec![5, 2, 2, 6, 1, 6];
451 to_sort.maybe_par_sort();
452 println!("{:?}", to_sort);
453
454 let mut owned = vec![1, 2, 3];
455 let slice = owned.as_slice();
456 slice.maybe_par_iter().for_each(|_| {});
457 let slice_mut = owned.as_mut_slice();
458 slice_mut.maybe_par_iter().for_each(|_| {});
459 slice_mut.maybe_par_iter_mut().for_each(|_| {});
460
461 (0..10).into_maybe_par_iter().for_each(|_| {});
462 }
463
464 #[test]
465 #[cfg(feature = "rayon")]
466 fn test_rayon() {
467 let mut a: Vec<i32> = (0..100).collect();
468 a.maybe_par_iter()
469 .with_min_sequential(5)
470 .for_each(|item| println!("{}", item));
471 a.maybe_par_iter_mut().for_each(|item| *item -= 5);
472 println!("{:?}", a);
473 a.into_maybe_par_iter()
474 .with_min_sequential(2)
475 .map(|n| -n)
476 .enumerate()
477 .flat_map(|(e, n)| vec![e as i32, n, n + 1000].into_maybe_par_iter())
478 .for_each(|item| {
479 println!("par: {:?}", item);
480 });
481
482 let mut to_sort: Vec<i32> = vec![5, 2, 2, 6, 1, 6];
483 to_sort.maybe_par_sort();
484 println!("{:?}", to_sort);
485
486 let mut owned = vec![1, 2, 3];
487 let slice = owned.as_slice();
488 slice.maybe_par_iter().for_each(|_| {});
489 let slice_mut = owned.as_mut_slice();
490 slice_mut.maybe_par_iter().for_each(|_| {});
491 slice_mut.maybe_par_iter_mut().for_each(|_| {});
492
493 (0..10).into_maybe_par_iter().for_each(|_| {});
494 }
495}