fugit/
lib.rs

1//! `fugit` provides a comprehensive library of [`Duration`] and [`Instant`] for the handling of
2//! time in embedded systems. The library is specifically designed to maximize const-ification
3//! which allows for most comparisons and changes of time-base to be made at compile time, rather
4//! than run time.
5//!
6//! The library is aimed at ease-of-use and performance first.
7//!
8//! ```
9//! use fugit::{Duration, ExtU32};
10//!
11//! // Efficient short-hands (`.millis()`, ...)
12//! let d = Duration::<u32, 1, 1_000>::from_ticks(111);
13//!
14//! let sum1 = d + 300.millis();
15//! //             ^^^ Compile time move of base, only a sum is needed and no change of base
16//!
17//!
18//! // -----------------------
19//!
20//! // Best effort for fixed types
21//! fn bar(d1: Duration<u32, 1, 1_000>, d2: Duration<u32, 1, 1_000_000>) {
22//!     let sum = d1 + d2.convert();
23//!     //        ^^^^^^^ Run time move of base, will use a `mul` and `div` instruction (Cortex-M3+) to
24//!     //                perform the move of base.
25//!     //                The `.convert()` explicitly signals the move of base.
26//!
27//!     let ops = d1 > d2;
28//!     //        ^^^^^^^ Run time comparison of different base, will use 2 `mul` instructions
29//!     //                (Cortex-M3+) to perform the comparison.
30//! }
31//!
32//! fn baz(d1: Duration<u64, 1, 1_000>, d2: Duration<u64, 1, 1_000_000>) {
33//!     let sum = d1 + d2.convert();
34//!     //        ^^^^^^^ Run time move of base, will use a `mul` insruction and `div`
35//!     //                soft-impl (Cortex-M3+) to perform the move of base.
36//!     //                The `.convert()` explicitly signals the move of base.
37//!
38//!     let ops = d1 > d2;
39//!     //        ^^^^^^^ Run time comparison of different base, will use 4 `mul` instructions
40//!     //                (Cortex-M3+) to perform the comparison.
41//! }
42//! ```
43
44#![cfg_attr(not(test), no_std)]
45#![deny(missing_docs)]
46
47mod aliases;
48mod duration;
49mod helpers;
50mod instant;
51mod rate;
52
53pub use aliases::*;
54pub use duration::{Duration, ExtU32, ExtU32Ceil, ExtU64, ExtU64Ceil};
55pub use instant::Instant;
56pub use rate::{ExtU32 as RateExtU32, ExtU64 as RateExtU64, Rate};
57
58#[cfg(test)]
59mod test {
60    use crate::Duration;
61    use crate::Instant;
62    use crate::Rate;
63    use crate::{
64        Hertz, HertzU32, HertzU64, Kilohertz, KilohertzU32, KilohertzU64, Megahertz, MegahertzU32,
65        MegahertzU64, TimerRate, TimerRateU32, TimerRateU64,
66    };
67
68    ////////////////////////////////////////////////////////////////////////////////
69    //
70    // Duration tests
71    //
72    ////////////////////////////////////////////////////////////////////////////////
73
74    #[test]
75    fn large_duration_converstion() {
76        use crate::ExtU64;
77
78        let sum = Duration::<u64, 1, 80_000_000>::from_ticks(0) + 15.minutes();
79
80        assert_eq!(
81            sum,
82            Duration::<u64, 1, 80_000_000>::from_ticks(80_000_000 * 60 * 15)
83        );
84    }
85
86    fn take_ms(d: Duration<u32, 1, 1_000>) -> Duration<u32, 1, 1_000> {
87        d
88    }
89
90    #[test]
91    fn duration_functions() {
92        assert_eq!(
93            take_ms(Duration::<u32, 1, 100>::from_ticks(1).convert()),
94            Duration::<u32, 1, 1_000>::from_ticks(10)
95        );
96    }
97
98    #[test]
99    fn duration_compare_u32() {
100        // Same fraction
101        assert!(
102            Duration::<u32, 1, 1_000>::from_ticks(2) > Duration::<u32, 1, 1_000>::from_ticks(1)
103        );
104        assert!(
105            Duration::<u32, 1, 1_000>::from_ticks(2) >= Duration::<u32, 1, 1_000>::from_ticks(1)
106        );
107        assert!(
108            Duration::<u32, 1, 1_000>::from_ticks(1) >= Duration::<u32, 1, 1_000>::from_ticks(1)
109        );
110        assert!(
111            Duration::<u32, 1, 1_000>::from_ticks(1) < Duration::<u32, 1, 1_000>::from_ticks(2)
112        );
113        assert!(
114            Duration::<u32, 1, 1_000>::from_ticks(1) <= Duration::<u32, 1, 1_000>::from_ticks(1)
115        );
116        assert!(
117            Duration::<u32, 1, 1_000>::from_ticks(1) <= Duration::<u32, 1, 1_000>::from_ticks(2)
118        );
119        assert!(
120            Duration::<u32, 1, 1_000>::from_ticks(1) == Duration::<u32, 1, 1_000>::from_ticks(1)
121        );
122        assert!(
123            Duration::<u32, 1, 1_000>::from_ticks(1) != Duration::<u32, 1, 1_000>::from_ticks(2)
124        );
125
126        // Different fraction
127        assert!(
128            Duration::<u32, 1, 10_000>::from_ticks(11) > Duration::<u32, 1, 1_000>::from_ticks(1)
129        );
130        assert!(
131            Duration::<u32, 1, 10_000>::from_ticks(11) >= Duration::<u32, 1, 1_000>::from_ticks(1)
132        );
133        assert!(
134            Duration::<u32, 1, 10_000>::from_ticks(10) >= Duration::<u32, 1, 1_000>::from_ticks(1)
135        );
136        assert!(
137            Duration::<u32, 1, 10_000>::from_ticks(11) < Duration::<u32, 1, 1_000>::from_ticks(2)
138        );
139        assert!(
140            Duration::<u32, 1, 10_000>::from_ticks(1) <= Duration::<u32, 1, 1_000>::from_ticks(1)
141        );
142        assert!(
143            Duration::<u32, 1, 10_000>::from_ticks(10) <= Duration::<u32, 1, 1_000>::from_ticks(1)
144        );
145        assert!(
146            Duration::<u32, 1, 10_000>::from_ticks(10) == Duration::<u32, 1, 1_000>::from_ticks(1)
147        );
148        assert!(
149            Duration::<u32, 1, 10_000>::from_ticks(9) != Duration::<u32, 1, 1_000>::from_ticks(2)
150        );
151
152        // From instants
153        assert!(
154            Instant::<u32, 1, 1_000>::from_ticks(10) - Instant::<u32, 1, 1_000>::from_ticks(5)
155                > Duration::<u32, 1, 1_000>::from_ticks(4)
156        );
157        assert!(
158            Instant::<u32, 1, 1_000>::from_ticks(10) - Instant::<u32, 1, 1_000>::from_ticks(5)
159                >= Duration::<u32, 1, 1_000>::from_ticks(4)
160        );
161        assert!(
162            Instant::<u32, 1, 1_000>::from_ticks(10) - Instant::<u32, 1, 1_000>::from_ticks(5)
163                >= Duration::<u32, 1, 1_000>::from_ticks(5)
164        );
165        assert!(
166            Instant::<u32, 1, 1_000>::from_ticks(10) - Instant::<u32, 1, 1_000>::from_ticks(5)
167                < Duration::<u32, 1, 1_000>::from_ticks(6)
168        );
169        assert!(
170            Instant::<u32, 1, 1_000>::from_ticks(10) - Instant::<u32, 1, 1_000>::from_ticks(5)
171                <= Duration::<u32, 1, 1_000>::from_ticks(6)
172        );
173        assert!(
174            Instant::<u32, 1, 1_000>::from_ticks(10) - Instant::<u32, 1, 1_000>::from_ticks(5)
175                <= Duration::<u32, 1, 1_000>::from_ticks(5)
176        );
177        assert!(
178            Instant::<u32, 1, 1_000>::from_ticks(10) - Instant::<u32, 1, 1_000>::from_ticks(5)
179                == Duration::<u32, 1, 1_000>::from_ticks(5)
180        );
181        assert!(
182            Instant::<u32, 1, 1_000>::from_ticks(10) - Instant::<u32, 1, 1_000>::from_ticks(5)
183                != Duration::<u32, 1, 1_000>::from_ticks(4)
184        );
185    }
186
187    #[test]
188    fn duration_compare_u64() {
189        // Same fraction
190        assert!(
191            Duration::<u64, 1, 1_000>::from_ticks(2) > Duration::<u64, 1, 1_000>::from_ticks(1)
192        );
193        assert!(
194            Duration::<u64, 1, 1_000>::from_ticks(2) >= Duration::<u64, 1, 1_000>::from_ticks(1)
195        );
196        assert!(
197            Duration::<u64, 1, 1_000>::from_ticks(1) >= Duration::<u64, 1, 1_000>::from_ticks(1)
198        );
199        assert!(
200            Duration::<u64, 1, 1_000>::from_ticks(1) < Duration::<u64, 1, 1_000>::from_ticks(2)
201        );
202        assert!(
203            Duration::<u64, 1, 1_000>::from_ticks(1) <= Duration::<u64, 1, 1_000>::from_ticks(1)
204        );
205        assert!(
206            Duration::<u64, 1, 1_000>::from_ticks(1) <= Duration::<u64, 1, 1_000>::from_ticks(2)
207        );
208        assert!(
209            Duration::<u64, 1, 1_000>::from_ticks(1) == Duration::<u64, 1, 1_000>::from_ticks(1)
210        );
211        assert!(
212            Duration::<u64, 1, 1_000>::from_ticks(1) != Duration::<u64, 1, 1_000>::from_ticks(2)
213        );
214
215        // Different fraction
216        assert!(
217            Duration::<u64, 1, 10_000>::from_ticks(11) > Duration::<u64, 1, 1_000>::from_ticks(1)
218        );
219        assert!(
220            Duration::<u64, 1, 10_000>::from_ticks(11) >= Duration::<u64, 1, 1_000>::from_ticks(1)
221        );
222        assert!(
223            Duration::<u64, 1, 10_000>::from_ticks(10) >= Duration::<u64, 1, 1_000>::from_ticks(1)
224        );
225        assert!(
226            Duration::<u64, 1, 10_000>::from_ticks(11) < Duration::<u64, 1, 1_000>::from_ticks(2)
227        );
228        assert!(
229            Duration::<u64, 1, 10_000>::from_ticks(1) <= Duration::<u64, 1, 1_000>::from_ticks(1)
230        );
231        assert!(
232            Duration::<u64, 1, 10_000>::from_ticks(10) <= Duration::<u64, 1, 1_000>::from_ticks(1)
233        );
234        assert!(
235            Duration::<u64, 1, 10_000>::from_ticks(10) == Duration::<u64, 1, 1_000>::from_ticks(1)
236        );
237        assert!(
238            Duration::<u64, 1, 10_000>::from_ticks(9) != Duration::<u64, 1, 1_000>::from_ticks(2)
239        );
240
241        // From instants
242        assert!(
243            Instant::<u64, 1, 1_000>::from_ticks(10) - Instant::<u64, 1, 1_000>::from_ticks(5)
244                > Duration::<u64, 1, 1_000>::from_ticks(4)
245        );
246        assert!(
247            Instant::<u64, 1, 1_000>::from_ticks(10) - Instant::<u64, 1, 1_000>::from_ticks(5)
248                >= Duration::<u64, 1, 1_000>::from_ticks(4)
249        );
250        assert!(
251            Instant::<u64, 1, 1_000>::from_ticks(10) - Instant::<u64, 1, 1_000>::from_ticks(5)
252                >= Duration::<u64, 1, 1_000>::from_ticks(5)
253        );
254        assert!(
255            Instant::<u64, 1, 1_000>::from_ticks(10) - Instant::<u64, 1, 1_000>::from_ticks(5)
256                < Duration::<u64, 1, 1_000>::from_ticks(6)
257        );
258        assert!(
259            Instant::<u64, 1, 1_000>::from_ticks(10) - Instant::<u64, 1, 1_000>::from_ticks(5)
260                <= Duration::<u64, 1, 1_000>::from_ticks(6)
261        );
262        assert!(
263            Instant::<u64, 1, 1_000>::from_ticks(10) - Instant::<u64, 1, 1_000>::from_ticks(5)
264                <= Duration::<u64, 1, 1_000>::from_ticks(5)
265        );
266        assert!(
267            Instant::<u64, 1, 1_000>::from_ticks(10) - Instant::<u64, 1, 1_000>::from_ticks(5)
268                == Duration::<u64, 1, 1_000>::from_ticks(5)
269        );
270        assert!(
271            Instant::<u64, 1, 1_000>::from_ticks(10) - Instant::<u64, 1, 1_000>::from_ticks(5)
272                != Duration::<u64, 1, 1_000>::from_ticks(4)
273        );
274    }
275
276    #[test]
277    fn duration_compare_u64_u32() {
278        // Same fraction
279        assert!(
280            Duration::<u64, 1, 1_000>::from_ticks(2) > Duration::<u32, 1, 1_000>::from_ticks(1)
281        );
282        assert!(
283            Duration::<u64, 1, 1_000>::from_ticks(2) >= Duration::<u32, 1, 1_000>::from_ticks(1)
284        );
285        assert!(
286            Duration::<u64, 1, 1_000>::from_ticks(1) >= Duration::<u32, 1, 1_000>::from_ticks(1)
287        );
288        assert!(
289            Duration::<u64, 1, 1_000>::from_ticks(1) < Duration::<u32, 1, 1_000>::from_ticks(2)
290        );
291        assert!(
292            Duration::<u64, 1, 1_000>::from_ticks(1) <= Duration::<u32, 1, 1_000>::from_ticks(1)
293        );
294        assert!(
295            Duration::<u64, 1, 1_000>::from_ticks(1) <= Duration::<u32, 1, 1_000>::from_ticks(2)
296        );
297        assert!(
298            Duration::<u64, 1, 1_000>::from_ticks(1) == Duration::<u32, 1, 1_000>::from_ticks(1)
299        );
300        assert!(
301            Duration::<u64, 1, 1_000>::from_ticks(1) != Duration::<u32, 1, 1_000>::from_ticks(2)
302        );
303
304        // Different fraction
305        assert!(
306            Duration::<u64, 1, 10_000>::from_ticks(11) > Duration::<u32, 1, 1_000>::from_ticks(1)
307        );
308        assert!(
309            Duration::<u64, 1, 10_000>::from_ticks(11) >= Duration::<u32, 1, 1_000>::from_ticks(1)
310        );
311        assert!(
312            Duration::<u64, 1, 10_000>::from_ticks(10) >= Duration::<u32, 1, 1_000>::from_ticks(1)
313        );
314        assert!(
315            Duration::<u64, 1, 10_000>::from_ticks(11) < Duration::<u32, 1, 1_000>::from_ticks(2)
316        );
317        assert!(
318            Duration::<u64, 1, 10_000>::from_ticks(1) <= Duration::<u32, 1, 1_000>::from_ticks(1)
319        );
320        assert!(
321            Duration::<u64, 1, 10_000>::from_ticks(10) <= Duration::<u32, 1, 1_000>::from_ticks(1)
322        );
323        assert!(
324            Duration::<u64, 1, 10_000>::from_ticks(10) == Duration::<u32, 1, 1_000>::from_ticks(1)
325        );
326        assert!(
327            Duration::<u64, 1, 10_000>::from_ticks(9) != Duration::<u32, 1, 1_000>::from_ticks(2)
328        );
329
330        // From instants
331        assert!(
332            Instant::<u64, 1, 1_000>::from_ticks(10) - Instant::<u64, 1, 1_000>::from_ticks(5)
333                > Duration::<u32, 1, 1_000>::from_ticks(4)
334        );
335        assert!(
336            Instant::<u64, 1, 1_000>::from_ticks(10) - Instant::<u64, 1, 1_000>::from_ticks(5)
337                >= Duration::<u32, 1, 1_000>::from_ticks(4)
338        );
339        assert!(
340            Instant::<u64, 1, 1_000>::from_ticks(10) - Instant::<u64, 1, 1_000>::from_ticks(5)
341                >= Duration::<u32, 1, 1_000>::from_ticks(5)
342        );
343        assert!(
344            Instant::<u64, 1, 1_000>::from_ticks(10) - Instant::<u64, 1, 1_000>::from_ticks(5)
345                < Duration::<u32, 1, 1_000>::from_ticks(6)
346        );
347        assert!(
348            Instant::<u64, 1, 1_000>::from_ticks(10) - Instant::<u64, 1, 1_000>::from_ticks(5)
349                <= Duration::<u32, 1, 1_000>::from_ticks(6)
350        );
351        assert!(
352            Instant::<u64, 1, 1_000>::from_ticks(10) - Instant::<u64, 1, 1_000>::from_ticks(5)
353                <= Duration::<u32, 1, 1_000>::from_ticks(5)
354        );
355        assert!(
356            Instant::<u64, 1, 1_000>::from_ticks(10) - Instant::<u64, 1, 1_000>::from_ticks(5)
357                == Duration::<u32, 1, 1_000>::from_ticks(5)
358        );
359        assert!(
360            Instant::<u64, 1, 1_000>::from_ticks(10) - Instant::<u64, 1, 1_000>::from_ticks(5)
361                != Duration::<u32, 1, 1_000>::from_ticks(4)
362        );
363    }
364
365    #[test]
366    fn duration_compare_u32_u64() {
367        // Same fraction
368        assert!(
369            Duration::<u32, 1, 1_000>::from_ticks(2) > Duration::<u64, 1, 1_000>::from_ticks(1)
370        );
371        assert!(
372            Duration::<u32, 1, 1_000>::from_ticks(2) >= Duration::<u64, 1, 1_000>::from_ticks(1)
373        );
374        assert!(
375            Duration::<u32, 1, 1_000>::from_ticks(1) >= Duration::<u64, 1, 1_000>::from_ticks(1)
376        );
377        assert!(
378            Duration::<u32, 1, 1_000>::from_ticks(1) < Duration::<u64, 1, 1_000>::from_ticks(2)
379        );
380        assert!(
381            Duration::<u32, 1, 1_000>::from_ticks(1) <= Duration::<u64, 1, 1_000>::from_ticks(1)
382        );
383        assert!(
384            Duration::<u32, 1, 1_000>::from_ticks(1) <= Duration::<u64, 1, 1_000>::from_ticks(2)
385        );
386        assert!(
387            Duration::<u32, 1, 1_000>::from_ticks(1) == Duration::<u64, 1, 1_000>::from_ticks(1)
388        );
389        assert!(
390            Duration::<u32, 1, 1_000>::from_ticks(1) != Duration::<u64, 1, 1_000>::from_ticks(2)
391        );
392
393        // Different fraction
394        assert!(
395            Duration::<u32, 1, 10_000>::from_ticks(11) > Duration::<u64, 1, 1_000>::from_ticks(1)
396        );
397        assert!(
398            Duration::<u32, 1, 10_000>::from_ticks(11) >= Duration::<u64, 1, 1_000>::from_ticks(1)
399        );
400        assert!(
401            Duration::<u32, 1, 10_000>::from_ticks(10) >= Duration::<u64, 1, 1_000>::from_ticks(1)
402        );
403        assert!(
404            Duration::<u32, 1, 10_000>::from_ticks(11) < Duration::<u64, 1, 1_000>::from_ticks(2)
405        );
406        assert!(
407            Duration::<u32, 1, 10_000>::from_ticks(1) <= Duration::<u64, 1, 1_000>::from_ticks(1)
408        );
409        assert!(
410            Duration::<u32, 1, 10_000>::from_ticks(10) <= Duration::<u64, 1, 1_000>::from_ticks(1)
411        );
412        assert!(
413            Duration::<u32, 1, 10_000>::from_ticks(10) == Duration::<u64, 1, 1_000>::from_ticks(1)
414        );
415        assert!(
416            Duration::<u32, 1, 10_000>::from_ticks(9) != Duration::<u64, 1, 1_000>::from_ticks(2)
417        );
418
419        // From instants
420        assert!(
421            Instant::<u32, 1, 1_000>::from_ticks(10) - Instant::<u32, 1, 1_000>::from_ticks(5)
422                > Duration::<u64, 1, 1_000>::from_ticks(4)
423        );
424        assert!(
425            Instant::<u32, 1, 1_000>::from_ticks(10) - Instant::<u32, 1, 1_000>::from_ticks(5)
426                >= Duration::<u64, 1, 1_000>::from_ticks(4)
427        );
428        assert!(
429            Instant::<u32, 1, 1_000>::from_ticks(10) - Instant::<u32, 1, 1_000>::from_ticks(5)
430                >= Duration::<u64, 1, 1_000>::from_ticks(5)
431        );
432        assert!(
433            Instant::<u32, 1, 1_000>::from_ticks(10) - Instant::<u32, 1, 1_000>::from_ticks(5)
434                < Duration::<u64, 1, 1_000>::from_ticks(6)
435        );
436        assert!(
437            Instant::<u32, 1, 1_000>::from_ticks(10) - Instant::<u32, 1, 1_000>::from_ticks(5)
438                <= Duration::<u64, 1, 1_000>::from_ticks(6)
439        );
440        assert!(
441            Instant::<u32, 1, 1_000>::from_ticks(10) - Instant::<u32, 1, 1_000>::from_ticks(5)
442                <= Duration::<u64, 1, 1_000>::from_ticks(5)
443        );
444        assert!(
445            Instant::<u32, 1, 1_000>::from_ticks(10) - Instant::<u32, 1, 1_000>::from_ticks(5)
446                == Duration::<u64, 1, 1_000>::from_ticks(5)
447        );
448        assert!(
449            Instant::<u32, 1, 1_000>::from_ticks(10) - Instant::<u32, 1, 1_000>::from_ticks(5)
450                != Duration::<u64, 1, 1_000>::from_ticks(4)
451        );
452    }
453
454    #[test]
455    fn duration_duration_math_u32() {
456        use crate::ExtU32;
457
458        // Same base
459        let sum: Duration<u32, 1, 1_000> =
460            Duration::<u32, 1, 1_000>::from_ticks(10) + Duration::<u32, 1, 1_000>::from_ticks(1);
461        assert_eq!(sum, Duration::<u32, 1, 1_000>::from_ticks(11));
462
463        let mut sum = Duration::<u32, 1, 1_000>::from_ticks(10);
464        sum += Duration::<u32, 1, 1_000>::from_ticks(1);
465        assert_eq!(sum, Duration::<u32, 1, 1_000>::from_ticks(11));
466
467        let diff: Duration<u32, 1, 1_000> =
468            Duration::<u32, 1, 1_000>::from_ticks(10) - Duration::<u32, 1, 1_000>::from_ticks(1);
469        assert_eq!(diff, Duration::<u32, 1, 1_000>::from_ticks(9));
470
471        let mut diff = Duration::<u32, 1, 1_000>::from_ticks(10);
472        diff -= Duration::<u32, 1, 1_000>::from_ticks(1);
473        assert_eq!(diff, Duration::<u32, 1, 1_000>::from_ticks(9));
474
475        // Different base
476        let sum: Duration<u32, 1, 10_000> = Duration::<u32, 1, 10_000>::from_ticks(10)
477            + Duration::<u32, 1, 1_000>::from_ticks(1).convert();
478        assert_eq!(sum, Duration::<u32, 1, 1_000>::from_ticks(2));
479
480        let mut sum = Duration::<u32, 1, 1_000>::from_ticks(1);
481        sum += Duration::<u32, 1, 10_000>::from_ticks(10).convert();
482        assert_eq!(sum, Duration::<u32, 1, 1_000>::from_ticks(2));
483
484        let diff: Duration<u32, 1, 10_000> = Duration::<u32, 1, 10_000>::from_ticks(10)
485            - Duration::<u32, 1, 1_000>::from_ticks(1).convert();
486        assert_eq!(diff, Duration::<u32, 1, 10_000>::from_ticks(0));
487
488        let mut diff = Duration::<u32, 1, 1_000>::from_ticks(1);
489        diff -= Duration::<u32, 1, 10_000>::from_ticks(10).convert();
490        assert_eq!(diff, Duration::<u32, 1, 1_000>::from_ticks(0));
491
492        // Short hand vs u32 (should not need `.into()`)
493        let sum = Duration::<u32, 1, 10_000>::from_ticks(10) + 1.millis();
494        assert_eq!(sum, Duration::<u32, 1, 10_000>::from_ticks(20));
495
496        let mut sum = Duration::<u32, 1, 10_000>::from_ticks(10);
497        sum += 1.millis();
498        assert_eq!(sum, Duration::<u32, 1, 10_000>::from_ticks(20));
499
500        // Fixed in v0.3.2
501        let d: Duration<u32, 1, 1_000> = Duration::<u32, 1, 32_768>::from_ticks(42949672).convert();
502        assert_eq!(d.ticks(), 1_310_719);
503
504        // Division and multiplication by integers
505        let mul: Duration<u32, 1, 1_000> = Duration::<u32, 1, 1_000>::from_ticks(10) * 2;
506        assert_eq!(mul, Duration::<u32, 1, 1_000>::from_ticks(20));
507
508        let mut mul = Duration::<u32, 1, 1_000>::from_ticks(10);
509        mul *= 2;
510        assert_eq!(mul, Duration::<u32, 1, 1_000>::from_ticks(20));
511
512        let div: Duration<u32, 1, 1_000> = Duration::<u32, 1, 1_000>::from_ticks(10) / 2;
513        assert_eq!(div, Duration::<u32, 1, 1_000>::from_ticks(5));
514
515        let mut div = Duration::<u32, 1, 1_000>::from_ticks(10);
516        div /= 2;
517        assert_eq!(div, Duration::<u32, 1, 1_000>::from_ticks(5));
518
519        assert_eq!(
520            Duration::<u32, 1, 100>::from_ticks(5) / Duration::<u32, 1, 1_000>::from_ticks(2),
521            25
522        );
523
524        assert_eq!(
525            Duration::<u32, 1, 1_000>::from_ticks(2) / Duration::<u32, 1, 100>::from_ticks(5),
526            0
527        );
528
529        assert_eq!(
530            Duration::<u32, 1, 1_000>::from_ticks(500) / Duration::<u32, 1, 100>::from_ticks(5),
531            10
532        );
533    }
534
535    #[test]
536    fn duration_duration_math_u64() {
537        use crate::ExtU64;
538
539        // Same base
540        let sum: Duration<u64, 1, 1_000> =
541            Duration::<u64, 1, 1_000>::from_ticks(10) + Duration::<u64, 1, 1_000>::from_ticks(1);
542        assert_eq!(sum, Duration::<u64, 1, 1_000>::from_ticks(11));
543
544        let mut sum = Duration::<u64, 1, 1_000>::from_ticks(10);
545        sum += Duration::<u64, 1, 1_000>::from_ticks(1);
546        assert_eq!(sum, Duration::<u64, 1, 1_000>::from_ticks(11));
547
548        let diff: Duration<u64, 1, 1_000> =
549            Duration::<u64, 1, 1_000>::from_ticks(10) - Duration::<u64, 1, 1_000>::from_ticks(1);
550        assert_eq!(diff, Duration::<u64, 1, 1_000>::from_ticks(9));
551
552        let mut diff = Duration::<u64, 1, 1_000>::from_ticks(10);
553        diff -= Duration::<u64, 1, 1_000>::from_ticks(1);
554        assert_eq!(diff, Duration::<u64, 1, 1_000>::from_ticks(9));
555
556        // Different base
557        let sum: Duration<u64, 1, 10_000> = Duration::<u64, 1, 10_000>::from_ticks(10)
558            + Duration::<u64, 1, 1_000>::from_ticks(1).convert();
559        assert_eq!(sum, Duration::<u64, 1, 1_000>::from_ticks(2));
560
561        let mut sum = Duration::<u64, 1, 1_000>::from_ticks(1);
562        sum += Duration::<u64, 1, 10_000>::from_ticks(10).convert();
563        assert_eq!(sum, Duration::<u64, 1, 1_000>::from_ticks(2));
564
565        let diff: Duration<u64, 1, 10_000> = Duration::<u64, 1, 10_000>::from_ticks(10)
566            - Duration::<u64, 1, 1_000>::from_ticks(1).convert();
567        assert_eq!(diff, Duration::<u64, 1, 1_000>::from_ticks(0));
568
569        let mut diff = Duration::<u64, 1, 1_000>::from_ticks(1);
570        diff -= Duration::<u64, 1, 10_000>::from_ticks(10).convert();
571        assert_eq!(diff, Duration::<u64, 1, 1_000>::from_ticks(0));
572
573        // Short hand vs u64 (should not need `.into()`)
574        let sum = Duration::<u64, 1, 10_000>::from_ticks(10) + 1.millis();
575        assert_eq!(sum, Duration::<u64, 1, 10_000>::from_ticks(20));
576
577        let mut sum = Duration::<u64, 1, 10_000>::from_ticks(10);
578        sum += 1.millis();
579        assert_eq!(sum, Duration::<u64, 1, 10_000>::from_ticks(20));
580
581        // Division and multiplication by integers
582        let mul: Duration<u64, 1, 1_000> = Duration::<u64, 1, 1_000>::from_ticks(10) * 2;
583        assert_eq!(mul, Duration::<u64, 1, 1_000>::from_ticks(20));
584
585        let mut mul = Duration::<u64, 1, 1_000>::from_ticks(10);
586        mul *= 2;
587        assert_eq!(mul, Duration::<u64, 1, 1_000>::from_ticks(20));
588
589        let div: Duration<u64, 1, 1_000> = Duration::<u64, 1, 1_000>::from_ticks(10) / 2;
590        assert_eq!(div, Duration::<u64, 1, 1_000>::from_ticks(5));
591
592        let mut div = Duration::<u64, 1, 1_000>::from_ticks(10);
593        div /= 2;
594        assert_eq!(div, Duration::<u64, 1, 1_000>::from_ticks(5));
595
596        assert_eq!(
597            Duration::<u64, 1, 1_00>::from_ticks(5) / Duration::<u64, 1, 1_000>::from_ticks(2),
598            25
599        );
600
601        assert_eq!(
602            Duration::<u64, 1, 1_000>::from_ticks(2) / Duration::<u64, 1, 1_00>::from_ticks(5),
603            0
604        );
605
606        assert_eq!(
607            Duration::<u64, 1, 1_000>::from_ticks(500) / Duration::<u64, 1, 1_00>::from_ticks(5),
608            10
609        );
610    }
611
612    #[test]
613    fn duration_duration_math_u64_u32() {
614        // Same base
615        let sum: Duration<u64, 1, 1_000> =
616            Duration::<u64, 1, 1_000>::from_ticks(10) + Duration::<u32, 1, 1_000>::from_ticks(1);
617        assert_eq!(sum, Duration::<u64, 1, 1_000>::from_ticks(11));
618
619        let mut sum = Duration::<u64, 1, 1_000>::from_ticks(10);
620        sum += Duration::<u32, 1, 1_000>::from_ticks(1);
621        assert_eq!(sum, Duration::<u64, 1, 1_000>::from_ticks(11));
622
623        let diff: Duration<u64, 1, 1_000> =
624            Duration::<u64, 1, 1_000>::from_ticks(10) - Duration::<u32, 1, 1_000>::from_ticks(1);
625        assert_eq!(diff, Duration::<u64, 1, 1_000>::from_ticks(9));
626
627        let mut diff = Duration::<u64, 1, 1_000>::from_ticks(10);
628        diff -= Duration::<u32, 1, 1_000>::from_ticks(1);
629        assert_eq!(diff, Duration::<u64, 1, 1_000>::from_ticks(9));
630
631        // Different base
632        let sum: Duration<u64, 1, 10_000> = Duration::<u64, 1, 10_000>::from_ticks(10)
633            + Duration::<u32, 1, 1_000>::from_ticks(1).convert();
634        assert_eq!(sum, Duration::<u64, 1, 1_000>::from_ticks(2));
635
636        let mut sum = Duration::<u64, 1, 1_000>::from_ticks(1);
637        sum += Duration::<u32, 1, 10_000>::from_ticks(10).convert();
638        assert_eq!(sum, Duration::<u64, 1, 1_000>::from_ticks(2));
639
640        let diff: Duration<u64, 1, 10_000> = Duration::<u64, 1, 10_000>::from_ticks(10)
641            - Duration::<u32, 1, 1_000>::from_ticks(1).convert();
642        assert_eq!(diff, Duration::<u64, 1, 1_000>::from_ticks(0));
643
644        let mut diff = Duration::<u64, 1, 1_000>::from_ticks(1);
645        diff -= Duration::<u32, 1, 10_000>::from_ticks(10).convert();
646        assert_eq!(diff, Duration::<u64, 1, 1_000>::from_ticks(0));
647    }
648
649    #[test]
650    fn duration_shorthands_u32() {
651        use crate::{ExtU32, ExtU32Ceil};
652
653        let d: Duration<u32, 1, 10_000> = 100_000_000.nanos();
654        assert_eq!(d.ticks(), 1_000);
655
656        let d: Duration<u32, 1, 1_000_000> = 40_000.nanos_at_least();
657        assert_eq!(d.ticks(), 40);
658
659        let d: Duration<u32, 1, 1_000_000> = 40_075.nanos_at_least();
660        assert_eq!(d.ticks(), 41);
661
662        let d: Duration<u32, 1, 1_000> = 4001.micros_at_least();
663        assert_eq!(d.ticks(), 5);
664
665        let d: Duration<u32, 1, 10_000> = 100_000.micros();
666        assert_eq!(d.ticks(), 1_000);
667
668        let d: Duration<u32, 1, 10_000> = 1.millis();
669        assert_eq!(d.ticks(), 10);
670
671        let d: Duration<u32, 1, 10_000> = 1.secs();
672        assert_eq!(d.ticks(), 10_000);
673
674        let d: Duration<u32, 1, 10_000> = 1.minutes();
675        assert_eq!(d.ticks(), 600_000);
676
677        let d: Duration<u32, 1, 10_000> = 1.hours();
678        assert_eq!(d.ticks(), 36_000_000);
679
680        let d = Duration::<u32, 1, 10_000>::millis(10);
681        assert_eq!(d.ticks(), 100);
682
683        let d = Duration::<u32, 1, 10_000>::Hz(200);
684        assert_eq!(d.ticks(), 50);
685
686        let d = Duration::<u32, 1, 1>::from_ticks(2);
687        assert_eq!(d.to_secs(), 2);
688        assert_eq!(d.to_nanos(), 2_000_000_000);
689
690        let d = Duration::<u32, 1, 1_000_000_000>::from_ticks(2_000_000_000);
691        assert_eq!(d.to_secs(), 2);
692        assert_eq!(d.to_nanos(), 2_000_000_000);
693
694        let d = Duration::<u32, 1, 10_000>::from_ticks(100);
695        assert_eq!(d.to_nanos(), 10_000_000);
696
697        let d = Duration::<u32, 1, 10_000>::from_ticks(100);
698        assert_eq!(d.to_micros(), 10_000);
699
700        let d = Duration::<u32, 1, 10_000>::from_ticks(100);
701        assert_eq!(d.to_millis(), 10);
702
703        let d = Duration::<u32, 1, 10_000>::from_ticks(100_000);
704        assert_eq!(d.to_secs(), 10);
705
706        let d = Duration::<u32, 1, 10_000>::from_ticks(1_800_000);
707        assert_eq!(d.to_minutes(), 3);
708
709        let d = Duration::<u32, 1, 10_000>::from_ticks(180_000_000);
710        assert_eq!(d.to_hours(), 5);
711    }
712
713    #[test]
714    fn duration_shorthands_u64() {
715        use crate::{ExtU64, ExtU64Ceil};
716
717        let d: Duration<u64, 1, 10_000> = 100_000_000.nanos();
718        assert_eq!(d.ticks(), 1_000);
719
720        let d: Duration<u64, 1, 1_000_000> = 40_000.nanos_at_least();
721        assert_eq!(d.ticks(), 40);
722
723        let d: Duration<u64, 1, 1_000_000> = 40_075.nanos_at_least();
724        assert_eq!(d.ticks(), 41);
725
726        let d: Duration<u64, 1, 1_000> = 4001.micros_at_least();
727        assert_eq!(d.ticks(), 5);
728
729        let d: Duration<u64, 1, 10_000> = 100_000.micros();
730        assert_eq!(d.ticks(), 1_000);
731
732        let d: Duration<u64, 1, 10_000> = 1.millis();
733        assert_eq!(d.ticks(), 10);
734
735        let d: Duration<u64, 1, 10_000> = 1.secs();
736        assert_eq!(d.ticks(), 10_000);
737
738        let d: Duration<u64, 1, 10_000> = 1.minutes();
739        assert_eq!(d.ticks(), 600_000);
740
741        let d: Duration<u64, 1, 10_000> = 1.hours();
742        assert_eq!(d.ticks(), 36_000_000);
743
744        let d = Duration::<u64, 1, 10_000>::millis(10);
745        assert_eq!(d.ticks(), 100);
746
747        let d = Duration::<u64, 1, 10_000>::Hz(200);
748        assert_eq!(d.ticks(), 50);
749
750        let d = Duration::<u32, 1, 1>::from_ticks(2);
751        assert_eq!(d.to_secs(), 2);
752        assert_eq!(d.to_nanos(), 2_000_000_000);
753
754        let d = Duration::<u32, 1, 1_000_000_000>::from_ticks(2_000_000_000);
755        assert_eq!(d.to_secs(), 2);
756        assert_eq!(d.to_nanos(), 2_000_000_000);
757
758        let d = Duration::<u64, 1, 10_000>::from_ticks(100);
759        assert_eq!(d.to_nanos(), 10_000_000);
760
761        let d = Duration::<u64, 1, 10_000>::from_ticks(100);
762        assert_eq!(d.to_micros(), 10_000);
763
764        let d = Duration::<u64, 1, 10_000>::from_ticks(100);
765        assert_eq!(d.to_millis(), 10);
766
767        let d = Duration::<u64, 1, 10_000>::from_ticks(100_000);
768        assert_eq!(d.to_secs(), 10);
769
770        let d = Duration::<u64, 1, 10_000>::from_ticks(1_800_000);
771        assert_eq!(d.to_minutes(), 3);
772
773        let d = Duration::<u64, 1, 10_000>::from_ticks(180_000_000);
774        assert_eq!(d.to_hours(), 5);
775    }
776
777    #[test]
778    fn duration_is_zero() {
779        let d = Duration::<u64, 1, 1_000>::from_ticks(0);
780        assert_eq!(d.is_zero(), true);
781        let d = Duration::<u64, 1, 1_000>::from_ticks(1);
782        assert_eq!(d.is_zero(), false);
783        let d = Duration::<u32, 1, 1_000>::from_ticks(0);
784        assert_eq!(d.is_zero(), true);
785        let d = Duration::<u32, 1, 1_000>::from_ticks(1);
786        assert_eq!(d.is_zero(), false);
787    }
788
789    ////////////////////////////////////////////////////////////////////////////////
790    //
791    // Instant tests
792    //
793    ////////////////////////////////////////////////////////////////////////////////
794
795    #[test]
796    fn instant_compare_u32() {
797        // Wrapping
798        assert!(
799            Instant::<u32, 1, 1_000>::from_ticks(1)
800                > Instant::<u32, 1, 1_000>::from_ticks(u32::MAX)
801        );
802        assert!(
803            Instant::<u32, 1, 1_000>::from_ticks(u32::MAX - 1)
804                < Instant::<u32, 1, 1_000>::from_ticks(u32::MAX)
805        );
806
807        // Non-wrapping
808        assert!(Instant::<u32, 1, 1_000>::from_ticks(2) > Instant::<u32, 1, 1_000>::from_ticks(1));
809        assert!(Instant::<u32, 1, 1_000>::from_ticks(2) >= Instant::<u32, 1, 1_000>::from_ticks(1));
810        assert!(Instant::<u32, 1, 1_000>::from_ticks(1) >= Instant::<u32, 1, 1_000>::from_ticks(1));
811        assert!(Instant::<u32, 1, 1_000>::from_ticks(1) < Instant::<u32, 1, 1_000>::from_ticks(2));
812        assert!(Instant::<u32, 1, 1_000>::from_ticks(1) <= Instant::<u32, 1, 1_000>::from_ticks(1));
813        assert!(Instant::<u32, 1, 1_000>::from_ticks(1) <= Instant::<u32, 1, 1_000>::from_ticks(2));
814        assert!(Instant::<u32, 1, 1_000>::from_ticks(1) == Instant::<u32, 1, 1_000>::from_ticks(1));
815        assert!(Instant::<u32, 1, 1_000>::from_ticks(1) != Instant::<u32, 1, 1_000>::from_ticks(2));
816
817        // Checked duration since non-wrapping
818        assert_eq!(
819            Instant::<u32, 1, 1_000>::from_ticks(1)
820                .checked_duration_since(Instant::<u32, 1, 1_000>::from_ticks(1)),
821            Some(Duration::<u32, 1, 1_000>::from_ticks(0))
822        );
823        assert_eq!(
824            Instant::<u32, 1, 1_000>::from_ticks(2)
825                .checked_duration_since(Instant::<u32, 1, 1_000>::from_ticks(1)),
826            Some(Duration::<u32, 1, 1_000>::from_ticks(1))
827        );
828        assert_eq!(
829            Instant::<u32, 1, 1_000>::from_ticks(2)
830                .checked_duration_since(Instant::<u32, 1, 1_000>::from_ticks(3)),
831            None
832        );
833
834        // Checked duration since wrapping
835        assert_eq!(
836            Instant::<u32, 1, 1_000>::from_ticks(2)
837                .checked_duration_since(Instant::<u32, 1, 1_000>::from_ticks(u32::MAX)),
838            Some(Duration::<u32, 1, 1_000>::from_ticks(3))
839        );
840        assert_eq!(
841            Instant::<u32, 1, 1_000>::from_ticks(2)
842                .checked_duration_since(Instant::<u32, 1, 1_000>::from_ticks(u32::MAX - 1)),
843            Some(Duration::<u32, 1, 1_000>::from_ticks(4))
844        );
845    }
846
847    #[test]
848    fn instant_compare_u64() {
849        // Wrapping
850        assert!(
851            Instant::<u64, 1, 1_000>::from_ticks(1)
852                > Instant::<u64, 1, 1_000>::from_ticks(u64::MAX)
853        );
854        assert!(
855            Instant::<u64, 1, 1_000>::from_ticks(u64::MAX - 1)
856                < Instant::<u64, 1, 1_000>::from_ticks(u64::MAX)
857        );
858
859        // Non-wrapping
860        assert!(Instant::<u64, 1, 1_000>::from_ticks(2) > Instant::<u64, 1, 1_000>::from_ticks(1));
861        assert!(Instant::<u64, 1, 1_000>::from_ticks(2) >= Instant::<u64, 1, 1_000>::from_ticks(1));
862        assert!(Instant::<u64, 1, 1_000>::from_ticks(1) >= Instant::<u64, 1, 1_000>::from_ticks(1));
863        assert!(Instant::<u64, 1, 1_000>::from_ticks(1) < Instant::<u64, 1, 1_000>::from_ticks(2));
864        assert!(Instant::<u64, 1, 1_000>::from_ticks(1) <= Instant::<u64, 1, 1_000>::from_ticks(1));
865        assert!(Instant::<u64, 1, 1_000>::from_ticks(1) <= Instant::<u64, 1, 1_000>::from_ticks(2));
866        assert!(Instant::<u64, 1, 1_000>::from_ticks(1) == Instant::<u64, 1, 1_000>::from_ticks(1));
867        assert!(Instant::<u64, 1, 1_000>::from_ticks(1) != Instant::<u64, 1, 1_000>::from_ticks(2));
868
869        // Checked duration since non-wrapping
870        assert_eq!(
871            Instant::<u64, 1, 1_000>::from_ticks(1)
872                .checked_duration_since(Instant::<u64, 1, 1_000>::from_ticks(1)),
873            Some(Duration::<u64, 1, 1_000>::from_ticks(0))
874        );
875        assert_eq!(
876            Instant::<u64, 1, 1_000>::from_ticks(2)
877                .checked_duration_since(Instant::<u64, 1, 1_000>::from_ticks(1)),
878            Some(Duration::<u64, 1, 1_000>::from_ticks(1))
879        );
880        assert_eq!(
881            Instant::<u64, 1, 1_000>::from_ticks(2)
882                .checked_duration_since(Instant::<u64, 1, 1_000>::from_ticks(3)),
883            None
884        );
885
886        // Checked duration since wrapping
887        assert_eq!(
888            Instant::<u64, 1, 1_000>::from_ticks(2)
889                .checked_duration_since(Instant::<u64, 1, 1_000>::from_ticks(u64::MAX)),
890            Some(Duration::<u64, 1, 1_000>::from_ticks(3))
891        );
892        assert_eq!(
893            Instant::<u64, 1, 1_000>::from_ticks(2)
894                .checked_duration_since(Instant::<u64, 1, 1_000>::from_ticks(u64::MAX - 1)),
895            Some(Duration::<u64, 1, 1_000>::from_ticks(4))
896        );
897    }
898
899    #[test]
900    fn instant_duration_math_u32() {
901        use crate::ExtU32;
902
903        // Instant - Instant, Same base
904        let diff: Duration<u32, 1, 1_000> =
905            Instant::<u32, 1, 1_000>::from_ticks(10) - Instant::<u32, 1, 1_000>::from_ticks(1);
906        assert_eq!(diff, Duration::<u32, 1, 1_000>::from_ticks(9));
907
908        // Instant +- Duration, Same base
909        let sum: Instant<u32, 1, 1_000> =
910            Instant::<u32, 1, 1_000>::from_ticks(10) + Duration::<u32, 1, 1_000>::from_ticks(1);
911        assert_eq!(sum, Instant::<u32, 1, 1_000>::from_ticks(11));
912
913        let mut sum = Instant::<u32, 1, 1_000>::from_ticks(10);
914        sum += Duration::<u32, 1, 1_000>::from_ticks(1);
915        assert_eq!(sum, Instant::<u32, 1, 1_000>::from_ticks(11));
916
917        let diff: Instant<u32, 1, 1_000> =
918            Instant::<u32, 1, 1_000>::from_ticks(10) - Duration::<u32, 1, 1_000>::from_ticks(1);
919        assert_eq!(diff, Instant::<u32, 1, 1_000>::from_ticks(9));
920
921        let mut diff = Instant::<u32, 1, 1_000>::from_ticks(10);
922        diff -= Duration::<u32, 1, 1_000>::from_ticks(1);
923        assert_eq!(diff, Instant::<u32, 1, 1_000>::from_ticks(9));
924
925        // Instant +- Duration, Different base
926        let sum: Instant<u32, 1, 10_000> = Instant::<u32, 1, 10_000>::from_ticks(10)
927            + Duration::<u32, 1, 1_000>::from_ticks(1).convert();
928        assert_eq!(sum, Instant::<u32, 1, 10_000>::from_ticks(20));
929
930        let mut sum = Instant::<u32, 1, 10_000>::from_ticks(10);
931        sum += Duration::<u32, 1, 1_000>::from_ticks(1).convert();
932        assert_eq!(sum, Instant::<u32, 1, 10_000>::from_ticks(20));
933
934        let diff: Instant<u32, 1, 10_000> = Instant::<u32, 1, 10_000>::from_ticks(10)
935            - Duration::<u32, 1, 1_000>::from_ticks(1).convert();
936        assert_eq!(diff, Instant::<u32, 1, 10_000>::from_ticks(0));
937
938        let mut diff = Instant::<u32, 1, 10_000>::from_ticks(10);
939        diff -= Duration::<u32, 1, 1_000>::from_ticks(1).convert();
940        assert_eq!(diff, Instant::<u32, 1, 10_000>::from_ticks(0));
941
942        // Instant + Extension trait
943        let sum: Instant<u32, 1, 10_000> = Instant::<u32, 1, 10_000>::from_ticks(10) + 1.millis();
944        assert_eq!(sum, Instant::<u32, 1, 10_000>::from_ticks(20));
945
946        // Instant - Extension trait
947        let diff: Instant<u32, 1, 10_000> = Instant::<u32, 1, 10_000>::from_ticks(10) - 1.millis();
948        assert_eq!(diff, Instant::<u32, 1, 10_000>::from_ticks(0));
949    }
950
951    #[test]
952    fn instant_duration_math_u64() {
953        use crate::ExtU64;
954
955        // Instant - Instant, Same base
956        let diff: Duration<u64, 1, 1_000> =
957            Instant::<u64, 1, 1_000>::from_ticks(10) - Instant::<u64, 1, 1_000>::from_ticks(1);
958        assert_eq!(diff, Duration::<u64, 1, 1_000>::from_ticks(9));
959
960        // Instant +- Duration, Same base
961        let sum: Instant<u64, 1, 1_000> =
962            Instant::<u64, 1, 1_000>::from_ticks(10) + Duration::<u64, 1, 1_000>::from_ticks(1);
963        assert_eq!(sum, Instant::<u64, 1, 1_000>::from_ticks(11));
964
965        let mut sum = Instant::<u64, 1, 1_000>::from_ticks(10);
966        sum += Duration::<u64, 1, 1_000>::from_ticks(1);
967        assert_eq!(sum, Instant::<u64, 1, 1_000>::from_ticks(11));
968
969        let diff: Instant<u64, 1, 1_000> =
970            Instant::<u64, 1, 1_000>::from_ticks(10) - Duration::<u64, 1, 1_000>::from_ticks(1);
971        assert_eq!(diff, Instant::<u64, 1, 1_000>::from_ticks(9));
972
973        let mut diff = Instant::<u64, 1, 1_000>::from_ticks(10);
974        diff -= Duration::<u64, 1, 1_000>::from_ticks(1);
975        assert_eq!(diff, Instant::<u64, 1, 1_000>::from_ticks(9));
976
977        // Instant +- Duration, Different base
978        let sum: Instant<u64, 1, 10_000> = Instant::<u64, 1, 10_000>::from_ticks(10)
979            + Duration::<u64, 1, 1_000>::from_ticks(1).convert();
980        assert_eq!(sum, Instant::<u64, 1, 10_000>::from_ticks(20));
981
982        let mut sum = Instant::<u64, 1, 10_000>::from_ticks(10);
983        sum += Duration::<u64, 1, 1_000>::from_ticks(1).convert();
984        assert_eq!(sum, Instant::<u64, 1, 10_000>::from_ticks(20));
985
986        let diff: Instant<u64, 1, 10_000> = Instant::<u64, 1, 10_000>::from_ticks(10)
987            - Duration::<u64, 1, 1_000>::from_ticks(1).convert();
988        assert_eq!(diff, Instant::<u64, 1, 10_000>::from_ticks(0));
989
990        let mut diff = Instant::<u64, 1, 10_000>::from_ticks(10);
991        diff -= Duration::<u64, 1, 1_000>::from_ticks(1).convert();
992        assert_eq!(diff, Instant::<u64, 1, 10_000>::from_ticks(0));
993
994        // Instant + Extension trait
995        let sum: Instant<u64, 1, 10_000> = Instant::<u64, 1, 10_000>::from_ticks(10) + 1.millis();
996        assert_eq!(sum, Instant::<u64, 1, 10_000>::from_ticks(20));
997
998        // Instant - Extension trait
999        let diff: Instant<u64, 1, 10_000> = Instant::<u64, 1, 10_000>::from_ticks(10) - 1.millis();
1000        assert_eq!(diff, Instant::<u64, 1, 10_000>::from_ticks(0));
1001    }
1002
1003    #[test]
1004    fn instant_duration_math_u64_u32() {
1005        // Instant +- Duration, Same base
1006        let sum: Instant<u64, 1, 1_000> =
1007            Instant::<u64, 1, 1_000>::from_ticks(10) + Duration::<u32, 1, 1_000>::from_ticks(1);
1008        assert_eq!(sum, Instant::<u64, 1, 1_000>::from_ticks(11));
1009
1010        let mut sum = Instant::<u64, 1, 1_000>::from_ticks(10);
1011        sum += Duration::<u32, 1, 1_000>::from_ticks(1);
1012        assert_eq!(sum, Instant::<u64, 1, 1_000>::from_ticks(11));
1013
1014        let diff: Instant<u64, 1, 1_000> =
1015            Instant::<u64, 1, 1_000>::from_ticks(10) - Duration::<u32, 1, 1_000>::from_ticks(1);
1016        assert_eq!(diff, Instant::<u64, 1, 1_000>::from_ticks(9));
1017
1018        let mut diff = Instant::<u64, 1, 1_000>::from_ticks(10);
1019        diff -= Duration::<u32, 1, 1_000>::from_ticks(1);
1020        assert_eq!(diff, Instant::<u64, 1, 1_000>::from_ticks(9));
1021
1022        // Instant +- Duration, Different base
1023        let sum: Instant<u64, 1, 10_000> = Instant::<u64, 1, 10_000>::from_ticks(10)
1024            + Duration::<u32, 1, 1_000>::from_ticks(1).convert();
1025        assert_eq!(sum, Instant::<u64, 1, 10_000>::from_ticks(20));
1026
1027        let mut sum = Instant::<u64, 1, 10_000>::from_ticks(10);
1028        sum += Duration::<u32, 1, 1_000>::from_ticks(1).convert();
1029        assert_eq!(sum, Instant::<u64, 1, 10_000>::from_ticks(20));
1030
1031        let diff: Instant<u64, 1, 10_000> = Instant::<u64, 1, 10_000>::from_ticks(10)
1032            - Duration::<u32, 1, 1_000>::from_ticks(1).convert();
1033        assert_eq!(diff, Instant::<u64, 1, 10_000>::from_ticks(0));
1034
1035        let mut diff = Instant::<u64, 1, 10_000>::from_ticks(10);
1036        diff -= Duration::<u32, 1, 1_000>::from_ticks(1).convert();
1037        assert_eq!(diff, Instant::<u64, 1, 10_000>::from_ticks(0));
1038    }
1039
1040    ////////////////////////////////////////////////////////////////////////////////
1041    //
1042    // Rate tests
1043    //
1044    ////////////////////////////////////////////////////////////////////////////////
1045
1046    fn take_khz(r: Rate<u32, 1_000, 1>) -> Rate<u32, 1_000, 1> {
1047        r
1048    }
1049
1050    #[test]
1051    fn rate_functions() {
1052        assert_eq!(
1053            take_khz(Rate::<u32, 10_000, 1>::from_raw(1).convert()),
1054            Rate::<u32, 1_000, 1>::from_raw(10)
1055        );
1056    }
1057
1058    #[test]
1059    fn rate_compare_u32() {
1060        // Same fraction
1061        assert!(Rate::<u32, 1_000, 1>::from_raw(2) > Rate::<u32, 1_000, 1>::from_raw(1));
1062        assert!(Rate::<u32, 1_000, 1>::from_raw(2) >= Rate::<u32, 1_000, 1>::from_raw(1));
1063        assert!(Rate::<u32, 1_000, 1>::from_raw(1) >= Rate::<u32, 1_000, 1>::from_raw(1));
1064        assert!(Rate::<u32, 1_000, 1>::from_raw(1) < Rate::<u32, 1_000, 1>::from_raw(2));
1065        assert!(Rate::<u32, 1_000, 1>::from_raw(1) <= Rate::<u32, 1_000, 1>::from_raw(1));
1066        assert!(Rate::<u32, 1_000, 1>::from_raw(1) <= Rate::<u32, 1_000, 1>::from_raw(2));
1067        assert!(Rate::<u32, 1_000, 1>::from_raw(1) == Rate::<u32, 1_000, 1>::from_raw(1));
1068        assert!(Rate::<u32, 1_000, 1>::from_raw(1) != Rate::<u32, 1_000, 1>::from_raw(2));
1069
1070        // Different fraction
1071        assert!(Rate::<u32, 1_000, 1>::from_raw(11) > Rate::<u32, 10_000, 1>::from_raw(1));
1072        assert!(Rate::<u32, 1_000, 1>::from_raw(11) >= Rate::<u32, 10_000, 1>::from_raw(1));
1073        assert!(Rate::<u32, 1_000, 1>::from_raw(10) >= Rate::<u32, 10_000, 1>::from_raw(1));
1074        assert!(Rate::<u32, 1_000, 1>::from_raw(11) < Rate::<u32, 10_000, 1>::from_raw(2));
1075        assert!(Rate::<u32, 1_000, 1>::from_raw(1) <= Rate::<u32, 10_000, 1>::from_raw(1));
1076        assert!(Rate::<u32, 1_000, 1>::from_raw(10) <= Rate::<u32, 10_000, 1>::from_raw(1));
1077        assert!(Rate::<u32, 1_000, 1>::from_raw(10) == Rate::<u32, 10_000, 1>::from_raw(1));
1078        assert!(Rate::<u32, 1_000, 1>::from_raw(9) != Rate::<u32, 10_000, 1>::from_raw(2));
1079    }
1080
1081    #[test]
1082    fn rate_compare_u64() {
1083        // Same fraction
1084        assert!(Rate::<u64, 1_000, 1>::from_raw(2) > Rate::<u64, 1_000, 1>::from_raw(1));
1085        assert!(Rate::<u64, 1_000, 1>::from_raw(2) >= Rate::<u64, 1_000, 1>::from_raw(1));
1086        assert!(Rate::<u64, 1_000, 1>::from_raw(1) >= Rate::<u64, 1_000, 1>::from_raw(1));
1087        assert!(Rate::<u64, 1_000, 1>::from_raw(1) < Rate::<u64, 1_000, 1>::from_raw(2));
1088        assert!(Rate::<u64, 1_000, 1>::from_raw(1) <= Rate::<u64, 1_000, 1>::from_raw(1));
1089        assert!(Rate::<u64, 1_000, 1>::from_raw(1) <= Rate::<u64, 1_000, 1>::from_raw(2));
1090        assert!(Rate::<u64, 1_000, 1>::from_raw(1) == Rate::<u64, 1_000, 1>::from_raw(1));
1091        assert!(Rate::<u64, 1_000, 1>::from_raw(1) != Rate::<u64, 1_000, 1>::from_raw(2));
1092
1093        // Different fraction
1094        assert!(Rate::<u64, 1_000, 1>::from_raw(11) > Rate::<u64, 10_000, 1>::from_raw(1));
1095        assert!(Rate::<u64, 1_000, 1>::from_raw(11) >= Rate::<u64, 10_000, 1>::from_raw(1));
1096        assert!(Rate::<u64, 1_000, 1>::from_raw(10) >= Rate::<u64, 10_000, 1>::from_raw(1));
1097        assert!(Rate::<u64, 1_000, 1>::from_raw(11) < Rate::<u64, 10_000, 1>::from_raw(2));
1098        assert!(Rate::<u64, 1_000, 1>::from_raw(1) <= Rate::<u64, 10_000, 1>::from_raw(1));
1099        assert!(Rate::<u64, 1_000, 1>::from_raw(10) <= Rate::<u64, 10_000, 1>::from_raw(1));
1100        assert!(Rate::<u64, 1_000, 1>::from_raw(10) == Rate::<u64, 10_000, 1>::from_raw(1));
1101        assert!(Rate::<u64, 1_000, 1>::from_raw(9) != Rate::<u64, 10_000, 1>::from_raw(2));
1102    }
1103
1104    #[test]
1105    fn rate_compare_u64_u32() {
1106        // Same fraction
1107        assert!(Rate::<u64, 1_000, 1>::from_raw(2) > Rate::<u32, 1_000, 1>::from_raw(1));
1108        assert!(Rate::<u64, 1_000, 1>::from_raw(2) >= Rate::<u32, 1_000, 1>::from_raw(1));
1109        assert!(Rate::<u64, 1_000, 1>::from_raw(1) >= Rate::<u32, 1_000, 1>::from_raw(1));
1110        assert!(Rate::<u64, 1_000, 1>::from_raw(1) < Rate::<u32, 1_000, 1>::from_raw(2));
1111        assert!(Rate::<u64, 1_000, 1>::from_raw(1) <= Rate::<u32, 1_000, 1>::from_raw(1));
1112        assert!(Rate::<u64, 1_000, 1>::from_raw(1) <= Rate::<u32, 1_000, 1>::from_raw(2));
1113        assert!(Rate::<u64, 1_000, 1>::from_raw(1) == Rate::<u32, 1_000, 1>::from_raw(1));
1114        assert!(Rate::<u64, 1_000, 1>::from_raw(1) != Rate::<u32, 1_000, 1>::from_raw(2));
1115
1116        // Different fraction
1117        assert!(Rate::<u64, 1_000, 1>::from_raw(11) > Rate::<u32, 10_000, 1>::from_raw(1));
1118        assert!(Rate::<u64, 1_000, 1>::from_raw(11) >= Rate::<u32, 10_000, 1>::from_raw(1));
1119        assert!(Rate::<u64, 1_000, 1>::from_raw(10) >= Rate::<u32, 10_000, 1>::from_raw(1));
1120        assert!(Rate::<u64, 1_000, 1>::from_raw(11) < Rate::<u32, 10_000, 1>::from_raw(2));
1121        assert!(Rate::<u64, 1_000, 1>::from_raw(1) <= Rate::<u32, 10_000, 1>::from_raw(1));
1122        assert!(Rate::<u64, 1_000, 1>::from_raw(10) <= Rate::<u32, 10_000, 1>::from_raw(1));
1123        assert!(Rate::<u64, 1_000, 1>::from_raw(10) == Rate::<u32, 10_000, 1>::from_raw(1));
1124        assert!(Rate::<u64, 1_000, 1>::from_raw(9) != Rate::<u32, 10_000, 1>::from_raw(2));
1125    }
1126
1127    #[test]
1128    fn rate_compare_u32_u64() {
1129        // Same fraction
1130        assert!(Rate::<u32, 1_000, 1>::from_raw(2) > Rate::<u64, 1_000, 1>::from_raw(1));
1131        assert!(Rate::<u32, 1_000, 1>::from_raw(2) >= Rate::<u64, 1_000, 1>::from_raw(1));
1132        assert!(Rate::<u32, 1_000, 1>::from_raw(1) >= Rate::<u64, 1_000, 1>::from_raw(1));
1133        assert!(Rate::<u32, 1_000, 1>::from_raw(1) < Rate::<u64, 1_000, 1>::from_raw(2));
1134        assert!(Rate::<u32, 1_000, 1>::from_raw(1) <= Rate::<u64, 1_000, 1>::from_raw(1));
1135        assert!(Rate::<u32, 1_000, 1>::from_raw(1) <= Rate::<u64, 1_000, 1>::from_raw(2));
1136        assert!(Rate::<u32, 1_000, 1>::from_raw(1) == Rate::<u64, 1_000, 1>::from_raw(1));
1137        assert!(Rate::<u32, 1_000, 1>::from_raw(1) != Rate::<u64, 1_000, 1>::from_raw(2));
1138
1139        // Different fraction
1140        assert!(Rate::<u32, 1_000, 1>::from_raw(11) > Rate::<u64, 10_000, 1>::from_raw(1));
1141        assert!(Rate::<u32, 1_000, 1>::from_raw(11) >= Rate::<u64, 10_000, 1>::from_raw(1));
1142        assert!(Rate::<u32, 1_000, 1>::from_raw(10) >= Rate::<u64, 10_000, 1>::from_raw(1));
1143        assert!(Rate::<u32, 1_000, 1>::from_raw(11) < Rate::<u64, 10_000, 1>::from_raw(2));
1144        assert!(Rate::<u32, 1_000, 1>::from_raw(1) <= Rate::<u64, 10_000, 1>::from_raw(1));
1145        assert!(Rate::<u32, 1_000, 1>::from_raw(10) <= Rate::<u64, 10_000, 1>::from_raw(1));
1146        assert!(Rate::<u32, 1_000, 1>::from_raw(10) == Rate::<u64, 10_000, 1>::from_raw(1));
1147        assert!(Rate::<u32, 1_000, 1>::from_raw(9) != Rate::<u64, 10_000, 1>::from_raw(2));
1148    }
1149
1150    #[test]
1151    fn rate_rate_math_u32() {
1152        use crate::RateExtU32;
1153
1154        // Same base
1155        let sum: Rate<u32, 1_000, 1> =
1156            Rate::<u32, 1_000, 1>::from_raw(10) + Rate::<u32, 1_000, 1>::from_raw(1);
1157        assert_eq!(sum, Rate::<u32, 1_000, 1>::from_raw(11));
1158
1159        let diff: Rate<u32, 1_000, 1> =
1160            Rate::<u32, 1_000, 1>::from_raw(10) - Rate::<u32, 1_000, 1>::from_raw(1);
1161        assert_eq!(diff, Rate::<u32, 1_000, 1>::from_raw(9));
1162
1163        // Different base
1164        let sum: Rate<u32, 10_000, 1> =
1165            Rate::<u32, 10_000, 1>::from_raw(10) + Rate::<u32, 1_000, 1>::from_raw(10).convert();
1166        assert_eq!(sum, Rate::<u32, 10_000, 1>::from_raw(11));
1167
1168        let diff: Rate<u32, 10_000, 1> =
1169            Rate::<u32, 10_000, 1>::from_raw(10) - Rate::<u32, 1_000, 1>::from_raw(10).convert();
1170        assert_eq!(diff, Rate::<u32, 10_000, 1>::from_raw(9));
1171
1172        // Short hand vs u32 (should not need `.into()`)
1173        let sum = Rate::<u32, 1_000, 1>::from_raw(1) + 1.MHz();
1174        assert_eq!(sum, Rate::<u32, 1_000, 1>::from_raw(1001));
1175
1176        assert_eq!(
1177            Rate::<u32, 1_000, 1>::from_raw(5) / Rate::<u32, 100, 1>::from_raw(2),
1178            25
1179        );
1180
1181        assert_eq!(
1182            Rate::<u32, 100, 1>::from_raw(2) / Rate::<u32, 1_000, 1>::from_raw(5),
1183            0
1184        );
1185
1186        assert_eq!(
1187            Rate::<u32, 100, 1>::from_raw(500) / Rate::<u32, 1_000, 1>::from_raw(5),
1188            10
1189        );
1190    }
1191
1192    #[test]
1193    fn rate_rate_math_u64() {
1194        use crate::RateExtU64;
1195
1196        // Same base
1197        let sum: Rate<u64, 1_000, 1> =
1198            Rate::<u64, 1_000, 1>::from_raw(10) + Rate::<u64, 1_000, 1>::from_raw(1);
1199        assert_eq!(sum, Rate::<u64, 1_000, 1>::from_raw(11));
1200
1201        let diff: Rate<u64, 1_000, 1> =
1202            Rate::<u64, 1_000, 1>::from_raw(10) - Rate::<u64, 1_000, 1>::from_raw(1);
1203        assert_eq!(diff, Rate::<u64, 1_000, 1>::from_raw(9));
1204
1205        // Different base
1206        let sum: Rate<u64, 10_000, 1> =
1207            Rate::<u64, 10_000, 1>::from_raw(10) + Rate::<u64, 1_000, 1>::from_raw(10).convert();
1208        assert_eq!(sum, Rate::<u64, 10_000, 1>::from_raw(11));
1209
1210        let diff: Rate<u64, 10_000, 1> =
1211            Rate::<u64, 10_000, 1>::from_raw(10) - Rate::<u64, 1_000, 1>::from_raw(10).convert();
1212        assert_eq!(diff, Rate::<u64, 10_000, 1>::from_raw(9));
1213
1214        // Short hand vs u64 (should not need `.into()`)
1215        let sum = Rate::<u64, 1_000, 1>::from_raw(1) + 1.MHz();
1216        assert_eq!(sum, Rate::<u64, 1_000, 1>::from_raw(1001));
1217
1218        assert_eq!(
1219            Rate::<u64, 1_000, 1>::from_raw(5) / Rate::<u64, 100, 1>::from_raw(2),
1220            25
1221        );
1222
1223        assert_eq!(
1224            Rate::<u64, 100, 1>::from_raw(2) / Rate::<u64, 1_000, 1>::from_raw(5),
1225            0
1226        );
1227
1228        assert_eq!(
1229            Rate::<u64, 100, 1>::from_raw(500) / Rate::<u64, 1_000, 1>::from_raw(5),
1230            10
1231        );
1232    }
1233
1234    #[test]
1235    fn rate_rate_math_u64_u32() {
1236        // Same base
1237        let sum: Rate<u64, 1_000, 1> =
1238            Rate::<u64, 1_000, 1>::from_raw(10) + Rate::<u32, 1_000, 1>::from_raw(1);
1239        assert_eq!(sum, Rate::<u64, 1_000, 1>::from_raw(11));
1240
1241        let diff: Rate<u64, 1_000, 1> =
1242            Rate::<u64, 1_000, 1>::from_raw(10) - Rate::<u32, 1_000, 1>::from_raw(1);
1243        assert_eq!(diff, Rate::<u64, 1_000, 1>::from_raw(9));
1244
1245        // Different base
1246        let sum: Rate<u64, 10_000, 1> =
1247            Rate::<u64, 10_000, 1>::from_raw(10) + Rate::<u32, 1_000, 1>::from_raw(10).convert();
1248        assert_eq!(sum, Rate::<u64, 10_000, 1>::from_raw(11));
1249
1250        let diff: Rate<u64, 10_000, 1> =
1251            Rate::<u64, 10_000, 1>::from_raw(10) - Rate::<u32, 1_000, 1>::from_raw(10).convert();
1252        assert_eq!(diff, Rate::<u64, 10_000, 1>::from_raw(9));
1253    }
1254
1255    #[test]
1256    fn rate_shorthands_u32() {
1257        use crate::RateExtU32;
1258
1259        let r: Rate<u32, 1, 1> = 1.Hz();
1260        assert_eq!(r.raw(), 1);
1261
1262        let r: Rate<u32, 1, 1> = 1.kHz();
1263        assert_eq!(r.raw(), 1_000);
1264
1265        let r: Rate<u32, 1, 1> = 1.MHz();
1266        assert_eq!(r.raw(), 1_000_000);
1267
1268        let r = Rate::<u32, 1, 1>::kHz(20);
1269        assert_eq!(r.raw(), 20_000);
1270
1271        let r = Rate::<u32, 1, 1>::micros(50);
1272        assert_eq!(r.raw(), 20_000);
1273    }
1274
1275    #[test]
1276    fn rate_shorthands_u64() {
1277        use crate::RateExtU64;
1278
1279        let r: Rate<u64, 1, 1> = 1.Hz();
1280        assert_eq!(r.raw(), 1);
1281
1282        let r: Rate<u64, 1, 1> = 1.kHz();
1283        assert_eq!(r.raw(), 1_000);
1284
1285        let r: Rate<u64, 1, 1> = 1.MHz();
1286        assert_eq!(r.raw(), 1_000_000);
1287
1288        let r = Rate::<u64, 1, 1>::kHz(20);
1289        assert_eq!(r.raw(), 20_000);
1290
1291        let r = Rate::<u64, 1, 1>::micros(50);
1292        assert_eq!(r.raw(), 20_000);
1293    }
1294
1295    #[test]
1296    fn rate_duration_conversion() {
1297        let r = Rate::<u32, 1_000, 1>::from_raw(1);
1298        let d: Duration<u32, 1, 1_000_000> = r.into_duration();
1299        assert_eq!(d.ticks(), 1_000);
1300        let d2 = Duration::<u32, 1, 1_000_000>::from_rate(r);
1301        assert_eq!(d2.ticks(), 1_000);
1302
1303        let r = Rate::<u64, 1_000, 1>::from_raw(1);
1304        let d: Duration<u64, 1, 1_000_000> = r.into_duration();
1305        assert_eq!(d.ticks(), 1_000);
1306        let d2 = Duration::<u64, 1, 1_000_000>::from_rate(r);
1307        assert_eq!(d2.ticks(), 1_000);
1308    }
1309
1310    #[test]
1311    fn rate_alias() {
1312        assert_eq!(
1313            TimerRate::<u32, 1>::from_raw(1),
1314            TimerRateU32::<1>::from_raw(1)
1315        );
1316        assert_eq!(
1317            TimerRate::<u64, 1>::from_raw(1),
1318            TimerRateU64::<1>::from_raw(1)
1319        );
1320        assert_eq!(Hertz::<u32>::from_raw(1), TimerRateU32::<1>::from_raw(1));
1321        assert_eq!(HertzU32::from_raw(1), TimerRateU32::<1>::from_raw(1));
1322        assert_eq!(HertzU64::from_raw(1), TimerRateU64::<1>::from_raw(1));
1323        assert_eq!(
1324            Kilohertz::<u32>::from_raw(1),
1325            TimerRateU32::<1_000>::from_raw(1)
1326        );
1327        assert_eq!(
1328            KilohertzU32::from_raw(1),
1329            TimerRateU32::<1_000>::from_raw(1)
1330        );
1331        assert_eq!(
1332            KilohertzU64::from_raw(1),
1333            TimerRateU64::<1_000>::from_raw(1)
1334        );
1335        assert_eq!(
1336            Megahertz::<u32>::from_raw(1),
1337            TimerRateU32::<1_000_000>::from_raw(1)
1338        );
1339        assert_eq!(
1340            MegahertzU32::from_raw(1),
1341            TimerRateU32::<1_000_000>::from_raw(1)
1342        );
1343        assert_eq!(
1344            MegahertzU64::from_raw(1),
1345            TimerRateU64::<1_000_000>::from_raw(1)
1346        );
1347    }
1348}