1use core::fmt;
17
18pub type ValueType = u32;
19pub type LargeValueType = u64;
20
21pub trait Quantity: Sized {}
22pub trait Time: Quantity + Into<NanoSeconds> {}
23pub trait Frequency: Quantity + Into<Hertz> {}
24pub trait Count: Quantity + Into<Ticks> {}
25
26pub trait TimeU64: Quantity + Into<NanoSecondsU64> {}
27pub trait FrequencyU64: Quantity + Into<HertzU64> {}
28pub trait CountU64: Quantity + Into<TicksU64> {}
29
30macro_rules! define {
32 ($primitive:ident, $trait:ident, $( ($type: ident, $quantity: ident, $unit: ident,
33 $print_unit: literal), )+) => {
34 $(
35 #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Default)]
36 pub struct $quantity(pub $primitive);
37
38 impl Quantity for $quantity {}
39 impl $type for $quantity {}
40 )*
41
42 pub trait $trait {
43 $(
44 #[allow(non_snake_case)]
45 fn $unit(self) -> $quantity;
46 )*
47 }
48
49 impl $trait for $primitive {
50 $(
51 fn $unit(self) -> $quantity {
52 $quantity(self)
53 }
54 )*
55 }
56
57 $(
58 impl From<$quantity> for $primitive {
59 fn from(x: $quantity) -> Self {
60 x.0
61 }
62 }
63
64 impl From<$primitive> for $quantity {
65 fn from(x: $primitive) -> $quantity {
66 $quantity(x)
67 }
68 }
69
70 impl fmt::Debug for $quantity {
71 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72 write!(f, "{}{}", self.0, $print_unit)
73 }
74 }
75
76 impl fmt::Display for $quantity {
77 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
78 write!(f, "{}{}", self.0, $print_unit)
79 }
80 }
81
82 impl core::ops::Div<$primitive> for $quantity {
83 type Output = Self;
84 fn div(self, rhs: $primitive) -> Self::Output {
85 $quantity(self.0/rhs)
86 }
87 }
88
89 impl core::ops::Mul<$primitive> for $quantity {
90 type Output = Self;
91 fn mul(self, rhs: $primitive) -> Self::Output {
92 $quantity(self.0*rhs)
93 }
94 }
95
96 impl core::ops::Mul<$quantity> for $primitive {
97 type Output = $quantity;
98 fn mul(self, rhs: $quantity) -> Self::Output {
99 $quantity(self*rhs.0)
100 }
101 }
102
103 impl core::ops::Div<$quantity> for $quantity {
104 type Output = $primitive;
105 fn div(self, rhs: Self) -> Self::Output {
106 self.0/rhs.0
107 }
108 }
109
110 impl core::ops::Add<$quantity> for $quantity {
111 type Output = Self;
112 fn add(self, rhs: Self) -> Self::Output {
113 Self(self.0+rhs.0)
114 }
115 }
116
117 impl core::ops::Sub<$quantity> for $quantity {
118 type Output = Self;
119 fn sub(self, rhs: Self) -> Self::Output {
120 Self(self.0-rhs.0)
121 }
122 }
123 )*
124 };
125}
126
127macro_rules! define_large {
129 ($( ($type: ident, $quantity: ident, $unit:ident, $type_large: ident,
130 $quantity_large: ident, $unit_large:ident, $print_unit: literal) ),+) => {
131
132 define!(
133 ValueType,
134 FromValueType,
135 $(($type, $quantity, $unit, $print_unit),)*
136 );
137
138 define!(
139 LargeValueType,
140 FromLargeValueType,
141 $(($type_large, $quantity_large, $unit_large, $print_unit),)*
142 );
143
144 $(
145 impl From<$quantity> for $quantity_large {
146 fn from(x: $quantity) -> Self {
147 Self(LargeValueType::from(x.0))
148 }
149 }
150 impl TryFrom<$quantity_large> for $quantity {
151 type Error=core::num::TryFromIntError;
152 fn try_from(x: $quantity_large) -> Result<$quantity, Self::Error> {
153 Ok(Self(ValueType::try_from(x.0)?))
154 }
155 }
156 )*
157
158 };
159}
160
161macro_rules! convert {
163 ($( ($from: ty, $from_large: ty, $into: ty, $into_large: ty, $factor: expr) ),+) => {
164 $(
165 impl From<$from> for $into {
166 fn from(x: $from) -> Self {
167 Self(x.0 * $factor)
168 }
169 }
170 impl From<$from> for $into_large {
171 fn from(x: $from) -> Self {
172 Self(LargeValueType::from(x.0) * $factor)
173 }
174 }
175 impl From<$from_large> for $into_large {
176 fn from(x: $from_large) -> Self {
177 Self(x.0 * $factor)
178 }
179 }
180 )*
181 };
182}
183
184macro_rules! multiply {
186 ($( ($time: ty, $time_large: ty, $freq: ty, $freq_large: ty,
187 $factor: expr, $divider: expr) ),+) => {
188 $(
189 impl core::ops::Mul<$freq> for $time {
190 type Output = Ticks;
191 fn mul(self, rhs: $freq) -> Self::Output {
192 TicksU64::from(LargeValueType::from(self.0) * LargeValueType::from(rhs.0)
193 * $factor / $divider).try_into().unwrap()
194 }
195 }
196
197 impl core::ops::Mul<$time> for $freq {
198 type Output = Ticks;
199 fn mul(self, rhs: $time) -> Self::Output {
200 TicksU64::from(LargeValueType::from(self.0) * LargeValueType::from(rhs.0)
201 * $factor / $divider).try_into().unwrap()
202 }
203 }
204
205 impl core::ops::Mul<$freq_large> for $time_large {
206 type Output = TicksU64;
207 fn mul(self, rhs: $freq_large) -> Self::Output {
208 (self.0 * rhs.0 * $factor / $divider).into()
209 }
210 }
211
212 impl core::ops::Mul<$time_large> for $freq_large {
213 type Output = TicksU64;
214 fn mul(self, rhs: $time_large) -> Self::Output {
215 (self.0 * rhs.0 * $factor / $divider).into()
216 }
217 }
218
219 impl core::ops::Mul<$freq> for $time_large {
220 type Output = TicksU64;
221 fn mul(self, rhs: $freq) -> Self::Output {
222 (self.0 * LargeValueType::from(rhs.0) * $factor / $divider).into()
223 }
224 }
225
226 impl core::ops::Mul<$time> for $freq_large {
227 type Output = TicksU64;
228 fn mul(self, rhs: $time) -> Self::Output {
229 (self.0 * LargeValueType::from(rhs.0) * $factor / $divider).into()
230 }
231 }
232
233 impl core::ops::Mul<$freq_large> for $time {
234 type Output = TicksU64;
235 fn mul(self, rhs: $freq_large) -> Self::Output {
236 (LargeValueType::from(self.0) * rhs.0 * $factor / $divider).into()
237 }
238 }
239
240 impl core::ops::Mul<$time_large> for $freq {
241 type Output = TicksU64;
242 fn mul(self, rhs: $time_large) -> Self::Output {
243 (LargeValueType::from(self.0) * rhs.0 * $factor / $divider).into()
244 }
245 }
246 )*
247 };
248}
249
250macro_rules! divide {
251 ($( ($freq: ty, $freq_large: ty, $time: ty, $time_large: ty, $factor: expr) ),+) => {
252 $(
253 impl core::ops::Div<$freq> for Ticks {
254 type Output = $time;
255 fn div(self, rhs: $freq) -> Self::Output {
256 ValueType::try_from(
257 LargeValueType::from(self.0) * $factor / LargeValueType::from(rhs.0)
258 ).unwrap().into()
259 }
260 }
261
262 impl core::ops::Div<$freq> for TicksU64 {
263 type Output = $time_large;
264 fn div(self, rhs: $freq) -> Self::Output {
265 (self.0 * $factor / LargeValueType::from(rhs.0)).into()
266 }
267 }
268
269 impl core::ops::Div<$freq_large> for TicksU64 {
270 type Output = $time_large;
271 fn div(self, rhs: $freq_large) -> Self::Output {
272 (self.0 * $factor / rhs.0).into()
273 }
274 }
275
276 impl core::ops::Div<$freq_large> for Ticks {
277 type Output = $time_large;
278 fn div(self, rhs: $freq_large) -> Self::Output {
279 (LargeValueType::from(self.0) * $factor / rhs.0).into()
280 }
281 }
282 )*
283 };
284}
285
286#[rustfmt::skip::macros(define_large)]
287define_large!(
288 (Frequency, Hertz, Hz, FrequencyU64, HertzU64, Hz_large, "Hz" ),
289 (Frequency, KiloHertz, kHz, FrequencyU64, KiloHertzU64, kHz_large, "kHz" ),
290 (Frequency, MegaHertz, MHz, FrequencyU64, MegaHertzU64, MHz_large, "MHz" ),
291 (Time, NanoSeconds, ns, TimeU64, NanoSecondsU64, ns_large, "ns" ),
292 (Time, MicroSeconds, us, TimeU64, MicroSecondsU64, us_large, "us" ),
293 (Time, MilliSeconds, ms, TimeU64, MilliSecondsU64, ms_large, "ms" ),
294 (Time, Seconds, s, TimeU64, SecondsU64, s_large, "s" ),
295 (Count, Ticks, ticks, CountU64, TicksU64, ticks_large, "" )
296);
297
298#[rustfmt::skip::macros(convert)]
299convert!(
300 (KiloHertz, KiloHertzU64, Hertz, HertzU64, 1_000 ),
301 (MegaHertz, MegaHertzU64, Hertz, HertzU64, 1_000_000 ),
302 (MegaHertz, MegaHertzU64, KiloHertz, KiloHertzU64, 1_000 ),
303 (Seconds, SecondsU64, MilliSeconds, MilliSecondsU64, 1_000 ),
304 (Seconds, SecondsU64, MicroSeconds, MicroSecondsU64, 1_000_000 ),
305 (Seconds, SecondsU64, NanoSeconds, NanoSecondsU64, 1_000_000_000 ),
306 (MilliSeconds, MilliSecondsU64, MicroSeconds, MicroSecondsU64, 1_000 ),
307 (MilliSeconds, MilliSecondsU64, NanoSeconds, NanoSecondsU64, 1_000_000 ),
308 (MicroSeconds, MicroSecondsU64, NanoSeconds, NanoSecondsU64, 1_000 )
309);
310
311#[rustfmt::skip::macros(multiply)]
312multiply!(
313 (Seconds, SecondsU64, Hertz, HertzU64, 1, 1 ),
314 (Seconds, SecondsU64, KiloHertz, KiloHertzU64, 1_000, 1 ),
315 (Seconds, SecondsU64, MegaHertz, MegaHertzU64, 1_000_000, 1 ),
316 (MilliSeconds, MilliSecondsU64, Hertz, HertzU64, 1, 1_000 ),
317 (MilliSeconds, MilliSecondsU64, KiloHertz, KiloHertzU64, 1, 1 ),
318 (MilliSeconds, MilliSecondsU64, MegaHertz, MegaHertzU64, 1_000, 1 ),
319 (MicroSeconds, MicroSecondsU64, Hertz, HertzU64, 1, 1_000_000 ),
320 (MicroSeconds, MicroSecondsU64, KiloHertz, KiloHertzU64, 1, 1_000 ),
321 (MicroSeconds, MicroSecondsU64, MegaHertz, MegaHertzU64, 1, 1 ),
322 (NanoSeconds, NanoSecondsU64, Hertz, HertzU64, 1, 1_000_000_000 ),
323 (NanoSeconds, NanoSecondsU64, KiloHertz, KiloHertzU64, 1, 1_000_000 ),
324 (NanoSeconds, NanoSecondsU64, MegaHertz, MegaHertzU64, 1, 1_000 )
325);
326
327#[rustfmt::skip::macros(divide)]
328divide!(
329 (Hertz, HertzU64, NanoSeconds, NanoSecondsU64, 1_000_000_000 ),
330 (KiloHertz, KiloHertzU64, NanoSeconds, NanoSecondsU64, 1_000_000 ),
331 (MegaHertz, MegaHertzU64, NanoSeconds, NanoSecondsU64, 1_000 )
332);