-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
mod.rs
292 lines (287 loc) · 9.96 KB
/
mod.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
//! In-progress implementation of the WebAssembly component model
//!
//! This module is a work-in-progress and currently represents an incomplete and
//! probably buggy implementation of the component model.
#![cfg_attr(nightlydoc, doc(cfg(feature = "component-model")))]
mod component;
mod func;
mod instance;
mod linker;
mod matching;
mod storage;
mod store;
pub mod types;
mod values;
pub use self::component::Component;
pub use self::func::{
ComponentNamedList, ComponentType, Func, Lift, Lower, TypedFunc, WasmList, WasmStr,
};
pub use self::instance::{ExportInstance, Exports, Instance, InstancePre};
pub use self::linker::{Linker, LinkerInstance};
pub use self::types::Type;
pub use self::values::Val;
pub use wasmtime_component_macro::{flags, ComponentType, Lift, Lower};
// These items are expected to be used by an eventual
// `#[derive(ComponentType)]`, they are not part of Wasmtime's API stability
// guarantees
#[doc(hidden)]
pub mod __internal {
pub use super::func::{
format_flags, lower_payload, typecheck_enum, typecheck_flags, typecheck_record,
typecheck_union, typecheck_variant, ComponentVariant, MaybeUninitExt, Memory, MemoryMut,
Options,
};
pub use crate::map_maybe_uninit;
pub use crate::store::StoreOpaque;
pub use anyhow;
#[cfg(feature = "async")]
pub use async_trait::async_trait;
pub use wasmtime_environ;
pub use wasmtime_environ::component::{CanonicalAbiInfo, ComponentTypes, InterfaceType};
}
pub(crate) use self::store::ComponentStoreData;
/// Generate bindings for a WIT package.
///
/// This macro ingests a [WIT package] and will generate all the necessary
/// bindings for instantiating and invoking a particular `world` in the
/// package. A `world` in a WIT package is a description of imports and exports
/// for a component. This provides a higher-level representation of working with
/// a component than the raw [`Instance`] type which must be manually-type-check
/// and manually have its imports provided via the [`Linker`] type.
///
/// The most basic usage of this macro is:
///
/// ```rust,ignore
/// wasmtime::component::bindgen!("my-component");
/// ```
///
/// This will parse your projects WIT package in a `wit` directory adjacent to
/// your crate's `Cargo.toml`. All of the `*.wit` files in that directory are
/// parsed and then the `default world` will be looked up within
/// `my-component.wit`. This world is then used as the basis for generating
/// bindings.
///
/// For example if your project contained:
///
/// ```text,ignore
/// // wit/my-component.wit
///
/// default world hello-world {
/// import name: func() -> string
/// export greet: func()
/// }
/// ```
///
/// Then you can interact with the generated bindings like so:
///
/// ```rust,ignore
/// use anyhow::Result;
/// use wasmtime::component::*;
/// use wasmtime::{Config, Engine, Store};
///
/// bindgen!("my-component");
///
/// struct MyState {
/// name: String,
/// }
///
/// // Imports into the world, like the `name` import for this world, are satisfied
/// // through traits.
/// impl HelloWorldImports for MyState {
/// // Note the `Result` return value here where `Ok` is returned back to
/// // the component and `Err` will raise a trap.
/// fn name(&mut self) -> Result<String> {
/// Ok(self.name.clone())
/// }
/// }
///
/// fn main() -> Result<()> {
/// // Configure an `Engine` and compile the `Component` that is being run for
/// // the application.
/// let mut config = Config::new();
/// config.wasm_component_model(true);
/// let engine = Engine::new(&config)?;
/// let component = Component::from_file(&engine, "./your-component.wasm")?;
///
/// // Instantiation of bindings always happens through a `Linker`.
/// // Configuration of the linker is done through a generated `add_to_linker`
/// // method on the bindings structure.
/// //
/// // Note that the closure provided here is a projection from `T` in
/// // `Store<T>` to `&mut U` where `U` implements the `HelloWorldImports`
/// // trait. In this case the `T`, `MyState`, is stored directly in the
/// // structure so no projection is necessary here.
/// let mut linker = Linker::new(&engine);
/// HelloWorld::add_to_linker(&mut linker, |state: &mut MyState| state)?;
///
/// // As with the core wasm API of Wasmtime instantiation occurs within a
/// // `Store`. The bindings structure contains an `instantiate` method which
/// // takes the store, component, and linker. This returns the `bindings`
/// // structure which is an instance of `HelloWorld` and supports typed access
/// // to the exports of the component.
/// let mut store = Store::new(
/// &engine,
/// MyState {
/// name: "me".to_string(),
/// },
/// );
/// let (bindings, _) = HelloWorld::instantiate(&mut store, &component, &linker)?;
///
/// // Here our `greet` function doesn't take any parameters for the component,
/// // but in the Wasmtime embedding API the first argument is always a `Store`.
/// bindings.greet(&mut store)?;
/// Ok(())
/// }
/// ```
///
/// The function signatures within generated traits and on generated exports
/// match the component-model signatures as specified in the WIT `world` item.
/// Note that WIT also has support for importing and exports interfaces within
/// worlds, which can be bound here as well:
///
/// For example this WIT input
///
/// ```text,ignore
/// // wit/my-component.wit
///
/// interface host {
/// gen-random-integer: func() -> u32
/// sha256: func(bytes: list<u8>) -> string
/// }
///
/// default world hello-world {
/// import host: self.host
///
/// export demo: interface {
/// run: func()
/// }
/// }
/// ```
///
/// Then you can interact with the generated bindings like so:
///
/// ```rust,ignore
/// use anyhow::Result;
/// use wasmtime::component::*;
/// use wasmtime::{Config, Engine, Store};
///
/// bindgen!("my-component");
///
/// struct MyState {
/// // ...
/// }
///
/// // Note that the trait here is per-interface and within a submodule now.
/// impl host::Host for MyState {
/// fn gen_random_integer(&mut self) -> Result<u32> {
/// Ok(rand::thread_rng().gen())
/// }
///
/// fn sha256(&mut self, bytes: Vec<u8>) -> Result<String> {
/// // ...
/// }
/// }
///
/// fn main() -> Result<()> {
/// let mut config = Config::new();
/// config.wasm_component_model(true);
/// let engine = Engine::new(&config)?;
/// let component = Component::from_file(&engine, "./your-component.wasm")?;
///
/// let mut linker = Linker::new(&engine);
/// HelloWorld::add_to_linker(&mut linker, |state: &mut MyState| state)?;
///
/// let mut store = Store::new(
/// &engine,
/// MyState { /* ... */ },
/// );
/// let (bindings, _) = HelloWorld::instantiate(&mut store, &component, &linker)?;
///
/// // Note that the `demo` method returns a `&Demo` through which we can
/// // run the methods on that interface.
/// bindings.demo().run(&mut store)?;
/// Ok(())
/// }
/// ```
///
/// The generated bindings can additionally be explored more fully with `cargo
/// doc` to see what types and traits and such are generated.
///
/// # Syntax
///
/// This procedural macro accepts a few different syntaxes. The primary purpose
/// of this macro is to locate a WIT package, parse it, and then extract a
/// `world` from the parsed package. There are then codegen-specific options to
/// the bindings themselves which can additionally be specified.
///
/// Basic usage of this macro looks like:
///
/// ```rust,ignore
/// // Parse the `wit/` folder adjacent to this crate's `Cargo.toml` and look
/// // for the document `foo`, which must have a `default world` contained
/// // within it.
/// bindgen!("foo");
///
/// // Parse the `wit/` folder adjacent to `Cargo.toml` and look up the document
/// // `foo` and the world named `bar`.
/// bindgen!("foo.bar");
///
/// // Parse the folder `other/wit/folder` adjacent to `Cargo.toml`.
/// bindgen!("foo" in "other/wit/folder");
/// bindgen!("foo.bar" in "other/wit/folder");
///
/// // Parse the file `foo.wit` as a single-file WIT package with no
/// // dependencies.
/// bindgen!("foo" in "foo.wit");
/// ```
///
/// A more configured version of invoking this macro looks like:
///
/// ```rust,ignore
/// bindgen!({
/// world: "foo", // or "foo.bar", same as in `bindgen!("foo")`
///
/// // same as in `bindgen!("foo" in "other/wit/folder")
/// path: "other/wit/folder",
///
/// // Instead of `path` the WIT document can be provided inline if
/// // desired.
/// inline: "
/// default world foo {
/// // ...
/// }
/// ",
///
/// // Add calls to `tracing::span!` before each import or export is called
/// // to log arguments and return values.
/// //
/// // This option defaults to `false`.
/// tracing: true,
///
/// // Imports will be async functions through #[async_trait] and exports
/// // are also invoked as async functions. Requires `Config::async_support`
/// // to be `true`.
/// //
/// // Note that this is only async for the host as the guest will still
/// // appear as if it's invoking blocking functions.
/// //
/// // This option defaults to `false`.
/// async: true,
///
/// // This can be used to translate WIT return values of the form
/// // `result<T, error-type>` into `Result<T, RustErrorType>` in Rust.
/// // The `RustErrorType` structure will have an automatically generated
/// // implementation of `From<ErrorType> for RustErrorType`. The
/// // `RustErrorType` additionally can also represent a trap to
/// // conveniently flatten all errors into one container.
/// //
/// // By default this option is not specified.
/// trappable_error_type: {
/// interface::ErrorType: RustErrorType,
/// },
///
/// });
/// ```
///
/// [WIT package]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md
pub use wasmtime_component_macro::bindgen;