composable_indexes/aggregation/
sum.rs

1use num_traits::Num;
2
3use crate::{
4    Index, ShallowClone,
5    core::{Insert, Remove, Seal, Update},
6};
7
8/// An index that provides the sum of indexed values.
9#[derive(Clone)]
10pub struct Sum<T> {
11    sum: T,
12}
13
14impl<T: Num + Copy> Default for Sum<T> {
15    fn default() -> Self {
16        Self::new()
17    }
18}
19
20impl<T: Num + Copy> Sum<T> {
21    pub fn new() -> Self {
22        Sum { sum: T::zero() }
23    }
24}
25
26impl<T> Index<T> for Sum<T>
27where
28    T: Num + Copy + 'static,
29{
30    #[inline]
31    fn insert(&mut self, _seal: Seal, op: &Insert<T>) {
32        self.sum = self.sum + *op.new;
33    }
34
35    #[inline]
36    fn remove(&mut self, _seal: Seal, op: &Remove<T>) {
37        self.sum = self.sum - *op.existing;
38    }
39
40    #[inline]
41    fn update(&mut self, _seal: Seal, op: &Update<T>) {
42        self.sum = self.sum - *op.existing + *op.new;
43    }
44}
45
46impl<T: Copy> Sum<T> {
47    #[inline]
48    pub fn get(&self) -> T {
49        self.sum
50    }
51}
52
53impl<T: Clone> ShallowClone for Sum<T> {}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58    use crate::testutils::prop_assert_reference;
59    use core::num::Wrapping;
60
61    #[test]
62    fn test_sum() {
63        prop_assert_reference(
64            Sum::<Wrapping<i16>>::new,
65            |db| db.query(|ix| ix.get().0),
66            |xs| xs.iter().map(|x| Wrapping(x.0)).sum::<Wrapping<i16>>().0,
67            None,
68        );
69    }
70}