moirai_iter/facade/
mod.rs1use crate::async_iter::{AsyncIterator, AsyncRangeIter};
4use crate::execution::{AsyncContext, ExecutionContext, HybridContext, ParallelContext};
5use crate::parallel::{ParallelIterator, RangeParIter};
6
7pub struct MoiraiIterator<T> {
9 data: Vec<T>,
10 context: ExecutionContext,
11}
12
13impl<T: Send + 'static> MoiraiIterator<T> {
14 pub fn new(data: Vec<T>, context: ExecutionContext) -> Self {
16 Self { data, context }
17 }
18
19 pub fn parallel(data: Vec<T>) -> Self {
21 Self::new(data, ExecutionContext::Parallel(ParallelContext::new()))
22 }
23
24 pub fn async_iter(data: Vec<T>) -> Self {
26 Self::new(data, ExecutionContext::Async(AsyncContext::new()))
27 }
28
29 pub fn hybrid(data: Vec<T>) -> Self {
31 Self::new(data, ExecutionContext::Hybrid(HybridContext::new()))
32 }
33
34 pub fn map<F, R>(self, func: F) -> MoiraiIterator<R>
36 where
37 F: Fn(T) -> R + Send + Sync + 'static,
38 R: Send + 'static,
39 {
40 let Self { data, context } = self;
41 let results = context
42 .execute_iter(data, func)
43 .expect("iterator map execution must not fail");
44
45 MoiraiIterator::new(results, context)
46 }
47
48 pub async fn map_async<F, Fut, R>(self, func: F) -> MoiraiIterator<R>
50 where
51 F: Fn(T) -> Fut + Send + Sync + 'static,
52 Fut: std::future::Future<Output = R> + Send + 'static,
53 R: Send + 'static,
54 {
55 let Self { data, context } = self;
56 let results = context
57 .execute_async_iter(data, func)
58 .await
59 .expect("async iterator map execution must not fail");
60
61 MoiraiIterator::new(results, context)
62 }
63
64 pub fn filter<F>(self, predicate: F) -> MoiraiIterator<T>
66 where
67 F: Fn(&T) -> bool + Send + Sync + 'static,
68 {
69 let Self { data, context } = self;
70 let filtered = data.into_iter().filter(|item| predicate(item)).collect();
71
72 MoiraiIterator::new(filtered, context)
73 }
74
75 pub async fn filter_async<F, Fut>(self, predicate: F) -> MoiraiIterator<T>
77 where
78 F: Fn(&T) -> Fut + Send + Sync + 'static,
79 Fut: std::future::Future<Output = bool> + Send + 'static,
80 {
81 let Self { data, context } = self;
82 let results = context
83 .execute_async_filter(data, predicate)
84 .await
85 .expect("async iterator filter execution must not fail");
86
87 MoiraiIterator::new(results, context)
88 }
89
90 pub async fn collect(self) -> Vec<T> {
92 self.data
93 }
94
95 pub async fn collect_async(self) -> Vec<T> {
97 self.collect().await
98 }
99
100 pub async fn reduce<F>(self, func: F) -> Option<T>
102 where
103 F: Fn(T, T) -> T + Send + Sync + 'static,
104 {
105 self.data.into_iter().reduce(func)
106 }
107
108 pub async fn reduce_parallel<F>(self, func: F) -> Option<T>
110 where
111 F: Fn(T, T) -> T + Send + Sync + 'static,
112 {
113 self.context
114 .execute_reduce(self.data, func)
115 .await
116 .expect("iterator reduce execution must not fail")
117 }
118
119 pub async fn for_each<F>(self, func: F)
121 where
122 F: Fn(T) + Send + Sync + 'static,
123 {
124 self.context
125 .execute_iter(self.data, func)
126 .expect("iterator for_each execution must not fail");
127 }
128
129 pub async fn for_each_async<F, Fut>(self, func: F)
131 where
132 F: Fn(T) -> Fut + Send + Sync + 'static,
133 Fut: std::future::Future<Output = ()> + Send + 'static,
134 {
135 self.context
136 .execute_async_for_each(self.data, func)
137 .await
138 .expect("async iterator for_each execution must not fail");
139 }
140
141 pub fn into_async_stream(self) -> impl futures::Stream<Item = T> + Send + 'static
143 where
144 T: 'static,
145 {
146 futures::stream::iter(self.data)
147 }
148}
149
150pub fn moirai_iter<T: Send + 'static>(data: Vec<T>) -> MoiraiIterator<T> {
152 MoiraiIterator::hybrid(data)
153}
154
155pub fn moirai_iter_parallel<T: Send + 'static>(data: Vec<T>) -> MoiraiIterator<T> {
157 MoiraiIterator::parallel(data)
158}
159
160pub fn moirai_iter_async<T: Send + 'static>(data: Vec<T>) -> MoiraiIterator<T> {
162 MoiraiIterator::async_iter(data)
163}
164
165pub fn moirai_iter_hybrid<T: Send + 'static>(data: Vec<T>) -> MoiraiIterator<T> {
167 MoiraiIterator::hybrid(data)
168}
169
170pub fn par_range(start: usize, end: usize) -> impl ParallelIterator<Item = usize> {
172 RangeParIter::new(start, end)
173}
174
175pub fn async_range(start: usize, end: usize) -> impl AsyncIterator<Item = usize> {
177 AsyncRangeIter::new(start, end)
178}
179
180#[cfg(test)]
181mod tests {
182 use super::*;
183
184 #[test]
185 fn map_preserves_context_without_string_dispatch() {
186 let values = MoiraiIterator::parallel(vec![1_u64, 2, 3])
187 .map(|value| value * 2)
188 .context
189 .context_type();
190
191 assert_eq!(values, "Parallel");
192 }
193
194 #[tokio::test]
195 async fn facade_map_filter_reduce_preserve_value_semantics() {
196 let values = moirai_iter_hybrid(vec![1_u64, 2, 3, 4, 5])
197 .map(|value| value * 3)
198 .filter(|value| value % 2 == 1)
199 .collect()
200 .await;
201 assert_eq!(values, vec![3, 9, 15]);
202
203 let reduced = moirai_iter_parallel(vec![1_u64, 2, 3, 4])
204 .reduce_parallel(|left, right| left + right)
205 .await;
206 assert_eq!(reduced, Some(10));
207 }
208}