1use crate::Currency;
4use std::ops::{Add, Div, Mul, Sub};
5
6impl Add for Currency {
11 type Output = Currency;
12
13 #[inline]
14 fn add(self, rhs: Currency) -> Currency {
15 if self.symbol == rhs.symbol || self.symbol.is_none() {
16 Currency {
17 symbol: rhs.symbol,
18 value: self.value + rhs.value,
19 }
20 } else {
21 panic!(
22 "Cannot add two different types of currency!\n{:?} vs {:?}",
23 self.symbol, rhs.symbol
24 );
25 }
26 }
27}
28
29impl Sub for Currency {
35 type Output = Currency;
36
37 #[inline]
38 fn sub(self, rhs: Currency) -> Currency {
39 if self.symbol == rhs.symbol || self.symbol.is_none() {
40 Currency {
41 symbol: rhs.symbol,
42 value: self.value - rhs.value,
43 }
44 } else {
45 panic!("Cannot subtract two different types of currency!");
46 }
47 }
48}
49
50impl Mul<i64> for Currency {
54 type Output = Currency;
55
56 #[inline]
57 fn mul(self, rhs: i64) -> Currency {
58 Currency {
59 symbol: self.symbol,
60 value: self.value * rhs,
61 }
62 }
63}
64
65impl Mul<Currency> for i64 {
70 type Output = Currency;
71
72 #[inline]
73 fn mul(self, rhs: Currency) -> Currency {
74 Currency {
75 symbol: rhs.symbol,
76 value: rhs.value * self,
77 }
78 }
79}
80
81impl Mul<f64> for Currency {
83 type Output = Currency;
84
85 #[inline]
86 fn mul(self, rhs: f64) -> Currency {
87 Currency {
88 symbol: self.symbol,
89 value: (self.value as f64 * rhs).round() as i64,
90 }
91 }
92}
93
94impl Mul<Currency> for f64 {
95 type Output = Currency;
96
97 #[inline]
98 fn mul(self, rhs: Currency) -> Currency {
99 rhs * self
100 }
101}
102
103impl Div<i64> for Currency {
107 type Output = Currency;
108
109 #[inline]
110 fn div(self, rhs: i64) -> Currency {
111 Currency {
112 symbol: self.symbol,
113 value: self.value / rhs,
114 }
115 }
116}
117
118#[cfg(test)]
119mod test_arithmetic {
120 use crate::Currency;
121
122 fn dollars(value: i64) -> Currency {
123 Currency {
124 symbol: Some('$'),
125 value,
126 }
127 }
128
129 fn bare(value: i64) -> Currency {
130 Currency::from_value(value)
131 }
132
133 #[test]
134 fn sub_same_symbol() {
135 assert_eq!(dollars(100) - dollars(50), dollars(50));
136 }
137
138 #[test]
139 fn add_same_symbol() {
140 assert_eq!(dollars(100) + dollars(50), dollars(150));
141 }
142
143 #[test]
144 fn bare_lhs_adopts_rhs_symbol_on_add() {
145 assert_eq!(bare(100) + dollars(50), dollars(150));
146 }
147
148 #[test]
149 fn bare_lhs_adopts_rhs_symbol_on_sub() {
150 assert_eq!(bare(100) - dollars(50), dollars(50));
151 }
152
153 #[test]
154 #[should_panic]
155 fn symbolled_lhs_plus_bare_rhs_panics() {
156 let _ = dollars(100) + bare(50);
157 }
158
159 #[test]
160 #[should_panic]
161 fn symbolled_lhs_minus_bare_rhs_panics() {
162 let _ = dollars(100) - bare(50);
163 }
164
165 #[test]
166 #[should_panic]
167 fn mixed_symbols_add_panics() {
168 let euro = Currency {
169 symbol: Some('€'),
170 value: 100,
171 };
172 let _ = dollars(100) + euro;
173 }
174
175 #[test]
176 #[should_panic]
177 fn mixed_symbols_sub_panics() {
178 let euro = Currency {
179 symbol: Some('€'),
180 value: 100,
181 };
182 let _ = dollars(100) - euro;
183 }
184}