null_kane/calculation/
add.rs1use 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}