Skip to content

Commit

Permalink
Merge pull request #110 from rylev/improve-rust
Browse files Browse the repository at this point in the history
Improve Rust language guide
  • Loading branch information
kate-goldenring committed Mar 18, 2024
2 parents 640469e + f20c486 commit c284e70
Showing 1 changed file with 11 additions and 12 deletions.
23 changes: 11 additions & 12 deletions component-model/src/language-support/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,23 @@ cargo install cargo-component
## Building a Component with `cargo component`

Create a Rust library that implements the `add` function in the [`example`
world](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host/add.wit). Note that it imports the bindings that will be created by
`cargo-component`. First scaffold a project:
world](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host/add.wit). First scaffold a project:

```sh
$ cargo component new add --lib && cd add
```

Update `wit/world.wit` to match `add.wit` and modify the component package reference to change the
Note that `cargo component` generates the necessary bindings as a module called `bindings`.

Next, update `wit/world.wit` to match `add.wit` and modify the component package reference to change the
package name to `example`. The `component` section of `Cargo.toml` should look like the following:

```toml
[package.metadata.component]
package = "component:example"
```

`cargo-component` will generate bindings for the world specified in a package's `Cargo.toml`. In particular, it will create a `Guest` trait that a component should implement. Since our `example` world has no interfaces, the trait lives directly under the bindings module. Implement the `Guest` trait in `add/src/lib.rs` such that it satisfied the `example` world, adding an `add` function. It should look similar to the following:
`cargo component` will generate bindings for the world specified in a package's `Cargo.toml`. In particular, it will create a `Guest` trait that a component should implement. Since our `example` world has no interfaces, the trait lives directly under the bindings module. Implement the `Guest` trait in `add/src/lib.rs` such that it satisfied the `example` world, adding an `add` function. It should look similar to the following:

```rs
mod bindings;
Expand All @@ -47,7 +48,7 @@ impl Guest for Component {
}
```

Now, build the component, being sure to optimize with a release build.
Now, use `cargo component` to build the component, being sure to optimize with a release build.

```sh
$ cargo component build --release
Expand All @@ -56,7 +57,7 @@ $ cargo component build --release
You can use `wasm-tools component wit` to output the WIT package of the component:

```sh
$ wasm-tools component wit add/target/wasm32-wasi/release/add.wasm
$ wasm-tools component wit target/wasm32-wasi/release/add.wasm
package root:component;

world root {
Expand All @@ -66,8 +67,8 @@ world root {

### Running a Component from Rust Applications

To verify that our component works, lets run it from a Rust application that knows how to import a
component of the [`example` world](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host/add.wit).
To verify that our component works, lets run it from a Rust application that knows how to run a
component targeting the [`example` world](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host/add.wit).

The application uses [`wasmtime`](https://github.com/bytecodealliance/wasmtime) crates to generate
Rust bindings, bring in WASI worlds, and execute the component.
Expand All @@ -78,8 +79,6 @@ $ cargo run --release -- 1 2 ../add/target/wasm32-wasi/release/add.wasm
1 + 2 = 3
```

See [the language guide](../language-support.md#building-a-component-with-cargo-component).

## Exporting an interface with `cargo component`

The [sample `add.wit` file](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host/add.wit) exports a function. However, to use your component from another component, it must export an interface. This results in slightly fiddlier bindings. For example, to implement the following world:
Expand All @@ -101,7 +100,7 @@ you would write the following Rust code:
```rust
mod bindings;
// Separating out the interface puts it in a sub-module
use crate::bindings::exports::docs::calculator::add::Guest;
use bindings::exports::docs::calculator::add::Guest;

struct Component;

Expand Down Expand Up @@ -191,7 +190,7 @@ world root {
}
```

As the import is unfulfilled, the `calculator.wasm` component could not run by itself in its current form. To fulfil the `add` import, so that the calculator can run, you would need to [compose the `calculator.wasm` and `adder.wasm` files into a single, self-contained component](../creating-and-consuming/composing.md).
As the import is unfulfilled, the `calculator.wasm` component could not run by itself in its current form. To fulfill the `add` import, so that only `calculate` is exported, you would need to [compose the `calculator.wasm` with some `exports-add.wasm` into a single, self-contained component](../creating-and-consuming/composing.md).

## Creating a command component with `cargo component`

Expand Down

0 comments on commit c284e70

Please sign in to comment.