Skip to main content

wasmtime_wasi/p3/clocks/
mod.rs

1mod host;
2
3use crate::clocks::{WasiClocks, WasiClocksNamed, WasiClocksNamedView, WasiClocksView};
4use crate::p3::Interface;
5use crate::p3::bindings::clocks::{monotonic_clock, system_clock, types};
6use crate::{NamedId, WasiCtxNamedView};
7use wasmtime::component::{Component, Linker};
8
9/// Add all WASI interfaces from this module into the `linker` provided.
10///
11/// This function will add all interfaces implemented by this module to the
12/// [`Linker`], which corresponds to the `wasi:clocks/imports` world supported by
13/// this module.
14///
15/// This is low-level API for advanced use cases,
16/// [`wasmtime_wasi::p3::add_to_linker`](crate::p3::add_to_linker) can be used instead
17/// to add *all* wasip3 interfaces (including the ones from this module) to the `linker`.
18///
19/// # Example
20///
21/// ```
22/// use wasmtime::{Engine, Result, Store, Config};
23/// use wasmtime::component::{Linker, ResourceTable};
24/// use wasmtime_wasi::clocks::{WasiClocksView, WasiClocksCtxView, WasiClocksCtx};
25///
26/// fn main() -> Result<()> {
27///     let mut config = Config::new();
28///     config.wasm_component_model_async(true);
29///     let engine = Engine::new(&config)?;
30///
31///     let mut linker = Linker::<MyState>::new(&engine);
32///     wasmtime_wasi::p3::clocks::add_to_linker(&mut linker)?;
33///     // ... add any further functionality to `linker` if desired ...
34///
35///     let mut store = Store::new(
36///         &engine,
37///         MyState::default(),
38///     );
39///
40///     // ... use `linker` to instantiate within `store` ...
41///
42///     Ok(())
43/// }
44///
45/// #[derive(Default)]
46/// struct MyState {
47///     clocks: WasiClocksCtx,
48///     table: ResourceTable,
49/// }
50///
51/// impl WasiClocksView for MyState {
52///     fn clocks(&mut self) -> WasiClocksCtxView {
53///         WasiClocksCtxView { ctx: &mut self.clocks, table: &mut self.table }
54///     }
55/// }
56/// ```
57pub fn add_to_linker<T>(linker: &mut Linker<T>) -> wasmtime::Result<()>
58where
59    T: WasiClocksView + 'static,
60{
61    types::add_to_linker::<_, WasiClocks>(linker, T::clocks)?;
62    monotonic_clock::add_to_linker::<_, WasiClocks>(linker, T::clocks)?;
63    system_clock::add_to_linker::<_, WasiClocks>(linker, T::clocks)?;
64    Ok(())
65}
66
67/// Convenience function to add `wasi:clocks` interfaces into `linker` for any
68/// named imports of `wasi:clocks` interfaces.
69///
70/// This function is similar to [`add_to_linker`] except that it's specifically
71/// designed to work with named imports of `wasi:clocks` interfaces that
72/// components may have. This requires a [`Component`] parameter to be passed in
73/// when populating the [`Linker`] provided to see what the [`Component`]
74/// actually imports.
75///
76/// Like [`add_to_linker`] this is a bit low level and you may want to possibly
77/// invoke [`wasmtime_wasi::p3::add_named_to_linker`] instead. Alternatively if
78/// this isn't low level enough you can additionally invoke bindgen-generated
79/// `add_to_linker` functions directly from within the
80/// [`named_imports::wasi::clocks`] module.
81///
82/// [`wasmtime_wasi::p3::add_named_to_linker`]: crate::p3::add_named_to_linker
83/// [`named_imports::wasi::clocks`]: crate::p3::bindings::named_imports::wasi::clocks
84///
85/// The `lookup` function provided here is invoked for every named import found
86/// for a particular interface. The [`Interface`] given is what's being bound,
87/// and the `&str` argument is the name that the component imports it as. The
88/// embedder can then decide how it would like to allocate a [`NamedId`] for
89/// this import. If `Ok` is returned then the linker is populated with this
90/// name, and imported functions will pass the [`NamedId`] later to the
91/// implementation of [`WasiClocksNamedView`] on `T` when invoked. If `Err` is
92/// returned then the error will cause this entire function to fail and this
93/// function call will return the same error.
94///
95/// # Example
96///
97/// ```
98/// use std::collections::HashMap;
99/// use wasmtime::component::{Component, Linker, ResourceTable};
100/// use wasmtime::{Engine, Result, Store, Config};
101/// use wasmtime_wasi::NamedId;
102/// use wasmtime_wasi::clocks::{WasiClocksCtx, WasiClocksCtxView, WasiClocksNamedView};
103///
104/// fn main() -> Result<()> {
105///     let engine = Engine::default();
106///     let component = Component::new(&engine, "(component)")?;
107///
108///     let mut linker = Linker::<MyState>::new(&engine);
109///
110///     // ... add default functionality to `linker` as needed ...
111///
112///     // and then additionally fill in any specific named imports `component`
113///     // might have for `wasi:clocks` interfaces.
114///     let mut name_map = HashMap::new();
115///     wasmtime_wasi::p3::clocks::add_named_to_linker(&mut linker, &component, |_i, name| {
116///         let len = name_map.len();
117///         Ok(NamedId(*name_map.entry(name.to_string()).or_insert(len)))
118///     })?;
119///
120///     // Here a `WasiClocksCtx` is allocated per-named-import and will then be
121///     // referred to internally by the [`NamedId`] allocated above. You could
122///     // also use `name_map` to configure each context differently.
123///     let mut my_state = MyState::default();
124///     for _ in 0..name_map.len() {
125///         my_state.contexts.push(WasiClocksCtx::default());
126///     }
127///     let mut store = Store::new(&engine, my_state);
128///     let instance = linker.instantiate(&mut store, &component)?;
129///
130///     // ... work with `instance` ...
131///
132///     Ok(())
133/// }
134///
135/// #[derive(Default)]
136/// struct MyState {
137///     table: ResourceTable,
138///     contexts: Vec<WasiClocksCtx>,
139/// }
140///
141/// impl WasiClocksNamedView for MyState {
142///     fn clocks(&mut self, id: NamedId) -> WasiClocksCtxView<'_> {
143///         WasiClocksCtxView {
144///             ctx: &mut self.contexts[id.0],
145///             table: &mut self.table,
146///         }
147///     }
148/// }
149/// ```
150pub fn add_named_to_linker<T>(
151    linker: &mut Linker<T>,
152    component: &Component,
153    mut lookup: impl FnMut(Interface, &str) -> wasmtime::Result<NamedId>,
154) -> wasmtime::Result<()>
155where
156    T: WasiClocksNamedView + 'static,
157{
158    use crate::p3::bindings::named_imports::wasi::clocks::{monotonic_clock, system_clock};
159    monotonic_clock::add_to_linker::<_, WasiClocksNamed<T>>(
160        linker,
161        component,
162        |name| lookup(Interface::ClocksMonotonicClock, name),
163        |x| WasiCtxNamedView(x),
164    )?;
165    system_clock::add_to_linker::<_, WasiClocksNamed<T>>(
166        linker,
167        component,
168        |name| lookup(Interface::ClocksSystemClock, name),
169        |x| WasiCtxNamedView(x),
170    )?;
171    Ok(())
172}
173
174impl From<crate::clocks::Datetime> for system_clock::Instant {
175    fn from(
176        crate::clocks::Datetime {
177            seconds,
178            nanoseconds,
179        }: crate::clocks::Datetime,
180    ) -> Self {
181        Self {
182            seconds,
183            nanoseconds,
184        }
185    }
186}
187
188impl From<system_clock::Instant> for crate::clocks::Datetime {
189    fn from(
190        system_clock::Instant {
191            seconds,
192            nanoseconds,
193        }: system_clock::Instant,
194    ) -> Self {
195        Self {
196            seconds,
197            nanoseconds,
198        }
199    }
200}