1
use std::{
2
    any::type_name,
3
    fmt::Debug,
4
    marker::PhantomData,
5
    ops::{Div, Mul},
6
};
7

            
8
use num_traits::One;
9

            
10
/// Allows converting between `UnitA` and `UnitB` by multiplying or dividing by
11
/// a scaling ratio.
12
#[derive(PartialEq, Eq, PartialOrd, Ord)]
13
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
14
pub struct Scale<T, UnitA, UnitB> {
15
    ratio: T,
16
    _units: PhantomData<(UnitA, UnitB)>,
17
}
18

            
19
impl<T, UnitA, UnitB> Scale<T, UnitA, UnitB> {
20
    /// Returns a new scale with the given `ratio`.
21
12
    pub const fn new(ratio: T) -> Self {
22
12
        Self {
23
12
            ratio,
24
12
            _units: PhantomData,
25
12
        }
26
12
    }
27
}
28

            
29
impl<T: One + Div<T, Output = T>, UnitA, UnitB> Scale<T, UnitA, UnitB> {
30
    /// Returns the inverse of this scale.
31
    pub fn inverse(self) -> Scale<T, UnitB, UnitA> {
32
        Scale {
33
            ratio: T::one() / self.ratio,
34
            _units: PhantomData,
35
        }
36
    }
37
}
38

            
39
impl<T: Debug, UnitA, UnitB> Debug for Scale<T, UnitA, UnitB> {
40
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41
        f.debug_tuple(&format!(
42
            "Scale<{}, {}, {}>",
43
            type_name::<T>(),
44
            type_name::<UnitA>(),
45
            type_name::<UnitB>(),
46
        ))
47
        .field(&self.ratio)
48
        .finish()
49
    }
50
}
51

            
52
impl<T: Copy, UnitA, UnitB> Copy for Scale<T, UnitA, UnitB> {}
53
impl<T: Clone, UnitA, UnitB> Clone for Scale<T, UnitA, UnitB> {
54
    fn clone(&self) -> Self {
55
        Self::from(self.ratio.clone())
56
    }
57
}
58

            
59
impl<T, UnitA, UnitB> From<T> for Scale<T, UnitA, UnitB> {
60
    fn from(ratio: T) -> Self {
61
        Self {
62
            ratio,
63
            _units: PhantomData::default(),
64
        }
65
    }
66
}
67

            
68
impl<T, UnitA, UnitB> Scale<T, UnitA, UnitB>
69
where
70
    T: Copy,
71
{
72
    /// Returns the scaling ratio.
73
50
    pub fn get(&self) -> T {
74
50
        self.ratio
75
50
    }
76
}
77

            
78
impl<T, UnitA, UnitB> One for Scale<T, UnitA, UnitB>
79
where
80
    T: One,
81
{
82
    fn one() -> Self {
83
        Self::from(T::one())
84
    }
85
}
86

            
87
impl<T, UnitA, UnitB> Mul for Scale<T, UnitA, UnitB>
88
where
89
    T: Mul<T, Output = T>,
90
{
91
    type Output = Self;
92

            
93
    fn mul(self, rhs: Self) -> Self::Output {
94
        Self::from(self.ratio.mul(rhs.ratio))
95
    }
96
}