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