Skip to main content

universal_time/
instant.rs

1use core::ops::{Add, Sub};
2use core::time::Duration;
3
4/// Monotonic clock reading.
5#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
6pub struct Instant {
7    ticks: Duration,
8}
9
10impl Instant {
11    /// Creates an `Instant` from monotonic ticks.
12    #[inline]
13    pub const fn from_ticks(ticks: Duration) -> Self {
14        Self { ticks }
15    }
16
17    /// Returns monotonic ticks for this instant.
18    #[inline]
19    pub const fn to_ticks(self) -> Duration {
20        self.ticks
21    }
22
23    /// Returns an instant corresponding to "now".
24    #[inline]
25    pub fn now() -> Self {
26        if let Some(context) = crate::global::global_time_context() {
27            if let Some(now) = context.instant() {
28                return now;
29            }
30        }
31
32        #[cfg(all(
33            feature = "std",
34            not(all(target_family = "wasm", target_os = "unknown"))
35        ))]
36        {
37            Self::from_ticks(std_now_ticks())
38        }
39
40        #[cfg(any(
41            not(feature = "std"),
42            all(feature = "std", all(target_family = "wasm", target_os = "unknown"))
43        ))]
44        {
45            crate::global::panic_missing_instant()
46        }
47    }
48
49    /// Returns the amount of time elapsed since this instant.
50    #[inline]
51    pub fn elapsed(&self) -> Duration {
52        Self::now().duration_since(*self)
53    }
54
55    /// Returns the duration since another instant, saturating at zero.
56    #[inline]
57    pub fn duration_since(&self, earlier: Instant) -> Duration {
58        self.ticks.saturating_sub(earlier.ticks)
59    }
60
61    /// Returns `Some(duration)` if `self` is not earlier than `other`.
62    #[inline]
63    pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
64        self.ticks.checked_sub(earlier.ticks)
65    }
66
67    /// Returns `Some(instant)` if adding the duration does not overflow.
68    #[inline]
69    pub fn checked_add(self, duration: Duration) -> Option<Self> {
70        self.ticks.checked_add(duration).map(Self::from_ticks)
71    }
72
73    /// Returns `Some(instant)` if subtracting the duration does not underflow.
74    #[inline]
75    pub fn checked_sub(self, duration: Duration) -> Option<Self> {
76        self.ticks.checked_sub(duration).map(Self::from_ticks)
77    }
78}
79
80#[cfg(all(
81    feature = "std",
82    not(all(target_family = "wasm", target_os = "unknown"))
83))]
84fn std_now_ticks() -> Duration {
85    use std::sync::OnceLock;
86
87    static START: OnceLock<std::time::Instant> = OnceLock::new();
88
89    START.get_or_init(std::time::Instant::now).elapsed()
90}
91
92impl Add<Duration> for Instant {
93    type Output = Instant;
94
95    fn add(self, other: Duration) -> Instant {
96        self.checked_add(other)
97            .expect("overflow while adding Duration to Instant")
98    }
99}
100
101impl Sub<Duration> for Instant {
102    type Output = Instant;
103
104    fn sub(self, other: Duration) -> Instant {
105        self.checked_sub(other)
106            .expect("underflow while subtracting Duration from Instant")
107    }
108}
109
110impl Sub<Instant> for Instant {
111    type Output = Duration;
112
113    fn sub(self, other: Instant) -> Duration {
114        self.duration_since(other)
115    }
116}