Skip to main content

fast_clock/
std_clocks.rs

1use crate::{Clock, DurationCalibration, InherentlyCalibrated, Time};
2use core::cmp::Ordering;
3use std::time::{Duration, Instant, SystemTime};
4
5/// [`Time`] implementation for [`std::time::Instant`].
6///
7/// [`instant_sub`](Time::instant_sub) panics if `a < b` because [`Duration`] cannot
8/// represent negative values. Use [`Time::instant_cmp`] to compare instants.
9pub struct InstantTime;
10impl Time for InstantTime {
11    type Instant = std::time::Instant;
12
13    type Duration = Duration;
14
15    #[inline]
16    fn instant_sub(a: Self::Instant, b: Self::Instant) -> Self::Duration {
17        a.checked_duration_since(b)
18            .expect("instant_sub: a is earlier than b; Duration cannot represent negative values")
19    }
20
21    #[inline]
22    fn duration_sub(a: Self::Duration, b: Self::Duration) -> Self::Duration {
23        a - b
24    }
25
26    #[inline]
27    fn duration_add(a: Self::Duration, b: Self::Duration) -> Self::Duration {
28        a + b
29    }
30
31    #[inline]
32    fn mixed_sub(a: Self::Instant, b: Self::Duration) -> Self::Instant {
33        a - b
34    }
35
36    #[inline]
37    fn mixed_add(a: Self::Instant, b: Self::Duration) -> Self::Instant {
38        a + b
39    }
40
41    #[inline]
42    fn instant_cmp(a: Self::Instant, b: Self::Instant) -> Ordering {
43        a.cmp(&b)
44    }
45}
46
47/// [`Time`] implementation for [`std::time::SystemTime`].
48///
49/// [`instant_sub`](Time::instant_sub) panics if `a < b` because [`Duration`] cannot
50/// represent negative values. Use [`Time::instant_cmp`] to compare instants.
51pub struct SystemTimeTime;
52
53impl Time for SystemTimeTime {
54    type Instant = SystemTime;
55    type Duration = Duration;
56
57    #[inline]
58    fn instant_sub(a: SystemTime, b: SystemTime) -> Duration {
59        a.duration_since(b)
60            .expect("instant_sub: a is earlier than b; Duration cannot represent negative values")
61    }
62
63    #[inline]
64    fn duration_sub(a: Duration, b: Duration) -> Duration {
65        a - b
66    }
67
68    #[inline]
69    fn duration_add(a: Duration, b: Duration) -> Duration {
70        a + b
71    }
72
73    #[inline]
74    fn mixed_sub(a: SystemTime, b: Duration) -> SystemTime {
75        a - b
76    }
77
78    #[inline]
79    fn mixed_add(a: SystemTime, b: Duration) -> SystemTime {
80        a + b
81    }
82
83    #[inline]
84    fn instant_cmp(a: Self::Instant, b: Self::Instant) -> Ordering {
85        a.cmp(&b)
86    }
87}
88
89macro_rules! std_clock {
90    ($(#[$meta:meta])* $Instant:ty, $Clock:ident, $TimeType:ty) => {
91        $(#[$meta])*
92        #[derive(Clone, Copy, Debug)]
93        pub struct $Clock;
94
95        impl Clock for $Clock {
96            type Time = $TimeType;
97            type Calibration = InherentlyCalibrated;
98
99            fn now(&self) -> $Instant {
100                <$Instant>::now()
101            }
102        }
103    };
104}
105
106std_clock!(
107    /// A [`Clock`] that reads [`std::time::Instant::now`].
108    Instant, InstantClock, InstantTime
109);
110std_clock!(
111    /// A [`Clock`] that reads [`std::time::SystemTime::now`].
112    SystemTime, SystemClock, SystemTimeTime
113);
114
115impl DurationCalibration<Duration> for InherentlyCalibrated {
116    #[inline]
117    fn convert_to_ns(&self, d: Duration) -> u64 {
118        d.as_nanos()
119            .try_into()
120            .expect("duration exceeds u64::MAX nanoseconds (~584 years)")
121    }
122
123    #[inline]
124    fn convert_from_ns(&self, ns: u64) -> Duration {
125        Duration::from_nanos(ns)
126    }
127}