use std::time::Instant;
pub trait MonotonicClock: Send + Sync {
fn now(&self) -> Instant;
}
#[derive(Clone, Copy, Debug, Default)]
pub struct SystemMonotonicClock;
impl MonotonicClock for SystemMonotonicClock {
fn now(&self) -> Instant {
Instant::now()
}
}
#[cfg(any(test, feature = "test-support"))]
#[derive(Debug)]
pub struct ManualMonotonicClock {
base: Instant,
offset: std::sync::Mutex<std::time::Duration>,
}
#[cfg(any(test, feature = "test-support"))]
impl ManualMonotonicClock {
#[must_use]
pub fn new() -> Self {
Self::starting_at(Instant::now())
}
#[must_use]
pub fn starting_at(base: Instant) -> Self {
Self {
base,
offset: std::sync::Mutex::new(std::time::Duration::ZERO),
}
}
pub fn advance(&self, duration: std::time::Duration) {
if let Ok(mut offset) = self.offset.lock() {
*offset = offset.saturating_add(duration);
}
}
}
#[cfg(any(test, feature = "test-support"))]
impl Default for ManualMonotonicClock {
fn default() -> Self {
Self::new()
}
}
#[cfg(any(test, feature = "test-support"))]
impl MonotonicClock for ManualMonotonicClock {
fn now(&self) -> Instant {
let offset = self
.offset
.lock()
.map_or(std::time::Duration::ZERO, |offset| *offset);
self.base.checked_add(offset).unwrap_or(self.base)
}
}