1use core::ops;
2use std::cmp::{Eq, PartialEq, PartialOrd};
3use serde::{Deserialize, Serialize};
6
7use crate::{Price, Worth};
8
9#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialOrd, PartialEq)]
13pub struct Amount(pub f64);
14
15impl Eq for Amount {}
16
17impl From<(Price, Worth)> for Amount {
18 fn from((p, w): (Price, Worth)) -> Self {
19 Self::from_pw(p, w)
20 }
21}
22
23impl Amount {
24 pub fn from_pw(p: Price, w: Worth) -> Self {
25 Self(w.0 / p.0)
26 }
27}
28
29impl ops::Sub<Amount> for Amount {
30 type Output = Self;
31 fn sub(self, rhs: Amount) -> Self {
32 Self(self.0 - rhs.0)
33 }
34}
35
36impl ops::Add<Amount> for Amount {
37 type Output = Self;
38 fn add(self, rhs: Amount) -> Self {
39 Self(self.0 + rhs.0)
40 }
41}
42
43impl ops::AddAssign<Amount> for Amount {
44 fn add_assign(&mut self, rhs: Amount) {
45 self.0 += rhs.0;
46 }
47}
48
49impl ops::SubAssign<Amount> for Amount {
50 fn sub_assign(&mut self, rhs: Amount) {
51 self.0 -= rhs.0;
52 }
53}
54
55impl ops::Mul<f64> for Amount {
56 type Output = Self;
57 fn mul(self, rhs: f64) -> Self {
58 Self(self.0 * rhs)
59 }
60}
61
62impl ops::Div<f64> for Amount {
63 type Output = Self;
64 fn div(self, rhs: f64) -> Self {
65 Self(self.0 / rhs)
66 }
67}
68
69impl ops::Div<Amount> for f64 {
70 type Output = Amount;
71 fn div(self, rhs: Amount) -> Amount {
72 Amount(self / rhs.0)
73 }
74}
75
76impl ops::Div<Amount> for Amount {
77 type Output = f64;
78 fn div(self, rhs: Amount) -> f64 {
79 self.0 / rhs.0
80 }
81}
82
83#[cfg(test)]
92mod tests {
93 use serde_json::json;
94
95 use super::*;
96
97 #[test]
98 fn test_amount_to_json() {
99 let a = Amount(1.0);
101 let v = json!(a);
102 assert_eq!(v, 1.0);
103 }
104
105 #[test]
106 fn test_json_to_amount() {
107 let a: Amount = serde_json::from_str(r#"1.0"#).unwrap();
108 assert_eq!(a, Amount(1.0));
109 }
110
111 #[test]
112 fn test_f64_div_amount() {
113 let a = Amount(10.);
114 let actual = 1. / a;
115 assert_eq!(Amount(0.1), actual)
116 }
117}