deterministic-wasi-ctx 0.1.32

A wasi-common WasiCtx implementation that is fully deterministic
Documentation
use cap_primitives::time::{Duration, Instant, SystemTime};
use wasi_common::clocks::{WasiClocks, WasiMonotonicClock, WasiSystemClock};

// There is no resolution given it's a stubbed clock
const TIMER_RESOLUTION_MS: u64 = 0;

pub fn new_clocks() -> WasiClocks {
    let instant = Instant::from_std(std::time::Instant::now());
    WasiClocks::new()
        .with_system(DeterministicSystemClock::new())
        .with_monotonic(DeterministicMonotonicClock::new(instant))
}

struct DeterministicSystemClock {
    stubbed_time: SystemTime,
}

impl DeterministicSystemClock {
    pub fn new() -> DeterministicSystemClock {
        let stubbed_time = SystemTime::from_std(std::time::UNIX_EPOCH);
        DeterministicSystemClock { stubbed_time }
    }
}

impl WasiSystemClock for DeterministicSystemClock {
    fn resolution(&self) -> Duration {
        Duration::from_millis(TIMER_RESOLUTION_MS)
    }

    fn now(&self, _precision: Duration) -> SystemTime {
        self.stubbed_time
    }
}

// `std::time::Instant` (and `cap_primitives::time::Instant`) are opaque and cannot be constructed from a particular
// datetime. This implementation results in a value of `0` being written into the memory for the Wasm module on each
// invocation of `clock_time_get`.
struct DeterministicMonotonicClock {
    instant: Instant,
}

impl DeterministicMonotonicClock {
    pub fn new(instant: Instant) -> DeterministicMonotonicClock {
        DeterministicMonotonicClock { instant }
    }
}

impl WasiMonotonicClock for DeterministicMonotonicClock {
    fn resolution(&self) -> Duration {
        Duration::from_millis(TIMER_RESOLUTION_MS)
    }

    fn now(&self, _precision: Duration) -> Instant {
        self.instant
    }
}