use std::time::SystemTime;
use std::time::Duration;
use std::ops::{Add, AddAssign, Sub, SubAssign};
use std::fmt;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Instant {
secs: u64,
nanos: u32,
}
impl Instant {
pub fn at(secs: u64, nanos: u32) -> Self {
Self { secs, nanos }
}
pub fn now() -> Self {
let since_epoch = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.expect("SystemTime before UNIX epoch?!?");
Self::at(since_epoch.as_secs(), since_epoch.subsec_nanos())
}
pub fn secs(&self) -> u64 {
self.secs
}
pub fn subsec_nanos(&self) -> u32 {
self.nanos
}
pub fn checked_add(&self, duration: Duration) -> Option<Instant> {
let d: Duration = (*self).into();
d.checked_add(duration).map(|x| x.into())
}
pub fn checked_sub(&self, duration: Duration) -> Option<Instant> {
let d: Duration = (*self).into();
d.checked_sub(duration).map(|x| x.into())
}
pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
let d: Duration = (*self).into();
d.checked_sub(earlier.into())
}
pub fn duration_since(&self, earlier: Instant) -> Duration {
self.checked_duration_since(earlier).expect("supplied instant is later than self")
}
pub fn saturating_duration_since(&self, earlier: Instant) -> Duration {
self.checked_duration_since(earlier).unwrap_or(Duration::new(0, 0))
}
pub fn elapsed(&self) -> Duration {
Instant::now() - *self
}
}
impl From<Instant> for Duration {
fn from(i: Instant) -> Duration {
Duration::new(i.secs, i.nanos)
}
}
impl From<Duration> for Instant {
fn from(d: Duration) -> Instant {
Instant::at(d.as_secs(), d.subsec_nanos())
}
}
impl Add<Duration> for Instant {
type Output = Instant;
fn add(self, other: Duration) -> Instant {
self.checked_add(other).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;
fn sub(self, other: Instant) -> Duration {
self.duration_since(other)
}
}
impl fmt::Debug for Instant {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Instant {{ secs: {}, nanos: {} }}", self.secs, self.nanos)
}
}