use std::num::NonZeroU64;
use std::time::Duration;
#[inline]
pub(crate) fn pack_deadline(deadline_ns: u64) -> Option<NonZeroU64> {
NonZeroU64::new(deadline_ns)
}
#[inline]
pub(crate) fn deadline_at(now_ns: u64, ttl: Duration) -> u64 {
now_ns.saturating_add(ttl.as_nanos().min(u128::from(u64::MAX)) as u64)
}
#[inline]
pub(crate) fn remaining_ms(deadline: NonZeroU64, now_ns: u64) -> u64 {
deadline.get().saturating_sub(now_ns) / 1_000_000
}
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
mod source {
use std::sync::OnceLock;
use std::time::Instant;
fn epoch() -> Instant {
static EPOCH: OnceLock<Instant> = OnceLock::new();
*EPOCH.get_or_init(Instant::now)
}
#[inline]
pub(crate) fn now_ns() -> u64 {
Instant::now().saturating_duration_since(epoch()).as_nanos() as u64
}
}
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
mod source {
use std::sync::atomic::{AtomicU64, Ordering};
static MONO_NS: AtomicU64 = AtomicU64::new(0);
#[inline]
pub(crate) fn now_ns() -> u64 {
MONO_NS.load(Ordering::Relaxed)
}
#[inline]
pub fn set_clock_ns(ns: u64) {
MONO_NS.store(ns, Ordering::Relaxed);
}
}
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
mod wall {
use std::sync::atomic::{AtomicU64, Ordering};
static WALL_MS: AtomicU64 = AtomicU64::new(0);
#[inline]
pub(crate) fn now_unix_ms() -> u64 {
WALL_MS.load(Ordering::Relaxed)
}
#[inline]
pub fn set_wall_clock_ms(ms: u64) {
WALL_MS.store(ms, Ordering::Relaxed);
}
}
pub(crate) use source::now_ns;
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
pub use source::set_clock_ns;
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
pub(crate) use wall::now_unix_ms as wall_now_unix_ms;
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
pub use wall::set_wall_clock_ms;