orx_parallel/infallible_use/par_enum.rs
1use crate::ParUse;
2use crate::infallible_use::{ParUseIter, XapUseEnumByInput};
3use orx_concurrent_iter::{ConcurrentIter, enumerate::Enumerate};
4
5/// Adds index-value pairs to `ParUse` pipelines.
6///
7/// This is the `ParUse` counterpart of parallel `enumerate`, preserving the
8/// worker-local state while changing each item into `(index, item)`.
9///
10/// # Example
11///
12/// ```
13/// use orx_parallel::*;
14///
15/// let values: Vec<_> = (10..15)
16/// .into_par()
17/// .use_new(|_| ())
18/// .enumerate()
19/// .map(|_, (i, x)| i + x)
20/// .collect();
21///
22/// assert_eq!(values.len(), 5);
23/// assert!(values.contains(&10));
24/// assert!(values.contains(&18));
25/// ```
26pub trait EnumerateParUse: ParUse {
27 /// Transforms each item into `(index, item)` while keeping worker-local state.
28 ///
29 /// Indices are zero-based and correspond to the iterator order.
30 ///
31 /// # Example
32 ///
33 /// ```
34 /// use orx_parallel::*;
35 ///
36 /// let idx_sum: usize = (1..6)
37 /// .into_par()
38 /// .use_new(|_| ())
39 /// .enumerate()
40 /// .map(|_, (i, _)| i)
41 /// .sum();
42 ///
43 /// assert_eq!(idx_sum, 10);
44 /// ```
45 fn enumerate(
46 self,
47 ) -> impl ParUse<
48 Using = Self::Using,
49 Use = Self::Use,
50 Item = (usize, Self::Item),
51 Input = Enumerate<Self::Input>,
52 >;
53}
54
55impl<P> EnumerateParUse for P
56where
57 P: ParUse,
58 P::Xap: XapUseEnumByInput,
59{
60 fn enumerate(
61 self,
62 ) -> impl ParUse<
63 Using = Self::Using,
64 Use = Self::Use,
65 Item = (usize, Self::Item),
66 Input = Enumerate<Self::Input>,
67 >
68 where
69 Self::Xap: XapUseEnumByInput,
70 {
71 let (u, iter, xap, exe, params) = self.destruct();
72 let iter = iter.enumerate();
73 let xap = xap.enumerate();
74 ParUseIter::new(u, iter, xap, exe, params)
75 }
76}