use core::{
cmp, fmt,
ops::{Add, AddAssign, Sub, SubAssign},
};
use std::time;
use crate::{Duration, TryFromTimeError, utils::pair_and_then};
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Instant(Option<time::Instant>);
impl Instant {
pub const NONE: Self = Self(None);
#[must_use]
pub fn now() -> Self {
Self(Some(time::Instant::now()))
}
#[must_use]
pub fn duration_since(&self, earlier: Self) -> Duration {
Duration(Some(
pair_and_then(self.0.as_ref(), earlier.0, time::Instant::checked_duration_since)
.unwrap_or_default(),
))
}
#[must_use]
pub fn elapsed(&self) -> Duration {
Self::now() - *self
}
#[inline]
#[must_use]
pub const fn is_some(&self) -> bool {
self.0.is_some()
}
#[inline]
#[must_use]
pub const fn is_none(&self) -> bool {
!self.is_some()
}
#[inline]
#[must_use]
pub const fn into_inner(self) -> Option<time::Instant> {
self.0
}
#[inline]
#[must_use]
pub const fn unwrap_or(self, default: time::Instant) -> time::Instant {
match self.0 {
Some(d) => d,
None => default,
}
}
#[inline]
pub fn unwrap_or_else<F>(self, default: F) -> time::Instant
where
F: FnOnce() -> time::Instant,
{
self.0.unwrap_or_else(default)
}
}
impl PartialEq<time::Instant> for Instant {
fn eq(&self, other: &time::Instant) -> bool {
self.0 == Some(*other)
}
}
impl PartialEq<Instant> for time::Instant {
fn eq(&self, other: &Instant) -> bool {
other.eq(self)
}
}
impl PartialOrd<time::Instant> for Instant {
fn partial_cmp(&self, other: &time::Instant) -> Option<cmp::Ordering> {
self.0.as_ref().and_then(|this| this.partial_cmp(other))
}
}
impl PartialOrd<Instant> for time::Instant {
fn partial_cmp(&self, other: &Instant) -> Option<cmp::Ordering> {
other.0.as_ref().and_then(|other| self.partial_cmp(other))
}
}
impl From<time::Instant> for Instant {
fn from(instant: time::Instant) -> Self {
Self(Some(instant))
}
}
impl From<Option<time::Instant>> for Instant {
fn from(dur: Option<time::Instant>) -> Self {
Self(dur)
}
}
impl TryFrom<Instant> for time::Instant {
type Error = TryFromTimeError;
fn try_from(instant: Instant) -> Result<Self, Self::Error> {
instant.into_inner().ok_or(TryFromTimeError(()))
}
}
impl Add<Duration> for Instant {
type Output = Self;
fn add(self, other: Duration) -> Self::Output {
Self(pair_and_then(self.0.as_ref(), other.0, time::Instant::checked_add))
}
}
impl Add<time::Duration> for Instant {
type Output = Self;
fn add(self, other: time::Duration) -> Self::Output {
Self(self.0.and_then(|this| this.checked_add(other)))
}
}
impl AddAssign<Duration> for Instant {
fn add_assign(&mut self, other: Duration) {
*self = *self + other;
}
}
impl AddAssign<time::Duration> for Instant {
fn add_assign(&mut self, other: time::Duration) {
*self = *self + other;
}
}
impl Sub<Duration> for Instant {
type Output = Self;
fn sub(self, other: Duration) -> Self::Output {
Self(pair_and_then(self.0.as_ref(), other.0, time::Instant::checked_sub))
}
}
impl Sub<time::Duration> for Instant {
type Output = Self;
fn sub(self, other: time::Duration) -> Self::Output {
Self(self.0.and_then(|this| this.checked_sub(other)))
}
}
impl SubAssign<Duration> for Instant {
fn sub_assign(&mut self, other: Duration) {
*self = *self - other;
}
}
impl SubAssign<time::Duration> for Instant {
fn sub_assign(&mut self, other: time::Duration) {
*self = *self - other;
}
}
impl Sub for Instant {
type Output = Duration;
fn sub(self, other: Self) -> Self::Output {
self.duration_since(other)
}
}
impl Sub<time::Instant> for Instant {
type Output = Duration;
fn sub(self, other: time::Instant) -> Self::Output {
self.duration_since(Self::from(other))
}
}
impl fmt::Debug for Instant {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}