1use crate::{Error, ErrorExt};
2use cap_std::time::{Duration, Instant, SystemTime};
3
4pub enum SystemTimeSpec {
5 SymbolicNow,
6 Absolute(SystemTime),
7}
8
9pub trait WasiSystemClock: Send + Sync {
10 fn resolution(&self) -> Duration;
11 fn now(&self, precision: Duration) -> SystemTime;
12}
13
14pub trait WasiMonotonicClock: Send + Sync {
15 fn resolution(&self) -> Duration;
16 fn now(&self, precision: Duration) -> Instant;
17}
18
19pub struct WasiMonotonicOffsetClock {
20 pub creation_time: cap_std::time::Instant,
21 pub abs_clock: Box<dyn WasiMonotonicClock>,
22}
23
24impl WasiMonotonicOffsetClock {
25 pub fn new(clock: impl 'static + WasiMonotonicClock) -> Self {
26 Self {
27 creation_time: clock.now(clock.resolution()),
28 abs_clock: Box::new(clock),
29 }
30 }
31}
32
33pub struct WasiClocks {
34 pub system: Option<Box<dyn WasiSystemClock>>,
35 pub monotonic: Option<WasiMonotonicOffsetClock>,
36}
37
38impl WasiClocks {
39 pub fn new() -> Self {
40 Self {
41 system: None,
42 monotonic: None,
43 }
44 }
45
46 pub fn with_system(mut self, clock: impl 'static + WasiSystemClock) -> Self {
47 self.system = Some(Box::new(clock));
48 self
49 }
50
51 pub fn with_monotonic(mut self, clock: impl 'static + WasiMonotonicClock) -> Self {
52 self.monotonic = Some(WasiMonotonicOffsetClock::new(clock));
53 self
54 }
55
56 pub fn system(&self) -> Result<&dyn WasiSystemClock, Error> {
57 self.system
58 .as_deref()
59 .ok_or_else(|| Error::badf().context("system clock is not supported"))
60 }
61
62 pub fn monotonic(&self) -> Result<&WasiMonotonicOffsetClock, Error> {
63 self.monotonic
64 .as_ref()
65 .ok_or_else(|| Error::badf().context("monotonic clock is not supported"))
66 }
67}