downsample/
aggregatable.rs

1use core::marker::ConstParamTy;
2
3#[derive(PartialEq, Eq, Debug, Clone, ConstParamTy)]
4pub enum Algorithm {
5    Average,
6    Min,
7    Max,
8}
9
10pub trait Aggregatable<const M: Algorithm> {
11    fn aggregate<I: Iterator<Item = Self>>(list: I) -> Self;
12}
13
14#[cfg(feature = "derive_aggregatable")]
15mod int {
16    use super::*;
17
18    macro_rules! impl_by_into {
19        ( $t:ty ) => {
20            impl Aggregatable<{ Algorithm::Average }> for $t {
21                fn aggregate<I: Iterator<Item = Self>>(list: I) -> Self {
22                    let mut total = <$t>::default();
23                    let mut count = 0;
24                    for e in list {
25                        total += e;
26                        count += 1;
27                    }
28                    total / count as $t
29                }
30            }
31
32            impl Aggregatable<{ Algorithm::Min }> for $t {
33                fn aggregate<I: Iterator<Item = Self>>(list: I) -> Self {
34                    let mut min = None;
35                    for e in list {
36                        if min.map(|m| e < m).unwrap_or(true) {
37                            min = Some(e);
38                        }
39                    }
40                    min.unwrap_or_default()
41                }
42            }
43
44            impl Aggregatable<{ Algorithm::Max }> for $t {
45                fn aggregate<I: Iterator<Item = Self>>(list: I) -> Self {
46                    let mut max = None;
47                    for e in list {
48                        if max.map(|m| e > m).unwrap_or(true) {
49                            max = Some(e);
50                        }
51                    }
52                    max.unwrap_or_default()
53                }
54            }
55        };
56    }
57
58    impl_by_into!(f32);
59    impl_by_into!(f64);
60    impl_by_into!(u8);
61    impl_by_into!(u16);
62    impl_by_into!(u32);
63    impl_by_into!(u64);
64    impl_by_into!(u128);
65    impl_by_into!(i8);
66    impl_by_into!(i16);
67    impl_by_into!(i32);
68    impl_by_into!(i64);
69    impl_by_into!(i128);
70    impl_by_into!(usize);
71    impl_by_into!(isize);
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77    use crate::Algorithm;
78
79    #[test]
80    fn average_f32() {
81        assert_eq!(
82            Aggregatable::<{ Algorithm::Average }>::aggregate((0..10).map(|x| x as f32)),
83            4.5
84        )
85    }
86
87    #[test]
88    fn min_f32() {
89        assert_eq!(
90            Aggregatable::<{ Algorithm::Min }>::aggregate((-10..10).map(|x| x as f32)),
91            -10.0
92        )
93    }
94
95    #[test]
96    fn max_f32() {
97        assert_eq!(
98            Aggregatable::<{ Algorithm::Max }>::aggregate((-10..10).map(|x| x as f32)),
99            9.0
100        )
101    }
102}