use crate::{core::Driver, Consumer, Executor, Folder, ParallelIterator}; use super::noop::NoOpReducer; pub struct ForEach { iterator: X, operation: O, } impl ForEach { pub fn new(iterator: X, operation: O) -> Self { Self { iterator, operation, } } } impl<'a, X, O> Driver<'a, ()> for ForEach where X: ParallelIterator<'a>, O: Fn(X::Item) + Clone + Send + 'a, { fn exec_with(self, executor: E) -> E::Result where E: Executor<'a, ()>, { let iterator = self.iterator; let operation = self.operation; let consumer = ForEachConsumer { operation }; iterator.drive(executor, consumer) } } pub struct ForEachConsumer { operation: O, } impl Consumer for ForEachConsumer where O: Fn(I) + Clone + Send, { type Folder = ForEachConsumer; type Reducer = NoOpReducer; type Result = (); fn split_off_left(&self) -> (Self, NoOpReducer) { ( ForEachConsumer { operation: self.operation.clone(), }, NoOpReducer, ) } fn into_folder(self) -> Self { self } } impl Folder for ForEachConsumer where O: Fn(I), { type Result = (); fn consume(self, item: I) -> Self { (self.operation)(item); self } fn consume_iter(self, iter: X) -> Self where X: IntoIterator, { iter.into_iter().for_each(&self.operation); self } fn complete(self) {} } #[cfg(test)] mod tests { use super::*; use crate::*; #[tokio::test] async fn test_for_each() { use ::std::sync::atomic::{AtomicUsize, Ordering}; use ::std::sync::Arc; let i = Arc::new(AtomicUsize::new(0)); let j = Arc::new(AtomicUsize::new(0)); let x = (0..10usize) .into_par_iter() .map_init( move || i.fetch_add(1, Ordering::Relaxed), |init, item| Some((*init, item)), ) .for_each_init( move || j.fetch_add(1, Ordering::Relaxed), |init, item| { println!("{:?} {:?}", init, item); }, ) .exec() .await; dbg!(x); } }