Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/wasi/src/clocks.rs
1691 views
1
use cap_std::time::{Duration, Instant, SystemClock, SystemTime};
2
use cap_std::{AmbientAuthority, ambient_authority};
3
use cap_time_ext::{MonotonicClockExt as _, SystemClockExt as _};
4
use wasmtime::component::{HasData, ResourceTable};
5
6
/// A helper struct which implements [`HasData`] for the `wasi:clocks` APIs.
7
///
8
/// This can be useful when directly calling `add_to_linker` functions directly,
9
/// such as [`wasmtime_wasi::p2::bindings::clocks::monotonic_clock::add_to_linker`] as
10
/// the `D` type parameter. See [`HasData`] for more information about the type
11
/// parameter's purpose.
12
///
13
/// When using this type you can skip the [`WasiClocksView`] trait, for
14
/// example.
15
///
16
/// # Examples
17
///
18
/// ```
19
/// use wasmtime::component::{Linker, ResourceTable};
20
/// use wasmtime::{Engine, Result, Config};
21
/// use wasmtime_wasi::clocks::*;
22
///
23
/// struct MyStoreState {
24
/// table: ResourceTable,
25
/// clocks: WasiClocksCtx,
26
/// }
27
///
28
/// fn main() -> Result<()> {
29
/// let mut config = Config::new();
30
/// config.async_support(true);
31
/// let engine = Engine::new(&config)?;
32
/// let mut linker = Linker::new(&engine);
33
///
34
/// wasmtime_wasi::p2::bindings::clocks::monotonic_clock::add_to_linker::<MyStoreState, WasiClocks>(
35
/// &mut linker,
36
/// |state| WasiClocksCtxView {
37
/// table: &mut state.table,
38
/// ctx: &mut state.clocks,
39
/// },
40
/// )?;
41
/// Ok(())
42
/// }
43
/// ```
44
pub struct WasiClocks;
45
46
impl HasData for WasiClocks {
47
type Data<'a> = WasiClocksCtxView<'a>;
48
}
49
50
pub struct WasiClocksCtx {
51
pub(crate) wall_clock: Box<dyn HostWallClock + Send>,
52
pub(crate) monotonic_clock: Box<dyn HostMonotonicClock + Send>,
53
}
54
55
impl Default for WasiClocksCtx {
56
fn default() -> Self {
57
Self {
58
wall_clock: wall_clock(),
59
monotonic_clock: monotonic_clock(),
60
}
61
}
62
}
63
64
pub trait WasiClocksView: Send {
65
fn clocks(&mut self) -> WasiClocksCtxView<'_>;
66
}
67
68
pub struct WasiClocksCtxView<'a> {
69
pub ctx: &'a mut WasiClocksCtx,
70
pub table: &'a mut ResourceTable,
71
}
72
73
pub trait HostWallClock: Send {
74
fn resolution(&self) -> Duration;
75
fn now(&self) -> Duration;
76
}
77
78
pub trait HostMonotonicClock: Send {
79
fn resolution(&self) -> u64;
80
fn now(&self) -> u64;
81
}
82
83
pub struct WallClock {
84
/// The underlying system clock.
85
clock: cap_std::time::SystemClock,
86
}
87
88
impl Default for WallClock {
89
fn default() -> Self {
90
Self::new(ambient_authority())
91
}
92
}
93
94
impl WallClock {
95
pub fn new(ambient_authority: AmbientAuthority) -> Self {
96
Self {
97
clock: cap_std::time::SystemClock::new(ambient_authority),
98
}
99
}
100
}
101
102
impl HostWallClock for WallClock {
103
fn resolution(&self) -> Duration {
104
self.clock.resolution()
105
}
106
107
fn now(&self) -> Duration {
108
// WASI defines wall clocks to return "Unix time".
109
self.clock
110
.now()
111
.duration_since(SystemClock::UNIX_EPOCH)
112
.unwrap()
113
}
114
}
115
116
pub struct MonotonicClock {
117
/// The underlying system clock.
118
clock: cap_std::time::MonotonicClock,
119
120
/// The `Instant` this clock was created. All returned times are
121
/// durations since that time.
122
initial: Instant,
123
}
124
125
impl Default for MonotonicClock {
126
fn default() -> Self {
127
Self::new(ambient_authority())
128
}
129
}
130
131
impl MonotonicClock {
132
pub fn new(ambient_authority: AmbientAuthority) -> Self {
133
let clock = cap_std::time::MonotonicClock::new(ambient_authority);
134
let initial = clock.now();
135
Self { clock, initial }
136
}
137
}
138
139
impl HostMonotonicClock for MonotonicClock {
140
fn resolution(&self) -> u64 {
141
self.clock.resolution().as_nanos().try_into().unwrap()
142
}
143
144
fn now(&self) -> u64 {
145
// Unwrap here and in `resolution` above; a `u64` is wide enough to
146
// hold over 584 years of nanoseconds.
147
self.clock
148
.now()
149
.duration_since(self.initial)
150
.as_nanos()
151
.try_into()
152
.unwrap()
153
}
154
}
155
156
pub fn monotonic_clock() -> Box<dyn HostMonotonicClock + Send> {
157
Box::new(MonotonicClock::default())
158
}
159
160
pub fn wall_clock() -> Box<dyn HostWallClock + Send> {
161
Box::new(WallClock::default())
162
}
163
164
pub(crate) struct Datetime {
165
pub seconds: u64,
166
pub nanoseconds: u32,
167
}
168
169
impl TryFrom<SystemTime> for Datetime {
170
type Error = wasmtime::Error;
171
172
fn try_from(time: SystemTime) -> Result<Self, Self::Error> {
173
let duration =
174
time.duration_since(SystemTime::from_std(std::time::SystemTime::UNIX_EPOCH))?;
175
176
Ok(Self {
177
seconds: duration.as_secs(),
178
nanoseconds: duration.subsec_nanos(),
179
})
180
}
181
}
182
183