null_kane/calculation/
add.rs

1use crate::{Currency, CurrencyLocale};
2use std::ops::{Add, AddAssign};
3
4impl<L, T> Add<T> for Currency<L>
5where
6    T: Into<Currency<L>>,
7    L: CurrencyLocale,
8{
9    type Output = Self;
10
11    fn add(self, rhs: T) -> Self::Output {
12        let rhs = rhs.into();
13        match (self.negative, rhs.negative) {
14            (true, true) | (false, false) => {
15                Self::new(self.negative, self.amount + rhs.amount, self.locale)
16            }
17            (true, false) | (false, true) => {
18                let negative = self.amount.checked_sub(rhs.amount).is_none();
19                let amount = if negative {
20                    rhs.amount - self.amount
21                } else {
22                    self.amount - rhs.amount
23                };
24                Self::new(self.negative ^ negative, amount, self.locale)
25            }
26        }
27    }
28}
29
30impl<L, T> AddAssign<T> for Currency<L>
31where
32    T: Into<Currency<L>>,
33    L: CurrencyLocale,
34{
35    fn add_assign(&mut self, rhs: T) {
36        let rhs = rhs.into();
37        match (self.negative, rhs.negative) {
38            (false, false) | (true, true) => self.amount += rhs.amount,
39            (false, true) | (true, false) => {
40                self.negative ^= self.amount.checked_sub(rhs.amount).is_none();
41                if self.negative {
42                    self.amount = rhs.amount - self.amount
43                } else {
44                    self.amount -= rhs.amount
45                };
46            }
47        }
48    }
49}
50
51#[cfg(test)]
52mod test {
53    use super::*;
54
55    #[derive(Clone, Copy, Default, Debug, PartialEq)]
56    enum CurrencyL {
57        #[default]
58        De,
59    }
60
61    impl CurrencyLocale for CurrencyL {
62        fn separator(&self) -> char {
63            ','
64        }
65
66        fn thousand_separator(&self) -> char {
67            '.'
68        }
69
70        fn currency_symbol(&self) -> &'static str {
71            "€"
72        }
73    }
74
75    #[test]
76    fn add_currencies() {
77        let curr1 = Currency::new(false, 24_000_22, CurrencyL::De);
78        let curr2 = Currency::new(false, 24_000_99, CurrencyL::De);
79
80        let expected = curr1 + curr2;
81        assert_eq!(expected, Currency::new(false, 48_001_21, CurrencyL::De));
82    }
83
84    #[test]
85    fn add_f32_to_currency() {
86        let curr1 = Currency::new(false, 24_000_22, CurrencyL::De);
87
88        let expected = curr1 + 24_000.99_f32;
89        assert_eq!(expected, Currency::new(false, 48_001_21, CurrencyL::De));
90    }
91
92    #[test]
93    fn add_assign_usize() {
94        let mut curr1 = Currency::new(false, 24_000_22, CurrencyL::De);
95        curr1 += 1usize;
96
97        assert_eq!(curr1, Currency::new(false, 24_000_23, CurrencyL::De));
98    }
99
100    #[test]
101    fn add_assign_f32() {
102        let mut curr1 = Currency::new(false, 24_000_22, CurrencyL::De);
103        curr1 += 1.12f32;
104
105        assert_eq!(curr1, Currency::new(false, 24_001_34, CurrencyL::De));
106    }
107
108    #[test]
109    fn add_assign_negative_f32() {
110        let mut curr1 = Currency::new(false, 24_000_22, CurrencyL::De);
111        curr1 += -1.12f32;
112
113        assert_eq!(curr1, Currency::new(false, 23_999_10, CurrencyL::De));
114    }
115
116    #[test]
117    fn add_assign_f64() {
118        let mut curr1 = Currency::new(false, 24_000_22, CurrencyL::De);
119        curr1 += 1.12f64;
120
121        assert_eq!(curr1, Currency::new(false, 24_001_34, CurrencyL::De));
122    }
123
124    #[test]
125    fn add_assign_negative_f64() {
126        let mut curr1 = Currency::new(false, 24_000_22, CurrencyL::De);
127        curr1 += -1.12f64;
128
129        assert_eq!(curr1, Currency::new(false, 23_999_10, CurrencyL::De));
130    }
131
132    #[test]
133    fn add_assign_currency() {
134        let mut curr1 = Currency::new(false, 24_000_22, CurrencyL::De);
135        let curr2 = Currency::new(false, 24_000_99, CurrencyL::De);
136
137        curr1 += curr2;
138        assert_eq!(curr1, Currency::new(false, 48_001_21, CurrencyL::De));
139    }
140
141    #[test]
142    fn add_assign_negative_currency() {
143        let mut curr1 = Currency::new(false, 24_000_22, CurrencyL::De);
144        let curr2 = Currency::new(true, 1_22, CurrencyL::De);
145
146        curr1 += curr2;
147        assert_eq!(curr1, Currency::new(false, 23_999_00, CurrencyL::De));
148    }
149}