cents.rs

 1use serde::Serialize;
 2
 3/// A number of cents.
 4#[derive(
 5    Debug,
 6    PartialEq,
 7    Eq,
 8    PartialOrd,
 9    Ord,
10    Hash,
11    Clone,
12    Copy,
13    derive_more::Add,
14    derive_more::AddAssign,
15    derive_more::Sub,
16    derive_more::SubAssign,
17    Serialize,
18)]
19pub struct Cents(pub u32);
20
21impl Cents {
22    pub const ZERO: Self = Self(0);
23
24    pub const fn new(cents: u32) -> Self {
25        Self(cents)
26    }
27
28    pub const fn from_dollars(dollars: u32) -> Self {
29        Self(dollars * 100)
30    }
31
32    pub fn saturating_sub(self, other: Cents) -> Self {
33        Self(self.0.saturating_sub(other.0))
34    }
35}
36
37#[cfg(test)]
38mod tests {
39    use pretty_assertions::assert_eq;
40
41    use super::*;
42
43    #[test]
44    fn test_cents_new() {
45        assert_eq!(Cents::new(50), Cents(50));
46    }
47
48    #[test]
49    fn test_cents_from_dollars() {
50        assert_eq!(Cents::from_dollars(1), Cents(100));
51        assert_eq!(Cents::from_dollars(5), Cents(500));
52    }
53
54    #[test]
55    fn test_cents_zero() {
56        assert_eq!(Cents::ZERO, Cents(0));
57    }
58
59    #[test]
60    fn test_cents_add() {
61        assert_eq!(Cents(50) + Cents(30), Cents(80));
62    }
63
64    #[test]
65    fn test_cents_add_assign() {
66        let mut cents = Cents(50);
67        cents += Cents(30);
68        assert_eq!(cents, Cents(80));
69    }
70
71    #[test]
72    fn test_cents_saturating_sub() {
73        assert_eq!(Cents(50).saturating_sub(Cents(30)), Cents(20));
74        assert_eq!(Cents(30).saturating_sub(Cents(50)), Cents(0));
75    }
76
77    #[test]
78    fn test_cents_ordering() {
79        assert!(Cents(50) > Cents(30));
80        assert!(Cents(30) < Cents(50));
81        assert_eq!(Cents(50), Cents(50));
82    }
83}