use core::{fmt, ops};
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Instant {
micros: i64,
}
impl Instant {
pub const ZERO: Instant = Instant::from_micros_const(0);
pub fn from_micros<T: Into<i64>>(micros: T) -> Instant {
Instant {
micros: micros.into(),
}
}
pub const fn from_micros_const(micros: i64) -> Instant {
Instant { micros }
}
pub fn from_millis<T: Into<i64>>(millis: T) -> Instant {
Instant {
micros: millis.into() * 1000,
}
}
pub const fn from_millis_const(millis: i64) -> Instant {
Instant {
micros: millis * 1000,
}
}
pub fn from_secs<T: Into<i64>>(secs: T) -> Instant {
Instant {
micros: secs.into() * 1000000,
}
}
#[cfg(feature = "std")]
pub fn now() -> Instant {
Self::from(::std::time::SystemTime::now())
}
pub const fn millis(&self) -> i64 {
self.micros % 1000000 / 1000
}
pub const fn micros(&self) -> i64 {
self.micros % 1000000
}
pub const fn secs(&self) -> i64 {
self.micros / 1000000
}
pub const fn total_millis(&self) -> i64 {
self.micros / 1000
}
pub const fn total_micros(&self) -> i64 {
self.micros
}
}
#[cfg(feature = "std")]
impl From<::std::time::Instant> for Instant {
fn from(other: ::std::time::Instant) -> Instant {
let elapsed = other.elapsed();
Instant::from_micros((elapsed.as_secs() * 1_000000) as i64 + elapsed.subsec_micros() as i64)
}
}
#[cfg(feature = "std")]
impl From<::std::time::SystemTime> for Instant {
fn from(other: ::std::time::SystemTime) -> Instant {
let n = other
.duration_since(::std::time::UNIX_EPOCH)
.expect("start time must not be before the unix epoch");
Self::from_micros(n.as_secs() as i64 * 1000000 + n.subsec_micros() as i64)
}
}
#[cfg(feature = "std")]
impl From<Instant> for ::std::time::SystemTime {
fn from(val: Instant) -> Self {
::std::time::UNIX_EPOCH + ::std::time::Duration::from_micros(val.micros as u64)
}
}
impl fmt::Display for Instant {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}.{:0>3}s", self.secs(), self.millis())
}
}
impl ops::Add<Duration> for Instant {
type Output = Instant;
fn add(self, rhs: Duration) -> Instant {
Instant::from_micros(self.micros + rhs.total_micros() as i64)
}
}
impl ops::AddAssign<Duration> for Instant {
fn add_assign(&mut self, rhs: Duration) {
self.micros += rhs.total_micros() as i64;
}
}
impl ops::Sub<Duration> for Instant {
type Output = Instant;
fn sub(self, rhs: Duration) -> Instant {
Instant::from_micros(self.micros - rhs.total_micros() as i64)
}
}
impl ops::SubAssign<Duration> for Instant {
fn sub_assign(&mut self, rhs: Duration) {
self.micros -= rhs.total_micros() as i64;
}
}
impl ops::Sub<Instant> for Instant {
type Output = Duration;
fn sub(self, rhs: Instant) -> Duration {
Duration::from_micros((self.micros - rhs.micros).unsigned_abs())
}
}
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Duration {
micros: u64,
}
impl Duration {
pub const ZERO: Duration = Duration::from_micros(0);
pub const fn from_micros(micros: u64) -> Duration {
Duration { micros }
}
pub const fn from_millis(millis: u64) -> Duration {
Duration {
micros: millis * 1000,
}
}
pub const fn from_secs(secs: u64) -> Duration {
Duration {
micros: secs * 1000000,
}
}
pub const fn millis(&self) -> u64 {
self.micros / 1000 % 1000
}
pub const fn micros(&self) -> u64 {
self.micros % 1000000
}
pub const fn secs(&self) -> u64 {
self.micros / 1000000
}
pub const fn total_millis(&self) -> u64 {
self.micros / 1000
}
pub const fn total_micros(&self) -> u64 {
self.micros
}
}
impl fmt::Display for Duration {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}.{:03}s", self.secs(), self.millis())
}
}
impl ops::Add<Duration> for Duration {
type Output = Duration;
fn add(self, rhs: Duration) -> Duration {
Duration::from_micros(self.micros + rhs.total_micros())
}
}
impl ops::AddAssign<Duration> for Duration {
fn add_assign(&mut self, rhs: Duration) {
self.micros += rhs.total_micros();
}
}
impl ops::Sub<Duration> for Duration {
type Output = Duration;
fn sub(self, rhs: Duration) -> Duration {
Duration::from_micros(
self.micros
.checked_sub(rhs.total_micros())
.expect("overflow when subtracting durations"),
)
}
}
impl ops::SubAssign<Duration> for Duration {
fn sub_assign(&mut self, rhs: Duration) {
self.micros = self
.micros
.checked_sub(rhs.total_micros())
.expect("overflow when subtracting durations");
}
}
impl ops::Mul<u32> for Duration {
type Output = Duration;
fn mul(self, rhs: u32) -> Duration {
Duration::from_micros(self.micros * rhs as u64)
}
}
impl ops::MulAssign<u32> for Duration {
fn mul_assign(&mut self, rhs: u32) {
self.micros *= rhs as u64;
}
}
impl ops::Div<u32> for Duration {
type Output = Duration;
fn div(self, rhs: u32) -> Duration {
Duration::from_micros(self.micros / rhs as u64)
}
}
impl ops::DivAssign<u32> for Duration {
fn div_assign(&mut self, rhs: u32) {
self.micros /= rhs as u64;
}
}
impl ops::Shl<u32> for Duration {
type Output = Duration;
fn shl(self, rhs: u32) -> Duration {
Duration::from_micros(self.micros << rhs)
}
}
impl ops::ShlAssign<u32> for Duration {
fn shl_assign(&mut self, rhs: u32) {
self.micros <<= rhs;
}
}
impl ops::Shr<u32> for Duration {
type Output = Duration;
fn shr(self, rhs: u32) -> Duration {
Duration::from_micros(self.micros >> rhs)
}
}
impl ops::ShrAssign<u32> for Duration {
fn shr_assign(&mut self, rhs: u32) {
self.micros >>= rhs;
}
}
impl From<::core::time::Duration> for Duration {
fn from(other: ::core::time::Duration) -> Duration {
Duration::from_micros(other.as_secs() * 1000000 + other.subsec_micros() as u64)
}
}
impl From<Duration> for ::core::time::Duration {
fn from(val: Duration) -> Self {
::core::time::Duration::from_micros(val.total_micros())
}
}