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}