use crate::{Error, Result};
use std::sync::OnceLock;
use web_time::{Instant, SystemTime, UNIX_EPOCH};
struct WasmClockBase {
base_wall_nanos: u128,
base_instant: Instant,
}
static WASM_CLOCK_BASE: OnceLock<WasmClockBase> = OnceLock::new();
pub fn now_nanos() -> Result<u128> {
let clock_base = WASM_CLOCK_BASE.get_or_init(|| {
let wall_nanos = get_wall_clock_nanos().unwrap_or(0);
WasmClockBase {
base_wall_nanos: wall_nanos,
base_instant: Instant::now(),
}
});
let elapsed = clock_base.base_instant.elapsed();
let elapsed_nanos =
u128::from(elapsed.as_secs()) * 1_000_000_000 + u128::from(elapsed.subsec_nanos());
Ok(clock_base.base_wall_nanos + elapsed_nanos)
}
fn get_wall_clock_nanos() -> Result<u128> {
let duration = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map_err(|_| Error::SystemTimeError)?;
Ok(u128::from(duration.as_secs()) * 1_000_000_000 + u128::from(duration.subsec_nanos()))
}