use std::sync::Arc;
use web_time::{SystemTime, UNIX_EPOCH};
pub(crate) trait Clock: Send + Sync {
fn now_unix_secs(&self) -> u64;
}
pub(crate) type SharedClock = Arc<dyn Clock>;
pub(crate) struct SystemClock;
impl Clock for SystemClock {
fn now_unix_secs(&self) -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs()
}
}
pub(crate) fn system_clock() -> SharedClock {
static CLOCK: std::sync::LazyLock<SharedClock> =
std::sync::LazyLock::new(|| Arc::new(SystemClock));
CLOCK.clone()
}
#[cfg(test)]
#[derive(Clone)]
pub(crate) struct TestClock(Arc<std::sync::atomic::AtomicU64>);
#[cfg(test)]
impl TestClock {
pub(crate) fn new(now: u64) -> Self {
Self(Arc::new(std::sync::atomic::AtomicU64::new(now)))
}
pub(crate) fn advance(&self, secs: u64) {
self.0.fetch_add(secs, std::sync::atomic::Ordering::SeqCst);
}
pub(crate) fn set(&self, now: u64) {
self.0.store(now, std::sync::atomic::Ordering::SeqCst);
}
pub(crate) fn now(&self) -> u64 {
self.0.load(std::sync::atomic::Ordering::SeqCst)
}
pub(crate) fn shared(&self) -> SharedClock {
Arc::new(self.clone())
}
}
#[cfg(test)]
impl Clock for TestClock {
fn now_unix_secs(&self) -> u64 {
self.now()
}
}