Crate wasi

source ·
Expand description

Raw API bindings to the WebAssembly System Interface (WASI)

This crate provides Rust API bindings to the imports of WASI worlds such as:

This crate is procedurally generated with the wit-bindgen bindings generator. Note that generated code is published to crates.io to slim this crate down in terms of build dependencies and resources.

§What is WASI?

WASI is a set of APIs defined for the WebAssembly Component Model to help components interact with the outside world. Core WebAssembly has no intrinsic ability to access the host, for example println! don’t work, but WASI defines how to do so with the wasi:cli/stdio package.

WASI is defined by an IDL called WIT using files that have the extension *.wit. WASI and WIT are themselves then both defined in terms of the Component Model in terms of types available and base semantics for APIs.

WASI defines a number of standard “worlds” which are a description of a what a WebAssembly component can import from an embedding and must export to an embedding. An example world is wasi:cli/command which is a world for running CLI applications. This world provides basic system utilities such as clocks, a filesystem, CLI arguments, etc. The one required export is a main function.

The purpose of this crate is to provide pregenerated bindings to access WASI-defined imports available to components.

§What is a Component?

An important aspect of WASI is that it is defined in terms of the Component Model. The Component Model is a proposal for WebAssembly which is a new format for wasm binaries, a component. A component contains “core” WebAssembly modules (which are standard WebAssembly modules) but also has the ability to do more:

  • A component can contain multiple core WebAssembly modules.
  • Types used with component imports and exports are more comprehensive than core WebAssembly. Core WebAssembly provides integers and floats, for example, and components build on this and add strings, records (aka a Rust struct), variants (aka a Rust enum), and resources (think a file descriptor on Unix).
  • A component provides procedural instructions of how to instantiate its internal core WebAssembly modules with the imports it has.

The Component Model is a not considered an official WebAssembly standard at this time. It has been in development for 5 years (as of January 2024), however, and the WASI 0.2.0 milestone (more on versioning in a moment) in January 2024 represents a concrete target for ecosystems to use. Runtimes such as Wasmtime support the Component Model for out-of-browser usage and jco is an example of how components can be run in a browser.

A full description of the component model is out of scope for this crate’s documentation but it suffices to say that WASI, and this crate, are intended to target components. Components use core WebAssembly modules as an important technical detail, but the final output of this crate is intended to be a component.

§What are generated bindings?

Above it was seen that WASI is defined with WIT. These programmatic descriptions of WASI APIs are not suitable for use directly in Rust, however these descriptions define how Rust can use them. Each WIT function has a defined meaning in core WebAssembly via the Canonical ABI. This is a lower level than most users want to operate at, however, so the generated bindings in this crate serve as the bridge.

More specifically the generated functions in this crate take the Canonical ABI format of WIT functions and provide idiomatic Rust functions to call. For example the wasi:cli/environment definition includes:

interface environment {
    // ...
    get-environment: func() -> list<tuple<string, string>>;
    // ...
}

This corresponds to wasi::cli::environment::get_environment.

Bindings are pre-generated in this crate with the wit-bindgen tool. You can also generate your own bindings with wit-bindgen and WASI WIT files too, but that’s not covered by this crate.

§WASI Today and wasi_snapshot_preview1

This crate is based on the 0.2.0 version of WASI APIs. This version of WASI was declared “phase 3” (suitable for general use and testing) in January of 2024. Prior to this 0.2.0 “preview2” release of WASI there was wasi_snapshot_preview1. This previous “preview1” release of WASI was circa 2019 and was the initial vision for WASI as a standard. Development of WASI migrated to the Component Model in the meantime.

This means that the old wasi_snapshot_preview1 interfaces are no longer provided by this crate because WASI is no longer defined by those interfaces. This includes the historical *.witx format which has now been sueprseded. Note that the 0.11.x release series of this crate contains bindings to the historical wasi_snapshot_preview1 APIs if you’re interested in using them.

§Crate Organization

This crate is currently entirely generated by wit-bindgen which has the following structure:

Note that WIT documentation is rendered as rustdoc documentation in these APIs as well.

§Using this Crate

This crate is intended to be easiest to use with a future wasm32-wasip2 target added to the Rust compiler. In the meantime it’s recommended to use the wasm32-wasi target (soon to be renamed to wasm32-wasip1) instead:

$ cargo build --target wasm32-wasi

Note that the output of the wasm32-wasi target is a core wasm module, not a component, so to turn it into a component you can use the wasm-tools CLI in combination with an “adapter module” for the wasi_snapshot_preview1 APIs that the Rust standard library uses (example adapters can be found on Wasmtime’s release page as wasi_snapshot_preview1.command.wasm for example)

$ wasm-tools component new ./target/wasm32-wasi/debug/my-app.wasm \
    --adapt ./wasi_snapshot_preview1.command.wasm \
    -o my-component.wasm

§Export Macros

In addition to providing bindings for imports this crate also provides macros to export the wasi:cli/run and wasi:http/proxy worlds, see their respective documentation for more information:

Modules§