use core::ops::Add;
use core::time::Duration;
pub trait InstantLike: Copy {
#[must_use]
fn duration_since(&self, earlier: Self) -> Duration;
}
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Millis(pub u64);
impl InstantLike for Millis {
fn duration_since(&self, earlier: Self) -> Duration {
Duration::from_millis(self.0 - earlier.0)
}
}
impl Add<Duration> for Millis {
type Output = Self;
fn add(self, rhs: Duration) -> Self::Output {
Millis(self.0 + rhs.as_millis() as u64)
}
}
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Micros(pub u64);
impl InstantLike for Micros {
fn duration_since(&self, earlier: Self) -> Duration {
Duration::from_micros(self.0 - earlier.0)
}
}
impl Add<Duration> for Micros {
type Output = Self;
fn add(self, rhs: Duration) -> Self::Output {
Micros(self.0 + rhs.as_micros() as u64)
}
}
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct SecondsF64(pub f64);
impl InstantLike for SecondsF64 {
fn duration_since(&self, earlier: Self) -> Duration {
let secs = self.0 - earlier.0;
if secs < 0.0 {
Duration::from_secs(0) } else {
Duration::from_secs_f64(secs)
}
}
}
impl Add<Duration> for SecondsF64 {
type Output = Self;
fn add(self, rhs: Duration) -> Self::Output {
SecondsF64(self.0 + rhs.as_secs_f64())
}
}
#[test]
fn test_millis() {
let t0 = Millis(1000);
let t1 = t0 + Duration::from_millis(100);
assert_eq!(t1.duration_since(t0), Duration::from_millis(100));
}
#[test]
fn test_micros() {
let t0 = Micros(1000);
let t1 = t0 + Duration::from_micros(100);
assert_eq!(t1.duration_since(t0), Duration::from_micros(100));
}
#[test]
fn test_seconds_f64() {
let t0 = SecondsF64(1.0);
let t1 = t0 + Duration::from_secs_f64(1.0);
assert_eq!(t1.duration_since(t0), Duration::from_secs_f64(1.0));
let t2 = SecondsF64(0.5);
assert_eq!(t2.duration_since(t1), Duration::from_secs_f64(0.0));
}
#[cfg(feature = "std")]
mod std_instant {
use super::{Add, Duration, InstantLike};
#[derive(Debug, Clone, Copy)]
pub struct StdInstant(pub std::time::Instant);
#[cfg(feature = "std")]
impl InstantLike for StdInstant {
fn duration_since(&self, other: Self) -> Duration {
self.0.duration_since(other.0)
}
}
#[cfg(feature = "std")]
impl Add<Duration> for StdInstant {
type Output = Self;
fn add(self, rhs: Duration) -> Self::Output {
StdInstant(self.0 + rhs)
}
}
#[cfg(all(test, feature = "std"))]
#[test]
fn test_std_instant_wrapper() {
let start = std::time::Instant::now();
let end = std::time::Instant::now();
let wrapped_start = StdInstant(start);
let wrapped_end = StdInstant(end);
let result = wrapped_end.duration_since(wrapped_start);
let expected = end.duration_since(start);
assert_eq!(result, expected);
let summed_end = wrapped_start + expected;
let result = summed_end.duration_since(wrapped_start);
assert_eq!(result, expected);
}
}
#[cfg(feature = "std")]
pub use std_instant::StdInstant;