From e7f43b8d21ed4502e91957d93b634b444e173c75 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Thu, 16 Jan 2025 14:07:35 -0800 Subject: [PATCH] wasmtime-wasi: Split a new `IoView` trait off of `WasiView` (#10016) * split IoView trait off of WasiView * move wasi-http over to split views * config and keyvalue: no changes to libraries, just tests where WasiView used * wasmtime-cli: fixes for IoView/WasiView split * move rest of wasi-io impl to be on IoImpl * wasi-http: linker with wasi IoImpl * wasi-nn tests: IoView impl --- crates/wasi-config/src/lib.rs | 6 +- crates/wasi-config/tests/main.rs | 9 ++- crates/wasi-http/src/http_impl.rs | 1 + crates/wasi-http/src/lib.rs | 59 +++++++++------- crates/wasi-http/src/types.rs | 45 +++++------- crates/wasi-http/src/types_impl.rs | 2 +- crates/wasi-http/tests/all/main.rs | 10 ++- crates/wasi-keyvalue/src/lib.rs | 6 +- crates/wasi-keyvalue/tests/main.rs | 7 +- crates/wasi-nn/tests/exec/wit.rs | 9 +-- crates/wasi/src/bindings.rs | 36 ++++++---- crates/wasi/src/ctx.rs | 80 ++------------------- crates/wasi/src/host/clocks.rs | 2 +- crates/wasi/src/host/filesystem.rs | 2 +- crates/wasi/src/host/instance_network.rs | 2 +- crates/wasi/src/host/io.rs | 34 ++++----- crates/wasi/src/host/network.rs | 2 +- crates/wasi/src/host/tcp.rs | 2 +- crates/wasi/src/host/tcp_create_socket.rs | 2 +- crates/wasi/src/host/udp.rs | 2 +- crates/wasi/src/host/udp_create_socket.rs | 2 +- crates/wasi/src/ip_name_lookup.rs | 2 +- crates/wasi/src/lib.rs | 41 +++++++---- crates/wasi/src/poll.rs | 24 +++---- crates/wasi/src/preview1.rs | 30 ++++---- crates/wasi/src/stdio.rs | 3 +- crates/wasi/src/view.rs | 86 +++++++++++++++++++++++ crates/wasi/tests/all/api.rs | 7 +- crates/wasi/tests/all/main.rs | 6 +- examples/wasip2-async/main.rs | 9 ++- examples/wasip2/main.rs | 9 ++- src/commands/run.rs | 11 ++- src/commands/serve.rs | 11 ++- 33 files changed, 309 insertions(+), 250 deletions(-) create mode 100644 crates/wasi/src/view.rs diff --git a/crates/wasi-config/src/lib.rs b/crates/wasi-config/src/lib.rs index 8d6906dfde47..ec6f3bd595b0 100644 --- a/crates/wasi-config/src/lib.rs +++ b/crates/wasi-config/src/lib.rs @@ -17,7 +17,7 @@ //! component::{Linker, ResourceTable}, //! Config, Engine, Result, Store, //! }; -//! use wasmtime_wasi::{WasiCtx, WasiCtxBuilder, WasiView}; +//! use wasmtime_wasi::{IoView, WasiCtx, WasiCtxBuilder, WasiView}; //! use wasmtime_wasi_config::{WasiConfig, WasiConfigVariables}; //! //! #[tokio::main] @@ -53,8 +53,10 @@ //! wasi_config_vars: WasiConfigVariables, //! } //! -//! impl WasiView for Ctx { +//! impl IoView for Ctx { //! fn table(&mut self) -> &mut ResourceTable { &mut self.table } +//! } +//! impl WasiView for Ctx { //! fn ctx(&mut self) -> &mut WasiCtx { &mut self.wasi_ctx } //! } //! ``` diff --git a/crates/wasi-config/tests/main.rs b/crates/wasi-config/tests/main.rs index 6bcb8ec77887..08619d30ec21 100644 --- a/crates/wasi-config/tests/main.rs +++ b/crates/wasi-config/tests/main.rs @@ -4,7 +4,9 @@ use wasmtime::{ component::{Component, Linker, ResourceTable}, Store, }; -use wasmtime_wasi::{add_to_linker_async, bindings::Command, WasiCtx, WasiCtxBuilder, WasiView}; +use wasmtime_wasi::{ + add_to_linker_async, bindings::Command, IoView, WasiCtx, WasiCtxBuilder, WasiView, +}; use wasmtime_wasi_config::{WasiConfig, WasiConfigVariables}; struct Ctx { @@ -13,11 +15,12 @@ struct Ctx { wasi_config_vars: WasiConfigVariables, } -impl WasiView for Ctx { +impl IoView for Ctx { fn table(&mut self) -> &mut ResourceTable { &mut self.table } - +} +impl WasiView for Ctx { fn ctx(&mut self) -> &mut WasiCtx { &mut self.wasi_ctx } diff --git a/crates/wasi-http/src/http_impl.rs b/crates/wasi-http/src/http_impl.rs index 53f3bc33b2be..8850b63f29c6 100644 --- a/crates/wasi-http/src/http_impl.rs +++ b/crates/wasi-http/src/http_impl.rs @@ -14,6 +14,7 @@ use bytes::Bytes; use http_body_util::{BodyExt, Empty}; use hyper::Method; use wasmtime::component::Resource; +use wasmtime_wasi::IoView; impl outgoing_handler::Host for WasiHttpImpl where diff --git a/crates/wasi-http/src/lib.rs b/crates/wasi-http/src/lib.rs index baf4bd6ba98d..9c57a6b6a974 100644 --- a/crates/wasi-http/src/lib.rs +++ b/crates/wasi-http/src/lib.rs @@ -71,7 +71,7 @@ //! use tokio::net::TcpListener; //! use wasmtime::component::{Component, Linker, ResourceTable}; //! use wasmtime::{Config, Engine, Result, Store}; -//! use wasmtime_wasi::{WasiCtx, WasiCtxBuilder, WasiView}; +//! use wasmtime_wasi::{IoView, WasiCtx, WasiCtxBuilder, WasiView}; //! use wasmtime_wasi_http::bindings::ProxyPre; //! use wasmtime_wasi_http::bindings::http::types::Scheme; //! use wasmtime_wasi_http::body::HyperOutgoingBody; @@ -193,23 +193,21 @@ //! http: WasiHttpCtx, //! table: ResourceTable, //! } -//! +//! impl IoView for MyClientState { +//! fn table(&mut self) -> &mut ResourceTable { +//! &mut self.table +//! } +//! } //! impl WasiView for MyClientState { //! fn ctx(&mut self) -> &mut WasiCtx { //! &mut self.wasi //! } -//! fn table(&mut self) -> &mut ResourceTable { -//! &mut self.table -//! } //! } //! //! impl WasiHttpView for MyClientState { //! fn ctx(&mut self) -> &mut WasiHttpCtx { //! &mut self.http //! } -//! fn table(&mut self) -> &mut ResourceTable { -//! &mut self.table -//! } //! } //! ``` @@ -236,7 +234,7 @@ pub use crate::types::{ WasiHttpCtx, WasiHttpImpl, WasiHttpView, DEFAULT_OUTGOING_BODY_BUFFER_CHUNKS, DEFAULT_OUTGOING_BODY_CHUNK_SIZE, }; - +use wasmtime_wasi::IoImpl; /// Add all of the `wasi:http/proxy` world's interfaces to a [`wasmtime::component::Linker`]. /// /// This function will add the `async` variant of all interfaces into the @@ -251,7 +249,7 @@ pub use crate::types::{ /// ``` /// use wasmtime::{Engine, Result, Config}; /// use wasmtime::component::{ResourceTable, Linker}; -/// use wasmtime_wasi::{WasiCtx, WasiView}; +/// use wasmtime_wasi::{IoView, WasiCtx, WasiView}; /// use wasmtime_wasi_http::{WasiHttpCtx, WasiHttpView}; /// /// fn main() -> Result<()> { @@ -272,25 +270,27 @@ pub use crate::types::{ /// table: ResourceTable, /// } /// +/// impl IoView for MyState { +/// fn table(&mut self) -> &mut ResourceTable { &mut self.table } +/// } /// impl WasiHttpView for MyState { /// fn ctx(&mut self) -> &mut WasiHttpCtx { &mut self.http_ctx } -/// fn table(&mut self) -> &mut ResourceTable { &mut self.table } /// } /// impl WasiView for MyState { /// fn ctx(&mut self) -> &mut WasiCtx { &mut self.ctx } -/// fn table(&mut self) -> &mut ResourceTable { &mut self.table } /// } /// ``` pub fn add_to_linker_async(l: &mut wasmtime::component::Linker) -> anyhow::Result<()> where T: WasiHttpView + wasmtime_wasi::WasiView, { - let closure = type_annotate_wasi::(|t| wasmtime_wasi::WasiImpl(t)); + let io_closure = type_annotate_io::(|t| wasmtime_wasi::IoImpl(t)); + let closure = type_annotate_wasi::(|t| wasmtime_wasi::WasiImpl(wasmtime_wasi::IoImpl(t))); wasmtime_wasi::bindings::clocks::wall_clock::add_to_linker_get_host(l, closure)?; wasmtime_wasi::bindings::clocks::monotonic_clock::add_to_linker_get_host(l, closure)?; - wasmtime_wasi::bindings::io::poll::add_to_linker_get_host(l, closure)?; - wasmtime_wasi::bindings::io::error::add_to_linker_get_host(l, closure)?; - wasmtime_wasi::bindings::io::streams::add_to_linker_get_host(l, closure)?; + wasmtime_wasi::bindings::io::poll::add_to_linker_get_host(l, io_closure)?; + wasmtime_wasi::bindings::io::error::add_to_linker_get_host(l, io_closure)?; + wasmtime_wasi::bindings::io::streams::add_to_linker_get_host(l, io_closure)?; wasmtime_wasi::bindings::cli::stdin::add_to_linker_get_host(l, closure)?; wasmtime_wasi::bindings::cli::stdout::add_to_linker_get_host(l, closure)?; wasmtime_wasi::bindings::cli::stderr::add_to_linker_get_host(l, closure)?; @@ -313,6 +313,12 @@ where { val } +fn type_annotate_io(val: F) -> F +where + F: Fn(&mut T) -> wasmtime_wasi::IoImpl<&mut T>, +{ + val +} /// A slimmed down version of [`add_to_linker_async`] which only adds /// `wasi:http` interfaces to the linker. @@ -325,7 +331,7 @@ pub fn add_only_http_to_linker_async( where T: WasiHttpView, { - let closure = type_annotate_http::(|t| WasiHttpImpl(t)); + let closure = type_annotate_http::(|t| WasiHttpImpl(IoImpl(t))); crate::bindings::http::outgoing_handler::add_to_linker_get_host(l, closure)?; crate::bindings::http::types::add_to_linker_get_host(l, closure)?; @@ -343,7 +349,7 @@ where /// ``` /// use wasmtime::{Engine, Result, Config}; /// use wasmtime::component::{ResourceTable, Linker}; -/// use wasmtime_wasi::{WasiCtx, WasiView}; +/// use wasmtime_wasi::{IoView, WasiCtx, WasiView}; /// use wasmtime_wasi_http::{WasiHttpCtx, WasiHttpView}; /// /// fn main() -> Result<()> { @@ -362,27 +368,28 @@ where /// http_ctx: WasiHttpCtx, /// table: ResourceTable, /// } -/// +/// impl IoView for MyState { +/// fn table(&mut self) -> &mut ResourceTable { &mut self.table } +/// } /// impl WasiHttpView for MyState { /// fn ctx(&mut self) -> &mut WasiHttpCtx { &mut self.http_ctx } -/// fn table(&mut self) -> &mut ResourceTable { &mut self.table } /// } /// impl WasiView for MyState { /// fn ctx(&mut self) -> &mut WasiCtx { &mut self.ctx } -/// fn table(&mut self) -> &mut ResourceTable { &mut self.table } /// } /// ``` pub fn add_to_linker_sync(l: &mut wasmtime::component::Linker) -> anyhow::Result<()> where T: WasiHttpView + wasmtime_wasi::WasiView, { - let closure = type_annotate_wasi::(|t| wasmtime_wasi::WasiImpl(t)); + let io_closure = type_annotate_io::(|t| wasmtime_wasi::IoImpl(t)); + let closure = type_annotate_wasi::(|t| wasmtime_wasi::WasiImpl(wasmtime_wasi::IoImpl(t))); wasmtime_wasi::bindings::clocks::wall_clock::add_to_linker_get_host(l, closure)?; wasmtime_wasi::bindings::clocks::monotonic_clock::add_to_linker_get_host(l, closure)?; - wasmtime_wasi::bindings::sync::io::poll::add_to_linker_get_host(l, closure)?; - wasmtime_wasi::bindings::sync::io::streams::add_to_linker_get_host(l, closure)?; - wasmtime_wasi::bindings::io::error::add_to_linker_get_host(l, closure)?; + wasmtime_wasi::bindings::sync::io::poll::add_to_linker_get_host(l, io_closure)?; + wasmtime_wasi::bindings::sync::io::streams::add_to_linker_get_host(l, io_closure)?; + wasmtime_wasi::bindings::io::error::add_to_linker_get_host(l, io_closure)?; wasmtime_wasi::bindings::cli::stdin::add_to_linker_get_host(l, closure)?; wasmtime_wasi::bindings::cli::stdout::add_to_linker_get_host(l, closure)?; wasmtime_wasi::bindings::cli::stderr::add_to_linker_get_host(l, closure)?; @@ -402,7 +409,7 @@ pub fn add_only_http_to_linker_sync(l: &mut wasmtime::component::Linker) - where T: WasiHttpView, { - let closure = type_annotate_http::(|t| WasiHttpImpl(t)); + let closure = type_annotate_http::(|t| WasiHttpImpl(IoImpl(t))); crate::bindings::http::outgoing_handler::add_to_linker_get_host(l, closure)?; crate::bindings::http::types::add_to_linker_get_host(l, closure)?; diff --git a/crates/wasi-http/src/types.rs b/crates/wasi-http/src/types.rs index bb2935f0b820..35bda46f3917 100644 --- a/crates/wasi-http/src/types.rs +++ b/crates/wasi-http/src/types.rs @@ -18,7 +18,7 @@ use std::time::Duration; use tokio::net::TcpStream; use tokio::time::timeout; use wasmtime::component::{Resource, ResourceTable}; -use wasmtime_wasi::{runtime::AbortOnDropJoinHandle, Subscribe}; +use wasmtime_wasi::{runtime::AbortOnDropJoinHandle, IoImpl, IoView, Subscribe}; /// Capture the state necessary for use in the wasi-http API implementation. #[derive(Debug)] @@ -39,7 +39,7 @@ impl WasiHttpCtx { /// /// ``` /// use wasmtime::component::ResourceTable; -/// use wasmtime_wasi::{WasiCtx, WasiView, WasiCtxBuilder}; +/// use wasmtime_wasi::{IoView, WasiCtx, WasiView, WasiCtxBuilder}; /// use wasmtime_wasi_http::{WasiHttpCtx, WasiHttpView}; /// /// struct MyState { @@ -48,14 +48,15 @@ impl WasiHttpCtx { /// table: ResourceTable, /// } /// +/// impl IoView for MyState { +/// fn table(&mut self) -> &mut ResourceTable { &mut self.table } +/// } /// impl WasiHttpView for MyState { /// fn ctx(&mut self) -> &mut WasiHttpCtx { &mut self.http_ctx } -/// fn table(&mut self) -> &mut ResourceTable { &mut self.table } /// } /// /// impl WasiView for MyState { /// fn ctx(&mut self) -> &mut WasiCtx { &mut self.ctx } -/// fn table(&mut self) -> &mut ResourceTable { &mut self.table } /// } /// /// impl MyState { @@ -73,13 +74,10 @@ impl WasiHttpCtx { /// } /// } /// ``` -pub trait WasiHttpView: Send { +pub trait WasiHttpView: IoView { /// Returns a mutable reference to the WASI HTTP context. fn ctx(&mut self) -> &mut WasiHttpCtx; - /// Returns a mutable reference to the WASI HTTP resource table. - fn table(&mut self) -> &mut ResourceTable; - /// Create a new incoming request resource. fn new_incoming_request( &mut self, @@ -150,10 +148,6 @@ impl WasiHttpView for &mut T { T::ctx(self) } - fn table(&mut self) -> &mut ResourceTable { - T::table(self) - } - fn new_response_outparam( &mut self, result: tokio::sync::oneshot::Sender< @@ -189,10 +183,6 @@ impl WasiHttpView for Box { T::ctx(self) } - fn table(&mut self) -> &mut ResourceTable { - T::table(self) - } - fn new_response_outparam( &mut self, result: tokio::sync::oneshot::Sender< @@ -236,15 +226,16 @@ impl WasiHttpView for Box { /// [`add_to_linker_sync`](crate::add_to_linker_sync) /// and doesn't need to be manually configured. #[repr(transparent)] -pub struct WasiHttpImpl(pub T); +pub struct WasiHttpImpl(pub IoImpl); +impl IoView for WasiHttpImpl { + fn table(&mut self) -> &mut ResourceTable { + T::table(&mut self.0 .0) + } +} impl WasiHttpView for WasiHttpImpl { fn ctx(&mut self) -> &mut WasiHttpCtx { - self.0.ctx() - } - - fn table(&mut self) -> &mut ResourceTable { - self.0.table() + self.0 .0.ctx() } fn new_response_outparam( @@ -253,7 +244,7 @@ impl WasiHttpView for WasiHttpImpl { Result, types::ErrorCode>, >, ) -> wasmtime::Result> { - self.0.new_response_outparam(result) + self.0 .0.new_response_outparam(result) } fn send_request( @@ -261,19 +252,19 @@ impl WasiHttpView for WasiHttpImpl { request: hyper::Request, config: OutgoingRequestConfig, ) -> crate::HttpResult { - self.0.send_request(request, config) + self.0 .0.send_request(request, config) } fn is_forbidden_header(&mut self, name: &HeaderName) -> bool { - self.0.is_forbidden_header(name) + self.0 .0.is_forbidden_header(name) } fn outgoing_body_buffer_chunks(&mut self) -> usize { - self.0.outgoing_body_buffer_chunks() + self.0 .0.outgoing_body_buffer_chunks() } fn outgoing_body_chunk_size(&mut self) -> usize { - self.0.outgoing_body_chunk_size() + self.0 .0.outgoing_body_chunk_size() } } diff --git a/crates/wasi-http/src/types_impl.rs b/crates/wasi-http/src/types_impl.rs index 337c1a3c76f7..f3a83f85d6d7 100644 --- a/crates/wasi-http/src/types_impl.rs +++ b/crates/wasi-http/src/types_impl.rs @@ -16,7 +16,7 @@ use std::str::FromStr; use wasmtime::component::{Resource, ResourceTable}; use wasmtime_wasi::{ bindings::io::streams::{InputStream, OutputStream}, - Pollable, ResourceTableError, + IoView, Pollable, ResourceTableError, }; impl crate::bindings::http::types::Host for WasiHttpImpl diff --git a/crates/wasi-http/tests/all/main.rs b/crates/wasi-http/tests/all/main.rs index 418ba66d4c35..0f6c1d7cf432 100644 --- a/crates/wasi-http/tests/all/main.rs +++ b/crates/wasi-http/tests/all/main.rs @@ -11,7 +11,7 @@ use wasmtime::{ component::{Component, Linker, ResourceTable}, Config, Engine, Store, }; -use wasmtime_wasi::{self, pipe::MemoryOutputPipe, WasiCtx, WasiCtxBuilder, WasiView}; +use wasmtime_wasi::{self, pipe::MemoryOutputPipe, IoView, WasiCtx, WasiCtxBuilder, WasiView}; use wasmtime_wasi_http::{ bindings::http::types::{ErrorCode, Scheme}, body::HyperOutgoingBody, @@ -38,10 +38,12 @@ struct Ctx { rejected_authority: Option, } -impl WasiView for Ctx { +impl IoView for Ctx { fn table(&mut self) -> &mut ResourceTable { &mut self.table } +} +impl WasiView for Ctx { fn ctx(&mut self) -> &mut WasiCtx { &mut self.wasi } @@ -52,10 +54,6 @@ impl WasiHttpView for Ctx { &mut self.http } - fn table(&mut self) -> &mut ResourceTable { - &mut self.table - } - fn send_request( &mut self, request: hyper::Request, diff --git a/crates/wasi-keyvalue/src/lib.rs b/crates/wasi-keyvalue/src/lib.rs index 4d53a9acf20b..ce8d5b276984 100644 --- a/crates/wasi-keyvalue/src/lib.rs +++ b/crates/wasi-keyvalue/src/lib.rs @@ -20,7 +20,7 @@ //! component::{Linker, ResourceTable}, //! Config, Engine, Result, Store, //! }; -//! use wasmtime_wasi::{WasiCtx, WasiCtxBuilder, WasiView}; +//! use wasmtime_wasi::{IoView, WasiCtx, WasiCtxBuilder, WasiView}; //! use wasmtime_wasi_keyvalue::{WasiKeyValue, WasiKeyValueCtx, WasiKeyValueCtxBuilder}; //! //! #[tokio::main] @@ -53,8 +53,10 @@ //! wasi_keyvalue_ctx: WasiKeyValueCtx, //! } //! -//! impl WasiView for Ctx { +//! impl IoView for Ctx { //! fn table(&mut self) -> &mut ResourceTable { &mut self.table } +//! } +//! impl WasiView for Ctx { //! fn ctx(&mut self) -> &mut WasiCtx { &mut self.wasi_ctx } //! } //! ``` diff --git a/crates/wasi-keyvalue/tests/main.rs b/crates/wasi-keyvalue/tests/main.rs index 6ae8eee18a56..5d0b6bf4a07e 100644 --- a/crates/wasi-keyvalue/tests/main.rs +++ b/crates/wasi-keyvalue/tests/main.rs @@ -4,7 +4,7 @@ use wasmtime::{ component::{Component, Linker, ResourceTable}, Store, }; -use wasmtime_wasi::{bindings::Command, WasiCtx, WasiCtxBuilder, WasiView}; +use wasmtime_wasi::{bindings::Command, IoView, WasiCtx, WasiCtxBuilder, WasiView}; use wasmtime_wasi_keyvalue::{WasiKeyValue, WasiKeyValueCtx, WasiKeyValueCtxBuilder}; struct Ctx { @@ -13,11 +13,12 @@ struct Ctx { wasi_keyvalue_ctx: WasiKeyValueCtx, } -impl WasiView for Ctx { +impl IoView for Ctx { fn table(&mut self) -> &mut ResourceTable { &mut self.table } - +} +impl WasiView for Ctx { fn ctx(&mut self) -> &mut WasiCtx { &mut self.wasi_ctx } diff --git a/crates/wasi-nn/tests/exec/wit.rs b/crates/wasi-nn/tests/exec/wit.rs index 5f2d546d667d..21a756c4ddf8 100644 --- a/crates/wasi-nn/tests/exec/wit.rs +++ b/crates/wasi-nn/tests/exec/wit.rs @@ -62,12 +62,13 @@ impl Ctx { } } +impl wasmtime_wasi::IoView for Ctx { + fn table(&mut self) -> &mut ResourceTable { + &mut self.table + } +} impl wasmtime_wasi::WasiView for Ctx { fn ctx(&mut self) -> &mut WasiCtx { &mut self.wasi } - - fn table(&mut self) -> &mut ResourceTable { - &mut self.table - } } diff --git a/crates/wasi/src/bindings.rs b/crates/wasi/src/bindings.rs index cefeec980ce3..7449b3a3f202 100644 --- a/crates/wasi/src/bindings.rs +++ b/crates/wasi/src/bindings.rs @@ -15,7 +15,7 @@ //! done using the `with` option to [`bindgen!`]: //! //! ```rust -//! use wasmtime_wasi::{WasiCtx, ResourceTable, WasiView}; +//! use wasmtime_wasi::{IoView, WasiCtx, ResourceTable, WasiView}; //! use wasmtime::{Result, Engine, Config}; //! use wasmtime::component::Linker; //! @@ -53,8 +53,10 @@ //! } //! } //! -//! impl WasiView for MyState { +//! impl IoView for MyState { //! fn table(&mut self) -> &mut ResourceTable { &mut self.table } +//! } +//! impl WasiView for MyState { //! fn ctx(&mut self) -> &mut WasiCtx { &mut self.ctx } //! } //! @@ -84,7 +86,7 @@ /// done using the `with` option to `bindgen!`: /// /// ```rust -/// use wasmtime_wasi::{WasiCtx, ResourceTable, WasiView}; +/// use wasmtime_wasi::{IoView, WasiCtx, ResourceTable, WasiView}; /// use wasmtime::{Result, Engine}; /// use wasmtime::component::Linker; /// @@ -124,8 +126,10 @@ /// } /// } /// -/// impl WasiView for MyState { +/// impl IoView for MyState { /// fn table(&mut self) -> &mut ResourceTable { &mut self.table } +/// } +/// impl WasiView for MyState { /// fn ctx(&mut self) -> &mut WasiCtx { &mut self.ctx } /// } /// @@ -201,7 +205,7 @@ pub mod sync { /// ```no_run /// use wasmtime::{Engine, Result, Store, Config}; /// use wasmtime::component::{ResourceTable, Linker, Component}; - /// use wasmtime_wasi::{WasiCtx, WasiView, WasiCtxBuilder}; + /// use wasmtime_wasi::{IoView, WasiCtx, WasiView, WasiCtxBuilder}; /// use wasmtime_wasi::bindings::sync::Command; /// /// // This example is an example shim of executing a component based on the @@ -245,9 +249,11 @@ pub mod sync { /// table: ResourceTable, /// } /// + /// impl IoView for MyState { + /// fn table(&mut self) -> &mut ResourceTable { &mut self.table } + /// } /// impl WasiView for MyState { /// fn ctx(&mut self) -> &mut WasiCtx { &mut self.ctx } - /// fn table(&mut self) -> &mut ResourceTable { &mut self.table } /// } /// ``` /// @@ -264,7 +270,7 @@ pub mod sync { /// ```no_run /// use wasmtime::{Engine, Result, Store, Config}; /// use wasmtime::component::{ResourceTable, Linker, Component}; - /// use wasmtime_wasi::{WasiCtx, WasiView, WasiCtxBuilder}; + /// use wasmtime_wasi::{IoView, WasiCtx, WasiView, WasiCtxBuilder}; /// use wasmtime_wasi::bindings::sync::CommandPre; /// /// // This example is an example shim of executing a component based on the @@ -309,9 +315,11 @@ pub mod sync { /// table: ResourceTable, /// } /// + /// impl IoView for MyState { + /// fn table(&mut self) -> &mut ResourceTable { &mut self.table } + /// } /// impl WasiView for MyState { /// fn ctx(&mut self) -> &mut WasiCtx { &mut self.ctx } - /// fn table(&mut self) -> &mut ResourceTable { &mut self.table } /// } /// ``` /// @@ -439,7 +447,7 @@ pub use self::async_io::LinkOptions; /// ```no_run /// use wasmtime::{Engine, Result, Store, Config}; /// use wasmtime::component::{ResourceTable, Linker, Component}; -/// use wasmtime_wasi::{WasiCtx, WasiView, WasiCtxBuilder}; +/// use wasmtime_wasi::{IoView, WasiCtx, WasiView, WasiCtxBuilder}; /// use wasmtime_wasi::bindings::Command; /// /// // This example is an example shim of executing a component based on the @@ -486,9 +494,11 @@ pub use self::async_io::LinkOptions; /// table: ResourceTable, /// } /// +/// impl IoView for MyState { +/// fn table(&mut self) -> &mut ResourceTable { &mut self.table } +/// } /// impl WasiView for MyState { /// fn ctx(&mut self) -> &mut WasiCtx { &mut self.ctx } -/// fn table(&mut self) -> &mut ResourceTable { &mut self.table } /// } /// ``` /// @@ -505,7 +515,7 @@ pub use self::async_io::Command; /// ```no_run /// use wasmtime::{Engine, Result, Store, Config}; /// use wasmtime::component::{ResourceTable, Linker, Component}; -/// use wasmtime_wasi::{WasiCtx, WasiView, WasiCtxBuilder}; +/// use wasmtime_wasi::{IoView, WasiCtx, WasiView, WasiCtxBuilder}; /// use wasmtime_wasi::bindings::CommandPre; /// /// // This example is an example shim of executing a component based on the @@ -553,9 +563,11 @@ pub use self::async_io::Command; /// table: ResourceTable, /// } /// +/// impl IoView for MyState { +/// fn table(&mut self) -> &mut ResourceTable { &mut self.table } +/// } /// impl WasiView for MyState { /// fn ctx(&mut self) -> &mut WasiCtx { &mut self.ctx } -/// fn table(&mut self) -> &mut ResourceTable { &mut self.table } /// } /// ``` /// diff --git a/crates/wasi/src/ctx.rs b/crates/wasi/src/ctx.rs index d7a5c4156ae0..b86895712a9e 100644 --- a/crates/wasi/src/ctx.rs +++ b/crates/wasi/src/ctx.rs @@ -16,7 +16,6 @@ use std::path::Path; use std::sync::Arc; use std::{future::Future, pin::Pin}; use std::{mem, net::SocketAddr}; -use wasmtime::component::ResourceTable; /// Builder-style structure used to create a [`WasiCtx`]. /// @@ -525,36 +524,23 @@ impl WasiCtxBuilder { } } -/// A trait which provides access to internal WASI state. -/// -/// This trait is the basis of implementation of all traits in this crate. All -/// traits are implemented like: -/// -/// ``` -/// # trait WasiView {} -/// # mod bindings { pub mod wasi { pub trait Host {} } } -/// impl bindings::wasi::Host for T { -/// // ... -/// } -/// ``` -/// -/// For a [`Store`](wasmtime::Store) this trait will be implemented -/// for the `T`. This also corresponds to the `T` in -/// [`Linker`](wasmtime::component::Linker). +/// A struct which provides access to internal WASI state. /// /// # Example /// /// ``` -/// use wasmtime_wasi::{WasiCtx, ResourceTable, WasiView, WasiCtxBuilder}; +/// use wasmtime_wasi::{WasiCtx, ResourceTable, WasiView, IoView, WasiCtxBuilder}; /// /// struct MyState { /// ctx: WasiCtx, /// table: ResourceTable, /// } /// +/// impl IoView for MyState { +/// fn table(&mut self) -> &mut ResourceTable { &mut self.table } +/// } /// impl WasiView for MyState { /// fn ctx(&mut self) -> &mut WasiCtx { &mut self.ctx } -/// fn table(&mut self) -> &mut ResourceTable { &mut self.table } /// } /// /// impl MyState { @@ -571,62 +557,6 @@ impl WasiCtxBuilder { /// } /// } /// ``` -pub trait WasiView: Send { - /// Yields mutable access to the internal resource management that this - /// context contains. - /// - /// Embedders can add custom resources to this table as well to give - /// resources to wasm as well. - fn table(&mut self) -> &mut ResourceTable; - - /// Yields mutable access to the configuration used for this context. - /// - /// The returned type is created through [`WasiCtxBuilder`]. - fn ctx(&mut self) -> &mut WasiCtx; -} - -impl WasiView for &mut T { - fn table(&mut self) -> &mut ResourceTable { - T::table(self) - } - fn ctx(&mut self) -> &mut WasiCtx { - T::ctx(self) - } -} - -impl WasiView for Box { - fn table(&mut self) -> &mut ResourceTable { - T::table(self) - } - fn ctx(&mut self) -> &mut WasiCtx { - T::ctx(self) - } -} - -/// A small newtype wrapper which serves as the basis for implementations of -/// `Host` WASI traits in this crate. -/// -/// This type is used as the basis for the implementation of all `Host` traits -/// generated by `bindgen!` for WASI interfaces. This is used automatically with -/// [`add_to_linker_sync`](crate::add_to_linker_sync) and -/// [`add_to_linker_async`](crate::add_to_linker_async). -/// -/// This type is otherwise provided if you're calling the `add_to_linker` -/// functions generated by `bindgen!` from the [`bindings` -/// module](crate::bindings). In this situation you'll want to create a value of -/// this type in the closures added to a `Linker`. -#[repr(transparent)] -pub struct WasiImpl(pub T); - -impl WasiView for WasiImpl { - fn table(&mut self) -> &mut ResourceTable { - T::table(&mut self.0) - } - fn ctx(&mut self) -> &mut WasiCtx { - T::ctx(&mut self.0) - } -} - /// Per-[`Store`] state which holds state necessary to implement WASI from this /// crate. /// diff --git a/crates/wasi/src/host/clocks.rs b/crates/wasi/src/host/clocks.rs index e94ca98555ff..feefb9473b27 100644 --- a/crates/wasi/src/host/clocks.rs +++ b/crates/wasi/src/host/clocks.rs @@ -5,7 +5,7 @@ use crate::bindings::{ clocks::wall_clock::{self, Datetime}, }; use crate::poll::{subscribe, Subscribe}; -use crate::{Pollable, WasiImpl, WasiView}; +use crate::{IoView, Pollable, WasiImpl, WasiView}; use cap_std::time::SystemTime; use std::time::Duration; use wasmtime::component::Resource; diff --git a/crates/wasi/src/host/filesystem.rs b/crates/wasi/src/host/filesystem.rs index 2d31e5c53fc4..a8cfb91754f3 100644 --- a/crates/wasi/src/host/filesystem.rs +++ b/crates/wasi/src/host/filesystem.rs @@ -7,7 +7,7 @@ use crate::bindings::io::streams::{InputStream, OutputStream}; use crate::filesystem::{ Descriptor, Dir, File, FileInputStream, FileOutputStream, OpenMode, ReaddirIterator, }; -use crate::{DirPerms, FilePerms, FsError, FsResult, WasiImpl, WasiView}; +use crate::{DirPerms, FilePerms, FsError, FsResult, IoView, WasiImpl, WasiView}; use anyhow::Context; use wasmtime::component::Resource; diff --git a/crates/wasi/src/host/instance_network.rs b/crates/wasi/src/host/instance_network.rs index edf097d8679c..d6b06718a8d0 100644 --- a/crates/wasi/src/host/instance_network.rs +++ b/crates/wasi/src/host/instance_network.rs @@ -1,6 +1,6 @@ use crate::bindings::sockets::instance_network; use crate::network::Network; -use crate::{WasiImpl, WasiView}; +use crate::{IoView, WasiImpl, WasiView}; use wasmtime::component::Resource; impl instance_network::Host for WasiImpl diff --git a/crates/wasi/src/host/io.rs b/crates/wasi/src/host/io.rs index 35a2e8e63aa9..5ad1a65e84da 100644 --- a/crates/wasi/src/host/io.rs +++ b/crates/wasi/src/host/io.rs @@ -2,15 +2,15 @@ use crate::{ bindings::io::error, bindings::io::streams::{self, InputStream, OutputStream}, poll::subscribe, - Pollable, StreamError, StreamResult, WasiImpl, WasiView, + IoImpl, IoView, Pollable, StreamError, StreamResult, }; use wasmtime::component::Resource; -impl error::Host for WasiImpl where T: WasiView {} +impl error::Host for IoImpl where T: IoView {} -impl streams::Host for WasiImpl +impl streams::Host for IoImpl where - T: WasiView, + T: IoView, { fn convert_stream_error(&mut self, err: StreamError) -> anyhow::Result { match err { @@ -23,9 +23,9 @@ where } } -impl error::HostError for WasiImpl +impl error::HostError for IoImpl where - T: WasiView, + T: IoView, { fn drop(&mut self, err: Resource) -> anyhow::Result<()> { self.table().delete(err)?; @@ -37,9 +37,9 @@ where } } -impl streams::HostOutputStream for WasiImpl +impl streams::HostOutputStream for IoImpl where - T: WasiView, + T: IoView, { async fn drop(&mut self, stream: Resource) -> anyhow::Result<()> { self.table().delete(stream)?.cancel().await; @@ -170,9 +170,9 @@ where } } -impl streams::HostInputStream for WasiImpl +impl streams::HostInputStream for IoImpl where - T: WasiView, + T: IoView, { async fn drop(&mut self, stream: Resource) -> anyhow::Result<()> { self.table().delete(stream)?.cancel().await; @@ -227,7 +227,7 @@ pub mod sync { bindings::sync::io::poll::Pollable, bindings::sync::io::streams::{self, InputStream, OutputStream}, runtime::in_tokio, - StreamError, StreamResult, WasiImpl, WasiView, + IoImpl, IoView, StreamError, StreamResult, }; use wasmtime::component::Resource; @@ -240,9 +240,9 @@ pub mod sync { } } - impl streams::Host for WasiImpl + impl streams::Host for IoImpl where - T: WasiView, + T: IoView, { fn convert_stream_error( &mut self, @@ -252,9 +252,9 @@ pub mod sync { } } - impl streams::HostOutputStream for WasiImpl + impl streams::HostOutputStream for IoImpl where - T: WasiView, + T: IoView, { fn drop(&mut self, stream: Resource) -> anyhow::Result<()> { in_tokio(async { AsyncHostOutputStream::drop(self, stream).await }) @@ -332,9 +332,9 @@ pub mod sync { } } - impl streams::HostInputStream for WasiImpl + impl streams::HostInputStream for IoImpl where - T: WasiView, + T: IoView, { fn drop(&mut self, stream: Resource) -> anyhow::Result<()> { in_tokio(async { AsyncHostInputStream::drop(self, stream).await }) diff --git a/crates/wasi/src/host/network.rs b/crates/wasi/src/host/network.rs index 110d4117502c..e7de7e92b656 100644 --- a/crates/wasi/src/host/network.rs +++ b/crates/wasi/src/host/network.rs @@ -3,7 +3,7 @@ use crate::bindings::sockets::network::{ Ipv6SocketAddress, }; use crate::network::{from_ipv4_addr, from_ipv6_addr, to_ipv4_addr, to_ipv6_addr}; -use crate::{SocketError, WasiImpl, WasiView}; +use crate::{IoView, SocketError, WasiImpl, WasiView}; use anyhow::Error; use rustix::io::Errno; use std::io; diff --git a/crates/wasi/src/host/tcp.rs b/crates/wasi/src/host/tcp.rs index 160cb8a757c0..04bfafd7141a 100644 --- a/crates/wasi/src/host/tcp.rs +++ b/crates/wasi/src/host/tcp.rs @@ -7,7 +7,7 @@ use crate::{ }, network::SocketAddressFamily, }; -use crate::{Pollable, SocketResult, WasiImpl, WasiView}; +use crate::{IoView, Pollable, SocketResult, WasiImpl, WasiView}; use std::net::SocketAddr; use std::time::Duration; use wasmtime::component::Resource; diff --git a/crates/wasi/src/host/tcp_create_socket.rs b/crates/wasi/src/host/tcp_create_socket.rs index eadacce05b58..4c846295f552 100644 --- a/crates/wasi/src/host/tcp_create_socket.rs +++ b/crates/wasi/src/host/tcp_create_socket.rs @@ -1,6 +1,6 @@ use crate::bindings::{sockets::network::IpAddressFamily, sockets::tcp_create_socket}; use crate::tcp::TcpSocket; -use crate::{SocketResult, WasiImpl, WasiView}; +use crate::{IoView, SocketResult, WasiImpl, WasiView}; use wasmtime::component::Resource; impl tcp_create_socket::Host for WasiImpl diff --git a/crates/wasi/src/host/udp.rs b/crates/wasi/src/host/udp.rs index 3dd73ff6ffe3..98f1a5644da6 100644 --- a/crates/wasi/src/host/udp.rs +++ b/crates/wasi/src/host/udp.rs @@ -8,7 +8,7 @@ use crate::{ udp::{IncomingDatagramStream, OutgoingDatagramStream, SendState, UdpState}, Subscribe, }; -use crate::{Pollable, SocketError, SocketResult, WasiImpl, WasiView}; +use crate::{IoView, Pollable, SocketError, SocketResult, WasiImpl, WasiView}; use anyhow::anyhow; use async_trait::async_trait; use io_lifetimes::AsSocketlike; diff --git a/crates/wasi/src/host/udp_create_socket.rs b/crates/wasi/src/host/udp_create_socket.rs index f27b574b99ee..533b4d7d5c92 100644 --- a/crates/wasi/src/host/udp_create_socket.rs +++ b/crates/wasi/src/host/udp_create_socket.rs @@ -1,6 +1,6 @@ use crate::bindings::{sockets::network::IpAddressFamily, sockets::udp_create_socket}; use crate::udp::UdpSocket; -use crate::{SocketResult, WasiImpl, WasiView}; +use crate::{IoView, SocketResult, WasiImpl, WasiView}; use wasmtime::component::Resource; impl udp_create_socket::Host for WasiImpl diff --git a/crates/wasi/src/ip_name_lookup.rs b/crates/wasi/src/ip_name_lookup.rs index e013cefb01fc..8ed47b0d1e50 100644 --- a/crates/wasi/src/ip_name_lookup.rs +++ b/crates/wasi/src/ip_name_lookup.rs @@ -3,7 +3,7 @@ use crate::bindings::sockets::network::{ErrorCode, IpAddress, Network}; use crate::host::network::util; use crate::poll::{subscribe, Pollable, Subscribe}; use crate::runtime::{spawn_blocking, AbortOnDropJoinHandle}; -use crate::{SocketError, WasiImpl, WasiView}; +use crate::{IoView, SocketError, WasiImpl, WasiView}; use anyhow::Result; use std::mem; use std::net::{Ipv6Addr, ToSocketAddrs}; diff --git a/crates/wasi/src/lib.rs b/crates/wasi/src/lib.rs index a19c6c42ba6d..58375b784f70 100644 --- a/crates/wasi/src/lib.rs +++ b/crates/wasi/src/lib.rs @@ -205,10 +205,11 @@ mod stdio; mod stream; mod tcp; mod udp; +mod view; mod write_stream; pub use self::clocks::{HostMonotonicClock, HostWallClock}; -pub use self::ctx::{WasiCtx, WasiCtxBuilder, WasiImpl, WasiView}; +pub use self::ctx::{WasiCtx, WasiCtxBuilder}; pub use self::error::{I32Exit, TrappableError}; pub use self::filesystem::{DirPerms, FileInputStream, FilePerms, FsError, FsResult}; pub use self::network::{Network, SocketAddrUse, SocketError, SocketResult}; @@ -221,6 +222,7 @@ pub use self::stdio::{ pub use self::stream::{ HostInputStream, HostOutputStream, InputStream, OutputStream, StreamError, StreamResult, }; +pub use self::view::{IoImpl, IoView, WasiImpl, WasiView}; #[doc(no_inline)] pub use async_trait::async_trait; #[doc(no_inline)] @@ -248,7 +250,7 @@ pub use wasmtime::component::{ResourceTable, ResourceTableError}; /// ``` /// use wasmtime::{Engine, Result, Store, Config}; /// use wasmtime::component::{ResourceTable, Linker}; -/// use wasmtime_wasi::{WasiCtx, WasiView, WasiCtxBuilder}; +/// use wasmtime_wasi::{IoView, WasiCtx, WasiView, WasiCtxBuilder}; /// /// fn main() -> Result<()> { /// let mut config = Config::new(); @@ -281,9 +283,11 @@ pub use wasmtime::component::{ResourceTable, ResourceTableError}; /// table: ResourceTable, /// } /// +/// impl IoView for MyState { +/// fn table(&mut self) -> &mut ResourceTable { &mut self.table } +/// } /// impl WasiView for MyState { /// fn ctx(&mut self) -> &mut WasiCtx { &mut self.ctx } -/// fn table(&mut self) -> &mut ResourceTable { &mut self.table } /// } /// ``` pub fn add_to_linker_async(linker: &mut Linker) -> anyhow::Result<()> { @@ -297,15 +301,16 @@ pub fn add_to_linker_with_options_async( options: &crate::bindings::LinkOptions, ) -> anyhow::Result<()> { let l = linker; - let closure = type_annotate::(|t| WasiImpl(t)); + let io_closure = io_type_annotate::(|t| IoImpl(t)); + let closure = type_annotate::(|t| WasiImpl(IoImpl(t))); crate::bindings::clocks::wall_clock::add_to_linker_get_host(l, closure)?; crate::bindings::clocks::monotonic_clock::add_to_linker_get_host(l, closure)?; crate::bindings::filesystem::types::add_to_linker_get_host(l, closure)?; crate::bindings::filesystem::preopens::add_to_linker_get_host(l, closure)?; - crate::bindings::io::error::add_to_linker_get_host(l, closure)?; - crate::bindings::io::poll::add_to_linker_get_host(l, closure)?; - crate::bindings::io::streams::add_to_linker_get_host(l, closure)?; + crate::bindings::io::error::add_to_linker_get_host(l, io_closure)?; + crate::bindings::io::poll::add_to_linker_get_host(l, io_closure)?; + crate::bindings::io::streams::add_to_linker_get_host(l, io_closure)?; crate::bindings::random::random::add_to_linker_get_host(l, closure)?; crate::bindings::random::insecure::add_to_linker_get_host(l, closure)?; crate::bindings::random::insecure_seed::add_to_linker_get_host(l, closure)?; @@ -347,7 +352,7 @@ pub fn add_to_linker_with_options_async( /// ``` /// use wasmtime::{Engine, Result, Store, Config}; /// use wasmtime::component::{ResourceTable, Linker}; -/// use wasmtime_wasi::{WasiCtx, WasiView, WasiCtxBuilder}; +/// use wasmtime_wasi::{IoView, WasiCtx, WasiView, WasiCtxBuilder}; /// /// fn main() -> Result<()> { /// let engine = Engine::default(); @@ -377,10 +382,11 @@ pub fn add_to_linker_with_options_async( /// ctx: WasiCtx, /// table: ResourceTable, /// } -/// +/// impl IoView for MyState { +/// fn table(&mut self) -> &mut ResourceTable { &mut self.table } +/// } /// impl WasiView for MyState { /// fn ctx(&mut self) -> &mut WasiCtx { &mut self.ctx } -/// fn table(&mut self) -> &mut ResourceTable { &mut self.table } /// } /// ``` pub fn add_to_linker_sync( @@ -396,15 +402,16 @@ pub fn add_to_linker_with_options_sync( options: &crate::bindings::sync::LinkOptions, ) -> anyhow::Result<()> { let l = linker; - let closure = type_annotate::(|t| WasiImpl(t)); + let io_closure = io_type_annotate::(|t| IoImpl(t)); + let closure = type_annotate::(|t| WasiImpl(IoImpl(t))); crate::bindings::clocks::wall_clock::add_to_linker_get_host(l, closure)?; crate::bindings::clocks::monotonic_clock::add_to_linker_get_host(l, closure)?; crate::bindings::sync::filesystem::types::add_to_linker_get_host(l, closure)?; crate::bindings::filesystem::preopens::add_to_linker_get_host(l, closure)?; - crate::bindings::io::error::add_to_linker_get_host(l, closure)?; - crate::bindings::sync::io::poll::add_to_linker_get_host(l, closure)?; - crate::bindings::sync::io::streams::add_to_linker_get_host(l, closure)?; + crate::bindings::io::error::add_to_linker_get_host(l, io_closure)?; + crate::bindings::sync::io::poll::add_to_linker_get_host(l, io_closure)?; + crate::bindings::sync::io::streams::add_to_linker_get_host(l, io_closure)?; crate::bindings::random::random::add_to_linker_get_host(l, closure)?; crate::bindings::random::insecure::add_to_linker_get_host(l, closure)?; crate::bindings::random::insecure_seed::add_to_linker_get_host(l, closure)?; @@ -430,6 +437,12 @@ pub fn add_to_linker_with_options_sync( // NB: workaround some rustc inference - a future refactoring may make this // obsolete. +fn io_type_annotate(val: F) -> F +where + F: Fn(&mut T) -> IoImpl<&mut T>, +{ + val +} fn type_annotate(val: F) -> F where F: Fn(&mut T) -> WasiImpl<&mut T>, diff --git a/crates/wasi/src/poll.rs b/crates/wasi/src/poll.rs index ea494a1dcc85..0d774b9b5e30 100644 --- a/crates/wasi/src/poll.rs +++ b/crates/wasi/src/poll.rs @@ -1,4 +1,4 @@ -use crate::{bindings::io::poll, WasiImpl, WasiView}; +use crate::{bindings::io::poll, IoImpl, IoView}; use anyhow::{anyhow, Result}; use std::any::Any; use std::collections::HashMap; @@ -42,11 +42,11 @@ pub struct Pollable { /// /// ``` /// use tokio::time::{self, Duration, Instant}; -/// use wasmtime_wasi::{WasiView, Subscribe, subscribe, Pollable, async_trait}; +/// use wasmtime_wasi::{IoView, Subscribe, subscribe, Pollable, async_trait}; /// use wasmtime::component::Resource; /// use wasmtime::Result; /// -/// fn sleep(cx: &mut dyn WasiView, dur: Duration) -> Result> { +/// fn sleep(cx: &mut dyn IoView, dur: Duration) -> Result> { /// let end = Instant::now() + dur; /// let sleep = MySleep { end }; /// let sleep_resource = cx.table().push(sleep)?; @@ -116,9 +116,9 @@ where Ok(table.push_child(pollable, &resource)?) } -impl poll::Host for WasiImpl +impl poll::Host for IoImpl where - T: WasiView, + T: IoView, { async fn poll(&mut self, pollables: Vec>) -> Result> { type ReadylistIndex = u32; @@ -177,9 +177,9 @@ where } } -impl crate::bindings::io::poll::HostPollable for WasiImpl +impl crate::bindings::io::poll::HostPollable for IoImpl where - T: WasiView, + T: IoView, { async fn block(&mut self, pollable: Resource) -> Result<()> { let table = self.table(); @@ -212,23 +212,23 @@ pub mod sync { bindings::io::poll as async_poll, bindings::sync::io::poll::{self, Pollable}, runtime::in_tokio, - WasiImpl, WasiView, + IoImpl, IoView, }; use anyhow::Result; use wasmtime::component::Resource; - impl poll::Host for WasiImpl + impl poll::Host for IoImpl where - T: WasiView, + T: IoView, { fn poll(&mut self, pollables: Vec>) -> Result> { in_tokio(async { async_poll::Host::poll(self, pollables).await }) } } - impl crate::bindings::sync::io::poll::HostPollable for WasiImpl + impl crate::bindings::sync::io::poll::HostPollable for IoImpl where - T: WasiView, + T: IoView, { fn ready(&mut self, pollable: Resource) -> Result { in_tokio(async { async_poll::HostPollable::ready(self, pollable).await }) diff --git a/crates/wasi/src/preview1.rs b/crates/wasi/src/preview1.rs index a4aec9b58110..838875d11342 100644 --- a/crates/wasi/src/preview1.rs +++ b/crates/wasi/src/preview1.rs @@ -73,7 +73,8 @@ use crate::bindings::{ io::streams, }; use crate::{ - FsError, IsATTY, ResourceTable, StreamError, StreamResult, WasiCtx, WasiImpl, WasiView, + FsError, IoImpl, IoView, IsATTY, ResourceTable, StreamError, StreamResult, WasiCtx, WasiImpl, + WasiView, }; use anyhow::{bail, Context}; use std::collections::{BTreeMap, HashSet}; @@ -153,14 +154,19 @@ impl WasiP1Ctx { } fn as_wasi_impl(&mut self) -> WasiImpl<&mut Self> { - WasiImpl(self) + WasiImpl(IoImpl(self)) + } + fn as_io_impl(&mut self) -> IoImpl<&mut Self> { + IoImpl(self) } } -impl WasiView for WasiP1Ctx { +impl IoView for WasiP1Ctx { fn table(&mut self) -> &mut ResourceTable { &mut self.table } +} +impl WasiView for WasiP1Ctx { fn ctx(&mut self) -> &mut WasiCtx { &mut self.wasi } @@ -648,7 +654,7 @@ impl WasiP1Ctx { drop(t); let buf = first_non_empty_ciovec(memory, ciovs)?; let n = BlockingMode::Blocking - .write(memory, &mut self.as_wasi_impl(), stream, buf) + .write(memory, &mut self.as_io_impl(), stream, buf) .await? .try_into()?; Ok(n) @@ -1323,12 +1329,12 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { .ok_or(types::Errno::Badf)?; match desc { Descriptor::Stdin { stream, .. } => { - streams::HostInputStream::drop(&mut self.as_wasi_impl(), stream) + streams::HostInputStream::drop(&mut self.as_io_impl(), stream) .await .context("failed to call `drop` on `input-stream`") } Descriptor::Stdout { stream, .. } | Descriptor::Stderr { stream, .. } => { - streams::HostOutputStream::drop(&mut self.as_wasi_impl(), stream) + streams::HostOutputStream::drop(&mut self.as_io_impl(), stream) .await .context("failed to call `drop` on `output-stream`") } @@ -1679,7 +1685,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { drop(t); let buf = first_non_empty_iovec(memory, iovs)?; let read = BlockingMode::Blocking - .read(&mut self.as_wasi_impl(), stream, buf.len().try_into()?) + .read(&mut self.as_io_impl(), stream, buf.len().try_into()?) .await?; if read.len() > buf.len().try_into()? { return Err(types::Errno::Range.into()); @@ -1717,12 +1723,12 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { let stream = self.as_wasi_impl().read_via_stream(fd, offset)?; let read = blocking_mode .read( - &mut self.as_wasi_impl(), + &mut self.as_io_impl(), stream.borrowed(), buf.len().try_into()?, ) .await; - streams::HostInputStream::drop(&mut self.as_wasi_impl(), stream) + streams::HostInputStream::drop(&mut self.as_io_impl(), stream) .await .map_err(|e| types::Error::trap(e))?; (buf, read?) @@ -2367,7 +2373,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { _ => return Err(types::Errno::Badf.into()), } }; - streams::HostInputStream::subscribe(&mut self.as_wasi_impl(), stream) + streams::HostInputStream::subscribe(&mut self.as_io_impl(), stream) .context("failed to call `subscribe` on `input-stream`") .map_err(types::Error::trap)? } @@ -2401,7 +2407,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { _ => return Err(types::Errno::Badf.into()), } }; - streams::HostOutputStream::subscribe(&mut self.as_wasi_impl(), stream) + streams::HostOutputStream::subscribe(&mut self.as_io_impl(), stream) .context("failed to call `subscribe` on `output-stream`") .map_err(types::Error::trap)? } @@ -2409,7 +2415,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { pollables.push(p); } let ready: HashSet<_> = self - .as_wasi_impl() + .as_io_impl() .poll(pollables) .await .context("failed to call `poll-oneoff`") diff --git a/crates/wasi/src/stdio.rs b/crates/wasi/src/stdio.rs index 4fb359f394fb..17ab5820db73 100644 --- a/crates/wasi/src/stdio.rs +++ b/crates/wasi/src/stdio.rs @@ -5,7 +5,8 @@ use crate::bindings::cli::{ use crate::bindings::io::streams; use crate::pipe; use crate::{ - HostInputStream, HostOutputStream, StreamError, StreamResult, Subscribe, WasiImpl, WasiView, + HostInputStream, HostOutputStream, IoView, StreamError, StreamResult, Subscribe, WasiImpl, + WasiView, }; use bytes::Bytes; use std::io::IsTerminal; diff --git a/crates/wasi/src/view.rs b/crates/wasi/src/view.rs new file mode 100644 index 000000000000..58375b1b60ab --- /dev/null +++ b/crates/wasi/src/view.rs @@ -0,0 +1,86 @@ +use crate::ctx::WasiCtx; +use wasmtime::component::ResourceTable; + +pub trait IoView: Send { + /// Yields mutable access to the internal resource management that this + /// context contains. + /// + /// Embedders can add custom resources to this table as well to give + /// resources to wasm as well. + fn table(&mut self) -> &mut ResourceTable; +} + +pub trait WasiView: IoView { + /// Yields mutable access to the configuration used for this context. + /// + /// The returned type is created through [`WasiCtxBuilder`]. + fn ctx(&mut self) -> &mut WasiCtx; +} + +impl IoView for &mut T { + fn table(&mut self) -> &mut ResourceTable { + T::table(self) + } +} +impl WasiView for &mut T { + fn ctx(&mut self) -> &mut WasiCtx { + T::ctx(self) + } +} + +impl IoView for Box { + fn table(&mut self) -> &mut ResourceTable { + T::table(self) + } +} +impl WasiView for Box { + fn ctx(&mut self) -> &mut WasiCtx { + T::ctx(self) + } +} + +/// A small newtype wrapper which serves as the basis for implementations of +/// `Host` WASI traits in this crate. +/// +/// This type is used as the basis for the implementation of all `Host` traits +/// generated by `bindgen!` for WASI interfaces. This is used automatically with +/// [`add_to_linker_sync`](crate::add_to_linker_sync) and +/// [`add_to_linker_async`](crate::add_to_linker_async). +/// +/// This type is otherwise provided if you're calling the `add_to_linker` +/// functions generated by `bindgen!` from the [`bindings` +/// module](crate::bindings). In this situation you'll want to create a value of +/// this type in the closures added to a `Linker`. +#[repr(transparent)] +pub struct IoImpl(pub T); +impl IoView for IoImpl { + fn table(&mut self) -> &mut ResourceTable { + T::table(&mut self.0) + } +} + +/// A small newtype wrapper which serves as the basis for implementations of +/// `Host` WASI traits in this crate. +/// +/// This type is used as the basis for the implementation of all `Host` traits +/// generated by `bindgen!` for WASI interfaces. This is used automatically with +/// [`add_to_linker_sync`](crate::add_to_linker_sync) and +/// [`add_to_linker_async`](crate::add_to_linker_async). +/// +/// This type is otherwise provided if you're calling the `add_to_linker` +/// functions generated by `bindgen!` from the [`bindings` +/// module](crate::bindings). In this situation you'll want to create a value of +/// this type in the closures added to a `Linker`. +#[repr(transparent)] +pub struct WasiImpl(pub IoImpl); + +impl IoView for WasiImpl { + fn table(&mut self) -> &mut ResourceTable { + T::table(&mut self.0 .0) + } +} +impl WasiView for WasiImpl { + fn ctx(&mut self) -> &mut WasiCtx { + T::ctx(&mut self.0 .0) + } +} diff --git a/crates/wasi/tests/all/api.rs b/crates/wasi/tests/all/api.rs index 39d68a5f71a7..ca5219988744 100644 --- a/crates/wasi/tests/all/api.rs +++ b/crates/wasi/tests/all/api.rs @@ -10,7 +10,8 @@ use wasmtime_wasi::bindings::Command; use wasmtime_wasi::{ add_to_linker_async, bindings::{clocks::wall_clock, filesystem::types as filesystem}, - DirPerms, FilePerms, HostMonotonicClock, HostWallClock, WasiCtx, WasiCtxBuilder, WasiView, + DirPerms, FilePerms, HostMonotonicClock, HostWallClock, IoView, WasiCtx, WasiCtxBuilder, + WasiView, }; struct CommandCtx { @@ -18,10 +19,12 @@ struct CommandCtx { wasi: WasiCtx, } -impl WasiView for CommandCtx { +impl IoView for CommandCtx { fn table(&mut self) -> &mut ResourceTable { &mut self.table } +} +impl WasiView for CommandCtx { fn ctx(&mut self) -> &mut WasiCtx { &mut self.wasi } diff --git a/crates/wasi/tests/all/main.rs b/crates/wasi/tests/all/main.rs index 19924d42c19a..9a7d0782ad83 100644 --- a/crates/wasi/tests/all/main.rs +++ b/crates/wasi/tests/all/main.rs @@ -6,7 +6,7 @@ use wasmtime::{ }; use wasmtime_wasi::preview1::WasiP1Ctx; use wasmtime_wasi::{ - pipe::MemoryOutputPipe, DirPerms, FilePerms, WasiCtx, WasiCtxBuilder, WasiView, + pipe::MemoryOutputPipe, DirPerms, FilePerms, IoView, WasiCtx, WasiCtxBuilder, WasiView, }; struct Ctx { @@ -15,10 +15,12 @@ struct Ctx { wasi: WasiP1Ctx, } -impl WasiView for Ctx { +impl IoView for Ctx { fn table(&mut self) -> &mut ResourceTable { self.wasi.table() } +} +impl WasiView for Ctx { fn ctx(&mut self) -> &mut WasiCtx { self.wasi.ctx() } diff --git a/examples/wasip2-async/main.rs b/examples/wasip2-async/main.rs index 29877ac3c693..9289773c3de5 100644 --- a/examples/wasip2-async/main.rs +++ b/examples/wasip2-async/main.rs @@ -10,20 +10,23 @@ You can execute this example with: use wasmtime::component::{Component, Linker, ResourceTable}; use wasmtime::*; use wasmtime_wasi::bindings::Command; -use wasmtime_wasi::{WasiCtx, WasiCtxBuilder, WasiView}; +use wasmtime_wasi::{IoView, WasiCtx, WasiCtxBuilder, WasiView}; pub struct ComponentRunStates { - // These two are required basically as a standard way to enable the impl of WasiView + // These two are required basically as a standard way to enable the impl of IoView and + // WasiView. // impl of WasiView is required by [`wasmtime_wasi::add_to_linker_sync`] pub wasi_ctx: WasiCtx, pub resource_table: ResourceTable, // You can add other custom host states if needed } -impl WasiView for ComponentRunStates { +impl IoView for ComponentRunStates { fn table(&mut self) -> &mut ResourceTable { &mut self.resource_table } +} +impl WasiView for ComponentRunStates { fn ctx(&mut self) -> &mut WasiCtx { &mut self.wasi_ctx } diff --git a/examples/wasip2/main.rs b/examples/wasip2/main.rs index cfcfcb543123..bda98b541d6c 100644 --- a/examples/wasip2/main.rs +++ b/examples/wasip2/main.rs @@ -9,20 +9,23 @@ You can execute this example with: use wasmtime::component::{Component, Linker, ResourceTable}; use wasmtime::*; use wasmtime_wasi::bindings::sync::Command; -use wasmtime_wasi::{WasiCtx, WasiCtxBuilder, WasiView}; +use wasmtime_wasi::{IoView, WasiCtx, WasiCtxBuilder, WasiView}; pub struct ComponentRunStates { - // These two are required basically as a standard way to enable the impl of WasiView + // These two are required basically as a standard way to enable the impl of IoView and + // WasiView. // impl of WasiView is required by [`wasmtime_wasi::add_to_linker_sync`] pub wasi_ctx: WasiCtx, pub resource_table: ResourceTable, // You can add other custom host states if needed } -impl WasiView for ComponentRunStates { +impl IoView for ComponentRunStates { fn table(&mut self) -> &mut ResourceTable { &mut self.resource_table } +} +impl WasiView for ComponentRunStates { fn ctx(&mut self) -> &mut WasiCtx { &mut self.wasi_ctx } diff --git a/src/commands/run.rs b/src/commands/run.rs index e154ad50542c..bd45e2daa5c2 100644 --- a/src/commands/run.rs +++ b/src/commands/run.rs @@ -15,7 +15,7 @@ use std::sync::{Arc, Mutex}; use std::thread; use wasi_common::sync::{ambient_authority, Dir, TcpListener, WasiCtxBuilder}; use wasmtime::{Engine, Func, Module, Store, StoreLimits, Val, ValType}; -use wasmtime_wasi::WasiView; +use wasmtime_wasi::{IoView, WasiView}; #[cfg(feature = "wasi-nn")] use wasmtime_wasi_nn::wit::WasiNnView; @@ -945,11 +945,12 @@ impl Host { } } -impl WasiView for Host { +impl IoView for Host { fn table(&mut self) -> &mut wasmtime::component::ResourceTable { self.preview2_ctx().table() } - +} +impl WasiView for Host { fn ctx(&mut self) -> &mut wasmtime_wasi::WasiCtx { self.preview2_ctx().ctx() } @@ -962,10 +963,6 @@ impl wasmtime_wasi_http::types::WasiHttpView for Host { Arc::get_mut(ctx).expect("wasmtime_wasi is not compatible with threads") } - fn table(&mut self) -> &mut wasmtime::component::ResourceTable { - self.preview2_ctx().table() - } - fn outgoing_body_buffer_chunks(&mut self) -> usize { self.wasi_http_outgoing_body_buffer_chunks .unwrap_or_else(|| DEFAULT_OUTGOING_BODY_BUFFER_CHUNKS) diff --git a/src/commands/serve.rs b/src/commands/serve.rs index 5f13d391feff..cd54a468a910 100644 --- a/src/commands/serve.rs +++ b/src/commands/serve.rs @@ -11,7 +11,7 @@ use std::{ }; use wasmtime::component::Linker; use wasmtime::{Engine, Store, StoreLimits}; -use wasmtime_wasi::{StreamError, StreamResult, WasiCtx, WasiCtxBuilder, WasiView}; +use wasmtime_wasi::{IoView, StreamError, StreamResult, WasiCtx, WasiCtxBuilder, WasiView}; use wasmtime_wasi_http::bindings::http::types::Scheme; use wasmtime_wasi_http::bindings::ProxyPre; use wasmtime_wasi_http::io::TokioIo; @@ -46,21 +46,18 @@ struct Host { wasi_keyvalue: Option, } -impl WasiView for Host { +impl IoView for Host { fn table(&mut self) -> &mut wasmtime::component::ResourceTable { &mut self.table } - +} +impl WasiView for Host { fn ctx(&mut self) -> &mut WasiCtx { &mut self.ctx } } impl WasiHttpView for Host { - fn table(&mut self) -> &mut wasmtime::component::ResourceTable { - &mut self.table - } - fn ctx(&mut self) -> &mut WasiHttpCtx { &mut self.http }