allowance/
unit.rs

1use super::Measure;
2use std::ops::Mul;
3
4#[derive(Debug)]
5pub enum Unit {
6    /// My-meter `μ` the equivalent to `DYN(1)`.
7    MY,
8    /// Millimeter `1 mm = 1000 μ` the equivalent to `DYN(4)`.
9    MM,
10    /// Centimeter `1 cm = 10 mm = 10_000 μ` the equivalent to `DYN(5)`.
11    CM,
12    /// Inch `1 in = 25.4 mm = 25_400 μ`.
13    INCH,
14    /// Foot `1 ft = 12 in = 304.8 mm = 304_800 μ`.
15    FT,
16    /// Yard `1 yd = 3 ft = 914.4 mm = 914_400 μ`.
17    YD,
18    /// Meter `100 cm = 1_000 mm = 1_000_000 μ` the equivalent to `DYN(7)`.
19    METER,
20    /// Kilometer `1 km = 1_000 m` the equivalent to `DYN(10)`.
21    KM,
22    /// Mile `1 mi = 1760 yd = 1609.344 m = 1_609_344_000 μ`.
23    MILE,
24    /// As exponent `10 ^ x`.  
25    DYN(usize),
26}
27
28impl Unit {
29    #[inline]
30    pub fn multiply(&self) -> i64 {
31        use Unit::*;
32        match self {
33            MY => Measure::MY,
34            MM => Measure::MY * 1_000,
35            CM => Measure::MY * 10_000,
36            INCH => Measure::MY * 25_400,
37            FT => Measure::MY * 304_800,
38            YD => Measure::MY * 914_400,
39            METER => Measure::MY * 1_000_000,
40            KM => Measure::MY * 1_000_000_000,
41            MILE => Measure::MY * 1_609_344_000,
42            DYN(p) => (0..*p).fold(1i64, |acc, _| acc * 10),
43        }
44    }
45}
46
47impl PartialEq for Unit {
48    fn eq(&self, other: &Self) -> bool {
49        self.multiply() == other.multiply()
50    }
51}
52
53macro_rules! unit_from_number {
54    ($($typ:ident),+) => {
55        $(
56            impl Mul<$typ> for Unit {
57                type Output = Measure;
58
59                fn mul(self, rhs: $typ) -> Self::Output {
60                    Measure::from(self.multiply() * rhs as i64)
61                }
62            }
63
64             impl Mul<Unit> for $typ {
65                type Output = Measure;
66
67                fn mul(self, rhs: Unit) -> Self::Output {
68                    Measure::from(rhs.multiply() * self as i64)
69                }
70            }
71        )+
72    }
73}
74
75unit_from_number!(i8, i16, i32, i64, u8, u16, u32, u64);
76
77#[cfg(test)]
78mod should {
79    use crate::{Measure, Unit};
80
81    #[test]
82    fn multiply_with_number() {
83        assert_eq!(Measure::from(3.0), 3 * Unit::MM);
84        assert_eq!(Measure::from(55000.0), 55 * Unit::METER);
85    }
86
87    #[test]
88    fn be_equal_dyn() {
89        assert_eq!(Unit::MY.multiply(), Unit::DYN(1).multiply());
90        assert_eq!(Unit::MM.multiply(), Unit::DYN(4).multiply());
91        assert_eq!(Unit::METER, Unit::DYN(7));
92    }
93}