281 lines
12 KiB
Rust
281 lines
12 KiB
Rust
|
|
//! Raw API bindings to the [WebAssembly System Interface p3 (WASIp3)][WASIp3]
|
||
|
|
//!
|
||
|
|
//! [WASIp3]: https://github.com/WebAssembly/WASI
|
||
|
|
//!
|
||
|
|
//! This crate provides Rust API bindings to the imports of [WASIp3] [worlds]
|
||
|
|
//! such as:
|
||
|
|
//!
|
||
|
|
//! * [`wasi:cli/command`]
|
||
|
|
//! * [`wasi:http/proxy`]
|
||
|
|
//!
|
||
|
|
//! 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 WASIp3?
|
||
|
|
//!
|
||
|
|
//! [WASIp3] 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
|
||
|
|
//! [WASIp3] defines how to do so with the [`wasi:cli/stdio`] package.
|
||
|
|
//!
|
||
|
|
//! [WASIp3] is defined by an IDL called [WIT] using files that have the extension
|
||
|
|
//! `*.wit`. [WASIp3] and [WIT] are themselves then both defined in terms of the
|
||
|
|
//! [Component Model] in terms of types available and base semantics for APIs.
|
||
|
|
//!
|
||
|
|
//! [WASIp3] 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
|
||
|
|
//! [WASIp3]-defined imports available to components.
|
||
|
|
//!
|
||
|
|
//! # What is a Component?
|
||
|
|
//!
|
||
|
|
//! An important aspect of [WASIp3] 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.
|
||
|
|
//!
|
||
|
|
//! A full description of the component model is out of scope for this crate's
|
||
|
|
//! documentation but it suffices to say that [WASIp3], 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 [WASIp3] is defined with [WIT]. These programmatic
|
||
|
|
//! descriptions of [WASIp3] 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:
|
||
|
|
//!
|
||
|
|
//! ```wit
|
||
|
|
//! interface environment {
|
||
|
|
//! // ...
|
||
|
|
//! get-environment: func() -> list<tuple<string, string>>;
|
||
|
|
//! // ...
|
||
|
|
//! }
|
||
|
|
//! ```
|
||
|
|
//!
|
||
|
|
//! This corresponds to
|
||
|
|
//! [`wasi::cli::environment::get_environment`](crate::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 [WASIp3] [WIT]
|
||
|
|
//! files too, but that's not covered by this crate.
|
||
|
|
//!
|
||
|
|
//! # WASIp3, WASIp2, and WASIp1
|
||
|
|
//!
|
||
|
|
//! The [WASIp3] version of the WASI standard is not yet complete nor stable. It
|
||
|
|
//! is under development and this crate represents a snapshot in time of what
|
||
|
|
//! the APIs may eventually look like.
|
||
|
|
//!
|
||
|
|
//! Users looking for stability should use WASIp2 (the `wasip2` crate) instead.
|
||
|
|
//! Users looking for core wasm, not components, should use the `wasip1` crate.
|
||
|
|
//!
|
||
|
|
//! # Crate Organization
|
||
|
|
//!
|
||
|
|
//! This crate is currently entirely generated by [`wit-bindgen`] which has the
|
||
|
|
//! following structure:
|
||
|
|
//!
|
||
|
|
//! * Each [WIT] package with bindings corresponds to a top-level module. For
|
||
|
|
//! example [`wasi:random`] can be found in the [`random`] module.
|
||
|
|
//! * Each [WIT] interface then corresponds to a submodule of its package's
|
||
|
|
//! module. For example [`wasi:random/insecure`] can be found in the
|
||
|
|
//! [`random::insecure`] module.
|
||
|
|
//! * Each [WIT] function has a Rust function with an idiomatic signature.
|
||
|
|
//! module. For example [`random::insecure::get_insecure_random_u64`].
|
||
|
|
//!
|
||
|
|
//! Note that [WIT] documentation is rendered as rustdoc documentation in these
|
||
|
|
//! APIs as well.
|
||
|
|
//!
|
||
|
|
//! # Using this Crate
|
||
|
|
//!
|
||
|
|
//! This crate is intended to be used with the `wasm32-wasip2` target to the
|
||
|
|
//! Rust compiler. You can compile your code as:
|
||
|
|
//!
|
||
|
|
//! ```sh
|
||
|
|
//! $ cargo build --target wasm32-wasip2
|
||
|
|
//! ```
|
||
|
|
//!
|
||
|
|
//! Eventually a `wasm32-wasip3` target will be added to the Rust compiler but
|
||
|
|
//! in the meantime the `wasm32-wasip2` target suffices. Using a WASIp2 target
|
||
|
|
//! means that the standard library will use WASIp2, but users of this crate
|
||
|
|
//! will use WASIp3.
|
||
|
|
//!
|
||
|
|
//! ## 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:
|
||
|
|
//!
|
||
|
|
//! - [`wasi::cli::command::export!`](crate::cli::command::export)
|
||
|
|
//! - [`wasi::http::proxy::export!`](crate::http::proxy::export)
|
||
|
|
//!
|
||
|
|
//! [worlds]: https://component-model.bytecodealliance.org/design/worlds.html
|
||
|
|
//! [`wasi:cli/command`]: https://github.com/WebAssembly/wasi-cli/
|
||
|
|
//! [`wasi:http/proxy`]: https://github.com/WebAssembly/wasi-http
|
||
|
|
//! [`wasi:cli/stdio`]: https://github.com/WebAssembly/wasi-cli/blob/main/wit-0.3.0-draft/stdio.wit
|
||
|
|
//! [`wit-bindgen`]: https://github.com/bytecodealliance/wit-bindgen/
|
||
|
|
//! [Component Model]: https://component-model.bytecodealliance.org/
|
||
|
|
//! [WIT]: https://component-model.bytecodealliance.org/design/wit.html
|
||
|
|
//! [standard WebAssembly modules]: https://webassembly.github.io/spec/
|
||
|
|
//! [Wasmtime]: https://github.com/bytecodealliance/wasmtime
|
||
|
|
//! [jco]: https://github.com/bytecodealliance/jco
|
||
|
|
//! [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
|
||
|
|
//! [`wasi:cli/environment`]: https://github.com/WebAssembly/wasi-cli/blob/main/wit-0.3.0-draft/environment.wit
|
||
|
|
//! [`wasi:random`]: https://github.com/WebAssembly/wasi-random
|
||
|
|
//! [`wasi:random/insecure`]: https://github.com/WebAssembly/wasi-random/blob/main/wit-0.3.0-draft/insecure.wit
|
||
|
|
//! [`wasm-tools`]: https://github.com/bytecodealliance/wasm-tools
|
||
|
|
//! [adapters]: https://github.com/bytecodealliance/wasmtime/releases
|
||
|
|
|
||
|
|
// These modules are all auto-generated by `./ci/regenerate.sh`
|
||
|
|
#[allow(unused_imports)]
|
||
|
|
mod command;
|
||
|
|
mod imports;
|
||
|
|
#[allow(unused_imports)]
|
||
|
|
mod service;
|
||
|
|
|
||
|
|
// generated bindings start with the package namespace, which in this case is
|
||
|
|
// `wasi`, but the crate is already called wasi, so lift everything up one level
|
||
|
|
// to the root of this crate.
|
||
|
|
pub use imports::wasi::*;
|
||
|
|
|
||
|
|
pub use imports::{wit_future, wit_stream};
|
||
|
|
|
||
|
|
// Forward one `wit_future` impl for another as there's a few extra types in the
|
||
|
|
// `proxy::wit_future` type. This might need changes if wit-bindgen's internal
|
||
|
|
// implementation here changes.
|
||
|
|
impl<T> wit_future::FuturePayload for T
|
||
|
|
where
|
||
|
|
T: service::wit_future::FuturePayload,
|
||
|
|
{
|
||
|
|
const VTABLE: &'static wit_bindgen::rt::async_support::FutureVtable<Self> = T::VTABLE;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Reexport wit-bindgen to downstream users don't have to depend on it.
|
||
|
|
pub use wit_bindgen;
|
||
|
|
|
||
|
|
// Expand the `cli` and `http` modules with `export!` macros for the
|
||
|
|
// command/proxy worlds, but also retain all the contents defined in the
|
||
|
|
// `bindings` module as well.
|
||
|
|
pub mod cli {
|
||
|
|
pub use super::imports::wasi::cli::*;
|
||
|
|
|
||
|
|
pub mod command {
|
||
|
|
/// Generate an exported instance of the `wasi:cli/command` world.
|
||
|
|
///
|
||
|
|
/// This macro generate the `#[no_mangle]` functions necessary to
|
||
|
|
/// export this interface. It takes an argument which is a type that
|
||
|
|
/// must implement the
|
||
|
|
/// [`exports::cli::run::Guest`](crate::exports::cli::run::Guest)
|
||
|
|
/// trait.
|
||
|
|
///
|
||
|
|
/// ```
|
||
|
|
/// struct MyCliRunner;
|
||
|
|
///
|
||
|
|
/// impl wasip3::exports::cli::run::Guest for MyCliRunner {
|
||
|
|
/// async fn run() -> Result<(), ()> {
|
||
|
|
/// // ...
|
||
|
|
/// # panic!();
|
||
|
|
/// }
|
||
|
|
/// }
|
||
|
|
///
|
||
|
|
/// wasip3::cli::command::export!(MyCliRunner);
|
||
|
|
/// ```
|
||
|
|
///
|
||
|
|
/// ## Incompatibility with `bin` target
|
||
|
|
///
|
||
|
|
/// This macro is not compatible with the Rust `bin` crate target
|
||
|
|
/// which instead use a `fn main()`. This macro can, however, be used
|
||
|
|
/// with the `cdylib` crate target.
|
||
|
|
///
|
||
|
|
/// <!--
|
||
|
|
/// The marker above hides the generated documentation by wit-bindgen for this
|
||
|
|
/// macro.
|
||
|
|
#[doc(inline)]
|
||
|
|
pub use crate::command::_export_command as export;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#[cfg(feature = "http-compat")]
|
||
|
|
pub mod http_compat;
|
||
|
|
|
||
|
|
pub mod http {
|
||
|
|
pub use super::service::wasi::http::*;
|
||
|
|
|
||
|
|
pub mod service {
|
||
|
|
/// Generate an exported instance of the `wasi:http/service` world.
|
||
|
|
///
|
||
|
|
/// This macro will generate `#[no_mangle]` functions as necessary to
|
||
|
|
/// export an implementation of the
|
||
|
|
/// [`exports::http::handler::Guest`](crate::exports::http::handler::Guest)
|
||
|
|
/// trait. This macro takes an argument which is a type that implements
|
||
|
|
/// this trait:
|
||
|
|
///
|
||
|
|
/// ```
|
||
|
|
/// use wasip3::http::types::{Request, Response, ErrorCode};
|
||
|
|
///
|
||
|
|
/// struct MyIncomingHandler;
|
||
|
|
///
|
||
|
|
/// impl wasip3::exports::http::handler::Guest for MyIncomingHandler {
|
||
|
|
/// async fn handle(request: Request) -> Result<Response, ErrorCode> {
|
||
|
|
/// // ...
|
||
|
|
/// # panic!();
|
||
|
|
/// }
|
||
|
|
/// }
|
||
|
|
///
|
||
|
|
/// wasip3::http::service::export!(MyIncomingHandler);
|
||
|
|
/// ```
|
||
|
|
///
|
||
|
|
/// <!--
|
||
|
|
/// The marker above hides the generated documentation by wit-bindgen
|
||
|
|
/// for this macro.
|
||
|
|
#[doc(inline)]
|
||
|
|
pub use crate::service::_export_service as export;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub mod exports {
|
||
|
|
// This is required by the `export!` macros of this crate which assume that
|
||
|
|
// the types it's referring to show up as `exports::wasi::...`.
|
||
|
|
//
|
||
|
|
// This isn't part of the public interface, though, so hide this.
|
||
|
|
#[doc(hidden)]
|
||
|
|
pub mod wasi {
|
||
|
|
pub use crate::command::exports::wasi::*;
|
||
|
|
pub use crate::service::exports::wasi::*;
|
||
|
|
}
|
||
|
|
|
||
|
|
// These are the restructured public interface of this crate.
|
||
|
|
pub use crate::command::exports::wasi::cli;
|
||
|
|
pub use crate::service::exports::wasi::http;
|
||
|
|
}
|
||
|
|
|
||
|
|
// These macros are used by recursive invocations of the macro, but they're
|
||
|
|
// `#[doc(hidden)]` as it's not part of the public interface.
|
||
|
|
#[doc(hidden)]
|
||
|
|
pub use crate::command::_export_command;
|
||
|
|
#[doc(hidden)]
|
||
|
|
pub use crate::service::_export_service;
|