Skip to main content

v_utils/trades/
usd.rs

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)]
30/// A struct representing USD (in future, inflation-adjusted) value. That's it. Just a newtype. But extremely powerful.
31pub 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}