use std::iter::Sum;
pub trait Combiner<R>: Send + Sync {
type Output;
fn combine(&self, iter: impl Iterator<Item=R>) -> Self::Output;
}
#[derive(Default)]
pub struct DefaultCombiner {}
impl<R> Combiner<R> for DefaultCombiner {
type Output = Option<R>;
fn combine(&self, iter: impl Iterator<Item=R>) -> Option<R> {
iter.last()
}
}
#[derive(Default)]
pub struct VecCombiner {}
impl<R> Combiner<R> for VecCombiner {
type Output = Vec<R>;
fn combine(&self, iter: impl Iterator<Item=R>) -> Vec<R> {
iter.collect()
}
}
#[derive(Default)]
pub struct SumCombiner {}
impl<R> Combiner<R> for SumCombiner
where
R: Sum
{
type Output = R;
fn combine(&self, iter: impl Iterator<Item=R>) -> R {
iter.sum()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_combiner_test() {
let combiner = DefaultCombiner::default();
let values1 = vec!(5, 1, 9);
let values2: Vec<i32> = Vec::new();
assert_eq!(combiner.combine(values1.into_iter()), Some(9));
assert_eq!(combiner.combine(values2.into_iter()), None);
}
#[test]
fn vec_combiner_test() {
let combiner = VecCombiner::default();
let values1 = vec!(5, 1, 9);
let values2: Vec<i32> = Vec::new();
assert_eq!(combiner.combine(values1.iter().cloned()), values1);
assert_eq!(combiner.combine(values2.iter().cloned()), values2);
}
#[test]
fn sum_combiner_test() {
let combiner = SumCombiner::default();
let values1 = vec!(5, 1, 9);
let values2: Vec<i32> = Vec::new();
assert_eq!(combiner.combine(values1.iter().cloned()), 15);
assert_eq!(combiner.combine(values2.iter().cloned()), 0);
}
}