1use serde::{Deserialize, Serialize};
2
3#[derive(
4 Clone,
5 Debug,
6 Default,
7 derive_new::new,
8 Copy,
9 PartialEq,
10 PartialOrd,
11 derive_more::Deref,
12 derive_more::DerefMut,
13 derive_more::Add,
14 derive_more::AddAssign,
15 derive_more::Sub,
16 derive_more::SubAssign,
17 derive_more::Mul,
18 derive_more::MulAssign,
19 derive_more::Div,
20 derive_more::DivAssign,
21 derive_more::Neg,
22 derive_more::From,
23 derive_more::Into,
24 derive_more::FromStr,
25 Serialize,
26 Deserialize,
27)]
28#[mul(forward)]
29#[div(forward)]
30pub struct Usd(pub f64);
32
33impl std::ops::Mul<f64> for Usd {
34 type Output = Self;
35
36 fn mul(self, rhs: f64) -> Self::Output {
37 Self(self.0 * rhs)
38 }
39}
40
41impl std::fmt::Display for Usd {
42 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
43 let s = match f.precision() {
44 Some(p) => format!("{:.*}", p, self.0),
45 None =>
46 if self.0.fract() != 0. {
47 format!("{:.2}", self.0)
48 } else {
49 format!("{}", self.0)
50 },
51 };
52
53 crate::fmt_with_width!(f, s)
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 #[test]
60 fn operators() {
61 use super::Usd;
62 let usd = Usd(1.0);
63 assert_eq!(usd, Usd(1.0));
64 assert_eq!(usd + Usd(1.0), Usd(2.0));
65 assert_eq!(usd - Usd(1.0), Usd(0.0));
66 assert_eq!(usd * Usd(2.0), Usd(2.0));
67 assert_eq!(usd / Usd(2.0), Usd(0.5));
68 assert_eq!(-usd, Usd(-1.0));
69 }
70
71 #[test]
72 fn precision_and_alignment() {
73 use super::Usd;
74 let usd = Usd(1.0);
75 assert_eq!(format!("{}", usd), "1");
76 assert_eq!(format!("{:.2}", usd), "1.00");
77 assert_eq!(format!("|{:10}|", usd), "|1 |");
78 assert_eq!(format!("|{:^10.2}|", usd), "| 1.00 |");
79 }
80}