1pub use core::time::Duration;
2
3use core::{
4 cmp::Ordering,
5 ops::{Add, AddAssign, Sub, SubAssign},
6};
7
8#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
15pub struct Instant {
16 ticks: u64,
17}
18
19const TICK_NANOS: u64 = 1;
21
22impl Instant {
23 #[inline]
25 pub fn now() -> Self {
26 Self {
27 ticks: monotonic_ticks(),
28 }
29 }
30
31 #[inline]
33 pub fn elapsed(&self) -> Duration {
34 Self::now().saturating_duration_since(*self)
35 }
36
37 #[inline]
39 pub fn duration_since(&self, earlier: Instant) -> Duration {
40 match self.ticks.cmp(&earlier.ticks) {
41 Ordering::Less => {
42 panic!("stub::time::Instant::duration_since: earlier > self")
43 }
44 _ => ticks_to_duration(self.ticks - earlier.ticks),
45 }
46 }
47
48 #[inline]
50 pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
51 self.ticks.checked_sub(earlier.ticks).map(ticks_to_duration)
52 }
53
54 #[inline]
56 pub fn saturating_duration_since(&self, earlier: Instant) -> Duration {
57 match self.ticks.checked_sub(earlier.ticks) {
58 Some(dt) => ticks_to_duration(dt),
59 None => Duration::from_secs(0),
60 }
61 }
62
63 #[inline]
65 pub fn checked_add(&self, duration: Duration) -> Option<Instant> {
66 let dt = duration_to_ticks(duration)?;
67 self.ticks.checked_add(dt).map(|t| Instant { ticks: t })
68 }
69
70 #[inline]
72 pub fn checked_sub(&self, duration: Duration) -> Option<Instant> {
73 let dt = duration_to_ticks(duration)?;
74 self.ticks.checked_sub(dt).map(|t| Instant { ticks: t })
75 }
76}
77
78impl Ord for Instant {
79 #[inline]
80 fn cmp(&self, other: &Self) -> Ordering {
81 self.ticks.cmp(&other.ticks)
82 }
83}
84
85impl PartialOrd for Instant {
86 #[inline]
87 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
88 Some(self.cmp(other))
89 }
90}
91
92impl Add<Duration> for Instant {
93 type Output = Instant;
94 #[inline]
95 fn add(self, rhs: Duration) -> Instant {
96 self.checked_add(rhs)
97 .expect("stub::time::Instant + Duration overflow")
98 }
99}
100
101impl AddAssign<Duration> for Instant {
102 #[inline]
103 fn add_assign(&mut self, rhs: Duration) {
104 *self = *self + rhs;
105 }
106}
107
108impl Sub<Duration> for Instant {
109 type Output = Instant;
110 #[inline]
111 fn sub(self, rhs: Duration) -> Instant {
112 self.checked_sub(rhs)
113 .expect("stub::time::Instant - Duration underflow")
114 }
115}
116
117impl SubAssign<Duration> for Instant {
118 #[inline]
119 fn sub_assign(&mut self, rhs: Duration) {
120 *self = *self - rhs;
121 }
122}
123
124impl Sub<Instant> for Instant {
125 type Output = Duration;
126 #[inline]
127 fn sub(self, rhs: Instant) -> Duration {
128 self.duration_since(rhs)
129 }
130}
131
132#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
138pub struct SystemTime {
139 since_epoch: Duration,
141}
142
143#[derive(Copy, Clone, Eq, PartialEq, Debug)]
144pub struct SystemTimeError {
145 _priv: (),
146}
147
148impl SystemTimeError {
149 #[inline]
150 pub fn duration(&self) -> Duration {
151 Duration::from_secs(0)
152 }
153}
154
155pub const UNIX_EPOCH: SystemTime = SystemTime {
156 since_epoch: Duration::from_secs(0),
157};
158
159impl SystemTime {
160 #[inline]
161 pub fn now() -> SystemTime {
162 UNIX_EPOCH
164 }
165
166 #[inline]
167 pub fn duration_since(
168 &self,
169 earlier: SystemTime,
170 ) -> Result<Duration, SystemTimeError> {
171 match self.since_epoch.checked_sub(earlier.since_epoch) {
172 Some(d) => Ok(d),
173 None => Err(SystemTimeError { _priv: () }),
174 }
175 }
176
177 #[inline]
178 pub fn elapsed(&self) -> Result<Duration, SystemTimeError> {
179 SystemTime::now().duration_since(*self)
180 }
181
182 #[inline]
183 pub fn checked_add(&self, duration: Duration) -> Option<SystemTime> {
184 self.since_epoch
185 .checked_add(duration)
186 .map(|d| SystemTime { since_epoch: d })
187 }
188
189 #[inline]
190 pub fn checked_sub(&self, duration: Duration) -> Option<SystemTime> {
191 self.since_epoch
192 .checked_sub(duration)
193 .map(|d| SystemTime { since_epoch: d })
194 }
195}
196
197#[inline]
200fn ticks_to_duration(ticks: u64) -> Duration {
201 let nanos = ticks.saturating_mul(TICK_NANOS);
203 Duration::from_nanos(nanos)
204}
205
206#[inline]
207fn duration_to_ticks(d: Duration) -> Option<u64> {
208 let secs = d.as_secs();
209 let sub = d.subsec_nanos() as u64;
210
211 let a = secs.checked_mul(1_000_000_000)?;
213 let total = a.checked_add(sub)?;
214 Some(total / TICK_NANOS)
215}
216
217#[inline]
218fn monotonic_ticks() -> u64 {
219 #[cfg(target_has_atomic = "64")]
222 {
223 use core::sync::atomic::{AtomicU64, Ordering};
224 static COUNTER: AtomicU64 = AtomicU64::new(0);
225 COUNTER.fetch_add(1, Ordering::Relaxed) + 1
227 }
228
229 #[cfg(not(target_has_atomic = "64"))]
230 {
231 0
232 }
233}