1use std::{
2 cell::RefCell,
3 cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd},
4 ops::{Add, AddAssign, Sub, SubAssign},
5 time::Duration,
6};
7
8use crate::SystemTime;
9
10#[cfg(not(target_arch = "wasm32"))]
11use std::time::Instant as InnerInstant;
12
13#[cfg(target_arch = "wasm32")]
14use wasm_timer::Instant as InnerInstant;
15
16#[derive(Copy, Clone)]
17pub struct Instant {
18 inner: InnerInstant,
19}
20
21impl PartialEq for Instant {
22 fn eq(&self, other: &Instant) -> bool {
23 self.inner == other.inner
24 }
25}
26
27impl Eq for Instant {}
28
29impl PartialOrd for Instant {
30 fn partial_cmp(&self, other: &Instant) -> Option<Ordering> {
31 Some(self.cmp(other))
32 }
33}
34
35impl Ord for Instant {
36 fn cmp(&self, other: &Self) -> Ordering {
37 self.inner.partial_cmp(&other.inner).unwrap()
38 }
39}
40
41thread_local! {
42 static INITIAL_AND_DRIFT: RefCell<Option<(SystemTime, InnerInstant, Duration)>> = const { RefCell::new(None) };
43}
44
45impl Instant {
46 pub fn now() -> Instant {
47 let inner = INITIAL_AND_DRIFT.with_borrow_mut(|initial_and_drift| {
48 let (initial_sys_time, initial_monotonic, drift) = initial_and_drift
49 .get_or_insert_with(|| (SystemTime::now(), InnerInstant::now(), Duration::ZERO));
50
51 let sys_time_passed = SystemTime::now()
52 .duration_since(*initial_sys_time)
53 .unwrap_or_default();
54 let monotonic_now = InnerInstant::now();
55 let monotonic_passed = monotonic_now.duration_since(*initial_monotonic);
56
57 if sys_time_passed > monotonic_passed + *drift {
58 *drift = sys_time_passed - monotonic_passed;
60 }
61
62 monotonic_now + *drift
63 });
64
65 Self { inner }
66 }
67
68 pub fn duration_since(&self, earlier: Instant) -> Duration {
69 *self - earlier
70 }
71
72 pub fn elapsed(&self) -> Duration {
73 Instant::now() - *self
74 }
75
76 pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
77 match self.cmp(&earlier) {
78 Ordering::Less => None,
79 _ => Some(self.duration_since(earlier)),
80 }
81 }
82
83 pub fn saturating_duration_since(&self, earlier: Instant) -> Duration {
84 self.checked_duration_since(earlier).unwrap_or_default()
85 }
86
87 pub fn checked_add(&self, duration: Duration) -> Option<Instant> {
88 Some(*self + duration)
89 }
90
91 pub fn checked_sub(&self, duration: Duration) -> Option<Instant> {
92 Some(*self - duration)
93 }
94}
95
96impl From<InnerInstant> for Instant {
97 fn from(inner: InnerInstant) -> Self {
98 Self { inner }
99 }
100}
101
102impl Add<Duration> for Instant {
103 type Output = Instant;
104
105 fn add(self, other: Duration) -> Instant {
106 Instant {
107 inner: self.inner + other,
108 }
109 }
110}
111
112impl Sub<Duration> for Instant {
113 type Output = Instant;
114
115 fn sub(self, other: Duration) -> Instant {
116 Instant {
117 inner: self.inner - other,
118 }
119 }
120}
121
122impl Sub<Instant> for Instant {
123 type Output = Duration;
124
125 fn sub(self, other: Instant) -> Duration {
126 self.inner - other.inner
127 }
128}
129
130impl AddAssign<Duration> for Instant {
131 fn add_assign(&mut self, other: Duration) {
132 *self = *self + other;
133 }
134}
135
136impl SubAssign<Duration> for Instant {
137 fn sub_assign(&mut self, other: Duration) {
138 *self = *self - other;
139 }
140}
141
142impl std::fmt::Debug for Instant {
143 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
144 self.inner.fmt(f)
145 }
146}