Coverage Report

Created: 2025-07-18 06:22

/rust/registry/src/index.crates.io-6f17d22bba15001f/time-0.3.37/src/instant.rs
Line
Count
Source (jump to first uncovered line)
1
//! The [`Instant`] struct and its associated `impl`s.
2
3
#![allow(deprecated)]
4
5
use core::borrow::Borrow;
6
use core::cmp::{Ord, Ordering, PartialEq, PartialOrd};
7
use core::ops::{Add, Sub};
8
use core::time::Duration as StdDuration;
9
use std::time::Instant as StdInstant;
10
11
use crate::internal_macros::{impl_add_assign, impl_sub_assign};
12
use crate::Duration;
13
14
/// A measurement of a monotonically non-decreasing clock. Opaque and useful only with [`Duration`].
15
///
16
/// Instants are always guaranteed to be no less than any previously measured instant when created,
17
/// and are often useful for tasks such as measuring benchmarks or timing how long an operation
18
/// takes.
19
///
20
/// Note, however, that instants are not guaranteed to be **steady**. In other words, each tick of
21
/// the underlying clock may not be the same length (e.g. some seconds may be longer than others).
22
/// An instant may jump forwards or experience time dilation (slow down or speed up), but it will
23
/// never go backwards.
24
///
25
/// Instants are opaque types that can only be compared to one another. There is no method to get
26
/// "the number of seconds" from an instant. Instead, it only allows measuring the duration between
27
/// two instants (or comparing two instants).
28
///
29
/// This implementation allows for operations with signed [`Duration`]s, but is otherwise identical
30
/// to [`std::time::Instant`].
31
#[doc(hidden)]
32
#[deprecated(
33
    since = "0.3.35",
34
    note = "import `std::time::Instant` and `time::ext::InstantExt` instead"
35
)]
36
#[repr(transparent)]
37
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
38
pub struct Instant(pub StdInstant);
39
40
impl Instant {
41
    // region: delegation
42
    /// Returns an `Instant` corresponding to "now".
43
    ///
44
    /// ```rust
45
    /// # #![allow(deprecated)]
46
    /// # use time::Instant;
47
    /// println!("{:?}", Instant::now());
48
    /// ```
49
0
    pub fn now() -> Self {
50
0
        Self(StdInstant::now())
51
0
    }
52
53
    /// Returns the amount of time elapsed since this instant was created. The duration will always
54
    /// be nonnegative if the instant is not synthetically created.
55
    ///
56
    /// ```rust
57
    /// # #![allow(deprecated)]
58
    /// # use time::{Instant, ext::{NumericalStdDuration, NumericalDuration}};
59
    /// # use std::thread;
60
    /// let instant = Instant::now();
61
    /// thread::sleep(1.std_milliseconds());
62
    /// assert!(instant.elapsed() >= 1.milliseconds());
63
    /// ```
64
0
    pub fn elapsed(self) -> Duration {
65
0
        Self::now() - self
66
0
    }
67
    // endregion delegation
68
69
    // region: checked arithmetic
70
    /// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as
71
    /// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
72
    /// otherwise.
73
    ///
74
    /// ```rust
75
    /// # #![allow(deprecated)]
76
    /// # use time::{Instant, ext::NumericalDuration};
77
    /// let now = Instant::now();
78
    /// assert_eq!(now.checked_add(5.seconds()), Some(now + 5.seconds()));
79
    /// assert_eq!(now.checked_add((-5).seconds()), Some(now + (-5).seconds()));
80
    /// ```
81
0
    pub fn checked_add(self, duration: Duration) -> Option<Self> {
82
0
        if duration.is_zero() {
83
0
            Some(self)
84
0
        } else if duration.is_positive() {
85
0
            self.0.checked_add(duration.unsigned_abs()).map(Self)
86
        } else {
87
0
            debug_assert!(duration.is_negative());
88
0
            self.0.checked_sub(duration.unsigned_abs()).map(Self)
89
        }
90
0
    }
91
92
    /// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as
93
    /// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
94
    /// otherwise.
95
    ///
96
    /// ```rust
97
    /// # #![allow(deprecated)]
98
    /// # use time::{Instant, ext::NumericalDuration};
99
    /// let now = Instant::now();
100
    /// assert_eq!(now.checked_sub(5.seconds()), Some(now - 5.seconds()));
101
    /// assert_eq!(now.checked_sub((-5).seconds()), Some(now - (-5).seconds()));
102
    /// ```
103
0
    pub fn checked_sub(self, duration: Duration) -> Option<Self> {
104
0
        if duration.is_zero() {
105
0
            Some(self)
106
0
        } else if duration.is_positive() {
107
0
            self.0.checked_sub(duration.unsigned_abs()).map(Self)
108
        } else {
109
0
            debug_assert!(duration.is_negative());
110
0
            self.0.checked_add(duration.unsigned_abs()).map(Self)
111
        }
112
0
    }
113
    // endregion checked arithmetic
114
115
    /// Obtain the inner [`std::time::Instant`].
116
    ///
117
    /// ```rust
118
    /// # #![allow(deprecated)]
119
    /// # use time::Instant;
120
    /// let now = Instant::now();
121
    /// assert_eq!(now.into_inner(), now.0);
122
    /// ```
123
0
    pub const fn into_inner(self) -> StdInstant {
124
0
        self.0
125
0
    }
126
}
127
128
// region: trait impls
129
impl From<StdInstant> for Instant {
130
0
    fn from(instant: StdInstant) -> Self {
131
0
        Self(instant)
132
0
    }
133
}
134
135
impl From<Instant> for StdInstant {
136
0
    fn from(instant: Instant) -> Self {
137
0
        instant.0
138
0
    }
139
}
140
141
impl Sub for Instant {
142
    type Output = Duration;
143
144
    /// # Panics
145
    ///
146
    /// This may panic if an overflow occurs.
147
0
    fn sub(self, other: Self) -> Self::Output {
148
0
        match self.0.cmp(&other.0) {
149
0
            Ordering::Equal => Duration::ZERO,
150
0
            Ordering::Greater => (self.0 - other.0)
151
0
                .try_into()
152
0
                .expect("overflow converting `std::time::Duration` to `time::Duration`"),
153
0
            Ordering::Less => -Duration::try_from(other.0 - self.0)
154
0
                .expect("overflow converting `std::time::Duration` to `time::Duration`"),
155
        }
156
0
    }
157
}
158
159
impl Sub<StdInstant> for Instant {
160
    type Output = Duration;
161
162
0
    fn sub(self, other: StdInstant) -> Self::Output {
163
0
        self - Self(other)
164
0
    }
165
}
166
167
impl Sub<Instant> for StdInstant {
168
    type Output = Duration;
169
170
0
    fn sub(self, other: Instant) -> Self::Output {
171
0
        Instant(self) - other
172
0
    }
173
}
174
175
impl Add<Duration> for Instant {
176
    type Output = Self;
177
178
    /// # Panics
179
    ///
180
    /// This function may panic if the resulting point in time cannot be represented by the
181
    /// underlying data structure.
182
0
    fn add(self, duration: Duration) -> Self::Output {
183
0
        if duration.is_positive() {
184
0
            Self(self.0 + duration.unsigned_abs())
185
0
        } else if duration.is_negative() {
186
            #[allow(clippy::unchecked_duration_subtraction)]
187
0
            Self(self.0 - duration.unsigned_abs())
188
        } else {
189
0
            debug_assert!(duration.is_zero());
190
0
            self
191
        }
192
0
    }
193
}
194
195
impl Add<Duration> for StdInstant {
196
    type Output = Self;
197
198
0
    fn add(self, duration: Duration) -> Self::Output {
199
0
        (Instant(self) + duration).0
200
0
    }
201
}
202
203
impl Add<StdDuration> for Instant {
204
    type Output = Self;
205
206
0
    fn add(self, duration: StdDuration) -> Self::Output {
207
0
        Self(self.0 + duration)
208
0
    }
209
}
210
211
impl_add_assign!(Instant: Duration, StdDuration);
212
impl_add_assign!(StdInstant: Duration);
213
214
impl Sub<Duration> for Instant {
215
    type Output = Self;
216
217
    /// # Panics
218
    ///
219
    /// This function may panic if the resulting point in time cannot be represented by the
220
    /// underlying data structure.
221
0
    fn sub(self, duration: Duration) -> Self::Output {
222
0
        if duration.is_positive() {
223
            #[allow(clippy::unchecked_duration_subtraction)]
224
0
            Self(self.0 - duration.unsigned_abs())
225
0
        } else if duration.is_negative() {
226
0
            Self(self.0 + duration.unsigned_abs())
227
        } else {
228
0
            debug_assert!(duration.is_zero());
229
0
            self
230
        }
231
0
    }
232
}
233
234
impl Sub<Duration> for StdInstant {
235
    type Output = Self;
236
237
0
    fn sub(self, duration: Duration) -> Self::Output {
238
0
        (Instant(self) - duration).0
239
0
    }
240
}
241
242
impl Sub<StdDuration> for Instant {
243
    type Output = Self;
244
245
    /// # Panics
246
    ///
247
    /// This function may panic if the resulting point in time cannot be represented by the
248
    /// underlying data structure.
249
0
    fn sub(self, duration: StdDuration) -> Self::Output {
250
0
        #[allow(clippy::unchecked_duration_subtraction)]
251
0
        Self(self.0 - duration)
252
0
    }
253
}
254
255
impl_sub_assign!(Instant: Duration, StdDuration);
256
impl_sub_assign!(StdInstant: Duration);
257
258
impl PartialEq<StdInstant> for Instant {
259
0
    fn eq(&self, rhs: &StdInstant) -> bool {
260
0
        self.0.eq(rhs)
261
0
    }
262
}
263
264
impl PartialEq<Instant> for StdInstant {
265
0
    fn eq(&self, rhs: &Instant) -> bool {
266
0
        self.eq(&rhs.0)
267
0
    }
268
}
269
270
impl PartialOrd<StdInstant> for Instant {
271
0
    fn partial_cmp(&self, rhs: &StdInstant) -> Option<Ordering> {
272
0
        self.0.partial_cmp(rhs)
273
0
    }
274
}
275
276
impl PartialOrd<Instant> for StdInstant {
277
0
    fn partial_cmp(&self, rhs: &Instant) -> Option<Ordering> {
278
0
        self.partial_cmp(&rhs.0)
279
0
    }
280
}
281
282
impl AsRef<StdInstant> for Instant {
283
0
    fn as_ref(&self) -> &StdInstant {
284
0
        &self.0
285
0
    }
286
}
287
288
impl Borrow<StdInstant> for Instant {
289
0
    fn borrow(&self) -> &StdInstant {
290
0
        &self.0
291
0
    }
292
}
293
// endregion trait impls