use std::time::Instant as StdInstant;
use crate::{Duration, Instant};
const MIDPOINT: Instant = Instant::from_nanos(1 << 63);
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[derive(Debug, Clone, Copy)]
pub struct HostClock {
origin: StdInstant,
zero: Instant,
source: fn() -> StdInstant,
}
impl HostClock {
#[must_use]
pub fn new(origin: StdInstant) -> Self {
Self {
origin,
zero: Instant::ZERO,
source: StdInstant::now,
}
}
#[must_use]
pub fn centred(origin: StdInstant) -> Self {
Self {
origin,
zero: MIDPOINT,
source: StdInstant::now,
}
}
#[must_use]
pub fn reading(self, now: fn() -> StdInstant) -> Self {
Self {
source: now,
..self
}
}
#[must_use]
pub fn origin(&self) -> StdInstant {
self.origin
}
#[must_use]
pub fn now(&self) -> Instant {
self.instant((self.source)())
}
#[must_use]
pub fn instant(&self, at: StdInstant) -> Instant {
if at >= self.origin {
self.zero + Duration::saturating_from_core(at.duration_since(self.origin))
} else {
self.zero - Duration::saturating_from_core(self.origin.duration_since(at))
}
}
#[must_use]
pub fn to_std(&self, at: Instant) -> Option<StdInstant> {
if at >= self.zero {
let after = at.saturating_duration_since(self.zero);
self.origin
.checked_add(core::time::Duration::from_nanos(after.as_nanos()))
} else {
let before = self.zero.saturating_duration_since(at);
self.origin
.checked_sub(core::time::Duration::from_nanos(before.as_nanos()))
}
}
}