wasmtime_wasi/p2/host/
clocks.rs1use crate::clocks::WasiClocksCtxView;
2use crate::p2::DynPollable;
3use crate::p2::bindings::{
4 clocks::monotonic_clock::{self, Duration as WasiDuration, Instant},
5 clocks::wall_clock::{self, Datetime},
6};
7use cap_std::time::SystemTime;
8use std::time::Duration;
9use wasmtime::component::Resource;
10use wasmtime_wasi_io::poll::{Pollable, subscribe};
11
12impl From<crate::clocks::Datetime> for Datetime {
13 fn from(
14 crate::clocks::Datetime {
15 seconds,
16 nanoseconds,
17 }: crate::clocks::Datetime,
18 ) -> Self {
19 Self {
20 seconds,
21 nanoseconds,
22 }
23 }
24}
25
26impl From<Datetime> for crate::clocks::Datetime {
27 fn from(
28 Datetime {
29 seconds,
30 nanoseconds,
31 }: Datetime,
32 ) -> Self {
33 Self {
34 seconds,
35 nanoseconds,
36 }
37 }
38}
39
40impl TryFrom<SystemTime> for Datetime {
41 type Error = wasmtime::Error;
42
43 fn try_from(time: SystemTime) -> Result<Self, Self::Error> {
44 let time = crate::clocks::Datetime::try_from(time)?;
45 Ok(time.into())
46 }
47}
48
49impl wall_clock::Host for WasiClocksCtxView<'_> {
50 fn now(&mut self) -> anyhow::Result<Datetime> {
51 let now = self.ctx.wall_clock.now();
52 Ok(Datetime {
53 seconds: now.as_secs(),
54 nanoseconds: now.subsec_nanos(),
55 })
56 }
57
58 fn resolution(&mut self) -> anyhow::Result<Datetime> {
59 let res = self.ctx.wall_clock.resolution();
60 Ok(Datetime {
61 seconds: res.as_secs(),
62 nanoseconds: res.subsec_nanos(),
63 })
64 }
65}
66
67fn subscribe_to_duration(
68 table: &mut wasmtime::component::ResourceTable,
69 duration: tokio::time::Duration,
70) -> anyhow::Result<Resource<DynPollable>> {
71 let sleep = if duration.is_zero() {
72 table.push(Deadline::Past)?
73 } else if let Some(deadline) = tokio::time::Instant::now().checked_add(duration) {
74 table.push(Deadline::Instant(deadline))?
78 } else {
79 table.push(Deadline::Never)?
82 };
83 subscribe(table, sleep)
84}
85
86impl monotonic_clock::Host for WasiClocksCtxView<'_> {
87 fn now(&mut self) -> anyhow::Result<Instant> {
88 Ok(self.ctx.monotonic_clock.now())
89 }
90
91 fn resolution(&mut self) -> anyhow::Result<Instant> {
92 Ok(self.ctx.monotonic_clock.resolution())
93 }
94
95 fn subscribe_instant(&mut self, when: Instant) -> anyhow::Result<Resource<DynPollable>> {
96 let clock_now = self.ctx.monotonic_clock.now();
97 let duration = if when > clock_now {
98 Duration::from_nanos(when - clock_now)
99 } else {
100 Duration::from_nanos(0)
101 };
102 subscribe_to_duration(self.table, duration)
103 }
104
105 fn subscribe_duration(
106 &mut self,
107 duration: WasiDuration,
108 ) -> anyhow::Result<Resource<DynPollable>> {
109 subscribe_to_duration(self.table, Duration::from_nanos(duration))
110 }
111}
112
113enum Deadline {
114 Past,
115 Instant(tokio::time::Instant),
116 Never,
117}
118
119#[async_trait::async_trait]
120impl Pollable for Deadline {
121 async fn ready(&mut self) {
122 match self {
123 Deadline::Past => {}
124 Deadline::Instant(instant) => tokio::time::sleep_until(*instant).await,
125 Deadline::Never => std::future::pending().await,
126 }
127 }
128}