use crate::{core::Driver, Consumer, Executor, Folder, ParallelIterator, Reducer, WithSetup}; /* Reduce */ pub struct Reduce { iterator: X, identity: S, operation: O, } impl Reduce { pub fn new(iterator: X, identity: S, operation: O) -> Self { Self { iterator, identity, operation, } } } impl<'a, X, S, O> Driver<'a, X::Item> for Reduce where X: ParallelIterator<'a>, S: Fn() -> X::Item + Clone + Send + 'a, O: Fn(X::Item, X::Item) -> X::Item + Clone + Send + 'a, { fn exec_with(self, executor: E) -> E::Result where E: Executor<'a, X::Item>, { let iterator = self.iterator; let identity = self.identity; let operation = self.operation; let consumer = ReduceConsumer { identity, operation, }; iterator.drive(executor, consumer) } } /* ReduceWith */ pub struct ReduceWith { iterator: X, operation: O, } impl ReduceWith { pub fn new(iterator: X, operation: O) -> Self { Self { iterator, operation, } } } impl<'a, X, O, T> Driver<'a, Option> for ReduceWith where X: ParallelIterator<'a, Item = T>, O: Fn(T, T) -> T + Clone + Send + 'a, T: Send + 'a, { fn exec_with(self, executor: E) -> E::Result where E: Executor<'a, Option>, { let fold_op = self.operation.clone(); let reduce_op = self.operation; self.iterator .fold(<_>::default, move |a, b| match a { Some(a) => Some(fold_op(a, b)), None => Some(b), }) .reduce(<_>::default, move |a, b| match (a, b) { (Some(a), Some(b)) => Some(reduce_op(a, b)), (Some(v), None) | (None, Some(v)) => Some(v), (None, None) => None, }) .exec_with(executor) } } /* ReduceConsumer */ struct ReduceConsumer { identity: S, operation: O, } impl WithSetup for ReduceConsumer {} impl Clone for ReduceConsumer where S: Clone, O: Clone, { fn clone(&self) -> Self { Self { identity: self.identity.clone(), operation: self.operation.clone(), } } } impl Consumer for ReduceConsumer where S: Fn() -> T + Clone + Send, O: Fn(T, T) -> T + Clone + Send, T: Send, { type Folder = ReduceFolder; type Reducer = Self; type Result = T; fn split(self) -> (Self, Self, Self::Reducer) { (self.clone(), self.clone(), self) } fn split_at(self, _index: usize) -> (Self, Self, Self::Reducer) { (self.clone(), self.clone(), self) } fn into_folder(self) -> Self::Folder { ReduceFolder { operation: self.operation, item: (self.identity)(), } } } impl Reducer for ReduceConsumer where O: Fn(T, T) -> T, S: Fn() -> T, T: Send, { fn reduce(self, left: T, right: T) -> T { (self.operation)(left, right) } } /* ReduceFolder */ struct ReduceFolder { operation: O, item: T, } impl Folder for ReduceFolder where O: Fn(T, T) -> T + Clone, { type Result = T; fn consume(mut self, item: T) -> Self { self.item = (self.operation)(self.item, item); self } fn consume_iter(mut self, iter: X) -> Self where X: IntoIterator, { self.item = iter.into_iter().fold(self.item, self.operation.clone()); self } fn complete(self) -> Self::Result { self.item } }