From 69a78fc1359769f320b5968042cb9d988336dd54 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 10 Jun 2024 17:45:45 -0500 Subject: [PATCH] [22.0.0] Change WASI trait impls back to being blanket impls (#8767) * Change WASI trait impls back to being blanket impls (#8766) This commit is a partial revert of #8609 to return `wasmtime-wasi` and `wasmtime-wasi-http` back to using blanket impls. The main change from before is to change the blanket impls to be in terms of a local newtype wrapper to avoid trait coherence issues. This is done because otherwise using the traits before required `&mut dyn WasiView` to exist but sometimes only a `Foo<'a>` is held which is not easy to get a `&mut dyn ...` view of. By changing to a blanket impl in terms of a newtype wrapper, `WasiImpl`, it's possible to call `bindgen!`-generated `add_to_linker_get_host` functions with a return value of `WasiImpl>` which enables hooking into all the generated bindings. * Update release notes --- RELEASES.md | 3 +- crates/wasi-http/src/http_impl.rs | 7 +- crates/wasi-http/src/lib.rs | 2 +- crates/wasi-http/src/proxy.rs | 16 +-- crates/wasi-http/src/types.rs | 77 ++++++++++++ crates/wasi-http/src/types_impl.rs | 62 ++++++++-- crates/wasi/src/ctx.rs | 33 +++++ crates/wasi/src/host/clocks.rs | 12 +- crates/wasi/src/host/env.rs | 7 +- crates/wasi/src/host/exit.rs | 7 +- crates/wasi/src/host/filesystem.rs | 22 +++- crates/wasi/src/host/filesystem/sync.rs | 17 ++- crates/wasi/src/host/instance_network.rs | 7 +- crates/wasi/src/host/io.rs | 41 +++++-- crates/wasi/src/host/network.rs | 12 +- crates/wasi/src/host/random.rs | 17 ++- crates/wasi/src/host/tcp.rs | 18 ++- crates/wasi/src/host/tcp_create_socket.rs | 7 +- crates/wasi/src/host/udp.rs | 38 ++++-- crates/wasi/src/host/udp_create_socket.rs | 7 +- crates/wasi/src/ip_name_lookup.rs | 12 +- crates/wasi/src/lib.rs | 8 +- crates/wasi/src/poll.rs | 24 +++- crates/wasi/src/preview1.rs | 142 ++++++++++++---------- crates/wasi/src/stdio.rs | 48 ++++++-- 25 files changed, 475 insertions(+), 171 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index ccd4e81dbfcf..029f05aeb407 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -86,8 +86,9 @@ Unreleased. [#8610](https://github.com/bytecodealliance/wasmtime/pull/8610) * Implementations of `Host` traits in the `wasmtime-wasi` crate are now for - `dyn WasiView` instead of blanket impls for `T: WasiView`. + `WasiImpl` instead of blanket impls for `T`. [#8609](https://github.com/bytecodealliance/wasmtime/pull/8609) + [#8766](https://github.com/bytecodealliance/wasmtime/pull/8766) * The concepts of "virtual sp offset" and "nominal sp" have been removed from all Cranelift backends. diff --git a/crates/wasi-http/src/http_impl.rs b/crates/wasi-http/src/http_impl.rs index 1fc03bbc2d33..53f3bc33b2be 100644 --- a/crates/wasi-http/src/http_impl.rs +++ b/crates/wasi-http/src/http_impl.rs @@ -8,14 +8,17 @@ use crate::{ error::internal_error, http_request_error, types::{HostFutureIncomingResponse, HostOutgoingRequest, OutgoingRequestConfig}, - WasiHttpView, + WasiHttpImpl, WasiHttpView, }; use bytes::Bytes; use http_body_util::{BodyExt, Empty}; use hyper::Method; use wasmtime::component::Resource; -impl outgoing_handler::Host for dyn WasiHttpView + '_ { +impl outgoing_handler::Host for WasiHttpImpl +where + T: WasiHttpView, +{ fn handle( &mut self, request_id: Resource, diff --git a/crates/wasi-http/src/lib.rs b/crates/wasi-http/src/lib.rs index f34184252b12..fc0d98b4aee3 100644 --- a/crates/wasi-http/src/lib.rs +++ b/crates/wasi-http/src/lib.rs @@ -87,4 +87,4 @@ pub use crate::error::{ http_request_error, hyper_request_error, hyper_response_error, HttpError, HttpResult, }; #[doc(inline)] -pub use crate::types::{WasiHttpCtx, WasiHttpView}; +pub use crate::types::{WasiHttpCtx, WasiHttpImpl, WasiHttpView}; diff --git a/crates/wasi-http/src/proxy.rs b/crates/wasi-http/src/proxy.rs index 23454af11798..2fdf3adb6c8c 100644 --- a/crates/wasi-http/src/proxy.rs +++ b/crates/wasi-http/src/proxy.rs @@ -3,7 +3,7 @@ //! The implementation at the top of the module for use in async contexts, //! while the `sync` module provides implementation for use in sync contexts. -use crate::WasiHttpView; +use crate::{WasiHttpImpl, WasiHttpView}; mod bindings { #![allow(missing_docs)] @@ -83,7 +83,7 @@ pub fn add_to_linker(l: &mut wasmtime::component::Linker) -> anyhow::Resul where T: WasiHttpView + wasmtime_wasi::WasiView, { - let closure = type_annotate_wasi::(|t| t); + let closure = type_annotate_wasi::(|t| wasmtime_wasi::WasiImpl(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)?; @@ -101,13 +101,13 @@ where // obsolete. fn type_annotate_http(val: F) -> F where - F: Fn(&mut T) -> &mut dyn WasiHttpView, + F: Fn(&mut T) -> WasiHttpImpl<&mut T>, { val } fn type_annotate_wasi(val: F) -> F where - F: Fn(&mut T) -> &mut dyn wasmtime_wasi::WasiView, + F: Fn(&mut T) -> wasmtime_wasi::WasiImpl<&mut T>, { val } @@ -117,7 +117,7 @@ pub fn add_only_http_to_linker(l: &mut wasmtime::component::Linker) -> any where T: WasiHttpView, { - let closure = type_annotate_http::(|t| t); + let closure = type_annotate_http::(|t| WasiHttpImpl(t)); crate::bindings::http::outgoing_handler::add_to_linker_get_host(l, closure)?; crate::bindings::http::types::add_to_linker_get_host(l, closure)?; @@ -126,7 +126,7 @@ where /// Sync implementation of the `wasi:http/proxy` world. pub mod sync { - use crate::WasiHttpView; + use crate::{WasiHttpImpl, WasiHttpView}; mod bindings { #![allow(missing_docs)] @@ -203,7 +203,7 @@ pub mod sync { where T: WasiHttpView + wasmtime_wasi::WasiView, { - let closure = super::type_annotate_wasi::(|t| t); + let closure = super::type_annotate_wasi::(|t| wasmtime_wasi::WasiImpl(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)?; @@ -226,7 +226,7 @@ pub mod sync { where T: WasiHttpView, { - let closure = super::type_annotate_http::(|t| t); + let closure = super::type_annotate_http::(|t| WasiHttpImpl(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 674cea88af3e..23baa6cb8359 100644 --- a/crates/wasi-http/src/types.rs +++ b/crates/wasi-http/src/types.rs @@ -112,6 +112,83 @@ impl WasiHttpView for &mut T { } } +impl WasiHttpView for Box { + fn ctx(&mut self) -> &mut WasiHttpCtx { + T::ctx(self) + } + + fn table(&mut self) -> &mut ResourceTable { + T::table(self) + } + + fn new_response_outparam( + &mut self, + result: tokio::sync::oneshot::Sender< + Result, types::ErrorCode>, + >, + ) -> wasmtime::Result> { + T::new_response_outparam(self, result) + } + + fn send_request( + &mut self, + request: hyper::Request, + config: OutgoingRequestConfig, + ) -> crate::HttpResult { + T::send_request(self, request, config) + } + + fn is_forbidden_header(&mut self, name: &HeaderName) -> bool { + T::is_forbidden_header(self, name) + } +} + +/// A concrete structure that all generated `Host` traits are implemented for. +/// +/// This type serves as a small newtype wrapper to implement all of the `Host` +/// traits for `wasi:http`. This type is internally used and is only needed if +/// you're interacting with `add_to_linker` functions generated by bindings +/// themselves (or `add_to_linker_get_host`). +/// +/// This type is automatically used when using +/// [`wasmtime_wasi_http::proxy::add_to_linker`](crate::proxy::add_to_linker) +/// or +/// [`wasmtime_wasi_http::proxy::sync::add_to_linker`](crate::proxy::sync::add_to_linker) +/// and doesn't need to be manually configured. +#[repr(transparent)] +pub struct WasiHttpImpl(pub T); + +impl WasiHttpView for WasiHttpImpl { + fn ctx(&mut self) -> &mut WasiHttpCtx { + self.0.ctx() + } + + fn table(&mut self) -> &mut ResourceTable { + self.0.table() + } + + fn new_response_outparam( + &mut self, + result: tokio::sync::oneshot::Sender< + Result, types::ErrorCode>, + >, + ) -> wasmtime::Result> { + self.0.new_response_outparam(result) + } + + fn send_request( + &mut self, + request: hyper::Request, + config: OutgoingRequestConfig, + ) -> crate::HttpResult { + self.0.send_request(request, config) + } + + fn is_forbidden_header(&mut self, name: &HeaderName) -> bool { + self.0.is_forbidden_header(name) + } +} + /// Returns `true` when the header is forbidden according to this [`WasiHttpView`] implementation. pub(crate) fn is_forbidden_header(view: &mut dyn WasiHttpView, name: &HeaderName) -> bool { static FORBIDDEN_HEADERS: [HeaderName; 10] = [ diff --git a/crates/wasi-http/src/types_impl.rs b/crates/wasi-http/src/types_impl.rs index 34213a034874..a1d637322abc 100644 --- a/crates/wasi-http/src/types_impl.rs +++ b/crates/wasi-http/src/types_impl.rs @@ -8,7 +8,7 @@ use crate::{ HostFutureIncomingResponse, HostIncomingRequest, HostIncomingResponse, HostOutgoingRequest, HostOutgoingResponse, HostResponseOutparam, }, - WasiHttpView, + WasiHttpImpl, WasiHttpView, }; use anyhow::Context; use std::any::Any; @@ -19,7 +19,10 @@ use wasmtime_wasi::{ Pollable, ResourceTableError, }; -impl crate::bindings::http::types::Host for dyn WasiHttpView + '_ { +impl crate::bindings::http::types::Host for WasiHttpImpl +where + T: WasiHttpView, +{ fn convert_error_code(&mut self, err: crate::HttpError) -> wasmtime::Result { err.downcast() } @@ -98,7 +101,10 @@ fn get_fields_mut<'a>( } } -impl crate::bindings::http::types::HostFields for dyn WasiHttpView + '_ { +impl crate::bindings::http::types::HostFields for WasiHttpImpl +where + T: WasiHttpView, +{ fn new(&mut self) -> wasmtime::Result> { let id = self .table() @@ -285,7 +291,10 @@ impl crate::bindings::http::types::HostFields for dyn WasiHttpView + '_ { } } -impl crate::bindings::http::types::HostIncomingRequest for dyn WasiHttpView + '_ { +impl crate::bindings::http::types::HostIncomingRequest for WasiHttpImpl +where + T: WasiHttpView, +{ fn method(&mut self, id: Resource) -> wasmtime::Result { let method = self.table().get(&id)?.parts.method.clone(); Ok(method.into()) @@ -370,7 +379,10 @@ impl crate::bindings::http::types::HostIncomingRequest for dyn WasiHttpView + '_ } } -impl crate::bindings::http::types::HostOutgoingRequest for dyn WasiHttpView + '_ { +impl crate::bindings::http::types::HostOutgoingRequest for WasiHttpImpl +where + T: WasiHttpView, +{ fn new( &mut self, headers: Resource, @@ -556,7 +568,10 @@ impl crate::bindings::http::types::HostOutgoingRequest for dyn WasiHttpView + '_ } } -impl crate::bindings::http::types::HostResponseOutparam for dyn WasiHttpView + '_ { +impl crate::bindings::http::types::HostResponseOutparam for WasiHttpImpl +where + T: WasiHttpView, +{ fn drop(&mut self, id: Resource) -> wasmtime::Result<()> { let _ = self.table().delete(id)?; Ok(()) @@ -579,7 +594,10 @@ impl crate::bindings::http::types::HostResponseOutparam for dyn WasiHttpView + ' } } -impl crate::bindings::http::types::HostIncomingResponse for dyn WasiHttpView + '_ { +impl crate::bindings::http::types::HostIncomingResponse for WasiHttpImpl +where + T: WasiHttpView, +{ fn drop(&mut self, response: Resource) -> wasmtime::Result<()> { let _ = self .table() @@ -640,7 +658,10 @@ impl crate::bindings::http::types::HostIncomingResponse for dyn WasiHttpView + ' } } -impl crate::bindings::http::types::HostFutureTrailers for dyn WasiHttpView + '_ { +impl crate::bindings::http::types::HostFutureTrailers for WasiHttpImpl +where + T: WasiHttpView, +{ fn drop(&mut self, id: Resource) -> wasmtime::Result<()> { let _ = self .table() @@ -687,7 +708,10 @@ impl crate::bindings::http::types::HostFutureTrailers for dyn WasiHttpView + '_ } } -impl crate::bindings::http::types::HostIncomingBody for dyn WasiHttpView + '_ { +impl crate::bindings::http::types::HostIncomingBody for WasiHttpImpl +where + T: WasiHttpView, +{ fn stream( &mut self, id: Resource, @@ -718,7 +742,10 @@ impl crate::bindings::http::types::HostIncomingBody for dyn WasiHttpView + '_ { } } -impl crate::bindings::http::types::HostOutgoingResponse for dyn WasiHttpView + '_ { +impl crate::bindings::http::types::HostOutgoingResponse for WasiHttpImpl +where + T: WasiHttpView, +{ fn new( &mut self, headers: Resource, @@ -807,7 +834,10 @@ impl crate::bindings::http::types::HostOutgoingResponse for dyn WasiHttpView + ' } } -impl crate::bindings::http::types::HostFutureIncomingResponse for dyn WasiHttpView + '_ { +impl crate::bindings::http::types::HostFutureIncomingResponse for WasiHttpImpl +where + T: WasiHttpView, +{ fn drop(&mut self, id: Resource) -> wasmtime::Result<()> { let _ = self.table().delete(id)?; Ok(()) @@ -866,7 +896,10 @@ impl crate::bindings::http::types::HostFutureIncomingResponse for dyn WasiHttpVi } } -impl crate::bindings::http::types::HostOutgoingBody for dyn WasiHttpView + '_ { +impl crate::bindings::http::types::HostOutgoingBody for WasiHttpImpl +where + T: WasiHttpView, +{ fn write( &mut self, id: Resource, @@ -903,7 +936,10 @@ impl crate::bindings::http::types::HostOutgoingBody for dyn WasiHttpView + '_ { } } -impl crate::bindings::http::types::HostRequestOptions for dyn WasiHttpView + '_ { +impl crate::bindings::http::types::HostRequestOptions for WasiHttpImpl +where + T: WasiHttpView, +{ fn new(&mut self) -> wasmtime::Result> { let id = self.table().push(types::RequestOptions::default())?; Ok(id) diff --git a/crates/wasi/src/ctx.rs b/crates/wasi/src/ctx.rs index c0d8c4b71d54..136047b9c887 100644 --- a/crates/wasi/src/ctx.rs +++ b/crates/wasi/src/ctx.rs @@ -594,6 +594,39 @@ impl WasiView for &mut T { } } +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 2dba6dc640fb..e94ca98555ff 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, WasiView}; +use crate::{Pollable, WasiImpl, WasiView}; use cap_std::time::SystemTime; use std::time::Duration; use wasmtime::component::Resource; @@ -24,7 +24,10 @@ impl TryFrom for Datetime { } } -impl wall_clock::Host for dyn WasiView + '_ { +impl wall_clock::Host for WasiImpl +where + T: WasiView, +{ fn now(&mut self) -> anyhow::Result { let now = self.ctx().wall_clock.now(); Ok(Datetime { @@ -61,7 +64,10 @@ fn subscribe_to_duration( subscribe(table, sleep) } -impl monotonic_clock::Host for dyn WasiView + '_ { +impl monotonic_clock::Host for WasiImpl +where + T: WasiView, +{ fn now(&mut self) -> anyhow::Result { Ok(self.ctx().monotonic_clock.now()) } diff --git a/crates/wasi/src/host/env.rs b/crates/wasi/src/host/env.rs index 77816e0364c6..db259d8caa14 100644 --- a/crates/wasi/src/host/env.rs +++ b/crates/wasi/src/host/env.rs @@ -1,7 +1,10 @@ use crate::bindings::cli::environment; -use crate::WasiView; +use crate::{WasiImpl, WasiView}; -impl environment::Host for dyn WasiView + '_ { +impl environment::Host for WasiImpl +where + T: WasiView, +{ fn get_environment(&mut self) -> anyhow::Result> { Ok(self.ctx().env.clone()) } diff --git a/crates/wasi/src/host/exit.rs b/crates/wasi/src/host/exit.rs index 26ef6acfe493..be3129fa12fc 100644 --- a/crates/wasi/src/host/exit.rs +++ b/crates/wasi/src/host/exit.rs @@ -1,6 +1,9 @@ -use crate::{bindings::cli::exit, I32Exit, WasiView}; +use crate::{bindings::cli::exit, I32Exit, WasiImpl, WasiView}; -impl exit::Host for dyn WasiView + '_ { +impl exit::Host for WasiImpl +where + T: WasiView, +{ fn exit(&mut self, status: Result<(), ()>) -> anyhow::Result<()> { let status = match status { Ok(()) => 0, diff --git a/crates/wasi/src/host/filesystem.rs b/crates/wasi/src/host/filesystem.rs index 53fa7355a14b..78dcbec4104d 100644 --- a/crates/wasi/src/host/filesystem.rs +++ b/crates/wasi/src/host/filesystem.rs @@ -7,13 +7,16 @@ use crate::bindings::io::streams::{InputStream, OutputStream}; use crate::filesystem::{ Descriptor, Dir, File, FileInputStream, FileOutputStream, OpenMode, ReaddirIterator, }; -use crate::{DirPerms, FilePerms, FsError, FsResult, WasiView}; +use crate::{DirPerms, FilePerms, FsError, FsResult, WasiImpl, WasiView}; use anyhow::Context; use wasmtime::component::Resource; mod sync; -impl preopens::Host for dyn WasiView + '_ { +impl preopens::Host for WasiImpl +where + T: WasiView, +{ fn get_directories( &mut self, ) -> Result, String)>, anyhow::Error> { @@ -30,7 +33,10 @@ impl preopens::Host for dyn WasiView + '_ { } #[async_trait::async_trait] -impl types::Host for dyn WasiView + '_ { +impl types::Host for WasiImpl +where + T: WasiView, +{ fn convert_error_code(&mut self, err: FsError) -> anyhow::Result { err.downcast() } @@ -52,7 +58,10 @@ impl types::Host for dyn WasiView + '_ { } #[async_trait::async_trait] -impl HostDescriptor for dyn WasiView + '_ { +impl HostDescriptor for WasiImpl +where + T: WasiView, +{ async fn advise( &mut self, fd: Resource, @@ -846,7 +855,10 @@ impl HostDescriptor for dyn WasiView + '_ { } #[async_trait::async_trait] -impl HostDirectoryEntryStream for dyn WasiView + '_ { +impl HostDirectoryEntryStream for WasiImpl +where + T: WasiView, +{ async fn read_directory_entry( &mut self, stream: Resource, diff --git a/crates/wasi/src/host/filesystem/sync.rs b/crates/wasi/src/host/filesystem/sync.rs index e3fabdcf5620..5de6b051921d 100644 --- a/crates/wasi/src/host/filesystem/sync.rs +++ b/crates/wasi/src/host/filesystem/sync.rs @@ -2,10 +2,13 @@ use crate::bindings::filesystem::types as async_filesystem; use crate::bindings::sync::filesystem::types as sync_filesystem; use crate::bindings::sync::io::streams; use crate::runtime::in_tokio; -use crate::{FsError, FsResult, WasiView}; +use crate::{FsError, FsResult, WasiImpl, WasiView}; use wasmtime::component::Resource; -impl sync_filesystem::Host for dyn WasiView + '_ { +impl sync_filesystem::Host for WasiImpl +where + T: WasiView, +{ fn convert_error_code(&mut self, err: FsError) -> anyhow::Result { Ok(async_filesystem::Host::convert_error_code(self, err)?.into()) } @@ -18,7 +21,10 @@ impl sync_filesystem::Host for dyn WasiView + '_ { } } -impl sync_filesystem::HostDescriptor for dyn WasiView + '_ { +impl sync_filesystem::HostDescriptor for WasiImpl +where + T: WasiView, +{ fn advise( &mut self, fd: Resource, @@ -302,7 +308,10 @@ impl sync_filesystem::HostDescriptor for dyn WasiView + '_ { } } -impl sync_filesystem::HostDirectoryEntryStream for dyn WasiView + '_ { +impl sync_filesystem::HostDirectoryEntryStream for WasiImpl +where + T: WasiView, +{ fn read_directory_entry( &mut self, stream: Resource, diff --git a/crates/wasi/src/host/instance_network.rs b/crates/wasi/src/host/instance_network.rs index 0bb35dbe4183..edf097d8679c 100644 --- a/crates/wasi/src/host/instance_network.rs +++ b/crates/wasi/src/host/instance_network.rs @@ -1,9 +1,12 @@ use crate::bindings::sockets::instance_network; use crate::network::Network; -use crate::WasiView; +use crate::{WasiImpl, WasiView}; use wasmtime::component::Resource; -impl instance_network::Host for dyn WasiView + '_ { +impl instance_network::Host for WasiImpl +where + T: WasiView, +{ fn instance_network(&mut self) -> Result, anyhow::Error> { let network = Network { socket_addr_check: self.ctx().socket_addr_check.clone(), diff --git a/crates/wasi/src/host/io.rs b/crates/wasi/src/host/io.rs index 1aee78259201..1b4504b17ac2 100644 --- a/crates/wasi/src/host/io.rs +++ b/crates/wasi/src/host/io.rs @@ -2,13 +2,16 @@ use crate::{ bindings::io::error, bindings::io::streams::{self, InputStream, OutputStream}, poll::subscribe, - Pollable, StreamError, StreamResult, WasiView, + Pollable, StreamError, StreamResult, WasiImpl, WasiView, }; use wasmtime::component::Resource; -impl error::Host for dyn WasiView + '_ {} +impl error::Host for WasiImpl where T: WasiView {} -impl streams::Host for dyn WasiView + '_ { +impl streams::Host for WasiImpl +where + T: WasiView, +{ fn convert_stream_error(&mut self, err: StreamError) -> anyhow::Result { match err { StreamError::Closed => Ok(streams::StreamError::Closed), @@ -20,7 +23,10 @@ impl streams::Host for dyn WasiView + '_ { } } -impl error::HostError for dyn WasiView + '_ { +impl error::HostError for WasiImpl +where + T: WasiView, +{ fn drop(&mut self, err: Resource) -> anyhow::Result<()> { self.table().delete(err)?; Ok(()) @@ -32,7 +38,10 @@ impl error::HostError for dyn WasiView + '_ { } #[async_trait::async_trait] -impl streams::HostOutputStream for dyn WasiView + '_ { +impl streams::HostOutputStream for WasiImpl +where + T: WasiView, +{ fn drop(&mut self, stream: Resource) -> anyhow::Result<()> { self.table().delete(stream)?; Ok(()) @@ -172,7 +181,10 @@ impl streams::HostOutputStream for dyn WasiView + '_ { } #[async_trait::async_trait] -impl streams::HostInputStream for dyn WasiView + '_ { +impl streams::HostInputStream for WasiImpl +where + T: WasiView, +{ fn drop(&mut self, stream: Resource) -> anyhow::Result<()> { self.table().delete(stream)?; Ok(()) @@ -233,7 +245,7 @@ pub mod sync { bindings::sync::io::poll::Pollable, bindings::sync::io::streams::{self, InputStream, OutputStream}, runtime::in_tokio, - StreamError, StreamResult, WasiView, + StreamError, StreamResult, WasiImpl, WasiView, }; use wasmtime::component::Resource; @@ -246,7 +258,10 @@ pub mod sync { } } - impl streams::Host for dyn WasiView + '_ { + impl streams::Host for WasiImpl + where + T: WasiView, + { fn convert_stream_error( &mut self, err: StreamError, @@ -255,7 +270,10 @@ pub mod sync { } } - impl streams::HostOutputStream for dyn WasiView + '_ { + impl streams::HostOutputStream for WasiImpl + where + T: WasiView, + { fn drop(&mut self, stream: Resource) -> anyhow::Result<()> { AsyncHostOutputStream::drop(self, stream) } @@ -332,7 +350,10 @@ pub mod sync { } } - impl streams::HostInputStream for dyn WasiView + '_ { + impl streams::HostInputStream for WasiImpl + where + T: WasiView, + { fn drop(&mut self, stream: Resource) -> anyhow::Result<()> { AsyncHostInputStream::drop(self, stream) } diff --git a/crates/wasi/src/host/network.rs b/crates/wasi/src/host/network.rs index 9fc0af43eef6..6772db788ace 100644 --- a/crates/wasi/src/host/network.rs +++ b/crates/wasi/src/host/network.rs @@ -3,18 +3,24 @@ use crate::bindings::sockets::network::{ Ipv6SocketAddress, }; use crate::network::{from_ipv4_addr, from_ipv6_addr, to_ipv4_addr, to_ipv6_addr}; -use crate::{SocketError, WasiView}; +use crate::{SocketError, WasiImpl, WasiView}; use rustix::io::Errno; use std::io; use wasmtime::component::Resource; -impl network::Host for dyn WasiView + '_ { +impl network::Host for WasiImpl +where + T: WasiView, +{ fn convert_error_code(&mut self, error: SocketError) -> anyhow::Result { error.downcast() } } -impl crate::bindings::sockets::network::HostNetwork for dyn WasiView + '_ { +impl crate::bindings::sockets::network::HostNetwork for WasiImpl +where + T: WasiView, +{ fn drop(&mut self, this: Resource) -> Result<(), anyhow::Error> { let table = self.table(); diff --git a/crates/wasi/src/host/random.rs b/crates/wasi/src/host/random.rs index 44e90e666673..a3fe59487d3f 100644 --- a/crates/wasi/src/host/random.rs +++ b/crates/wasi/src/host/random.rs @@ -1,8 +1,11 @@ use crate::bindings::random::{insecure, insecure_seed, random}; -use crate::WasiView; +use crate::{WasiImpl, WasiView}; use cap_rand::{distributions::Standard, Rng}; -impl random::Host for dyn WasiView + '_ { +impl random::Host for WasiImpl +where + T: WasiView, +{ fn get_random_bytes(&mut self, len: u64) -> anyhow::Result> { Ok((&mut self.ctx().random) .sample_iter(Standard) @@ -15,7 +18,10 @@ impl random::Host for dyn WasiView + '_ { } } -impl insecure::Host for dyn WasiView + '_ { +impl insecure::Host for WasiImpl +where + T: WasiView, +{ fn get_insecure_random_bytes(&mut self, len: u64) -> anyhow::Result> { Ok((&mut self.ctx().insecure_random) .sample_iter(Standard) @@ -28,7 +34,10 @@ impl insecure::Host for dyn WasiView + '_ { } } -impl insecure_seed::Host for dyn WasiView + '_ { +impl insecure_seed::Host for WasiImpl +where + T: WasiView, +{ fn insecure_seed(&mut self) -> anyhow::Result<(u64, u64)> { let seed: u128 = self.ctx().insecure_random_seed; Ok((seed as u64, (seed >> 64) as u64)) diff --git a/crates/wasi/src/host/tcp.rs b/crates/wasi/src/host/tcp.rs index 303278e9fd03..2f20cdc2590e 100644 --- a/crates/wasi/src/host/tcp.rs +++ b/crates/wasi/src/host/tcp.rs @@ -7,15 +7,18 @@ use crate::{ }, network::SocketAddressFamily, }; -use crate::{Pollable, SocketResult, WasiView}; +use crate::{Pollable, SocketResult, WasiImpl, WasiView}; use std::net::SocketAddr; use std::time::Duration; use wasmtime::component::Resource; -impl tcp::Host for dyn WasiView + '_ {} +impl tcp::Host for WasiImpl where T: WasiView {} #[async_trait::async_trait] -impl crate::host::tcp::tcp::HostTcpSocket for dyn WasiView + '_ { +impl crate::host::tcp::tcp::HostTcpSocket for WasiImpl +where + T: WasiView, +{ async fn start_bind( &mut self, this: Resource, @@ -325,12 +328,15 @@ pub mod sync { }, }, runtime::in_tokio, - SocketError, WasiView, + SocketError, WasiImpl, WasiView, }; - impl tcp::Host for dyn WasiView + '_ {} + impl tcp::Host for WasiImpl where T: WasiView {} - impl HostTcpSocket for dyn WasiView + '_ { + impl HostTcpSocket for WasiImpl + where + T: WasiView, + { fn start_bind( &mut self, self_: Resource, diff --git a/crates/wasi/src/host/tcp_create_socket.rs b/crates/wasi/src/host/tcp_create_socket.rs index 62cb04fbe351..eadacce05b58 100644 --- a/crates/wasi/src/host/tcp_create_socket.rs +++ b/crates/wasi/src/host/tcp_create_socket.rs @@ -1,9 +1,12 @@ use crate::bindings::{sockets::network::IpAddressFamily, sockets::tcp_create_socket}; use crate::tcp::TcpSocket; -use crate::{SocketResult, WasiView}; +use crate::{SocketResult, WasiImpl, WasiView}; use wasmtime::component::Resource; -impl tcp_create_socket::Host for dyn WasiView + '_ { +impl tcp_create_socket::Host for WasiImpl +where + T: WasiView, +{ fn create_tcp_socket( &mut self, address_family: IpAddressFamily, diff --git a/crates/wasi/src/host/udp.rs b/crates/wasi/src/host/udp.rs index a9aba728cdb0..d1ea5d204b6b 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, WasiView}; +use crate::{Pollable, SocketError, SocketResult, WasiImpl, WasiView}; use anyhow::anyhow; use async_trait::async_trait; use io_lifetimes::AsSocketlike; @@ -22,10 +22,13 @@ use wasmtime::component::Resource; /// In practice, datagrams are typically less than 1500 bytes. const MAX_UDP_DATAGRAM_SIZE: usize = u16::MAX as usize; -impl udp::Host for dyn WasiView + '_ {} +impl udp::Host for WasiImpl where T: WasiView {} #[async_trait::async_trait] -impl udp::HostUdpSocket for dyn WasiView + '_ { +impl udp::HostUdpSocket for WasiImpl +where + T: WasiView, +{ async fn start_bind( &mut self, this: Resource, @@ -301,7 +304,10 @@ impl udp::HostUdpSocket for dyn WasiView + '_ { } } -impl udp::HostIncomingDatagramStream for dyn WasiView + '_ { +impl udp::HostIncomingDatagramStream for WasiImpl +where + T: WasiView, +{ fn receive( &mut self, this: Resource, @@ -393,7 +399,10 @@ impl Subscribe for IncomingDatagramStream { } #[async_trait::async_trait] -impl udp::HostOutgoingDatagramStream for dyn WasiView + '_ { +impl udp::HostOutgoingDatagramStream for WasiImpl +where + T: WasiView, +{ fn check_send(&mut self, this: Resource) -> SocketResult { let table = self.table(); let stream = table.get_mut(&this)?; @@ -557,12 +566,15 @@ pub mod sync { }, }, runtime::in_tokio, - SocketError, WasiView, + SocketError, WasiImpl, WasiView, }; - impl udp::Host for dyn WasiView + '_ {} + impl udp::Host for WasiImpl where T: WasiView {} - impl HostUdpSocket for dyn WasiView + '_ { + impl HostUdpSocket for WasiImpl + where + T: WasiView, + { fn start_bind( &mut self, self_: Resource, @@ -661,7 +673,10 @@ pub mod sync { } } - impl HostIncomingDatagramStream for dyn WasiView + '_ { + impl HostIncomingDatagramStream for WasiImpl + where + T: WasiView, + { fn receive( &mut self, self_: Resource, @@ -700,7 +715,10 @@ pub mod sync { } } - impl HostOutgoingDatagramStream for dyn WasiView + '_ { + impl HostOutgoingDatagramStream for WasiImpl + where + T: WasiView, + { fn check_send( &mut self, self_: Resource, diff --git a/crates/wasi/src/host/udp_create_socket.rs b/crates/wasi/src/host/udp_create_socket.rs index 7049331e9741..f27b574b99ee 100644 --- a/crates/wasi/src/host/udp_create_socket.rs +++ b/crates/wasi/src/host/udp_create_socket.rs @@ -1,9 +1,12 @@ use crate::bindings::{sockets::network::IpAddressFamily, sockets::udp_create_socket}; use crate::udp::UdpSocket; -use crate::{SocketResult, WasiView}; +use crate::{SocketResult, WasiImpl, WasiView}; use wasmtime::component::Resource; -impl udp_create_socket::Host for dyn WasiView + '_ { +impl udp_create_socket::Host for WasiImpl +where + T: WasiView, +{ fn create_udp_socket( &mut self, address_family: IpAddressFamily, diff --git a/crates/wasi/src/ip_name_lookup.rs b/crates/wasi/src/ip_name_lookup.rs index 4b17f013036c..900d90800265 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, WasiView}; +use crate::{SocketError, WasiImpl, WasiView}; use anyhow::Result; use std::mem; use std::net::{Ipv6Addr, ToSocketAddrs}; @@ -20,7 +20,10 @@ pub enum ResolveAddressStream { } #[async_trait::async_trait] -impl Host for dyn WasiView + '_ { +impl Host for WasiImpl +where + T: WasiView, +{ fn resolve_addresses( &mut self, network: Resource, @@ -41,7 +44,10 @@ impl Host for dyn WasiView + '_ { } #[async_trait::async_trait] -impl HostResolveAddressStream for dyn WasiView + '_ { +impl HostResolveAddressStream for WasiImpl +where + T: WasiView, +{ fn resolve_next_address( &mut self, resource: Resource, diff --git a/crates/wasi/src/lib.rs b/crates/wasi/src/lib.rs index c2a95e0b0081..d3e76737d4ed 100644 --- a/crates/wasi/src/lib.rs +++ b/crates/wasi/src/lib.rs @@ -205,7 +205,7 @@ mod udp; mod write_stream; pub use self::clocks::{HostMonotonicClock, HostWallClock}; -pub use self::ctx::{WasiCtx, WasiCtxBuilder, WasiView}; +pub use self::ctx::{WasiCtx, WasiCtxBuilder, WasiImpl, WasiView}; pub use self::error::{I32Exit, TrappableError}; pub use self::filesystem::{DirPerms, FileInputStream, FilePerms, FsError, FsResult}; pub use self::network::{Network, SocketAddrUse, SocketError, SocketResult}; @@ -285,7 +285,7 @@ pub use wasmtime::component::{ResourceTable, ResourceTableError}; /// ``` pub fn add_to_linker_async(linker: &mut Linker) -> anyhow::Result<()> { let l = linker; - let closure = type_annotate::(|t| t); + let closure = type_annotate::(|t| WasiImpl(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)?; @@ -375,7 +375,7 @@ pub fn add_to_linker_sync( linker: &mut wasmtime::component::Linker, ) -> anyhow::Result<()> { let l = linker; - let closure = type_annotate::(|t| t); + let closure = type_annotate::(|t| WasiImpl(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)?; @@ -411,7 +411,7 @@ pub fn add_to_linker_sync( // obsolete. fn type_annotate(val: F) -> F where - F: Fn(&mut T) -> &mut dyn WasiView, + F: Fn(&mut T) -> WasiImpl<&mut T>, { val } diff --git a/crates/wasi/src/poll.rs b/crates/wasi/src/poll.rs index dfa5bb96b519..6e2923f3482f 100644 --- a/crates/wasi/src/poll.rs +++ b/crates/wasi/src/poll.rs @@ -1,4 +1,4 @@ -use crate::{bindings::io::poll, WasiView}; +use crate::{bindings::io::poll, WasiImpl, WasiView}; use anyhow::{anyhow, Result}; use std::any::Any; use std::collections::HashMap; @@ -117,7 +117,10 @@ where } #[async_trait::async_trait] -impl poll::Host for dyn WasiView + '_ { +impl poll::Host for WasiImpl +where + T: WasiView, +{ async fn poll(&mut self, pollables: Vec>) -> Result> { type ReadylistIndex = u32; @@ -176,7 +179,10 @@ impl poll::Host for dyn WasiView + '_ { } #[async_trait::async_trait] -impl crate::bindings::io::poll::HostPollable for dyn WasiView + '_ { +impl crate::bindings::io::poll::HostPollable for WasiImpl +where + T: WasiView, +{ async fn block(&mut self, pollable: Resource) -> Result<()> { let table = self.table(); let pollable = table.get(&pollable)?; @@ -208,18 +214,24 @@ pub mod sync { bindings::io::poll as async_poll, bindings::sync::io::poll::{self, Pollable}, runtime::in_tokio, - WasiView, + WasiImpl, WasiView, }; use anyhow::Result; use wasmtime::component::Resource; - impl poll::Host for dyn WasiView + '_ { + impl poll::Host for WasiImpl + where + T: WasiView, + { 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 dyn WasiView + '_ { + impl crate::bindings::sync::io::poll::HostPollable for WasiImpl + where + T: WasiView, + { 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 dc915dcb9852..26e2007154a7 100644 --- a/crates/wasi/src/preview1.rs +++ b/crates/wasi/src/preview1.rs @@ -72,7 +72,9 @@ use crate::bindings::{ filesystem::{preopens::Host as _, types as filesystem}, io::streams, }; -use crate::{FsError, IsATTY, ResourceTable, StreamError, StreamResult, WasiCtx, WasiView}; +use crate::{ + FsError, IsATTY, ResourceTable, StreamError, StreamResult, WasiCtx, WasiImpl, WasiView, +}; use anyhow::{bail, Context}; use std::collections::{BTreeMap, HashSet}; use std::mem::{self, size_of, size_of_val}; @@ -150,8 +152,8 @@ impl WasiP1Ctx { } } - fn as_wasi_view(&mut self) -> &mut dyn WasiView { - self + fn as_wasi_impl(&mut self) -> WasiImpl<&mut Self> { + WasiImpl(self) } } @@ -196,7 +198,7 @@ impl BlockingMode { } async fn read( &self, - host: &mut dyn WasiView, + host: &mut impl streams::HostInputStream, input_stream: Resource, max_size: usize, ) -> Result, types::Error> { @@ -223,7 +225,7 @@ impl BlockingMode { async fn write( &self, memory: &mut GuestMemory<'_>, - host: &mut dyn WasiView, + host: &mut impl streams::HostOutputStream, output_stream: Resource, bytes: GuestPtr<[u8]>, ) -> StreamResult { @@ -335,7 +337,7 @@ impl DerefMut for Descriptors { impl Descriptors { /// Initializes [Self] using `preopens` - fn new(host: &mut dyn WasiView) -> Result { + fn new(mut host: WasiImpl<&mut WasiP1Ctx>) -> Result { let mut descriptors = Self::default(); descriptors.push(Descriptor::Stdin { stream: host @@ -347,7 +349,7 @@ impl Descriptors { .context("failed to call `get-terminal-stdin`") .map_err(types::Error::trap)? { - terminal_input::HostTerminalInput::drop(host, term_in) + terminal_input::HostTerminalInput::drop(&mut host, term_in) .context("failed to call `drop-terminal-input`") .map_err(types::Error::trap)?; IsATTY::Yes @@ -365,7 +367,7 @@ impl Descriptors { .context("failed to call `get-terminal-stdout`") .map_err(types::Error::trap)? { - terminal_output::HostTerminalOutput::drop(host, term_out) + terminal_output::HostTerminalOutput::drop(&mut host, term_out) .context("failed to call `drop-terminal-output`") .map_err(types::Error::trap)?; IsATTY::Yes @@ -383,7 +385,7 @@ impl Descriptors { .context("failed to call `get-terminal-stderr`") .map_err(types::Error::trap)? { - terminal_output::HostTerminalOutput::drop(host, term_out) + terminal_output::HostTerminalOutput::drop(&mut host, term_out) .context("failed to call `drop-terminal-output`") .map_err(types::Error::trap)?; IsATTY::Yes @@ -562,7 +564,7 @@ impl WasiP1Ctx { let descriptors = if let Some(descriptors) = self.adapter.descriptors.take() { descriptors } else { - Descriptors::new(self.as_wasi_view())? + Descriptors::new(self.as_wasi_impl())? } .into(); Ok(Transaction { @@ -1087,7 +1089,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { argv: GuestPtr>, argv_buf: GuestPtr, ) -> Result<(), types::Error> { - self.as_wasi_view() + self.as_wasi_impl() .get_arguments() .context("failed to call `get-arguments`") .map_err(types::Error::trap)? @@ -1110,7 +1112,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { _memory: &mut GuestMemory<'_>, ) -> Result<(types::Size, types::Size), types::Error> { let args = self - .as_wasi_view() + .as_wasi_impl() .get_arguments() .context("failed to call `get-arguments`") .map_err(types::Error::trap)?; @@ -1131,7 +1133,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { environ: GuestPtr>, environ_buf: GuestPtr, ) -> Result<(), types::Error> { - self.as_wasi_view() + self.as_wasi_impl() .get_environment() .context("failed to call `get-environment`") .map_err(types::Error::trap)? @@ -1159,7 +1161,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { _memory: &mut GuestMemory<'_>, ) -> Result<(types::Size, types::Size), types::Error> { let environ = self - .as_wasi_view() + .as_wasi_impl() .get_environment() .context("failed to call `get-environment`") .map_err(types::Error::trap)?; @@ -1179,13 +1181,15 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { id: types::Clockid, ) -> Result { let res = match id { - types::Clockid::Realtime => wall_clock::Host::resolution(self.as_wasi_view()) + types::Clockid::Realtime => wall_clock::Host::resolution(&mut self.as_wasi_impl()) .context("failed to call `wall_clock::resolution`") .map_err(types::Error::trap)? .try_into()?, - types::Clockid::Monotonic => monotonic_clock::Host::resolution(self.as_wasi_view()) - .context("failed to call `monotonic_clock::resolution`") - .map_err(types::Error::trap)?, + types::Clockid::Monotonic => { + monotonic_clock::Host::resolution(&mut self.as_wasi_impl()) + .context("failed to call `monotonic_clock::resolution`") + .map_err(types::Error::trap)? + } types::Clockid::ProcessCputimeId | types::Clockid::ThreadCputimeId => { return Err(types::Errno::Badf.into()) } @@ -1201,11 +1205,11 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { _precision: types::Timestamp, ) -> Result { let now = match id { - types::Clockid::Realtime => wall_clock::Host::now(self.as_wasi_view()) + types::Clockid::Realtime => wall_clock::Host::now(&mut self.as_wasi_impl()) .context("failed to call `wall_clock::now`") .map_err(types::Error::trap)? .try_into()?, - types::Clockid::Monotonic => monotonic_clock::Host::now(self.as_wasi_view()) + types::Clockid::Monotonic => monotonic_clock::Host::now(&mut self.as_wasi_impl()) .context("failed to call `monotonic_clock::now`") .map_err(types::Error::trap)?, types::Clockid::ProcessCputimeId | types::Clockid::ThreadCputimeId => { @@ -1225,7 +1229,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { advice: types::Advice, ) -> Result<(), types::Error> { let fd = self.get_file_fd(fd)?; - self.as_wasi_view() + self.as_wasi_impl() .advise(fd, offset, len, advice.into()) .await .map_err(|e| { @@ -1264,15 +1268,15 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { .ok_or(types::Errno::Badf)?; match desc { Descriptor::Stdin { stream, .. } => { - streams::HostInputStream::drop(self.as_wasi_view(), stream) + streams::HostInputStream::drop(&mut self.as_wasi_impl(), stream) .context("failed to call `drop` on `input-stream`") } Descriptor::Stdout { stream, .. } | Descriptor::Stderr { stream, .. } => { - streams::HostOutputStream::drop(self.as_wasi_view(), stream) + streams::HostOutputStream::drop(&mut self.as_wasi_impl(), stream) .context("failed to call `drop` on `output-stream`") } Descriptor::File(File { fd, .. }) | Descriptor::Directory { fd, .. } => { - filesystem::HostDescriptor::drop(self.as_wasi_view(), fd) + filesystem::HostDescriptor::drop(&mut self.as_wasi_impl(), fd) .context("failed to call `drop`") } } @@ -1288,7 +1292,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { fd: types::Fd, ) -> Result<(), types::Error> { let fd = self.get_file_fd(fd)?; - self.as_wasi_view().sync_data(fd).await.map_err(|e| { + self.as_wasi_impl().sync_data(fd).await.map_err(|e| { e.try_into() .context("failed to call `sync-data`") .unwrap_or_else(types::Error::trap) @@ -1375,7 +1379,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { }) => (fd.borrowed(), *blocking_mode, *append), }; let flags = self - .as_wasi_view() + .as_wasi_impl() .get_flags(fd.borrowed()) .await .map_err(|e| { @@ -1384,7 +1388,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { .unwrap_or_else(types::Error::trap) })?; let fs_filetype = self - .as_wasi_view() + .as_wasi_impl() .get_type(fd.borrowed()) .await .map_err(|e| { @@ -1501,12 +1505,12 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { data_access_timestamp, data_modification_timestamp, status_change_timestamp, - } = self.as_wasi_view().stat(fd.borrowed()).await.map_err(|e| { + } = self.as_wasi_impl().stat(fd.borrowed()).await.map_err(|e| { e.try_into() .context("failed to call `stat`") .unwrap_or_else(types::Error::trap) })?; - let metadata_hash = self.as_wasi_view().metadata_hash(fd).await.map_err(|e| { + let metadata_hash = self.as_wasi_impl().metadata_hash(fd).await.map_err(|e| { e.try_into() .context("failed to call `metadata_hash`") .unwrap_or_else(types::Error::trap) @@ -1543,7 +1547,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { size: types::Filesize, ) -> Result<(), types::Error> { let fd = self.get_file_fd(fd)?; - self.as_wasi_view().set_size(fd, size).await.map_err(|e| { + self.as_wasi_impl().set_size(fd, size).await.map_err(|e| { e.try_into() .context("failed to call `set-size`") .unwrap_or_else(types::Error::trap) @@ -1573,7 +1577,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { )?; let fd = self.get_fd(fd)?; - self.as_wasi_view() + self.as_wasi_impl() .set_times(fd, atim, mtim) .await .map_err(|e| { @@ -1653,7 +1657,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { return Ok(0); }; let read = BlockingMode::Blocking - .read(self, stream, buf.len().try_into()?) + .read(&mut self.as_wasi_impl(), stream, buf.len().try_into()?) .await?; if read.len() > buf.len().try_into()? { return Err(types::Errno::Range.into()); @@ -1691,7 +1695,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { }; let stream = self - .as_wasi_view() + .as_wasi_impl() .read_via_stream(fd, offset) .map_err(|e| { e.try_into() @@ -1699,9 +1703,13 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { .unwrap_or_else(types::Error::trap) })?; let read = blocking_mode - .read(self, stream.borrowed(), buf.len().try_into()?) + .read( + &mut self.as_wasi_impl(), + stream.borrowed(), + buf.len().try_into()?, + ) .await; - streams::HostInputStream::drop(self.as_wasi_view(), stream) + streams::HostInputStream::drop(&mut self.as_wasi_impl(), stream) .map_err(|e| types::Error::trap(e))?; (buf, read?) } @@ -1777,7 +1785,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { let nwritten = nwritten.map_err(|e| StreamError::LastOperationFailed(e.into()))?; if append { - let len = self.as_wasi_view().stat(fd).await?; + let len = self.as_wasi_impl().stat(fd).await?; position.store(len.size, Ordering::Relaxed); } else { let pos = pos @@ -1794,7 +1802,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { return Ok(0); }; let n = BlockingMode::Blocking - .write(memory, self, stream, buf) + .write(memory, &mut self.as_wasi_impl(), stream, buf) .await? .try_into()?; Ok(n) @@ -1826,7 +1834,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { return Ok(0); }; let stream = self - .as_wasi_view() + .as_wasi_impl() .write_via_stream(fd, offset) .map_err(|e| { e.try_into() @@ -1834,9 +1842,9 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { .unwrap_or_else(types::Error::trap) })?; let result = blocking_mode - .write(memory, self.as_wasi_view(), stream.borrowed(), buf) + .write(memory, &mut self.as_wasi_impl(), stream.borrowed(), buf) .await; - streams::HostOutputStream::drop(self.as_wasi_view(), stream) + streams::HostOutputStream::drop(&mut self.as_wasi_impl(), stream) .map_err(|e| types::Error::trap(e))?; result? } @@ -1930,7 +1938,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { .ok_or(types::Errno::Inval)?, types::Whence::End => { let filesystem::DescriptorStat { size, .. } = - self.as_wasi_view().stat(fd).await.map_err(|e| { + self.as_wasi_impl().stat(fd).await.map_err(|e| { e.try_into() .context("failed to call `stat`") .unwrap_or_else(types::Error::trap) @@ -1952,7 +1960,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { fd: types::Fd, ) -> Result<(), types::Error> { let fd = self.get_file_fd(fd)?; - self.as_wasi_view().sync(fd).await.map_err(|e| { + self.as_wasi_impl().sync(fd).await.map_err(|e| { e.try_into() .context("failed to call `sync`") .unwrap_or_else(types::Error::trap) @@ -1985,7 +1993,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { ) -> Result { let fd = self.get_dir_fd(fd)?; let stream = self - .as_wasi_view() + .as_wasi_impl() .read_directory(fd.borrowed()) .await .map_err(|e| { @@ -1994,7 +2002,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { .unwrap_or_else(types::Error::trap) })?; let dir_metadata_hash = self - .as_wasi_view() + .as_wasi_impl() .metadata_hash(fd.borrowed()) .await .map_err(|e| { @@ -2039,7 +2047,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { .unwrap_or_else(types::Error::trap) })?; let metadata_hash = self - .as_wasi_view() + .as_wasi_impl() .metadata_hash_at(fd.borrowed(), filesystem::PathFlags::empty(), name.clone()) .await .map_err(|e| { @@ -2107,7 +2115,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { ) -> Result<(), types::Error> { let dirfd = self.get_dir_fd(dirfd)?; let path = read_string(memory, path)?; - self.as_wasi_view() + self.as_wasi_impl() .create_directory_at(dirfd.borrowed(), path) .await .map_err(|e| { @@ -2137,7 +2145,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { data_modification_timestamp, status_change_timestamp, } = self - .as_wasi_view() + .as_wasi_impl() .stat_at(dirfd.borrowed(), flags.into(), path.clone()) .await .map_err(|e| { @@ -2146,7 +2154,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { .unwrap_or_else(types::Error::trap) })?; let metadata_hash = self - .as_wasi_view() + .as_wasi_impl() .metadata_hash_at(dirfd, flags.into(), path) .await .map_err(|e| { @@ -2200,7 +2208,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { let dirfd = self.get_dir_fd(dirfd)?; let path = read_string(memory, path)?; - self.as_wasi_view() + self.as_wasi_impl() .set_times_at(dirfd, flags.into(), path, atim, mtim) .await .map_err(|e| { @@ -2226,7 +2234,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { let target_fd = self.get_dir_fd(target_fd)?; let src_path = read_string(memory, src_path)?; let target_path = read_string(memory, target_path)?; - self.as_wasi_view() + self.as_wasi_impl() .link_at(src_fd, src_flags.into(), src_path, target_fd, target_path) .await .map_err(|e| { @@ -2277,7 +2285,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { }; drop(t); let fd = self - .as_wasi_view() + .as_wasi_impl() .open_at(dirfd, dirflags.into(), path, oflags.into(), flags) .await .map_err(|e| { @@ -2316,7 +2324,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { let dirfd = self.get_dir_fd(dirfd)?; let path = read_string(memory, path)?; let mut path = self - .as_wasi_view() + .as_wasi_impl() .readlink_at(dirfd, path) .await .map_err(|e| { @@ -2343,7 +2351,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { ) -> Result<(), types::Error> { let dirfd = self.get_dir_fd(dirfd)?; let path = read_string(memory, path)?; - self.as_wasi_view() + self.as_wasi_impl() .remove_directory_at(dirfd, path) .await .map_err(|e| { @@ -2368,7 +2376,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { let dest_fd = self.get_dir_fd(dest_fd)?; let src_path = read_string(memory, src_path)?; let dest_path = read_string(memory, dest_path)?; - self.as_wasi_view() + self.as_wasi_impl() .rename_at(src_fd, src_path, dest_fd, dest_path) .await .map_err(|e| { @@ -2389,7 +2397,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { let dirfd = self.get_dir_fd(dirfd)?; let src_path = read_string(memory, src_path)?; let dest_path = read_string(memory, dest_path)?; - self.as_wasi_view() + self.as_wasi_impl() .symlink_at(dirfd.borrowed(), src_path, dest_path) .await .map_err(|e| { @@ -2408,7 +2416,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { ) -> Result<(), types::Error> { let dirfd = self.get_dir_fd(dirfd)?; let path = memory.as_cow_str(path)?.into_owned(); - self.as_wasi_view() + self.as_wasi_impl() .unlink_file_at(dirfd.borrowed(), path) .await .map_err(|e| { @@ -2481,7 +2489,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { types::Clockid::Monotonic => (timeout, absolute), types::Clockid::Realtime if !absolute => (timeout, false), types::Clockid::Realtime => { - let now = wall_clock::Host::now(self.as_wasi_view()) + let now = wall_clock::Host::now(&mut self.as_wasi_impl()) .context("failed to call `wall_clock::now`") .map_err(types::Error::trap)?; @@ -2504,11 +2512,11 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { _ => return Err(types::Errno::Inval.into()), }; if absolute { - monotonic_clock::Host::subscribe_instant(self.as_wasi_view(), timeout) + monotonic_clock::Host::subscribe_instant(&mut self.as_wasi_impl(), timeout) .context("failed to call `monotonic_clock::subscribe_instant`") .map_err(types::Error::trap)? } else { - monotonic_clock::Host::subscribe_duration(self.as_wasi_view(), timeout) + monotonic_clock::Host::subscribe_duration(&mut self.as_wasi_impl(), timeout) .context("failed to call `monotonic_clock::subscribe_duration`") .map_err(types::Error::trap)? } @@ -2525,7 +2533,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { let pos = position.load(Ordering::Relaxed); let fd = fd.borrowed(); drop(t); - self.as_wasi_view().read_via_stream(fd, pos).map_err(|e| { + self.as_wasi_impl().read_via_stream(fd, pos).map_err(|e| { e.try_into() .context("failed to call `read-via-stream`") .unwrap_or_else(types::Error::trap) @@ -2535,7 +2543,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { _ => return Err(types::Errno::Badf.into()), } }; - streams::HostInputStream::subscribe(self.as_wasi_view(), stream) + streams::HostInputStream::subscribe(&mut self.as_wasi_impl(), stream) .context("failed to call `subscribe` on `input-stream`") .map_err(types::Error::trap)? } @@ -2559,14 +2567,14 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { let append = *append; drop(t); if append { - self.as_wasi_view().append_via_stream(fd).map_err(|e| { + self.as_wasi_impl().append_via_stream(fd).map_err(|e| { e.try_into() .context("failed to call `append-via-stream`") .unwrap_or_else(types::Error::trap) })? } else { let pos = position.load(Ordering::Relaxed); - self.as_wasi_view().write_via_stream(fd, pos).map_err(|e| { + self.as_wasi_impl().write_via_stream(fd, pos).map_err(|e| { e.try_into() .context("failed to call `write-via-stream`") .unwrap_or_else(types::Error::trap) @@ -2577,7 +2585,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { _ => return Err(types::Errno::Badf.into()), } }; - streams::HostOutputStream::subscribe(self.as_wasi_view(), stream) + streams::HostOutputStream::subscribe(&mut self.as_wasi_impl(), stream) .context("failed to call `subscribe` on `output-stream`") .map_err(types::Error::trap)? } @@ -2585,7 +2593,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { pollables.push(p); } let ready: HashSet<_> = self - .as_wasi_view() + .as_wasi_impl() .poll(pollables) .await .context("failed to call `poll-oneoff`") @@ -2630,7 +2638,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { let fd = fd.borrowed(); let position = position.clone(); drop(t); - match self.as_wasi_view().stat(fd).await? { + match self.as_wasi_impl().stat(fd).await? { filesystem::DescriptorStat { size, .. } => { let pos = position.load(Ordering::Relaxed); let nbytes = size.saturating_sub(pos); @@ -2727,7 +2735,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiP1Ctx { buf_len: types::Size, ) -> Result<(), types::Error> { let rand = self - .as_wasi_view() + .as_wasi_impl() .get_random_bytes(buf_len.into()) .context("failed to call `get-random-bytes`") .map_err(types::Error::trap)?; diff --git a/crates/wasi/src/stdio.rs b/crates/wasi/src/stdio.rs index f2726ab83fae..2a4aae18db96 100644 --- a/crates/wasi/src/stdio.rs +++ b/crates/wasi/src/stdio.rs @@ -4,7 +4,9 @@ use crate::bindings::cli::{ }; use crate::bindings::io::streams; use crate::pipe; -use crate::{HostInputStream, HostOutputStream, StreamError, StreamResult, Subscribe, WasiView}; +use crate::{ + HostInputStream, HostOutputStream, StreamError, StreamResult, Subscribe, WasiImpl, WasiView, +}; use bytes::Bytes; use std::future::Future; use std::io::IsTerminal; @@ -367,21 +369,30 @@ pub enum IsATTY { No, } -impl stdin::Host for dyn WasiView + '_ { +impl stdin::Host for WasiImpl +where + T: WasiView, +{ fn get_stdin(&mut self) -> Result, anyhow::Error> { let stream = self.ctx().stdin.stream(); Ok(self.table().push(streams::InputStream::Host(stream))?) } } -impl stdout::Host for dyn WasiView + '_ { +impl stdout::Host for WasiImpl +where + T: WasiView, +{ fn get_stdout(&mut self) -> Result, anyhow::Error> { let stream = self.ctx().stdout.stream(); Ok(self.table().push(stream)?) } } -impl stderr::Host for dyn WasiView + '_ { +impl stderr::Host for WasiImpl +where + T: WasiView, +{ fn get_stderr(&mut self) -> Result, anyhow::Error> { let stream = self.ctx().stderr.stream(); Ok(self.table().push(stream)?) @@ -391,21 +402,30 @@ impl stderr::Host for dyn WasiView + '_ { pub struct TerminalInput; pub struct TerminalOutput; -impl terminal_input::Host for dyn WasiView + '_ {} -impl terminal_input::HostTerminalInput for dyn WasiView + '_ { +impl terminal_input::Host for WasiImpl where T: WasiView {} +impl terminal_input::HostTerminalInput for WasiImpl +where + T: WasiView, +{ fn drop(&mut self, r: Resource) -> anyhow::Result<()> { self.table().delete(r)?; Ok(()) } } -impl terminal_output::Host for dyn WasiView + '_ {} -impl terminal_output::HostTerminalOutput for dyn WasiView + '_ { +impl terminal_output::Host for WasiImpl where T: WasiView {} +impl terminal_output::HostTerminalOutput for WasiImpl +where + T: WasiView, +{ fn drop(&mut self, r: Resource) -> anyhow::Result<()> { self.table().delete(r)?; Ok(()) } } -impl terminal_stdin::Host for dyn WasiView + '_ { +impl terminal_stdin::Host for WasiImpl +where + T: WasiView, +{ fn get_terminal_stdin(&mut self) -> anyhow::Result>> { if self.ctx().stdin.isatty() { let fd = self.table().push(TerminalInput)?; @@ -415,7 +435,10 @@ impl terminal_stdin::Host for dyn WasiView + '_ { } } } -impl terminal_stdout::Host for dyn WasiView + '_ { +impl terminal_stdout::Host for WasiImpl +where + T: WasiView, +{ fn get_terminal_stdout(&mut self) -> anyhow::Result>> { if self.ctx().stdout.isatty() { let fd = self.table().push(TerminalOutput)?; @@ -425,7 +448,10 @@ impl terminal_stdout::Host for dyn WasiView + '_ { } } } -impl terminal_stderr::Host for dyn WasiView + '_ { +impl terminal_stderr::Host for WasiImpl +where + T: WasiView, +{ fn get_terminal_stderr(&mut self) -> anyhow::Result>> { if self.ctx().stderr.isatty() { let fd = self.table().push(TerminalOutput)?;