sumcol/
lib.rs

1use std::fmt;
2use std::ops::{Add, AddAssign};
3
4/// This enum represents the sum of a sequence of numbers that may be integers or floating point.
5/// Integer is the default. When a floating point number is added to the sum, the type is converted
6/// to Float.
7#[derive(Debug, PartialEq, Clone, Copy)]
8pub enum Sum {
9    Integer(i128),
10    Float(f64),
11}
12
13impl Add for Sum {
14    type Output = Self;
15
16    /// Adds two Sums. If either is a Float, the result will be a Float.
17    fn add(self, other: Self) -> Self {
18        match (self, other) {
19            (Sum::Integer(a), Sum::Integer(b)) => Sum::Integer(a + b),
20            (Sum::Float(a), Sum::Float(b)) => Sum::Float(a + b),
21            (Sum::Integer(a), Sum::Float(b)) => Sum::Float(a as f64 + b),
22            (Sum::Float(a), Sum::Integer(b)) => Sum::Float(a + b as f64),
23        }
24    }
25}
26
27impl AddAssign for Sum {
28    /// Adds two Sums. If either is a Float, the result will be a Float.
29    fn add_assign(&mut self, other: Self) {
30        *self = *self + other;
31    }
32}
33
34impl fmt::Display for Sum {
35    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36        match self {
37            Sum::Integer(n) => write!(f, "{n}"),
38            Sum::Float(n) => write!(f, "{n}"),
39        }
40    }
41}
42
43impl fmt::UpperHex for Sum {
44    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45        match self {
46            Sum::Integer(n) => fmt::UpperHex::fmt(n, f),
47            Sum::Float(n) => fmt::Display::fmt(n, f),
48        }
49    }
50}
51
52#[cfg(test)]
53mod tests {
54    use super::*;
55
56    #[test]
57    fn sum_integer_works() {
58        let a = Sum::Integer(1);
59        let b = Sum::Integer(2);
60        assert_eq!(a + b, Sum::Integer(3));
61
62        let mut c = a;
63        c += b;
64        assert_eq!(c, Sum::Integer(3));
65    }
66
67    #[test]
68    fn sum_float_works() {
69        let a = Sum::Float(0.2);
70        let b = Sum::Float(0.8);
71        assert_eq!(a + b, Sum::Float(1.0));
72    }
73
74    #[test]
75    fn sum_mixed_works() {
76        let a = Sum::Integer(1);
77        let b = Sum::Float(0.2);
78        assert_eq!(a + b, Sum::Float(1.2));
79        assert_eq!(b + a, Sum::Float(1.2));
80    }
81}