ratio_def/
lib.rs

1#[macro_export]
2macro_rules! units {
3    (
4        $(#[$blanket_meta:meta])*
5        $blanket:ident($($super:tt)*);
6        #[$derive:meta] $base:ty:
7        $(
8            $(#[$meta:meta])*
9            $tys:ident;
10        )*
11        $(
12            <$a:path> * <$b:path> = $c:path;
13        )*
14    ) => {
15        $(#[$blanket_meta])*
16        pub trait $blanket : $($super)* {
17            /// Returns the raw value of this struct.
18            fn value(self) -> $base;
19        }
20
21        $(
22            $(#[$meta])*
23            #[$derive]
24            pub struct $tys(pub $base);
25
26            impl From<$base> for $tys {
27                #[inline(always)]
28                fn from(base: $base) -> Self {
29                    Self(base)
30                }
31            }
32
33            impl $tys {
34                /// Returns the raw value of this struct.
35                #[inline(always)]
36                pub fn value(self) -> $base {
37                    self.0
38                }
39            }
40
41            impl $blanket for $tys {
42                #[inline(always)]
43                fn value(self) -> $base {
44                    self.0
45                }
46            }
47
48            impl ::std::ops::Add for $tys {
49                type Output = Self;
50
51                #[inline(always)]
52                fn add(self, other: Self) -> Self {
53                    $tys(self.value() + other.value())
54                }
55            }
56
57            impl ::std::ops::AddAssign for $tys {
58                #[inline(always)]
59                fn add_assign(&mut self, other: Self) {
60                    self.0 += other.value();
61                }
62            }
63
64            impl ::std::ops::Sub for $tys {
65                type Output = Self;
66
67                #[inline(always)]
68                fn sub(self, other: Self) -> Self {
69                    $tys(self.value() - other.value())
70                }
71            }
72
73            impl ::std::ops::SubAssign for $tys {
74                #[inline(always)]
75                fn sub_assign(&mut self, other: Self) {
76                    self.0 -= other.value();
77                }
78            }
79
80            impl ::std::ops::Mul<$base> for $tys {
81                type Output = Self;
82
83                #[inline(always)]
84                fn mul(self, other: $base) -> Self {
85                    Self(self.0 * other)
86                }
87            }
88
89            impl ::std::ops::MulAssign<$base> for $tys {
90                #[inline(always)]
91                fn mul_assign(&mut self, other: $base) {
92                    self.0 *= other;
93                }
94            }
95
96            impl ::std::ops::DivAssign<$base> for $tys {
97                #[inline(always)]
98                fn div_assign(&mut self, other: $base) {
99                    self.0 /= other;
100                }
101            }
102        )*
103
104        $(
105            impl ::std::ops::Mul<$b> for $a {
106                type Output = $c;
107
108                #[inline(always)]
109                fn mul(self, other: $b) -> $c {
110                    $c(self.value() * other.value())
111                }
112            }
113
114            impl ::std::ops::Mul<$a> for $b {
115                type Output = $c;
116
117                #[inline(always)]
118                fn mul(self, other: $a) -> $c {
119                    $c(self.value() * other.value())
120                }
121            }
122
123            impl ::std::ops::Div<$b> for $c {
124                type Output = $a;
125
126                #[inline(always)]
127                fn div(self, other: $b) -> $a {
128                    $a(self.value() / other.value())
129                }
130            }
131
132            impl ::std::ops::Div<$a> for $c {
133                type Output = $b;
134
135                #[inline(always)]
136                fn div(self, other: $a) -> $b {
137                    $b(self.value() / other.value())
138                }
139            }
140        )*
141    };
142}
143
144#[cfg(test)]
145mod tests {
146    units! {
147        Blanket(std::fmt::Debug + Clone + Copy + Default + PartialEq + PartialOrd);
148
149        #[derive(Debug, Clone, Copy, Default, PartialEq, PartialOrd)] f64:
150        Accel; Veloc; Length; Time; Mass; Force; Energy;
151
152        <Accel> * <Time> = Veloc;
153        <Veloc> * <Time> = Length;
154        <Mass> * <Accel> = Force;
155        <Force> * <Length> = Energy;
156    }
157}