pros_core/
time.rs

1//! Temporal quantification.
2
3use core::{
4    fmt,
5    ops::{Add, AddAssign, Sub, SubAssign},
6    time::Duration,
7};
8
9/// Represents a timestamp on a monotonically nondecreasing clock relative to the
10/// start of the user program.
11///
12/// # Precision
13/// This type has a precision of 1 microsecond, and uses [`pros_sys::micros`] internally.
14#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
15pub struct Instant(u64);
16
17impl Instant {
18    /// Returns an instant corresponding to "now".
19    ///
20    /// # Examples
21    ///
22    /// ```
23    /// use pros::time::Instant;
24    ///
25    /// let now = Instant::now();
26    /// ```
27    pub fn now() -> Self {
28        Self(unsafe { pros_sys::rtos::micros() })
29    }
30
31    /// Returns the amount of time elapsed from another instant to this one,
32    /// or zero duration if that instant is later than this one.
33    ///
34    /// # Examples
35    ///
36    /// ```no_run
37    /// use core::time::Duration;
38    /// use pros::{time::Instant, task::delay};
39    ///
40    /// let now = Instant::now();
41    /// delay(Duration::new(1, 0));
42    /// let new_now = Instant::now();
43    /// println!("{:?}", new_now.duration_since(now));
44    /// println!("{:?}", now.duration_since(new_now)); // 0ns
45    /// ```
46    pub fn duration_since(&self, earlier: Instant) -> Duration {
47        self.checked_duration_since(earlier).unwrap_or_default()
48    }
49
50    /// Returns the amount of time elapsed from another instant to this one,
51    /// or None if that instant is later than this one.
52    ///
53    /// # Examples
54    ///
55    /// ```no_run
56    /// use core::time::Duration;
57    /// use pros::{time::Instant, task::delay};
58    ///
59    /// let now = Instant::now();
60    /// delay(Duration::new(1, 0));
61    /// let new_now = Instant::now();
62    /// println!("{:?}", new_now.checked_duration_since(now));
63    /// println!("{:?}", now.checked_duration_since(new_now)); // None
64    /// ```
65    pub const fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
66        if earlier.0 < self.0 {
67            Some(Duration::from_micros(self.0 - earlier.0))
68        } else {
69            None
70        }
71    }
72
73    /// Returns the amount of time elapsed from another instant to this one,
74    /// or zero duration if that instant is later than this one.
75    ///
76    /// # Examples
77    ///
78    /// ```no_run
79    /// use core::time::Duration;
80    /// use pros::{time::Instant, task::delay};
81    ///
82    /// let instant = Instant::now();
83    /// let three_secs = Duration::from_secs(3);
84    /// delay(three_secs);
85    /// assert!(instant.elapsed() >= three_secs);
86    /// ```
87    pub fn saturating_duration_since(&self, earlier: Instant) -> Duration {
88        self.checked_duration_since(earlier).unwrap_or_default()
89    }
90
91    /// Returns the amount of time elapsed since this instant.
92    ///
93    /// # Examples
94    ///
95    /// ```no_run
96    /// use core::time::Duration;
97    /// use pros::{time::Instant, task::delay};
98    ///
99    /// let instant = Instant::now();
100    /// let three_secs = Duration::from_secs(3);
101    /// delay(three_secs);
102    /// assert!(instant.elapsed() >= three_secs);
103    /// ```
104    pub fn elapsed(&self) -> Duration {
105        Instant::now() - *self
106    }
107
108    /// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as
109    /// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
110    /// otherwise.
111    pub fn checked_add(self, rhs: Duration) -> Option<Instant> {
112        Some(Self(self.0.checked_add(rhs.as_micros().try_into().ok()?)?))
113    }
114
115    /// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as
116    /// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
117    /// otherwise.
118    pub fn checked_sub(self, rhs: Duration) -> Option<Instant> {
119        Some(Self(self.0.checked_sub(rhs.as_micros().try_into().ok()?)?))
120    }
121}
122
123impl Add<Duration> for Instant {
124    type Output = Instant;
125
126    /// # Panics
127    ///
128    /// This function may panic if the resulting point in time cannot be represented by the
129    /// underlying data structure. See [`Instant::checked_add`] for a version without panic.
130    fn add(self, rhs: Duration) -> Self::Output {
131        self.checked_add(rhs)
132            .expect("overflow when adding duration to instant")
133    }
134}
135
136impl AddAssign<Duration> for Instant {
137    fn add_assign(&mut self, other: Duration) {
138        *self = *self + other;
139    }
140}
141
142impl Sub<Duration> for Instant {
143    type Output = Instant;
144
145    fn sub(self, other: Duration) -> Instant {
146        self.checked_sub(other)
147            .expect("overflow when subtracting duration from instant")
148    }
149}
150
151impl SubAssign<Duration> for Instant {
152    fn sub_assign(&mut self, other: Duration) {
153        *self = *self - other;
154    }
155}
156
157impl Sub<Instant> for Instant {
158    type Output = Duration;
159
160    /// Returns the amount of time elapsed from another instant to this one,
161    /// or zero duration if that instant is later than this one.
162    fn sub(self, other: Instant) -> Duration {
163        self.duration_since(other)
164    }
165}
166
167impl fmt::Debug for Instant {
168    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
169        self.0.fmt(f)
170    }
171}