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