-## Goals
-
-The goal of this crate is to "run wasmtime on the web".
-
-Since wasmtime cannot actually _run_ on the web, the goal is to **provide a unified API** for both sys (desktop) and js (web) runtimes.
-
-## How to use
-
-The provided API is identical to wasmtime's API, so read [wasmtime's documentation](https://docs.wasmtime.dev/) on how to use this crate.
-
-Here is an example of adding three using a WASM module compiled from WAT, using `wasm-bridge` version `0.1.1`:
-```rust
-use wasm_bride::*;
-
-fn add_three(number: i32) -> Result {
- let mut store = Store::<()>::default();
-
- let wat = r#"
- (module
- (func $add_three (export "add_three")
- (param $p0 i32) (result i32)
- (i32.add (local.get $p0) (i32.const 3))
- )
- )
- "#;
- let module = Module::new(store.engine(), wat.as_bytes())?;
-
- let instance = Instance::new(&mut store, &module, &[])?;
- let add_three_wasm = instance.get_typed_func::(&mut store, "add_three")?;
-
- let result = add_three_wasm.call(&mut store, number)?;
- Ok(result)
-}
-```
-
-Alternatively, watch the [video tutorial](https://youtu.be/CqpZjouAOvg):
+## Goals
-[![Youtube video](https://img.youtube.com/vi/CqpZjouAOvg/0.jpg)](https://youtu.be/CqpZjouAOvg)
+The goal of this crate is to "run wasmtime on the web", that means **providing a unified API** for desktop and web runtimes.
-## Using `component-model`
+With `wasm-bridge`, you can write a *single source code in Rust* that you would normally write when using wasmtime,
+but it works on desktop as well as on the web.
-Component model is available since version `0.1.2`, but only some types are supported.
-See [Component model](/docs/component_model.md).
-## Switching from `wasmtime`
+## Component model
-Simply replace the `wasmtime` dependency and imports with `wasm-bridge`, and you _should_ be good to go.
+The main focus is to support [wasmtime's component model](https://github.com/WebAssembly/component-model).
+See the [Component model](/docs/component_model.md) page on how to get started.
-Most of wasmtime's API is still not implemented, so you will likely run into compile errors when compiling to wasm.
-Create an issue with a code snippet describing your use case.
+## Non-component model use
-## Implemented features
+The provided API is identical to wasmtime's API, so read [wasmtime's documentation](https://docs.wasmtime.dev/) on how to use this crate.
-- Load a module from bytes or from WAT text
-- Instantiate a module with or without imports
-- Get (typed) exported function and call it
-- Multivalue returns from exported and imported functions
-- Supported value types: `i32`, `i64`, `u32`, `u64`, `f32`, `f64`
-- Access store's data from Caller (imported fn)
+See [this page](/docs/wasm_modules.md) for an example usage.
-See the [`no_bindgen`](/tests/no_bindgen) test folder for supported example usages.
## License
diff --git a/docs/CM/my_first_component.md b/docs/CM/my_first_component.md
index 71469aa0..5e37e852 100644
--- a/docs/CM/my_first_component.md
+++ b/docs/CM/my_first_component.md
@@ -5,7 +5,7 @@ and call it from Rust runtime on desktop and on the web using the same source co
## Full minimal example
-Full minimal example can be found [here](https://github.com/kajacx/wasm-playground/tree/wasm-bridge-03-universal-component).
+Full minimal example can be found [here](https://github.com/kajacx/wasm-playground/tree/wasm-bridge-05-cargo-component).
## Prerequisites
@@ -13,18 +13,20 @@ Be sure to install all the necessary tooling, list is in [Component model](../co
## Create the WIT protocol
-1. Create a simple file describing the interface using the [wit format](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md), for example:
+1. Create a simple file describing the interface using
+the [wit format](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md), for example:
+
```wit
package usage:example
world calculator {
- export add: func(a: s32, b: s32) -> s32
+ export add_three: func(a: s32) -> s32
}
```
## Create the Rust guest
-1. Create a new Rust crate for the guest and add `wit-bindgen` crate as a dependency. Example `Cargo.toml`:
+1. Create a new Rust library crate for the guest and add `wit-bindgen` crate as a dependency. Example `Cargo.toml`:
```toml
[package]
name = "guest"
@@ -34,10 +36,16 @@ edition = "2021"
[lib]
crate-type = ["cdylib"]
+[package.metadata.component]
+package = "component:guest"
+
[dependencies]
wit-bindgen = "0.8.0"
```
+Be sure to specify `cdylib` as the library type and include the `package.metadata.component` info
+so that `cargo component` can recognize the crate as a proper wasm component.
+
2. Import the WIT world definition in the guest like this:
```rust
wit_bindgen::generate!({
@@ -51,8 +59,8 @@ wit_bindgen::generate!({
struct MyCalculator;
impl Calculator for MyCalculator {
- fn add(a: i32, b: i32) -> i32 {
- a + b
+ fn add_three(num: i32) -> i32 {
+ num + 3
}
}
```
@@ -64,20 +72,19 @@ export_calculator!(MyCalculator);
## Build the guest
-1. Build the guest with `cargo build --target=wasm32-unknown-unknown`
+1. Build the guest with `cargo component --target=wasm32-unknown-unknown`
-2. `cd` into the build folder `target/wasm32-unknown-unknown/debug` (use `/release` in release mode)
+2. This should generate a `guest.wasm` file in the `target/wasm32-unknown-unknown/debug` folder
-3. Convert the WASM module into a WASM component with `wasm-tools component new guest.wasm -o component.wasm`
+3. Your wasm component will be in `target/wasm32-unknown-unknown/debug` if you use `--release`
-This is the `component.wasm` file you would use with wasmtime normally. We will need it later.
## Create the runtime
-1. Add the `wasm-bridge` crate as a dependency with the `component-model` feature. Use version at least `0.2.0`. Example:
+1. Create a new Rust crate with `wasm-bridge` as a dependency with the `component-model` feature. Use version at least `0.2.0`. Example:
```toml
[dependencies]
-wasm-bridge = { version = "0.1.4", features = ["component-model"] }
+wasm-bridge = { version = "0.2.0", features = ["component-model"] }
```
2. Generate the host bindings with the `bindgen` macro, like this:
@@ -108,20 +115,25 @@ let linker = Linker::new(store.engine());
let (calculator, _) = Calculator::instantiate(&mut store, &component, &linker)?;
```
-5. Call the exported function on the component:
+5. Call the exported function on the component instance:
```rust
-let result = calculator.call_add(&mut store, 5, 3)?;
+let result = calculator.call_add_three(&mut store, 5)?;
assert_eq!(result, 8);
```
+
## Summary
The steps are identical to using wasmtime with component model "normally",
except we used `wasm-bridge` instead of `wasmtime` as our dependency.
+
## Next steps
-If your wit world defines imports, you can read the [Wit imports](./wit_imports.md) guide. The code is identical to wasmtime, though.
+If your wit world defines imports, you can read the [Wit imports](./wit_imports.md) guide.
+
+The code is again the same as when using wasmtime.
+
## Universal mode / zipped components discontinuation
diff --git a/docs/CM/wit_imports.md b/docs/CM/wit_imports.md
index d7f6f4d5..b2ce76d9 100644
--- a/docs/CM/wit_imports.md
+++ b/docs/CM/wit_imports.md
@@ -4,21 +4,22 @@ First, read [My first component](./my_first_component.md) to understand how to g
## Full minimal example
-A full example of using wit imports can be found [here](https://github.com/kajacx/wasm-playground/tree/wasm-bridge-04-wit-imports).
+A full example of using wit imports can be found [here](https://github.com/kajacx/wasm-playground/tree/wasm-bridge-06-readd-imports).
## Steps to add imports
-Wit imports work the same way as they do in wasmtime. Here is a quick refresher:
+Wit imports work the same way as they do in wasmtime.
-1. Define a wit file with imports
+This is how to add imports to the "My first component" created in the previous tutorial:
+
+1. Add an "import" function to the wit file
```wit
package usage:example
world calculator {
- import store-variable(name: string, value: s32)
- import get-variable(name: string) -> option
+ import add-one: func(num: s32) -> s32
- export add: func(a: s32, b: s32) -> s32
+ export add-three: func(num: s32) -> s32
}
```
@@ -29,10 +30,11 @@ world calculator {
struct MyCalculator;
impl Calculator for MyCalculator {
- fn add(a: i32, b: i32) -> i32 {
- let times_called = get_variable("times_called").unwrap_or(0);
- store_variable("times_called", times_called + 1);
- a + b + times_called
+ fn add(num: i32) -> i32 {
+ let num = add_one(num);
+ let num = add_one(num);
+ let num = add_one(num);
+ num
}
}
```
@@ -41,32 +43,28 @@ impl Calculator for MyCalculator {
```rust
// In host (runtime)
-struct CalculatorData {
- variables: HashMap,
-}
+struct CalculatorData {}
```
4. Implement the world imports for your struct
```rust
// Name based on world name
impl CalculatorImports for CalculatorData {
- fn store_variable(&mut self, name: String, value: i32) -> Result<()> {
- self.variables.insert(name, value);
- Ok(())
- }
-
- fn get_variable(&mut self, name: String) -> Result