frclib-core 0.2.4

A collection of utilities to be used across the FRC in rust ecosystem
Documentation
use std::{
    ops::{Add, AddAssign, Sub, SubAssign},
    time::Duration,
};

type StdInstant = std::time::Instant;

#[ctor::ctor]
static START_INSTANT: StdInstant = StdInstant::now();

/// A new-type wrapper around [`std::time::Duration`]
/// that can be used as an alternative to [`std::time::Instant`].
///
/// Unlike [`std::time::Instant`], this type is not guaranteed to be monotonic.
/// Can be safely converted to and from [`std::time::Instant`] but is not recommended unless you know what you're doing.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Instant(Duration);

impl Instant {
    /// Returns an instant corresponding to "uptime" of the program.
    #[must_use]
    pub fn now() -> Self {
        Self(super::uptime())
    }

    /// Returns the amount of time elapsed from another instant to this one,
    /// or zero duration if that instant is later than this one.
    #[must_use]
    pub fn duration_since(&self, earlier: Self) -> Duration {
        self.checked_duration_since(earlier).unwrap_or_default()
    }

    /// Returns the amount of time elapsed since this instant.
    #[must_use]
    pub fn elapsed(&self) -> Duration {
        Self::now().duration_since(*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, duration: Duration) -> Option<Self> {
        self.0.checked_add(duration).map(Instant)
    }

    /// 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, duration: Duration) -> Option<Self> {
        self.0.checked_sub(duration).map(Instant)
    }

    /// Returns the amount of time elapsed from another instant to this one, or None if that
    /// instant is later than this one.
    #[must_use]
    pub fn checked_duration_since(&self, earlier: Self) -> Option<Duration> {
        if earlier.0 > self.0 {
            None
        } else {
            Some(self.0 - earlier.0)
        }
    }

    /// Returns the amount of time elapsed from another instant to this one, or zero duration if
    /// that instant is later than this one.
    #[must_use]
    pub fn saturating_duration_since(&self, earlier: Self) -> Duration {
        self.checked_duration_since(earlier).unwrap_or_default()
    }
}

impl Add<Duration> for Instant {
    type Output = Self;

    fn add(self, rhs: Duration) -> Self {
        Self(self.0 + rhs)
    }
}

impl AddAssign<Duration> for Instant {
    fn add_assign(&mut self, rhs: Duration) {
        self.0 += rhs;
    }
}

impl Sub<Duration> for Instant {
    type Output = Self;

    fn sub(self, rhs: Duration) -> Self {
        Self(self.0 - rhs)
    }
}

impl Sub<Self> for Instant {
    type Output = Duration;

    fn sub(self, rhs: Self) -> Duration {
        self.duration_since(rhs)
    }
}

impl SubAssign<Duration> for Instant {
    fn sub_assign(&mut self, rhs: Duration) {
        self.0 -= rhs;
    }
}

impl From<StdInstant> for Instant {
    fn from(instant: StdInstant) -> Self {
        Self(instant.duration_since(*START_INSTANT))
    }
}

impl From<Instant> for StdInstant {
    fn from(instant: Instant) -> Self {
        *START_INSTANT + instant.0
    }
}