From 7cda1ea16179c2f26210c8ff616dffbc813c8ba9 Mon Sep 17 00:00:00 2001 From: Lann Martin Date: Thu, 18 Jul 2024 17:27:02 -0400 Subject: [PATCH 1/3] factors: Pare down spin-core and spin-app These features are moving as part of the migration to factors. Signed-off-by: Lann Martin --- Cargo.lock | 20 +- crates/app/Cargo.toml | 2 - crates/app/src/host_component.rs | 123 - crates/app/src/lib.rs | 245 +- crates/core/Cargo.toml | 26 +- crates/core/src/host_component.rs | 305 --- crates/core/src/io.rs | 34 - crates/core/src/lib.rs | 278 +- crates/core/src/preview1.rs | 212 -- crates/core/src/store.rs | 546 +--- crates/core/src/wasi_2023_10_18.rs | 2465 ------------------ crates/core/src/wasi_2023_11_10.rs | 2455 ----------------- crates/core/tests/core-wasi-test/src/main.rs | 11 - crates/core/tests/integration_test.rs | 261 +- crates/factor-wasi/Cargo.toml | 1 + crates/factor-wasi/src/lib.rs | 10 +- crates/factors-test/src/lib.rs | 4 +- crates/factors/src/lib.rs | 4 +- crates/factors/src/prepare.rs | 4 +- crates/factors/tests/smoke.rs | 2 +- 20 files changed, 175 insertions(+), 6833 deletions(-) delete mode 100644 crates/app/src/host_component.rs delete mode 100644 crates/core/src/host_component.rs delete mode 100644 crates/core/src/io.rs delete mode 100644 crates/core/src/preview1.rs delete mode 100644 crates/core/src/wasi_2023_10_18.rs delete mode 100644 crates/core/src/wasi_2023_11_10.rs diff --git a/Cargo.lock b/Cargo.lock index cf9ea14a0..4fbcc3c94 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7341,10 +7341,8 @@ version = "2.7.0-pre0" dependencies = [ "anyhow", "async-trait", - "ouroboros", "serde 1.0.197", "serde_json", - "spin-core", "spin-locked-app", "spin-serde", "thiserror", @@ -7493,24 +7491,17 @@ version = "2.7.0-pre0" dependencies = [ "anyhow", "async-trait", - "bytes", - "cap-primitives 3.0.0", - "cap-std 3.0.0", "crossbeam-channel", - "futures", - "http 1.1.0", - "io-extras", - "rustix 0.37.27", + "serde_json", "spin-componentize", - "spin-telemetry", - "system-interface", - "tempfile", + "spin-factor-wasi", + "spin-factors", + "spin-factors-test", + "spin-locked-app", "tokio", "tracing", - "wasi-common", "wasmtime", "wasmtime-wasi", - "wasmtime-wasi-http", ] [[package]] @@ -7672,6 +7663,7 @@ version = "2.7.0-pre0" dependencies = [ "async-trait", "cap-primitives 3.0.0", + "spin-app", "spin-factors", "spin-factors-test", "tokio", diff --git a/crates/app/Cargo.toml b/crates/app/Cargo.toml index fadb5e350..2f0d0cf18 100644 --- a/crates/app/Cargo.toml +++ b/crates/app/Cargo.toml @@ -7,10 +7,8 @@ edition = { workspace = true } [dependencies] anyhow = "1.0" async-trait = "0.1" -ouroboros = "0.18.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -spin-core = { path = "../core" } spin-locked-app = { path = "../locked-app" } spin-serde = { path = "../serde" } thiserror = "1.0" diff --git a/crates/app/src/host_component.rs b/crates/app/src/host_component.rs deleted file mode 100644 index c5ab96c4e..000000000 --- a/crates/app/src/host_component.rs +++ /dev/null @@ -1,123 +0,0 @@ -use std::{any::Any, sync::Arc}; - -use anyhow::Context; -use spin_core::{ - AnyHostComponentDataHandle, EngineBuilder, HostComponent, HostComponentDataHandle, - HostComponentsData, -}; - -use crate::{App, AppComponent}; - -/// A trait for "dynamic" Spin host components. -/// -/// This extends [`HostComponent`] to support per-[`AppComponent`] dynamic -/// runtime configuration. -/// -/// Dynamic host components differ from regular host components in that they can be -/// configured on a per-component basis. -pub trait DynamicHostComponent: HostComponent { - /// Called on [`AppComponent`] instance initialization. - /// - /// The `data` returned by [`HostComponent::build_data`] is passed, along - /// with a reference to the `component` being instantiated. - fn update_data(&self, data: &mut Self::Data, component: &AppComponent) -> anyhow::Result<()>; - - /// Called on [`App`] load to validate any configuration needed by this - /// host component. - /// - /// Note that the _absence_ of configuration should not be treated as an - /// error here, as the app may not use this host component at all. - #[allow(unused_variables)] - fn validate_app(&self, app: &App) -> anyhow::Result<()> { - Ok(()) - } -} - -impl DynamicHostComponent for Arc { - fn update_data(&self, data: &mut Self::Data, component: &AppComponent) -> anyhow::Result<()> { - (**self).update_data(data, component) - } -} - -/// A version of `DynamicHostComponent` which can be made into a trait object. -/// -/// This is only implemented for `T: DynamicHostComponent`. We want to make `DynamicHostComponent` -/// into a trait object so that we can store them into a heterogeneous collection in `DynamicHostComponents`. -/// -/// `DynamicHostComponent` can't be made into a trait object itself since `HostComponent::add_to_linker` -/// does not have a `self` parameter (and thus cannot be add to the object's vtable). -trait DynSafeDynamicHostComponent { - /// The moral equivalent to `DynamicHostComponent::update_data` - fn update_data_any(&self, data: &mut dyn Any, component: &AppComponent) -> anyhow::Result<()>; - /// The moral equivalent to `DynamicHostComponent::validate_app` - fn validate_app(&self, app: &App) -> anyhow::Result<()>; -} - -impl DynSafeDynamicHostComponent for T -where - T::Data: Any, -{ - fn update_data_any(&self, data: &mut dyn Any, component: &AppComponent) -> anyhow::Result<()> { - let data = data.downcast_mut().context("wrong data type")?; - self.update_data(data, component) - } - - fn validate_app(&self, app: &App) -> anyhow::Result<()> { - T::validate_app(self, app) - } -} - -struct DynamicHostComponentWithHandle { - host_component: Arc, - handle: AnyHostComponentDataHandle, -} - -/// A heterogeneous collection of dynamic host components. -/// -/// This is stored in an `AppLoader` so that the host components -/// can be referenced and updated at a later point. This is effectively -/// what makes a `DynamicHostComponent` "dynamic" and differentiates it from -/// a regular `HostComponent`. -#[derive(Default)] -pub(crate) struct DynamicHostComponents { - host_components: Vec, -} - -impl DynamicHostComponents { - pub fn add_dynamic_host_component( - &mut self, - engine_builder: &mut EngineBuilder, - host_component: DHC, - ) -> anyhow::Result> { - let host_component = Arc::new(host_component); - let handle = engine_builder.add_host_component(host_component.clone())?; - self.host_components.push(DynamicHostComponentWithHandle { - host_component, - handle: handle.into(), - }); - Ok(handle.into()) - } - - pub fn update_data( - &self, - host_components_data: &mut HostComponentsData, - component: &AppComponent, - ) -> anyhow::Result<()> { - for DynamicHostComponentWithHandle { - host_component, - handle, - } in &self.host_components - { - let data = host_components_data.get_or_insert_any(*handle); - host_component.update_data_any(data.as_mut(), component)?; - } - Ok(()) - } - - pub fn validate_app(&self, app: &App) -> anyhow::Result<()> { - for DynamicHostComponentWithHandle { host_component, .. } in &self.host_components { - host_component.validate_app(app)?; - } - Ok(()) - } -} diff --git a/crates/app/src/lib.rs b/crates/app/src/lib.rs index 97077032d..22d97ceba 100644 --- a/crates/app/src/lib.rs +++ b/crates/app/src/lib.rs @@ -6,22 +6,16 @@ #![deny(missing_docs)] -mod host_component; +use serde::Deserialize; use serde_json::Value; +use spin_locked_app::MetadataExt; + +use locked::{ContentPath, LockedApp, LockedComponent, LockedComponentSource, LockedTrigger}; + pub use spin_locked_app::locked; pub use spin_locked_app::values; pub use spin_locked_app::{Error, MetadataKey, Result}; -use ouroboros::self_referencing; -use serde::Deserialize; -use spin_core::{wasmtime, Engine, EngineBuilder, HostComponentDataHandle, StoreBuilder}; - -use host_component::DynamicHostComponents; -use locked::{ContentPath, LockedApp, LockedComponent, LockedComponentSource, LockedTrigger}; -use spin_locked_app::MetadataExt; - -pub use async_trait::async_trait; -pub use host_component::DynamicHostComponent; pub use locked::Variable; /// MetadataKey for extracting the application name. @@ -33,130 +27,28 @@ pub const APP_DESCRIPTION_KEY: MetadataKey = MetadataKey::new("description"); /// MetadataKey for extracting the OCI image digest. pub const OCI_IMAGE_DIGEST_KEY: MetadataKey = MetadataKey::new("oci_image_digest"); -/// A trait for implementing the low-level operations needed to load an [`App`]. -// TODO(lann): Should this migrate to spin-loader? -#[async_trait] -pub trait Loader { - /// Called with an implementation-defined `uri` pointing to some - /// representation of a [`LockedApp`], which will be loaded. - async fn load_app(&self, uri: &str) -> anyhow::Result; - - /// Called with a [`LockedComponentSource`] pointing to a Wasm component - /// binary, which will be loaded. - async fn load_component( - &self, - engine: &wasmtime::Engine, - source: &LockedComponentSource, - ) -> anyhow::Result; - - /// Called with a [`LockedComponentSource`] pointing to a Wasm module - /// binary, which will be loaded. - async fn load_module( - &self, - engine: &wasmtime::Engine, - source: &LockedComponentSource, - ) -> anyhow::Result; - - /// Called with an [`AppComponent`]; any `files` configured with the - /// component should be "mounted" into the `store_builder`, via e.g. - /// [`StoreBuilder::read_only_preopened_dir`]. - async fn mount_files( - &self, - store_builder: &mut StoreBuilder, - component: &AppComponent, - ) -> anyhow::Result<()>; -} - -/// An `AppLoader` holds an implementation of [`Loader`] along with -/// [`DynamicHostComponent`]s configuration. -pub struct AppLoader { - inner: Box, - dynamic_host_components: DynamicHostComponents, +/// An `App` holds loaded configuration for a Spin application. +#[derive(Debug)] +pub struct App { + id: String, + locked: LockedApp, } -impl AppLoader { - /// Creates a new [`AppLoader`]. - pub fn new(loader: impl Loader + Send + Sync + 'static) -> Self { +impl App { + /// Returns a new app for the given runtime-specific identifier and locked + /// app. + pub fn new(id: impl Into, locked: LockedApp) -> Self { Self { - inner: Box::new(loader), - dynamic_host_components: Default::default(), - } - } - - /// Adds a [`DynamicHostComponent`] to the given [`EngineBuilder`] and - /// configures this [`AppLoader`] to update it on component instantiation. - /// - /// This calls [`EngineBuilder::add_host_component`] for you; it should not - /// be called separately. - pub fn add_dynamic_host_component( - &mut self, - engine_builder: &mut EngineBuilder, - host_component: DHC, - ) -> anyhow::Result> { - self.dynamic_host_components - .add_dynamic_host_component(engine_builder, host_component) - } - - /// Loads an [`App`] from the given `Loader`-implementation-specific `uri`. - pub async fn load_app(&self, uri: String) -> Result { - let locked = self - .inner - .load_app(&uri) - .await - .map_err(Error::LoaderError)?; - let app = App { - loader: self, - uri, + id: id.into(), locked, - }; - self.dynamic_host_components - .validate_app(&app) - .map_err(Error::ValidationError)?; - Ok(app) - } - - /// Loads an [`OwnedApp`] from the given `Loader`-implementation-specific - /// `uri`; the [`OwnedApp`] takes ownership of this [`AppLoader`]. - pub async fn load_owned_app(self, uri: String) -> Result { - OwnedApp::try_new_async(self, |loader| Box::pin(loader.load_app(uri))).await - } -} - -impl std::fmt::Debug for AppLoader { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("AppLoader").finish() + } } -} - -#[self_referencing] -#[derive(Debug)] -pub struct OwnedApp { - loader: AppLoader, - - #[borrows(loader)] - #[covariant] - app: App<'this>, -} -impl OwnedApp { - /// Returns a reference to the owned [`App`]. - pub fn borrowed(&self) -> &App { - self.borrow_app() + /// Returns a runtime-specific identifier for this app. + pub fn id(&self) -> &str { + &self.id } -} -/// An `App` holds loaded configuration for a Spin application. -/// -/// Note: The `L` param is an implementation detail to support the -/// [`App::inert`] constructor. -#[derive(Debug)] -pub struct App<'a, L = AppLoader> { - loader: &'a L, - uri: String, - locked: LockedApp, -} - -impl<'a, L> App<'a, L> { /// Deserializes typed metadata for this app. /// /// Returns `Ok(None)` if there is no metadata for the given `key` and an @@ -186,7 +78,7 @@ impl<'a, L> App<'a, L> { } /// Returns an iterator of [`AppComponent`]s defined for this app. - pub fn components(&self) -> impl Iterator> { + pub fn components(&self) -> impl Iterator> { self.locked .components .iter() @@ -195,13 +87,13 @@ impl<'a, L> App<'a, L> { /// Returns the [`AppComponent`] with the given `component_id`, or `None` /// if it doesn't exist. - pub fn get_component(&self, component_id: &str) -> Option> { + pub fn get_component(&self, component_id: &str) -> Option> { self.components() .find(|component| component.locked.id == component_id) } /// Returns an iterator of [`AppTrigger`]s defined for this app. - pub fn triggers(&self) -> impl Iterator> { + pub fn triggers(&self) -> impl Iterator> + '_ { self.locked .triggers .iter() @@ -211,7 +103,7 @@ impl<'a, L> App<'a, L> { /// Returns the trigger metadata for a specific trigger type. pub fn get_trigger_metadata<'this, T: Deserialize<'this> + Default>( &'this self, - trigger_type: &'a str, + trigger_type: &str, ) -> Result> { let Some(value) = self.get_trigger_metadata_value(trigger_type) else { return Ok(None); @@ -240,10 +132,10 @@ impl<'a, L> App<'a, L> { /// Returns an iterator of [`AppTrigger`]s defined for this app with /// the given `trigger_type`. - pub fn triggers_with_type( + pub fn triggers_with_type<'a>( &'a self, trigger_type: &'a str, - ) -> impl Iterator> { + ) -> impl Iterator { self.triggers() .filter(move |trigger| trigger.locked.trigger_type == trigger_type) } @@ -256,36 +148,14 @@ impl<'a, L> App<'a, L> { } } -impl<'a> App<'a> { - /// Returns a [`Loader`]-implementation-specific URI for this app. - pub fn uri(&self) -> &str { - &self.uri - } -} - -#[doc(hidden)] -pub struct InertLoader; - -impl App<'static, InertLoader> { - /// Return an "inert" App which does not have an associated [`AppLoader`] - /// and cannot be used to instantiate components. - pub fn inert(locked: LockedApp) -> Self { - App { - loader: &InertLoader, - uri: "".into(), - locked, - } - } -} - /// An `AppComponent` holds configuration for a Spin application component. -pub struct AppComponent<'a, L = AppLoader> { +pub struct AppComponent<'a> { /// The app this component belongs to. - pub app: &'a App<'a, L>, + pub app: &'a App, locked: &'a LockedComponent, } -impl<'a, L> AppComponent<'a, L> { +impl<'a> AppComponent<'a> { /// Returns this component's app-unique ID. pub fn id(&self) -> &str { &self.locked.id @@ -336,65 +206,14 @@ impl<'a, L> AppComponent<'a, L> { } } -impl<'a> AppComponent<'a> { - /// Loads and returns the [`spin_core::Component`] for this component. - pub async fn load_component( - &self, - engine: &Engine, - ) -> Result { - self.app - .loader - .inner - .load_component(engine.as_ref(), &self.locked.source) - .await - .map_err(Error::LoaderError) - } - - /// Loads and returns the [`spin_core::Module`] for this component. - pub async fn load_module( - &self, - engine: &Engine, - ) -> Result { - self.app - .loader - .inner - .load_module(engine.as_ref(), &self.locked.source) - .await - .map_err(Error::LoaderError) - } - - /// Updates the given [`StoreBuilder`] with configuration for this component. - /// - /// In particular, the WASI 'env' and "preloaded dirs" are set up, and any - /// [`DynamicHostComponent`]s associated with the source [`AppLoader`] are - /// configured. - pub async fn apply_store_config(&self, builder: &mut StoreBuilder) -> Result<()> { - builder.env(&self.locked.env).map_err(Error::CoreError)?; - - let loader = self.app.loader; - loader - .inner - .mount_files(builder, self) - .await - .map_err(Error::LoaderError)?; - - loader - .dynamic_host_components - .update_data(builder.host_components_data(), self) - .map_err(Error::HostComponentError)?; - - Ok(()) - } -} - /// An `AppTrigger` holds configuration for a Spin application trigger. -pub struct AppTrigger<'a, L = AppLoader> { +pub struct AppTrigger<'a> { /// The app this trigger belongs to. - pub app: &'a App<'a, L>, + pub app: &'a App, locked: &'a LockedTrigger, } -impl<'a, L> AppTrigger<'a, L> { +impl<'a> AppTrigger<'a> { /// Returns this trigger's app-unique ID. pub fn id(&self) -> &str { &self.locked.id @@ -414,7 +233,7 @@ impl<'a, L> AppTrigger<'a, L> { /// /// This is a convenience wrapper that looks up the component based on the /// 'component' metadata value which is conventionally a component ID. - pub fn component(&self) -> Result> { + pub fn component(&self) -> Result> { let id = &self.locked.id; let common_config: CommonTriggerConfig = self.typed_config()?; let component_id = common_config.component.ok_or_else(|| { diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index cba62cd50..175888c76 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -10,25 +10,13 @@ async-trait = "0.1" crossbeam-channel = "0.5" tracing = { workspace = true } wasmtime = { workspace = true } -wasmtime-wasi = { workspace = true } -wasmtime-wasi-http = { workspace = true } -wasi-common-preview1 = { workspace = true } -system-interface = { version = "0.27.0", features = ["cap_std_impls"] } -cap-std = "3.0.0" -cap-primitives = "3.0.0" -tokio = "1.0" -bytes = "1.0" -spin-telemetry = { path = "../telemetry" } -http = "1.0" - -[target.'cfg(unix)'.dependencies] -rustix = "0.37.19" - -[target.'cfg(windows)'.dependencies] -io-extras = "0.18.0" [dev-dependencies] -tempfile = "3" -tokio = { version = "1", features = ["macros", "rt", "rt-multi-thread"] } +serde_json = "1" spin-componentize = { workspace = true } -futures = "0.3" +tokio = { version = "1", features = ["macros", "rt", "rt-multi-thread"] } +spin-factor-wasi = { path = "../factor-wasi" } +spin-factors = { path = "../factors" } +spin-factors-test = { path = "../factors-test" } +spin-locked-app = { path = "../locked-app" } +wasmtime-wasi = { workspace = true } \ No newline at end of file diff --git a/crates/core/src/host_component.rs b/crates/core/src/host_component.rs deleted file mode 100644 index a2b428a5f..000000000 --- a/crates/core/src/host_component.rs +++ /dev/null @@ -1,305 +0,0 @@ -use std::{ - any::{type_name, Any, TypeId}, - collections::HashMap, - marker::PhantomData, - sync::Arc, -}; - -use anyhow::{bail, Result}; - -use super::{Data, Linker}; - -/// A trait for Spin "host components". -/// -/// A Spin host component is an interface provided to Spin components that is -/// implemented by the host. This trait is designed to be compatible with -/// [`wasmtime::component::bindgen`]'s generated bindings. -/// -/// # Example -/// -/// ```ignore -/// use spin_core::my_interface; -/// -/// #[derive(Default)] -/// struct MyHostComponent { -/// // ... -/// } -/// -/// #[async_trait] -/// impl my_interface::Host for MyHostComponent { -/// // ... -/// } -/// -/// impl HostComponent for MyHostComponent { -/// type Data = Self; -/// -/// fn add_to_linker( -/// linker: &mut Linker, -/// get: impl Fn(&mut spin_core::Data) -> &mut Self::Data + Send + Sync + Copy + 'static, -/// ) -> anyhow::Result<()> { -/// my_interface::add_to_linker(linker, get) -/// } -/// -/// fn build_data(&self) -> Self::Data { -/// Default::default() -/// } -/// } -/// ``` -pub trait HostComponent: Send + Sync + 'static { - /// Host component runtime data. - type Data: Send + Sized + 'static; - - /// Add this component to the given Linker, using the given runtime state-getting handle. - /// - /// This function signature mirrors those generated by [`wasmtime::component::bindgen`]. - fn add_to_linker( - linker: &mut Linker, - get: impl Fn(&mut Data) -> &mut Self::Data + Send + Sync + Copy + 'static, - ) -> Result<()>; - - /// Builds new host component runtime data for [`HostComponentsData`]. - fn build_data(&self) -> Self::Data; -} - -impl HostComponent for Arc { - type Data = HC::Data; - - fn add_to_linker( - linker: &mut Linker, - get: impl Fn(&mut Data) -> &mut Self::Data + Send + Sync + Copy + 'static, - ) -> Result<()> { - HC::add_to_linker(linker, get) - } - - fn build_data(&self) -> Self::Data { - (**self).build_data() - } -} - -/// An opaque handle which can be passed to [`HostComponentsData`] to access -/// host component data. -#[derive(Clone, Copy)] -pub struct AnyHostComponentDataHandle(usize); - -impl From> for AnyHostComponentDataHandle { - fn from(value: HostComponentDataHandle) -> Self { - value.inner - } -} - -/// An opaque handle returned by [`crate::EngineBuilder::add_host_component`] -/// which can be passed to [`HostComponentsData`] to access or set associated -/// [`HostComponent::Data`]. -pub struct HostComponentDataHandle { - inner: AnyHostComponentDataHandle, - _phantom: PhantomData HC::Data>, -} - -impl HostComponentDataHandle { - fn from_any(handle: AnyHostComponentDataHandle) -> Self { - Self { - inner: handle, - _phantom: PhantomData, - } - } -} - -impl Clone for HostComponentDataHandle { - fn clone(&self) -> Self { - *self - } -} - -impl Copy for HostComponentDataHandle {} - -impl From>> for HostComponentDataHandle { - fn from(value: HostComponentDataHandle>) -> Self { - Self::from_any(value.inner) - } -} - -#[doc(hidden)] -pub trait DynSafeHostComponent { - fn build_data_box(&self) -> AnyData; -} - -impl DynSafeHostComponent for T -where - T::Data: Any + Send, -{ - fn build_data_box(&self) -> AnyData { - Box::new(self.build_data()) - } -} - -type BoxHostComponent = Box; - -#[derive(Default)] -pub struct HostComponentsBuilder { - handles: HashMap, - host_components: Vec, -} - -impl HostComponentsBuilder { - pub fn add_host_component( - &mut self, - linker: &mut Linker, - host_component: HC, - ) -> Result> { - let type_id = TypeId::of::(); - if self.handles.contains_key(&type_id) { - bail!( - "already have a host component of type {}", - type_name::() - ) - } - - let handle = AnyHostComponentDataHandle(self.host_components.len()); - self.handles.insert(type_id, handle); - - self.host_components.push(Box::new(host_component)); - HC::add_to_linker(linker, move |data| { - data.host_components_data - .get_or_insert_any(handle) - .downcast_mut() - .unwrap() - })?; - Ok(HostComponentDataHandle:: { - inner: handle, - _phantom: PhantomData, - }) - } - - pub fn build(self) -> HostComponents { - HostComponents { - handles: self.handles, - host_components: Arc::new(self.host_components), - } - } -} - -pub struct HostComponents { - handles: HashMap, - host_components: Arc>, -} - -impl HostComponents { - pub fn builder() -> HostComponentsBuilder { - Default::default() - } - - pub fn new_data(&self) -> HostComponentsData { - // Fill with `None` - let data = std::iter::repeat_with(Default::default) - .take(self.host_components.len()) - .collect(); - HostComponentsData { - data, - host_components: self.host_components.clone(), - } - } - - pub fn find_handle(&self) -> Option> { - self.handles - .get(&TypeId::of::()) - .map(|handle| HostComponentDataHandle::from_any(*handle)) - } -} - -type AnyData = Box; - -/// Holds a heterogenous set of [`HostComponent::Data`]s. -pub struct HostComponentsData { - data: Vec>, - host_components: Arc>, -} - -impl HostComponentsData { - /// Sets the [`HostComponent::Data`] for the given `handle`. - pub fn set(&mut self, handle: HostComponentDataHandle, data: HC::Data) { - self.data[handle.inner.0] = Some(Box::new(data)); - } - - /// Retrieves a mutable reference to [`HostComponent::Data`] for the given `handle`. - /// - /// If unset, the data will be initialized with [`HostComponent::build_data`]. - /// - /// # Panics - /// - /// If the given handle was not obtained from the same [`HostComponentsBuilder`] that - /// was the source of this [`HostComponentsData`], this function may panic. - pub fn get_or_insert( - &mut self, - handle: HostComponentDataHandle, - ) -> &mut HC::Data { - let data = self.get_or_insert_any(handle.inner); - data.downcast_mut().unwrap() - } - - /// Retrieves a mutable reference to [`HostComponent::Data`] for the given `handle`. - /// - /// If unset, the data will be initialized with [`HostComponent::build_data`]. - /// - /// # Panics - /// - /// If the given handle was not obtained from the same [`HostComponentsBuilder`] that - /// was the source of this [`HostComponentsData`], this function may panic. - pub fn get_or_insert_any(&mut self, handle: AnyHostComponentDataHandle) -> &mut AnyData { - let idx = handle.0; - self.data[idx].get_or_insert_with(|| self.host_components[idx].build_data_box()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - struct TestHC; - - impl HostComponent for TestHC { - type Data = u8; - - fn add_to_linker( - _linker: &mut Linker, - _get: impl Fn(&mut Data) -> &mut Self::Data + Send + Sync + Copy + 'static, - ) -> Result<()> { - Ok(()) - } - - fn build_data(&self) -> Self::Data { - 0 - } - } - - #[test] - fn host_components_data() { - let engine = wasmtime::Engine::default(); - let mut linker: crate::Linker<()> = crate::Linker::new(&engine); - - let mut builder = HostComponents::builder(); - let handle1 = builder - .add_host_component(&mut linker, Arc::new(TestHC)) - .unwrap(); - let handle2 = builder.add_host_component(&mut linker, TestHC).unwrap(); - let host_components = builder.build(); - let mut hc_data = host_components.new_data(); - - assert_eq!(hc_data.get_or_insert(handle1), &0); - - hc_data.set(handle2, 1); - assert_eq!(hc_data.get_or_insert(handle2), &1); - } - - #[test] - fn find_handle() { - let engine = wasmtime::Engine::default(); - let mut linker: crate::Linker<()> = crate::Linker::new(&engine); - - let mut builder = HostComponents::builder(); - builder.add_host_component(&mut linker, TestHC).unwrap(); - let host_components = builder.build(); - let handle = host_components.find_handle::().unwrap(); - let mut hc_data = host_components.new_data(); - assert_eq!(hc_data.get_or_insert(handle), &0); - } -} diff --git a/crates/core/src/io.rs b/crates/core/src/io.rs deleted file mode 100644 index a8bb7bd3d..000000000 --- a/crates/core/src/io.rs +++ /dev/null @@ -1,34 +0,0 @@ -use wasmtime_wasi::{pipe::MemoryOutputPipe, HostOutputStream}; - -/// An in-memory stdio output buffer. -#[derive(Clone)] -pub struct OutputBuffer(MemoryOutputPipe); - -impl OutputBuffer { - /// Clones the buffered output from this buffer. - pub fn contents(&self) -> bytes::Bytes { - self.0.contents() - } - - pub(crate) fn writer(&self) -> impl HostOutputStream { - self.0.clone() - } -} - -impl Default for OutputBuffer { - fn default() -> Self { - Self(MemoryOutputPipe::new(usize::MAX)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[tokio::test] - async fn take_what_you_write() { - let buf = OutputBuffer::default(); - buf.writer().write(b"foo".to_vec().into()).unwrap(); - assert_eq!(buf.contents().as_ref(), b"foo"); - } -} diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs index b9dc8fbb9..cd02404ba 100644 --- a/crates/core/src/lib.rs +++ b/crates/core/src/lib.rs @@ -1,33 +1,23 @@ //! Spin core execution engine //! -//! This crate provides low-level Wasm and WASI functionality required by Spin. -//! Most of this functionality consists of wrappers around [`wasmtime`] and -//! [`wasi_common`] that narrows the flexibility of `wasmtime` to the set of -//! features used by Spin (such as only supporting `wasmtime`'s async calling style). +//! This crate provides low-level Wasm functionality required by Spin. Most of +//! this functionality consists of wrappers around [`wasmtime`] that narrow the +//! flexibility of `wasmtime` to the set of features used by Spin (such as only +//! supporting `wasmtime`'s async calling style). #![deny(missing_docs)] -mod host_component; -mod io; mod limits; -mod preview1; mod store; -pub mod wasi_2023_10_18; -pub mod wasi_2023_11_10; use std::sync::OnceLock; use std::{path::PathBuf, time::Duration}; use anyhow::Result; use crossbeam_channel::Sender; -use http::Request; -use tracing::{field::Empty, instrument}; +use tracing::instrument; +use wasmtime::component::{InstancePre, Linker}; use wasmtime::{InstanceAllocationStrategy, PoolingAllocationConfig}; -use wasmtime_wasi::ResourceTable; -use wasmtime_wasi_http::body::HyperOutgoingBody; -use wasmtime_wasi_http::types::{default_send_request, WasiHttpCtx, WasiHttpView}; - -use self::host_component::{HostComponents, HostComponentsBuilder}; pub use async_trait::async_trait; pub use wasmtime::{ @@ -35,13 +25,8 @@ pub use wasmtime::{ component::{Component, Instance}, Instance as ModuleInstance, Module, Trap, }; -pub use wasmtime_wasi::I32Exit; -pub use host_component::{ - AnyHostComponentDataHandle, HostComponent, HostComponentDataHandle, HostComponentsData, -}; -pub use io::OutputBuffer; -pub use store::{Store, StoreBuilder, Wasi, WasiVersion}; +pub use store::{Store, StoreBuilder}; /// The default [`EngineBuilder::epoch_tick_interval`]. pub const DEFAULT_EPOCH_TICK_INTERVAL: Duration = Duration::from_millis(10); @@ -205,183 +190,43 @@ fn use_pooling_allocator_by_default() -> bool { } /// Host state data associated with individual [Store]s and [Instance]s. -pub struct Data { - inner: T, - wasi: Wasi, - host_components_data: HostComponentsData, +#[derive(Default)] +pub struct State { store_limits: limits::StoreLimitsAsync, - table: ResourceTable, } -impl Data { +impl State { /// Get the amount of memory in bytes consumed by instances in the store pub fn memory_consumed(&self) -> u64 { self.store_limits.memory_consumed() } } -impl AsRef for Data { - fn as_ref(&self) -> &T { - &self.inner - } -} - -impl AsMut for Data { - fn as_mut(&mut self) -> &mut T { - &mut self.inner - } -} - -impl wasmtime_wasi::WasiView for Data { - fn table(&mut self) -> &mut ResourceTable { - &mut self.table - } - - fn ctx(&mut self) -> &mut wasmtime_wasi::WasiCtx { - match &mut self.wasi { - Wasi::Preview1(_) => panic!("using WASI Preview 1 functions with Preview 2 store"), - Wasi::Preview2 { wasi_ctx, .. } => wasi_ctx, - } - } -} - -impl WasiHttpView for Data { - fn ctx(&mut self) -> &mut WasiHttpCtx { - match &mut self.wasi { - Wasi::Preview1(_) => panic!("using WASI Preview 1 functions with Preview 2 store"), - Wasi::Preview2 { wasi_http_ctx, .. } => wasi_http_ctx, - } - } - - fn table(&mut self) -> &mut ResourceTable { - &mut self.table - } - - #[instrument( - name = "spin_core.send_request", - skip_all, - fields( - otel.kind = "client", - url.full = %request.uri(), - http.request.method = %request.method(), - otel.name = %request.method(), - http.response.status_code = Empty, - server.address = Empty, - server.port = Empty, - ), - )] - fn send_request( - &mut self, - mut request: Request, - config: wasmtime_wasi_http::types::OutgoingRequestConfig, - ) -> wasmtime_wasi_http::HttpResult - where - Self: Sized, - { - spin_telemetry::inject_trace_context(&mut request); - T::send_request(self, request, config) - } -} - -/// Handler for wasi-http based requests -pub trait OutboundWasiHttpHandler { - /// Send the request - fn send_request( - data: &mut Data, - request: Request, - config: wasmtime_wasi_http::types::OutgoingRequestConfig, - ) -> wasmtime_wasi_http::HttpResult - where - Self: Sized; -} - -impl OutboundWasiHttpHandler for () { - fn send_request( - _data: &mut Data, - request: Request, - config: wasmtime_wasi_http::types::OutgoingRequestConfig, - ) -> wasmtime_wasi_http::HttpResult - where - Self: Sized, - { - Ok(default_send_request(request, config)) - } -} - -/// An alias for [`wasmtime::Linker`] specialized to [`Data`]. -pub type ModuleLinker = wasmtime::Linker>; - -/// An alias for [`wasmtime::component::Linker`] specialized to [`Data`]. -pub type Linker = wasmtime::component::Linker>; - /// A builder interface for configuring a new [`Engine`]. /// /// A new [`EngineBuilder`] can be obtained with [`Engine::builder`]. pub struct EngineBuilder { engine: wasmtime::Engine, linker: Linker, - module_linker: ModuleLinker, - host_components_builder: HostComponentsBuilder, epoch_tick_interval: Duration, epoch_ticker_thread: bool, } -impl EngineBuilder { +impl EngineBuilder { fn new(config: &Config) -> Result { let engine = wasmtime::Engine::new(&config.inner)?; let linker: Linker = Linker::new(&engine); - let mut module_linker = ModuleLinker::new(&engine); - - wasi_common_preview1::tokio::add_to_linker(&mut module_linker, |data| { - match &mut data.wasi { - Wasi::Preview1(ctx) => ctx, - Wasi::Preview2 { .. } => { - panic!("using WASI Preview 2 functions with Preview 1 store") - } - } - })?; - Ok(Self { engine, linker, - module_linker, - host_components_builder: HostComponents::builder(), epoch_tick_interval: DEFAULT_EPOCH_TICK_INTERVAL, epoch_ticker_thread: true, }) } -} - -impl EngineBuilder { - /// Adds definition(s) to the built [`Engine`]. - /// - /// This method's signature is meant to be used with - /// [`wasmtime::component::bindgen`]'s generated `add_to_linker` functions, e.g.: - /// - /// ```ignore - /// use spin_core::my_interface; - /// // ... - /// let mut builder: EngineBuilder = Engine::builder(); - /// builder.link_import(my_interface::add_to_linker)?; - /// ``` - pub fn link_import( - &mut self, - f: impl FnOnce(&mut Linker, fn(&mut Data) -> &mut T) -> Result<()>, - ) -> Result<()> { - f(&mut self.linker, Data::as_mut) - } - /// Adds a [`HostComponent`] to the built [`Engine`]. - /// - /// Returns a [`HostComponentDataHandle`] which can be passed to - /// [`HostComponentsData`] to access or set associated - /// [`HostComponent::Data`] for an instance. - pub fn add_host_component( - &mut self, - host_component: HC, - ) -> Result> { - self.host_components_builder - .add_host_component(&mut self.linker, host_component) + /// Returns a reference to the [`Linker`] for this [`Engine`]. + pub fn linker(&mut self) -> &mut Linker { + &mut self.linker } /// Sets the epoch tick internal for the built [`Engine`]. @@ -427,14 +272,9 @@ impl EngineBuilder { /// Builds an [`Engine`] from this builder. pub fn build(self) -> Engine { let epoch_ticker_signal = self.maybe_spawn_epoch_ticker(); - - let host_components = self.host_components_builder.build(); - Engine { inner: self.engine, linker: self.linker, - module_linker: self.module_linker, - host_components, epoch_tick_interval: self.epoch_tick_interval, _epoch_ticker_signal: epoch_ticker_signal, } @@ -446,50 +286,26 @@ impl EngineBuilder { pub struct Engine { inner: wasmtime::Engine, linker: Linker, - module_linker: ModuleLinker, - host_components: HostComponents, epoch_tick_interval: Duration, // Matching receiver closes on drop _epoch_ticker_signal: Option>, } -impl Engine { +impl Engine { /// Creates a new [`EngineBuilder`] with the given [`Config`]. pub fn builder(config: &Config) -> Result> { EngineBuilder::new(config) } /// Creates a new [`StoreBuilder`]. - pub fn store_builder(&self, wasi_version: WasiVersion) -> StoreBuilder { - StoreBuilder::new( - self.inner.clone(), - self.epoch_tick_interval, - &self.host_components, - wasi_version, - ) + pub fn store_builder(&self) -> StoreBuilder { + StoreBuilder::new(self.inner.clone(), self.epoch_tick_interval) } /// Creates a new [`InstancePre`] for the given [`Component`]. #[instrument(skip_all, level = "debug")] pub fn instantiate_pre(&self, component: &Component) -> Result> { - let inner = self.linker.instantiate_pre(component)?; - Ok(InstancePre { inner }) - } - - /// Creates a new [`ModuleInstancePre`] for the given [`Module`]. - #[instrument(skip_all, level = "debug")] - pub fn module_instantiate_pre(&self, module: &Module) -> Result> { - let inner = self.module_linker.instantiate_pre(module)?; - Ok(ModuleInstancePre { inner }) - } - - /// Find the [`HostComponentDataHandle`] for a [`HostComponent`] if configured for this engine. - /// Note: [`DynamicHostComponent`]s are implicitly wrapped in `Arc`s and need to be explicitly - /// typed as such here, e.g. `find_host_component_handle::>()`. - pub fn find_host_component_handle( - &self, - ) -> Option> { - self.host_components.find_handle() + self.linker.instantiate_pre(component) } } @@ -498,61 +314,3 @@ impl AsRef for Engine { &self.inner } } - -/// A pre-initialized instance that is ready to be instantiated. -/// -/// See [`wasmtime::component::InstancePre`] for more information. -pub struct InstancePre { - inner: wasmtime::component::InstancePre>, -} - -impl InstancePre { - /// Instantiates this instance with the given [`Store`]. - #[instrument(skip_all, level = "debug")] - pub async fn instantiate_async(&self, store: &mut Store) -> Result { - self.inner.instantiate_async(store).await - } -} - -impl Clone for InstancePre { - fn clone(&self) -> Self { - Self { - inner: self.inner.clone(), - } - } -} - -impl AsRef>> for InstancePre { - fn as_ref(&self) -> &wasmtime::component::InstancePre> { - &self.inner - } -} - -/// A pre-initialized module instance that is ready to be instantiated. -/// -/// See [`wasmtime::InstancePre`] for more information. -pub struct ModuleInstancePre { - inner: wasmtime::InstancePre>, -} - -impl ModuleInstancePre { - /// Instantiates this instance with the given [`Store`]. - #[instrument(skip_all, level = "debug")] - pub async fn instantiate_async(&self, store: &mut Store) -> Result { - self.inner.instantiate_async(store).await - } -} - -impl Clone for ModuleInstancePre { - fn clone(&self) -> Self { - Self { - inner: self.inner.clone(), - } - } -} - -impl AsRef>> for ModuleInstancePre { - fn as_ref(&self) -> &wasmtime::InstancePre> { - &self.inner - } -} diff --git a/crates/core/src/preview1.rs b/crates/core/src/preview1.rs deleted file mode 100644 index 3b1cd967c..000000000 --- a/crates/core/src/preview1.rs +++ /dev/null @@ -1,212 +0,0 @@ -//! Ports of `ReadOnlyDir` and `ReadOnlyFile` to Preview 1 API. -//! Adapted from https://github.com/bytecodealliance/preview2-prototyping/pull/121 - -use std::{any::Any, path::PathBuf}; - -use wasi_common_preview1::{ - dir::{OpenResult, ReaddirCursor, ReaddirEntity}, - file::{Advice, FdFlags, FileType, Filestat, OFlags}, - Error, ErrorExt, SystemTimeSpec, WasiDir, WasiFile, -}; - -pub struct ReadOnlyDir(pub Box); - -#[async_trait::async_trait] -impl WasiDir for ReadOnlyDir { - fn as_any(&self) -> &dyn Any { - self - } - - async fn open_file( - &self, - symlink_follow: bool, - path: &str, - oflags: OFlags, - read: bool, - write: bool, - fdflags: FdFlags, - ) -> Result { - if write { - Err(Error::perm()) - } else { - let open_result = self - .0 - .open_file(symlink_follow, path, oflags, read, write, fdflags) - .await?; - Ok(match open_result { - OpenResult::File(f) => OpenResult::File(Box::new(ReadOnlyFile(f))), - OpenResult::Dir(d) => OpenResult::Dir(Box::new(ReadOnlyDir(d))), - }) - } - } - - async fn create_dir(&self, _path: &str) -> Result<(), Error> { - Err(Error::perm()) - } - - async fn readdir( - &self, - cursor: ReaddirCursor, - ) -> Result> + Send>, Error> { - self.0.readdir(cursor).await - } - - async fn symlink(&self, _old_path: &str, _new_path: &str) -> Result<(), Error> { - Err(Error::perm()) - } - - async fn remove_dir(&self, _path: &str) -> Result<(), Error> { - Err(Error::perm()) - } - - async fn unlink_file(&self, _path: &str) -> Result<(), Error> { - Err(Error::perm()) - } - - async fn read_link(&self, path: &str) -> Result { - self.0.read_link(path).await - } - - async fn get_filestat(&self) -> Result { - self.0.get_filestat().await - } - - async fn get_path_filestat( - &self, - path: &str, - follow_symlinks: bool, - ) -> Result { - self.0.get_path_filestat(path, follow_symlinks).await - } - - async fn rename( - &self, - _path: &str, - _dest_dir: &dyn WasiDir, - _dest_path: &str, - ) -> Result<(), Error> { - Err(Error::perm()) - } - - async fn hard_link( - &self, - _path: &str, - _target_dir: &dyn WasiDir, - _target_path: &str, - ) -> Result<(), Error> { - Err(Error::perm()) - } - - async fn set_times( - &self, - _path: &str, - _atime: Option, - _mtime: Option, - _follow_symlinks: bool, - ) -> Result<(), Error> { - Err(Error::perm()) - } -} - -pub struct ReadOnlyFile(pub Box); - -#[async_trait::async_trait] -impl WasiFile for ReadOnlyFile { - fn as_any(&self) -> &dyn Any { - self - } - - async fn get_filetype(&self) -> Result { - self.0.get_filetype().await - } - - #[cfg(unix)] - fn pollable(&self) -> Option { - self.0.pollable() - } - - #[cfg(windows)] - fn pollable(&self) -> Option { - self.0.pollable() - } - - fn isatty(&self) -> bool { - self.0.isatty() - } - - async fn datasync(&self) -> Result<(), Error> { - self.0.datasync().await - } - - async fn sync(&self) -> Result<(), Error> { - self.0.sync().await - } - - async fn get_fdflags(&self) -> Result { - self.0.get_fdflags().await - } - - async fn set_fdflags(&mut self, _flags: FdFlags) -> Result<(), Error> { - Err(Error::perm()) - } - - async fn get_filestat(&self) -> Result { - self.0.get_filestat().await - } - - async fn set_filestat_size(&self, _size: u64) -> Result<(), Error> { - Err(Error::perm()) - } - - async fn advise(&self, offset: u64, len: u64, advice: Advice) -> Result<(), Error> { - self.0.advise(offset, len, advice).await - } - - async fn set_times( - &self, - _atime: Option, - _mtime: Option, - ) -> Result<(), Error> { - Err(Error::perm()) - } - - async fn read_vectored<'a>(&self, bufs: &mut [std::io::IoSliceMut<'a>]) -> Result { - self.0.read_vectored(bufs).await - } - - async fn read_vectored_at<'a>( - &self, - bufs: &mut [std::io::IoSliceMut<'a>], - offset: u64, - ) -> Result { - self.0.read_vectored_at(bufs, offset).await - } - - async fn write_vectored_at<'a>( - &self, - _bufs: &[std::io::IoSlice<'a>], - _offset: u64, - ) -> Result { - Err(Error::perm()) - } - - async fn seek(&self, pos: std::io::SeekFrom) -> Result { - self.0.seek(pos).await - } - - async fn peek(&self, buf: &mut [u8]) -> Result { - self.0.peek(buf).await - } - - fn num_ready_bytes(&self) -> Result { - self.0.num_ready_bytes() - } - - async fn readable(&self) -> Result<(), Error> { - self.0.readable().await - } - - async fn writable(&self) -> Result<(), Error> { - Err(Error::perm()) - } -} diff --git a/crates/core/src/store.rs b/crates/core/src/store.rs index eeb36006b..b2b950b5f 100644 --- a/crates/core/src/store.rs +++ b/crates/core/src/store.rs @@ -1,70 +1,11 @@ -use anyhow::{anyhow, Result}; -use bytes::Bytes; -use cap_primitives::net::Pool; -use cap_std::ipnet::{IpNet, Ipv4Net, Ipv6Net}; -use std::{ - io::{Read, Write}, - mem, - net::{Ipv4Addr, Ipv6Addr}, - path::{Path, PathBuf}, - sync::{Arc, Mutex}, - time::{Duration, Instant}, -}; -use system_interface::io::ReadReady; -use tokio::io::{AsyncRead, AsyncWrite}; -use wasi_common_preview1 as wasi_preview1; -use wasmtime_wasi::{ - self as wasi_preview2, HostInputStream, HostOutputStream, StdinStream, StdoutStream, - StreamError, StreamResult, Subscribe, -}; -use wasmtime_wasi_http::types::WasiHttpCtx; +use anyhow::Result; +use std::time::{Duration, Instant}; -use crate::{ - async_trait, - host_component::{HostComponents, HostComponentsData}, - io::OutputBuffer, - limits::StoreLimitsAsync, - preview1, Data, -}; +use crate::{limits::StoreLimitsAsync, State}; #[cfg(doc)] use crate::EngineBuilder; -/// Wrapper for the Preview 1 and Preview 2 versions of `WasiCtx`. -/// -/// Currently, only WAGI uses Preview 1, while everything else uses Preview 2 (possibly via an adapter). WAGI is -/// stuck on Preview 1 and modules because there's no reliable way to wrap an arbitrary Preview 1 command in a -/// component -- the Preview 1 -> 2 adapter only works with modules that either export `canonical_abi_realloc` -/// (e.g. native Spin apps) or use a recent version of `wasi-sdk`, which contains patches to allow the adapter to -/// safely allocate memory via `memory.grow`. -/// -/// In theory, someone could build a WAGI app using a new-enough version of `wasi-sdk` and wrap it in a component -/// using the adapter, but that wouldn't add any value beyond leaving it as a module, and any toolchain capable of -/// natively producing components will be capable enough to produce native Spin apps, so we probably won't ever -/// support WAGI components. -/// -// TODO: As of this writing, the plan is to merge the WASI Preview 1 and Preview 2 implementations together, at -// which point we'll be able to avoid all the duplication here and below. -pub enum Wasi { - /// Preview 1 `WasiCtx` - Preview1(wasi_preview1::WasiCtx), - /// Preview 2 `WasiCtx` - Preview2 { - /// `wasi-cli` context - wasi_ctx: wasi_preview2::WasiCtx, - - /// `wasi-http` context - wasi_http_ctx: WasiHttpCtx, - }, -} - -/// The version of Wasi being used -#[allow(missing_docs)] -pub enum WasiVersion { - Preview1, - Preview2, -} - /// A `Store` holds the runtime state of a Spin instance. /// /// In general, a `Store` is expected to live only for the lifetime of a single @@ -72,16 +13,11 @@ pub enum WasiVersion { /// /// A `Store` can be built with a [`StoreBuilder`]. pub struct Store { - inner: wasmtime::Store>, + inner: wasmtime::Store, epoch_tick_interval: Duration, } impl Store { - /// Returns a mutable reference to the [`HostComponentsData`] of this [`Store`]. - pub fn host_components_data(&mut self) -> &mut HostComponentsData { - &mut self.inner.data_mut().host_components_data - } - /// Sets the execution deadline. /// /// This is a rough deadline; an instance will trap some time after this @@ -104,20 +40,20 @@ impl Store { } } -impl AsRef>> for Store { - fn as_ref(&self) -> &wasmtime::Store> { +impl AsRef> for Store { + fn as_ref(&self) -> &wasmtime::Store { &self.inner } } -impl AsMut>> for Store { - fn as_mut(&mut self) -> &mut wasmtime::Store> { +impl AsMut> for Store { + fn as_mut(&mut self) -> &mut wasmtime::Store { &mut self.inner } } impl wasmtime::AsContext for Store { - type Data = Data; + type Data = T; fn as_context(&self) -> wasmtime::StoreContext<'_, Self::Data> { self.inner.as_context() @@ -136,27 +72,16 @@ impl wasmtime::AsContextMut for Store { pub struct StoreBuilder { engine: wasmtime::Engine, epoch_tick_interval: Duration, - wasi: std::result::Result, - host_components_data: HostComponentsData, store_limits: StoreLimitsAsync, - net_pool: Pool, } impl StoreBuilder { // Called by Engine::store_builder. - pub(crate) fn new( - engine: wasmtime::Engine, - epoch_tick_interval: Duration, - host_components: &HostComponents, - wasi: WasiVersion, - ) -> Self { + pub(crate) fn new(engine: wasmtime::Engine, epoch_tick_interval: Duration) -> Self { Self { engine, epoch_tick_interval, - wasi: Ok(wasi.into()), - host_components_data: host_components.new_data(), store_limits: StoreLimitsAsync::default(), - net_pool: Pool::default(), } } @@ -168,281 +93,15 @@ impl StoreBuilder { self.store_limits = StoreLimitsAsync::new(Some(max_memory_size), None); } - /// Inherit stdin from the host process. - pub fn inherit_stdin(&mut self) { - self.with_wasi(|wasi| match wasi { - WasiCtxBuilder::Preview1(ctx) => { - ctx.set_stdin(Box::new(wasi_common_preview1::tokio::stdio::stdin())) - } - WasiCtxBuilder::Preview2(ctx) => { - ctx.inherit_stdin(); - } - }); - } - - /// Insert IP network with a given port range - pub fn insert_ip_net_port_range( - &mut self, - ip_net: IpNet, - ports_start: u16, - ports_end: Option, - ) { - self.with_wasi(|wasi| match wasi { - WasiCtxBuilder::Preview1(_) => { - panic!("Enabling network only allowed in preview2") - } - WasiCtxBuilder::Preview2(_) => {} - }); - - self.net_pool.insert_ip_net_port_range( - ip_net, - ports_start, - ports_end, - cap_primitives::ambient_authority(), - ); - } - - /// Allow unrestricted outbound access to the host network. - pub fn inherit_network(&mut self) { - self.with_wasi(|wasi| match wasi { - WasiCtxBuilder::Preview1(_) => { - panic!("Enabling network only allowed in preview2") - } - WasiCtxBuilder::Preview2(_) => { - // TODO: ctx.allow_udp(false); - } - }); - - // Allow access to 0.0.0.0/0, i.e. all IPv4 addresses - self.net_pool.insert_ip_net_port_any( - IpNet::V4(Ipv4Net::new(Ipv4Addr::new(0, 0, 0, 0), 0).unwrap()), - cap_primitives::ambient_authority(), - ); - // Allow access to 0:/0, i.e. all IPv6 addresses - self.net_pool.insert_ip_net_port_any( - IpNet::V6(Ipv6Net::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 0).unwrap()), - cap_primitives::ambient_authority(), - ); - } - - /// Sets the WASI `stdin` descriptor to the given [`Read`]er. - pub fn stdin_pipe( - &mut self, - r: impl AsyncRead + Read + ReadReady + Send + Sync + Unpin + 'static, - ) { - self.with_wasi(|wasi| match wasi { - WasiCtxBuilder::Preview1(ctx) => { - ctx.set_stdin(Box::new(wasi_preview1::pipe::ReadPipe::new(r))) - } - WasiCtxBuilder::Preview2(ctx) => { - ctx.stdin(PipeStdinStream::new(r)); - } - }) - } - - /// Inherit stdin from the host process. - pub fn inherit_stdout(&mut self) { - self.with_wasi(|wasi| match wasi { - WasiCtxBuilder::Preview1(ctx) => { - ctx.set_stdout(Box::new(wasi_common_preview1::tokio::stdio::stdout())) - } - WasiCtxBuilder::Preview2(ctx) => { - ctx.inherit_stdout(); - } - }); - } - - /// Sets the WASI `stdout` descriptor to the given [`Write`]er. - pub fn stdout(&mut self, w: Box) -> Result<()> { - self.try_with_wasi(|wasi| match wasi { - WasiCtxBuilder::Preview1(ctx) => { - ctx.set_stdout(w); - Ok(()) - } - WasiCtxBuilder::Preview2(_) => Err(anyhow!( - "`Store::stdout` only supported with WASI Preview 1" - )), - }) - } - - /// Sets the WASI `stdout` descriptor to the given [`Write`]er. - pub fn stdout_pipe(&mut self, w: impl AsyncWrite + Write + Send + Sync + Unpin + 'static) { - self.with_wasi(|wasi| match wasi { - WasiCtxBuilder::Preview1(ctx) => { - ctx.set_stdout(Box::new(wasi_preview1::pipe::WritePipe::new(w))) - } - WasiCtxBuilder::Preview2(ctx) => { - ctx.stdout(PipeStdoutStream::new(w)); - } - }) - } - - /// Sets the WASI `stdout` descriptor to an in-memory buffer which can be - /// retrieved after execution from the returned [`OutputBuffer`]. - pub fn stdout_buffered(&mut self) -> Result { - let buffer = OutputBuffer::default(); - // This only needs to work with Preview 2 since WAGI does its own thing with Preview 1: - self.try_with_wasi(|wasi| match wasi { - WasiCtxBuilder::Preview1(_) => Err(anyhow!( - "`Store::stdout_buffered` only supported with WASI Preview 2" - )), - WasiCtxBuilder::Preview2(ctx) => { - ctx.stdout(BufferStdoutStream(buffer.clone())); - Ok(()) - } - })?; - Ok(buffer) - } - - /// Inherit stdin from the host process. - pub fn inherit_stderr(&mut self) { - self.with_wasi(|wasi| match wasi { - WasiCtxBuilder::Preview1(ctx) => { - ctx.set_stderr(Box::new(wasi_common_preview1::tokio::stdio::stderr())) - } - WasiCtxBuilder::Preview2(ctx) => { - ctx.inherit_stderr(); - } - }); - } - - /// Sets the WASI `stderr` descriptor to the given [`Write`]er. - pub fn stderr_pipe(&mut self, w: impl AsyncWrite + Write + Send + Sync + Unpin + 'static) { - self.with_wasi(|wasi| match wasi { - WasiCtxBuilder::Preview1(ctx) => { - ctx.set_stderr(Box::new(wasi_preview1::pipe::WritePipe::new(w))) - } - WasiCtxBuilder::Preview2(ctx) => { - ctx.stderr(PipeStdoutStream::new(w)); - } - }) - } - - /// Appends the given strings to the the WASI 'args'. - pub fn args<'b>(&mut self, args: impl IntoIterator) -> Result<()> { - self.try_with_wasi(|wasi| { - for arg in args { - match wasi { - WasiCtxBuilder::Preview1(ctx) => ctx.push_arg(arg)?, - WasiCtxBuilder::Preview2(ctx) => { - ctx.arg(arg); - } - } - } - Ok(()) - }) - } - - /// Sets the given key/value string entries on the the WASI 'env'. - pub fn env( - &mut self, - vars: impl IntoIterator, impl AsRef)>, - ) -> Result<()> { - self.try_with_wasi(|wasi| { - for (k, v) in vars { - match wasi { - WasiCtxBuilder::Preview1(ctx) => ctx.push_env(k.as_ref(), v.as_ref())?, - WasiCtxBuilder::Preview2(ctx) => { - ctx.env(k, v); - } - } - } - - Ok(()) - }) - } - - /// "Mounts" the given `host_path` into the WASI filesystem at the given - /// `guest_path` with read-only capabilities. - pub fn read_only_preopened_dir( - &mut self, - host_path: impl AsRef, - guest_path: PathBuf, - ) -> Result<()> { - self.preopened_dir_impl(host_path, guest_path, false) - } - - /// "Mounts" the given `host_path` into the WASI filesystem at the given - /// `guest_path` with read and write capabilities. - pub fn read_write_preopened_dir( - &mut self, - host_path: impl AsRef, - guest_path: PathBuf, - ) -> Result<()> { - self.preopened_dir_impl(host_path, guest_path, true) - } - - fn preopened_dir_impl( - &mut self, - host_path: impl AsRef, - guest_path: PathBuf, - writable: bool, - ) -> Result<()> { - let cap_std_dir = - cap_std::fs::Dir::open_ambient_dir(host_path.as_ref(), cap_std::ambient_authority())?; - let path = guest_path - .to_str() - .ok_or_else(|| anyhow!("non-utf8 path: {}", guest_path.display()))?; - - self.try_with_wasi(|wasi| { - match wasi { - WasiCtxBuilder::Preview1(ctx) => { - let mut dir = - Box::new(wasi_common_preview1::tokio::Dir::from_cap_std(cap_std_dir)) as _; - if !writable { - dir = Box::new(preview1::ReadOnlyDir(dir)); - } - ctx.push_preopened_dir(dir, path)?; - } - WasiCtxBuilder::Preview2(ctx) => { - let dir_perms = if writable { - wasi_preview2::DirPerms::all() - } else { - wasi_preview2::DirPerms::READ - }; - let file_perms = wasi_preview2::FilePerms::all(); - - ctx.preopened_dir(host_path.as_ref(), path, dir_perms, file_perms)?; - } - } - Ok(()) - }) - } - - /// Returns a mutable reference to the built - pub fn host_components_data(&mut self) -> &mut HostComponentsData { - &mut self.host_components_data - } - /// Builds a [`Store`] from this builder with given host state data. /// - /// If `T: Default`, it may be preferable to use [`Store::build`]. - pub fn build_with_data(mut self, inner_data: T) -> Result> { - let net_pool = mem::take(&mut self.net_pool); - self.with_wasi(move |wasi| match wasi { - WasiCtxBuilder::Preview1(_) => {} - WasiCtxBuilder::Preview2(ctx) => { - ctx.socket_addr_check(move |addr, _| { - let net_pool = net_pool.clone(); - Box::pin(async move { net_pool.check_addr(&addr).is_ok() }) - }); - } - }); - - let wasi = self.wasi.map_err(anyhow::Error::msg)?.build(); - - let mut inner = wasmtime::Store::new( - &self.engine, - Data { - inner: inner_data, - wasi, - host_components_data: self.host_components_data, - store_limits: self.store_limits, - table: wasi_preview2::ResourceTable::new(), - }, - ); + /// The `T` parameter must provide access to a [`State`] via `impl + /// AsMut`. + pub fn build>(self, mut data: T) -> Result> { + data.as_mut().store_limits = self.store_limits; - inner.limiter_async(move |data| &mut data.store_limits); + let mut inner = wasmtime::Store::new(&self.engine, data); + inner.limiter_async(|data| &mut data.as_mut().store_limits); // With epoch interruption enabled, there must be _some_ deadline set // or execution will trap immediately. Since this is a delta, we need @@ -455,177 +114,4 @@ impl StoreBuilder { epoch_tick_interval: self.epoch_tick_interval, }) } - - /// Builds a [`Store`] from this builder with `Default` host state data. - pub fn build(self) -> Result> { - self.build_with_data(T::default()) - } - - fn with_wasi(&mut self, f: impl FnOnce(&mut WasiCtxBuilder)) { - let _ = self.try_with_wasi(|wasi| { - f(wasi); - Ok(()) - }); - } - - fn try_with_wasi(&mut self, f: impl FnOnce(&mut WasiCtxBuilder) -> Result<()>) -> Result<()> { - let wasi = self - .wasi - .as_mut() - .map_err(|err| anyhow!("StoreBuilder already failed: {}", err))?; - - match f(wasi) { - Ok(()) => Ok(()), - Err(err) => { - self.wasi = Err(err.to_string()); - Err(err) - } - } - } -} - -struct PipeStdinStream { - buffer: Vec, - inner: Arc>, -} - -impl PipeStdinStream { - fn new(inner: T) -> Self { - Self { - buffer: vec![0_u8; 64 * 1024], - inner: Arc::new(Mutex::new(inner)), - } - } -} - -impl Clone for PipeStdinStream { - fn clone(&self) -> Self { - Self { - buffer: vec![0_u8; 64 * 1024], - inner: self.inner.clone(), - } - } -} - -impl HostInputStream for PipeStdinStream { - fn read(&mut self, size: usize) -> StreamResult { - let size = size.min(self.buffer.len()); - - let count = self - .inner - .lock() - .unwrap() - .read(&mut self.buffer[..size]) - .map_err(|e| StreamError::LastOperationFailed(anyhow::anyhow!(e)))?; - - Ok(Bytes::copy_from_slice(&self.buffer[..count])) - } -} - -#[async_trait] -impl Subscribe for PipeStdinStream { - async fn ready(&mut self) {} -} - -impl StdinStream for PipeStdinStream { - fn stream(&self) -> Box { - Box::new(self.clone()) - } - - fn isatty(&self) -> bool { - false - } -} - -struct PipeStdoutStream(Arc>); - -impl Clone for PipeStdoutStream { - fn clone(&self) -> Self { - Self(self.0.clone()) - } -} - -impl PipeStdoutStream { - fn new(inner: T) -> Self { - Self(Arc::new(Mutex::new(inner))) - } -} - -impl HostOutputStream for PipeStdoutStream { - fn write(&mut self, bytes: Bytes) -> Result<(), StreamError> { - self.0 - .lock() - .unwrap() - .write_all(&bytes) - .map_err(|e| StreamError::LastOperationFailed(anyhow::anyhow!(e))) - } - - fn flush(&mut self) -> Result<(), StreamError> { - self.0 - .lock() - .unwrap() - .flush() - .map_err(|e| StreamError::LastOperationFailed(anyhow::anyhow!(e))) - } - - fn check_write(&mut self) -> Result { - Ok(1024 * 1024) - } -} - -impl StdoutStream for PipeStdoutStream { - fn stream(&self) -> Box { - Box::new(self.clone()) - } - - fn isatty(&self) -> bool { - false - } -} - -#[async_trait] -impl Subscribe for PipeStdoutStream { - async fn ready(&mut self) {} -} - -struct BufferStdoutStream(OutputBuffer); - -impl StdoutStream for BufferStdoutStream { - fn stream(&self) -> Box { - Box::new(self.0.writer()) - } - - fn isatty(&self) -> bool { - false - } -} - -/// A builder of a `WasiCtx` for all versions of Wasi -#[allow(clippy::large_enum_variant)] -enum WasiCtxBuilder { - Preview1(wasi_preview1::WasiCtx), - Preview2(wasi_preview2::WasiCtxBuilder), -} - -impl From for WasiCtxBuilder { - fn from(value: WasiVersion) -> Self { - match value { - WasiVersion::Preview1 => { - Self::Preview1(wasi_common_preview1::tokio::WasiCtxBuilder::new().build()) - } - WasiVersion::Preview2 => Self::Preview2(wasi_preview2::WasiCtxBuilder::new()), - } - } -} - -impl WasiCtxBuilder { - fn build(self) -> Wasi { - match self { - WasiCtxBuilder::Preview1(ctx) => Wasi::Preview1(ctx), - WasiCtxBuilder::Preview2(mut b) => Wasi::Preview2 { - wasi_ctx: b.build(), - wasi_http_ctx: WasiHttpCtx::new(), - }, - } - } } diff --git a/crates/core/src/wasi_2023_10_18.rs b/crates/core/src/wasi_2023_10_18.rs deleted file mode 100644 index 9918f5a5e..000000000 --- a/crates/core/src/wasi_2023_10_18.rs +++ /dev/null @@ -1,2465 +0,0 @@ -#![doc(hidden)] // internal implementation detail used in tests and spin-trigger - -use anyhow::Result; -use async_trait::async_trait; -use std::mem; -use wasmtime::component::{Linker, Resource}; -use wasmtime_wasi::{TrappableError, WasiImpl, WasiView}; -use wasmtime_wasi_http::{WasiHttpImpl, WasiHttpView}; - -mod latest { - pub use wasmtime_wasi::bindings::*; - pub mod http { - pub use wasmtime_wasi_http::bindings::http::*; - } -} - -mod bindings { - use super::latest; - pub use super::UdpSocket; - - wasmtime::component::bindgen!({ - path: "../../wit", - interfaces: r#" - include wasi:http/proxy@0.2.0-rc-2023-10-18; - - // NB: this is handling the historical behavior where Spin supported - // more than "just" this snaphsot of the proxy world but additionally - // other CLI-related interfaces. - include wasi:cli/reactor@0.2.0-rc-2023-10-18; - "#, - async: { - only_imports: [ - "[method]descriptor.access-at", - "[method]descriptor.advise", - "[method]descriptor.change-directory-permissions-at", - "[method]descriptor.change-file-permissions-at", - "[method]descriptor.create-directory-at", - "[method]descriptor.get-flags", - "[method]descriptor.get-type", - "[method]descriptor.is-same-object", - "[method]descriptor.link-at", - "[method]descriptor.lock-exclusive", - "[method]descriptor.lock-shared", - "[method]descriptor.metadata-hash", - "[method]descriptor.metadata-hash-at", - "[method]descriptor.open-at", - "[method]descriptor.read", - "[method]descriptor.read-directory", - "[method]descriptor.readlink-at", - "[method]descriptor.remove-directory-at", - "[method]descriptor.rename-at", - "[method]descriptor.set-size", - "[method]descriptor.set-times", - "[method]descriptor.set-times-at", - "[method]descriptor.stat", - "[method]descriptor.stat-at", - "[method]descriptor.symlink-at", - "[method]descriptor.sync", - "[method]descriptor.sync-data", - "[method]descriptor.try-lock-exclusive", - "[method]descriptor.try-lock-shared", - "[method]descriptor.unlink-file-at", - "[method]descriptor.unlock", - "[method]descriptor.write", - "[method]input-stream.read", - "[method]input-stream.blocking-read", - "[method]input-stream.blocking-skip", - "[method]input-stream.skip", - "[method]output-stream.forward", - "[method]output-stream.splice", - "[method]output-stream.blocking-splice", - "[method]output-stream.blocking-flush", - "[method]output-stream.blocking-write", - "[method]output-stream.blocking-write-and-flush", - "[method]output-stream.blocking-write-zeroes-and-flush", - "[method]directory-entry-stream.read-directory-entry", - "poll-list", - "poll-one", - - "[method]tcp-socket.start-bind", - "[method]tcp-socket.start-connect", - "[method]udp-socket.finish-connect", - "[method]udp-socket.receive", - "[method]udp-socket.send", - "[method]udp-socket.start-bind", - "[method]udp-socket.stream", - "[method]outgoing-datagram-stream.send", - ], - }, - with: { - "wasi:io/poll/pollable": latest::io::poll::Pollable, - "wasi:io/streams/input-stream": latest::io::streams::InputStream, - "wasi:io/streams/output-stream": latest::io::streams::OutputStream, - "wasi:io/streams/error": latest::io::streams::Error, - "wasi:filesystem/types/directory-entry-stream": latest::filesystem::types::DirectoryEntryStream, - "wasi:filesystem/types/descriptor": latest::filesystem::types::Descriptor, - "wasi:cli/terminal-input/terminal-input": latest::cli::terminal_input::TerminalInput, - "wasi:cli/terminal-output/terminal-output": latest::cli::terminal_output::TerminalOutput, - "wasi:sockets/tcp/tcp-socket": latest::sockets::tcp::TcpSocket, - "wasi:sockets/udp/udp-socket": UdpSocket, - "wasi:sockets/network/network": latest::sockets::network::Network, - "wasi:sockets/ip-name-lookup/resolve-address-stream": latest::sockets::ip_name_lookup::ResolveAddressStream, - "wasi:http/types/incoming-response": latest::http::types::IncomingResponse, - "wasi:http/types/incoming-request": latest::http::types::IncomingRequest, - "wasi:http/types/incoming-body": latest::http::types::IncomingBody, - "wasi:http/types/outgoing-response": latest::http::types::OutgoingResponse, - "wasi:http/types/outgoing-request": latest::http::types::OutgoingRequest, - "wasi:http/types/outgoing-body": latest::http::types::OutgoingBody, - "wasi:http/types/fields": latest::http::types::Fields, - "wasi:http/types/response-outparam": latest::http::types::ResponseOutparam, - "wasi:http/types/future-incoming-response": latest::http::types::FutureIncomingResponse, - "wasi:http/types/future-trailers": latest::http::types::FutureTrailers, - }, - trappable_imports: true, - }); -} - -mod wasi { - pub use super::bindings::wasi::{ - cli0_2_0_rc_2023_10_18 as cli, clocks0_2_0_rc_2023_10_18 as clocks, - filesystem0_2_0_rc_2023_10_18 as filesystem, http0_2_0_rc_2023_10_18 as http, - io0_2_0_rc_2023_10_18 as io, random0_2_0_rc_2023_10_18 as random, - sockets0_2_0_rc_2023_10_18 as sockets, - }; -} - -pub mod exports { - pub mod wasi { - pub use super::super::bindings::exports::wasi::http0_2_0_rc_2023_10_18 as http; - } -} - -use wasi::cli::terminal_input::TerminalInput; -use wasi::cli::terminal_output::TerminalOutput; -use wasi::clocks::monotonic_clock::Instant; -use wasi::clocks::wall_clock::Datetime; -use wasi::filesystem::types::{ - AccessType, Advice, Descriptor, DescriptorFlags, DescriptorStat, DescriptorType, - DirectoryEntry, DirectoryEntryStream, Error, ErrorCode as FsErrorCode, Filesize, - MetadataHashValue, Modes, NewTimestamp, OpenFlags, PathFlags, -}; -use wasi::http::types::{ - Error as HttpError, Fields, FutureIncomingResponse, FutureTrailers, Headers, IncomingBody, - IncomingRequest, IncomingResponse, Method, OutgoingBody, OutgoingRequest, OutgoingResponse, - RequestOptions, ResponseOutparam, Scheme, StatusCode, Trailers, -}; -use wasi::io::poll::Pollable; -use wasi::io::streams::{InputStream, OutputStream, StreamError}; -use wasi::sockets::ip_name_lookup::{IpAddress, ResolveAddressStream}; -use wasi::sockets::network::{Ipv4SocketAddress, Ipv6SocketAddress}; -use wasi::sockets::tcp::{ - ErrorCode as SocketErrorCode, IpAddressFamily, IpSocketAddress, Network, ShutdownType, - TcpSocket, -}; -use wasi::sockets::udp::Datagram; - -pub fn add_to_linker(linker: &mut Linker) -> Result<()> -where - T: WasiView + WasiHttpView, -{ - // interfaces from the "command" world - fn type_annotate_wasi(f: F) -> F - where - F: Fn(&mut T) -> WasiImpl<&mut T>, - { - f - } - let closure = type_annotate_wasi::(|t| WasiImpl(t)); - wasi::clocks::monotonic_clock::add_to_linker_get_host(linker, closure)?; - wasi::clocks::wall_clock::add_to_linker_get_host(linker, closure)?; - wasi::filesystem::types::add_to_linker_get_host(linker, closure)?; - wasi::filesystem::preopens::add_to_linker_get_host(linker, closure)?; - wasi::io::poll::add_to_linker_get_host(linker, closure)?; - wasi::io::streams::add_to_linker_get_host(linker, closure)?; - wasi::random::random::add_to_linker_get_host(linker, closure)?; - wasi::random::insecure::add_to_linker_get_host(linker, closure)?; - wasi::random::insecure_seed::add_to_linker_get_host(linker, closure)?; - wasi::cli::exit::add_to_linker_get_host(linker, closure)?; - wasi::cli::environment::add_to_linker_get_host(linker, closure)?; - wasi::cli::stdin::add_to_linker_get_host(linker, closure)?; - wasi::cli::stdout::add_to_linker_get_host(linker, closure)?; - wasi::cli::stderr::add_to_linker_get_host(linker, closure)?; - wasi::cli::terminal_input::add_to_linker_get_host(linker, closure)?; - wasi::cli::terminal_output::add_to_linker_get_host(linker, closure)?; - wasi::cli::terminal_stdin::add_to_linker_get_host(linker, closure)?; - wasi::cli::terminal_stdout::add_to_linker_get_host(linker, closure)?; - wasi::cli::terminal_stderr::add_to_linker_get_host(linker, closure)?; - wasi::sockets::tcp::add_to_linker_get_host(linker, closure)?; - wasi::sockets::tcp_create_socket::add_to_linker_get_host(linker, closure)?; - wasi::sockets::udp::add_to_linker_get_host(linker, closure)?; - wasi::sockets::udp_create_socket::add_to_linker_get_host(linker, closure)?; - wasi::sockets::instance_network::add_to_linker_get_host(linker, closure)?; - wasi::sockets::network::add_to_linker_get_host(linker, closure)?; - wasi::sockets::ip_name_lookup::add_to_linker_get_host(linker, closure)?; - - fn type_annotate_http(f: F) -> F - where - F: Fn(&mut T) -> WasiHttpImpl<&mut T>, - { - f - } - let closure = type_annotate_http::(|t| WasiHttpImpl(t)); - wasi::http::types::add_to_linker_get_host(linker, closure)?; - wasi::http::outgoing_handler::add_to_linker_get_host(linker, closure)?; - Ok(()) -} - -impl wasi::clocks::monotonic_clock::Host for WasiImpl -where - T: WasiView, -{ - fn now(&mut self) -> wasmtime::Result { - latest::clocks::monotonic_clock::Host::now(self) - } - - fn resolution(&mut self) -> wasmtime::Result { - latest::clocks::monotonic_clock::Host::resolution(self) - } - - fn subscribe(&mut self, when: Instant, absolute: bool) -> wasmtime::Result> { - if absolute { - latest::clocks::monotonic_clock::Host::subscribe_instant(self, when) - } else { - latest::clocks::monotonic_clock::Host::subscribe_duration(self, when) - } - } -} - -impl wasi::clocks::wall_clock::Host for WasiImpl -where - T: WasiView, -{ - fn now(&mut self) -> wasmtime::Result { - Ok(latest::clocks::wall_clock::Host::now(self)?.into()) - } - - fn resolution(&mut self) -> wasmtime::Result { - Ok(latest::clocks::wall_clock::Host::resolution(self)?.into()) - } -} - -impl wasi::filesystem::types::Host for WasiImpl -where - T: WasiView, -{ - fn filesystem_error_code( - &mut self, - err: Resource, - ) -> wasmtime::Result> { - Ok(latest::filesystem::types::Host::filesystem_error_code(self, err)?.map(|e| e.into())) - } -} - -#[async_trait] -impl wasi::filesystem::types::HostDescriptor for WasiImpl -where - T: WasiView, -{ - fn read_via_stream( - &mut self, - self_: Resource, - offset: Filesize, - ) -> wasmtime::Result, FsErrorCode>> { - convert_result(latest::filesystem::types::HostDescriptor::read_via_stream( - self, self_, offset, - )) - } - - fn write_via_stream( - &mut self, - self_: Resource, - offset: Filesize, - ) -> wasmtime::Result, FsErrorCode>> { - convert_result(latest::filesystem::types::HostDescriptor::write_via_stream( - self, self_, offset, - )) - } - - fn append_via_stream( - &mut self, - self_: Resource, - ) -> wasmtime::Result, FsErrorCode>> { - convert_result(latest::filesystem::types::HostDescriptor::append_via_stream(self, self_)) - } - - async fn advise( - &mut self, - self_: Resource, - offset: Filesize, - length: Filesize, - advice: Advice, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::advise( - self, - self_, - offset, - length, - advice.into(), - ) - .await, - ) - } - - async fn sync_data( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::filesystem::types::HostDescriptor::sync_data(self, self_).await) - } - - async fn get_flags( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::filesystem::types::HostDescriptor::get_flags(self, self_).await) - } - - async fn get_type( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::filesystem::types::HostDescriptor::get_type(self, self_).await) - } - - async fn set_size( - &mut self, - self_: Resource, - size: Filesize, - ) -> wasmtime::Result> { - convert_result(latest::filesystem::types::HostDescriptor::set_size(self, self_, size).await) - } - - async fn set_times( - &mut self, - self_: Resource, - data_access_timestamp: NewTimestamp, - data_modification_timestamp: NewTimestamp, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::set_times( - self, - self_, - data_access_timestamp.into(), - data_modification_timestamp.into(), - ) - .await, - ) - } - - async fn read( - &mut self, - self_: Resource, - length: Filesize, - offset: Filesize, - ) -> wasmtime::Result, bool), FsErrorCode>> { - convert_result( - latest::filesystem::types::HostDescriptor::read(self, self_, length, offset).await, - ) - } - - async fn write( - &mut self, - self_: Resource, - buffer: Vec, - offset: Filesize, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::write(self, self_, buffer, offset).await, - ) - } - - async fn read_directory( - &mut self, - self_: Resource, - ) -> wasmtime::Result, FsErrorCode>> { - convert_result(latest::filesystem::types::HostDescriptor::read_directory(self, self_).await) - } - - async fn sync( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::filesystem::types::HostDescriptor::sync(self, self_).await) - } - - async fn create_directory_at( - &mut self, - self_: Resource, - path: String, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::create_directory_at(self, self_, path).await, - ) - } - - async fn stat( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::filesystem::types::HostDescriptor::stat(self, self_).await) - } - - async fn stat_at( - &mut self, - self_: Resource, - path_flags: PathFlags, - path: String, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::stat_at( - self, - self_, - path_flags.into(), - path, - ) - .await, - ) - } - - async fn set_times_at( - &mut self, - self_: Resource, - path_flags: PathFlags, - path: String, - data_access_timestamp: NewTimestamp, - data_modification_timestamp: NewTimestamp, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::set_times_at( - self, - self_, - path_flags.into(), - path, - data_access_timestamp.into(), - data_modification_timestamp.into(), - ) - .await, - ) - } - - async fn link_at( - &mut self, - self_: Resource, - old_path_flags: PathFlags, - old_path: String, - new_descriptor: Resource, - new_path: String, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::link_at( - self, - self_, - old_path_flags.into(), - old_path, - new_descriptor, - new_path, - ) - .await, - ) - } - - async fn open_at( - &mut self, - self_: Resource, - path_flags: PathFlags, - path: String, - open_flags: OpenFlags, - flags: DescriptorFlags, - _modes: Modes, - ) -> wasmtime::Result, FsErrorCode>> { - convert_result( - latest::filesystem::types::HostDescriptor::open_at( - self, - self_, - path_flags.into(), - path, - open_flags.into(), - flags.into(), - ) - .await, - ) - } - - async fn readlink_at( - &mut self, - self_: Resource, - path: String, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::readlink_at(self, self_, path).await, - ) - } - - async fn remove_directory_at( - &mut self, - self_: Resource, - path: String, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::remove_directory_at(self, self_, path).await, - ) - } - - async fn rename_at( - &mut self, - self_: Resource, - old_path: String, - new_descriptor: Resource, - new_path: String, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::rename_at( - self, - self_, - old_path, - new_descriptor, - new_path, - ) - .await, - ) - } - - async fn symlink_at( - &mut self, - self_: Resource, - old_path: String, - new_path: String, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::symlink_at(self, self_, old_path, new_path) - .await, - ) - } - - async fn access_at( - &mut self, - _self_: Resource, - _path_flags: PathFlags, - _path: String, - _type_: AccessType, - ) -> wasmtime::Result> { - anyhow::bail!("access-at API is no longer supported in the latest snapshot") - } - - async fn unlink_file_at( - &mut self, - self_: Resource, - path: String, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::unlink_file_at(self, self_, path).await, - ) - } - - async fn change_file_permissions_at( - &mut self, - _self_: Resource, - _path_flags: PathFlags, - _path: String, - _modes: Modes, - ) -> wasmtime::Result> { - anyhow::bail!( - "change-file-permissions-at API is no longer supported in the latest snapshot" - ) - } - - async fn change_directory_permissions_at( - &mut self, - _self_: Resource, - _path_flags: PathFlags, - _path: String, - _modes: Modes, - ) -> wasmtime::Result> { - anyhow::bail!( - "change-directory-permissions-at API is no longer supported in the latest snapshot" - ) - } - - async fn lock_shared( - &mut self, - _self_: Resource, - ) -> wasmtime::Result> { - anyhow::bail!("lock-shared API is no longer supported in the latest snapshot") - } - - async fn lock_exclusive( - &mut self, - _self_: Resource, - ) -> wasmtime::Result> { - anyhow::bail!("lock-exclusive API is no longer supported in the latest snapshot") - } - - async fn try_lock_shared( - &mut self, - _self_: Resource, - ) -> wasmtime::Result> { - anyhow::bail!("try-lock-shared API is no longer supported in the latest snapshot") - } - - async fn try_lock_exclusive( - &mut self, - _self_: Resource, - ) -> wasmtime::Result> { - anyhow::bail!("try-lock-exclusive API is no longer supported in the latest snapshot") - } - - async fn unlock( - &mut self, - _self_: Resource, - ) -> wasmtime::Result> { - anyhow::bail!("unlock API is no longer supported in the latest snapshot") - } - - async fn is_same_object( - &mut self, - self_: Resource, - other: Resource, - ) -> wasmtime::Result { - latest::filesystem::types::HostDescriptor::is_same_object(self, self_, other).await - } - - async fn metadata_hash( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::filesystem::types::HostDescriptor::metadata_hash(self, self_).await) - } - - async fn metadata_hash_at( - &mut self, - self_: Resource, - path_flags: PathFlags, - path: String, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::metadata_hash_at( - self, - self_, - path_flags.into(), - path, - ) - .await, - ) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::filesystem::types::HostDescriptor::drop(self, rep) - } -} - -#[async_trait] -impl wasi::filesystem::types::HostDirectoryEntryStream for WasiImpl -where - T: WasiView, -{ - async fn read_directory_entry( - &mut self, - self_: Resource, - ) -> wasmtime::Result, FsErrorCode>> { - convert_result( - latest::filesystem::types::HostDirectoryEntryStream::read_directory_entry(self, self_) - .await - .map(|e| e.map(DirectoryEntry::from)), - ) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::filesystem::types::HostDirectoryEntryStream::drop(self, rep) - } -} - -impl wasi::filesystem::preopens::Host for WasiImpl -where - T: WasiView, -{ - fn get_directories(&mut self) -> wasmtime::Result, String)>> { - latest::filesystem::preopens::Host::get_directories(self) - } -} - -#[async_trait] -impl wasi::io::poll::Host for WasiImpl -where - T: WasiView, -{ - async fn poll_list(&mut self, list: Vec>) -> wasmtime::Result> { - latest::io::poll::Host::poll(self, list).await - } - - async fn poll_one(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::io::poll::HostPollable::block(self, rep).await - } -} - -impl wasi::io::poll::HostPollable for WasiImpl -where - T: WasiView, -{ - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::io::poll::HostPollable::drop(self, rep) - } -} - -impl wasi::io::streams::Host for WasiImpl where T: WasiView {} - -impl wasi::io::streams::HostError for WasiImpl -where - T: WasiView, -{ - fn to_debug_string(&mut self, self_: Resource) -> wasmtime::Result { - latest::io::error::HostError::to_debug_string(self, self_) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::io::error::HostError::drop(self, rep) - } -} - -#[async_trait] -impl wasi::io::streams::HostInputStream for WasiImpl -where - T: WasiView, -{ - async fn read( - &mut self, - self_: Resource, - len: u64, - ) -> wasmtime::Result, StreamError>> { - let result = latest::io::streams::HostInputStream::read(self, self_, len).await; - convert_stream_result(self, result) - } - - async fn blocking_read( - &mut self, - self_: Resource, - len: u64, - ) -> wasmtime::Result, StreamError>> { - let result = latest::io::streams::HostInputStream::blocking_read(self, self_, len).await; - convert_stream_result(self, result) - } - - async fn skip( - &mut self, - self_: Resource, - len: u64, - ) -> wasmtime::Result> { - let result = latest::io::streams::HostInputStream::skip(self, self_, len).await; - convert_stream_result(self, result) - } - - async fn blocking_skip( - &mut self, - self_: Resource, - len: u64, - ) -> wasmtime::Result> { - let result = latest::io::streams::HostInputStream::blocking_skip(self, self_, len).await; - convert_stream_result(self, result) - } - - fn subscribe(&mut self, self_: Resource) -> wasmtime::Result> { - latest::io::streams::HostInputStream::subscribe(self, self_) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::io::streams::HostInputStream::drop(self, rep) - } -} - -#[async_trait] -impl wasi::io::streams::HostOutputStream for WasiImpl -where - T: WasiView, -{ - fn check_write( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - let result = latest::io::streams::HostOutputStream::check_write(self, self_); - convert_stream_result(self, result) - } - - fn write( - &mut self, - self_: Resource, - contents: Vec, - ) -> wasmtime::Result> { - let result = latest::io::streams::HostOutputStream::write(self, self_, contents); - convert_stream_result(self, result) - } - - async fn blocking_write_and_flush( - &mut self, - self_: Resource, - contents: Vec, - ) -> wasmtime::Result> { - let result = - latest::io::streams::HostOutputStream::blocking_write_and_flush(self, self_, contents) - .await; - convert_stream_result(self, result) - } - - fn flush( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - let result = latest::io::streams::HostOutputStream::flush(self, self_); - convert_stream_result(self, result) - } - - async fn blocking_flush( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - let result = latest::io::streams::HostOutputStream::blocking_flush(self, self_).await; - convert_stream_result(self, result) - } - - fn subscribe(&mut self, self_: Resource) -> wasmtime::Result> { - latest::io::streams::HostOutputStream::subscribe(self, self_) - } - - fn write_zeroes( - &mut self, - self_: Resource, - len: u64, - ) -> wasmtime::Result> { - let result = latest::io::streams::HostOutputStream::write_zeroes(self, self_, len); - convert_stream_result(self, result) - } - - async fn blocking_write_zeroes_and_flush( - &mut self, - self_: Resource, - len: u64, - ) -> wasmtime::Result> { - let result = latest::io::streams::HostOutputStream::blocking_write_zeroes_and_flush( - self, self_, len, - ) - .await; - convert_stream_result(self, result) - } - - async fn splice( - &mut self, - self_: Resource, - src: Resource, - len: u64, - ) -> wasmtime::Result> { - let result = latest::io::streams::HostOutputStream::splice(self, self_, src, len).await; - convert_stream_result(self, result) - } - - async fn blocking_splice( - &mut self, - self_: Resource, - src: Resource, - len: u64, - ) -> wasmtime::Result> { - let result = - latest::io::streams::HostOutputStream::blocking_splice(self, self_, src, len).await; - convert_stream_result(self, result) - } - - async fn forward( - &mut self, - _self_: Resource, - _src: Resource, - ) -> wasmtime::Result> { - anyhow::bail!("forward API no longer supported") - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::io::streams::HostOutputStream::drop(self, rep) - } -} - -impl wasi::random::random::Host for WasiImpl -where - T: WasiView, -{ - fn get_random_bytes(&mut self, len: u64) -> wasmtime::Result> { - latest::random::random::Host::get_random_bytes(self, len) - } - - fn get_random_u64(&mut self) -> wasmtime::Result { - latest::random::random::Host::get_random_u64(self) - } -} - -impl wasi::random::insecure::Host for WasiImpl -where - T: WasiView, -{ - fn get_insecure_random_bytes(&mut self, len: u64) -> wasmtime::Result> { - latest::random::insecure::Host::get_insecure_random_bytes(self, len) - } - - fn get_insecure_random_u64(&mut self) -> wasmtime::Result { - latest::random::insecure::Host::get_insecure_random_u64(self) - } -} - -impl wasi::random::insecure_seed::Host for WasiImpl -where - T: WasiView, -{ - fn insecure_seed(&mut self) -> wasmtime::Result<(u64, u64)> { - latest::random::insecure_seed::Host::insecure_seed(self) - } -} - -impl wasi::cli::exit::Host for WasiImpl -where - T: WasiView, -{ - fn exit(&mut self, status: Result<(), ()>) -> wasmtime::Result<()> { - latest::cli::exit::Host::exit(self, status) - } -} - -impl wasi::cli::environment::Host for WasiImpl -where - T: WasiView, -{ - fn get_environment(&mut self) -> wasmtime::Result> { - latest::cli::environment::Host::get_environment(self) - } - - fn get_arguments(&mut self) -> wasmtime::Result> { - latest::cli::environment::Host::get_arguments(self) - } - - fn initial_cwd(&mut self) -> wasmtime::Result> { - latest::cli::environment::Host::initial_cwd(self) - } -} - -impl wasi::cli::stdin::Host for WasiImpl -where - T: WasiView, -{ - fn get_stdin(&mut self) -> wasmtime::Result> { - latest::cli::stdin::Host::get_stdin(self) - } -} - -impl wasi::cli::stdout::Host for WasiImpl -where - T: WasiView, -{ - fn get_stdout(&mut self) -> wasmtime::Result> { - latest::cli::stdout::Host::get_stdout(self) - } -} - -impl wasi::cli::stderr::Host for WasiImpl -where - T: WasiView, -{ - fn get_stderr(&mut self) -> wasmtime::Result> { - latest::cli::stderr::Host::get_stderr(self) - } -} - -impl wasi::cli::terminal_stdin::Host for WasiImpl -where - T: WasiView, -{ - fn get_terminal_stdin(&mut self) -> wasmtime::Result>> { - latest::cli::terminal_stdin::Host::get_terminal_stdin(self) - } -} - -impl wasi::cli::terminal_stdout::Host for WasiImpl -where - T: WasiView, -{ - fn get_terminal_stdout(&mut self) -> wasmtime::Result>> { - latest::cli::terminal_stdout::Host::get_terminal_stdout(self) - } -} - -impl wasi::cli::terminal_stderr::Host for WasiImpl -where - T: WasiView, -{ - fn get_terminal_stderr(&mut self) -> wasmtime::Result>> { - latest::cli::terminal_stderr::Host::get_terminal_stderr(self) - } -} - -impl wasi::cli::terminal_input::Host for WasiImpl where T: WasiView {} - -impl wasi::cli::terminal_input::HostTerminalInput for WasiImpl -where - T: WasiView, -{ - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::cli::terminal_input::HostTerminalInput::drop(self, rep) - } -} - -impl wasi::cli::terminal_output::Host for WasiImpl where T: WasiView {} - -impl wasi::cli::terminal_output::HostTerminalOutput for WasiImpl -where - T: WasiView, -{ - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::cli::terminal_output::HostTerminalOutput::drop(self, rep) - } -} - -impl wasi::sockets::tcp::Host for WasiImpl where T: WasiView {} - -#[async_trait] -impl wasi::sockets::tcp::HostTcpSocket for WasiImpl -where - T: WasiView, -{ - async fn start_bind( - &mut self, - self_: Resource, - network: Resource, - local_address: IpSocketAddress, - ) -> wasmtime::Result> { - convert_result( - latest::sockets::tcp::HostTcpSocket::start_bind( - self, - self_, - network, - local_address.into(), - ) - .await, - ) - } - - fn finish_bind( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::finish_bind( - self, self_, - )) - } - - async fn start_connect( - &mut self, - self_: Resource, - network: Resource, - remote_address: IpSocketAddress, - ) -> wasmtime::Result> { - convert_result( - latest::sockets::tcp::HostTcpSocket::start_connect( - self, - self_, - network, - remote_address.into(), - ) - .await, - ) - } - - fn finish_connect( - &mut self, - self_: Resource, - ) -> wasmtime::Result, Resource), SocketErrorCode>> - { - convert_result(latest::sockets::tcp::HostTcpSocket::finish_connect( - self, self_, - )) - } - - fn start_listen( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::start_listen( - self, self_, - )) - } - - fn finish_listen( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::finish_listen( - self, self_, - )) - } - - fn accept( - &mut self, - self_: Resource, - ) -> wasmtime::Result< - Result< - ( - Resource, - Resource, - Resource, - ), - SocketErrorCode, - >, - > { - convert_result(latest::sockets::tcp::HostTcpSocket::accept(self, self_)) - } - - fn local_address( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::local_address( - self, self_, - )) - } - - fn remote_address( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::remote_address( - self, self_, - )) - } - - fn address_family(&mut self, self_: Resource) -> wasmtime::Result { - latest::sockets::tcp::HostTcpSocket::address_family(self, self_).map(|e| e.into()) - } - - fn ipv6_only( - &mut self, - _self_: Resource, - ) -> wasmtime::Result> { - anyhow::bail!("ipv6-only API no longer supported") - } - - fn set_ipv6_only( - &mut self, - _self_: Resource, - _value: bool, - ) -> wasmtime::Result> { - anyhow::bail!("ipv6-only API no longer supported") - } - - fn set_listen_backlog_size( - &mut self, - self_: Resource, - value: u64, - ) -> wasmtime::Result> { - convert_result( - latest::sockets::tcp::HostTcpSocket::set_listen_backlog_size(self, self_, value), - ) - } - - fn keep_alive( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::keep_alive_enabled( - self, self_, - )) - } - - fn set_keep_alive( - &mut self, - self_: Resource, - value: bool, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::set_keep_alive_enabled( - self, self_, value, - )) - } - - fn no_delay( - &mut self, - _self_: Resource, - ) -> wasmtime::Result> { - anyhow::bail!("no-delay API no longer supported") - } - - fn set_no_delay( - &mut self, - _self_: Resource, - _value: bool, - ) -> wasmtime::Result> { - anyhow::bail!("set-no-delay API no longer supported") - } - - fn unicast_hop_limit( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::hop_limit(self, self_)) - } - - fn set_unicast_hop_limit( - &mut self, - self_: Resource, - value: u8, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::set_hop_limit( - self, self_, value, - )) - } - - fn receive_buffer_size( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::receive_buffer_size( - self, self_, - )) - } - - fn set_receive_buffer_size( - &mut self, - self_: Resource, - value: u64, - ) -> wasmtime::Result> { - convert_result( - latest::sockets::tcp::HostTcpSocket::set_receive_buffer_size(self, self_, value), - ) - } - - fn send_buffer_size( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::send_buffer_size( - self, self_, - )) - } - - fn set_send_buffer_size( - &mut self, - self_: Resource, - value: u64, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::set_send_buffer_size( - self, self_, value, - )) - } - - fn subscribe(&mut self, self_: Resource) -> wasmtime::Result> { - latest::sockets::tcp::HostTcpSocket::subscribe(self, self_) - } - - fn shutdown( - &mut self, - self_: Resource, - shutdown_type: ShutdownType, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::shutdown( - self, - self_, - shutdown_type.into(), - )) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::sockets::tcp::HostTcpSocket::drop(self, rep) - } -} - -impl wasi::sockets::tcp_create_socket::Host for WasiImpl -where - T: WasiView, -{ - fn create_tcp_socket( - &mut self, - address_family: IpAddressFamily, - ) -> wasmtime::Result, SocketErrorCode>> { - convert_result(latest::sockets::tcp_create_socket::Host::create_tcp_socket( - self, - address_family.into(), - )) - } -} - -impl wasi::sockets::udp::Host for WasiImpl where T: WasiView {} - -/// Between the snapshot of WASI that this file is implementing and the current -/// implementation of WASI UDP sockets were redesigned slightly to deal with -/// a different way of managing incoming and outgoing datagrams. This means -/// that this snapshot's `{start,finish}_connect`, `send`, and `receive` -/// methods are no longer natively implemented, so they're polyfilled by this -/// implementation. -pub enum UdpSocket { - Initial(Resource), - Connecting(Resource, IpSocketAddress), - Connected { - socket: Resource, - incoming: Resource, - outgoing: Resource, - }, - Dummy, -} - -impl UdpSocket { - async fn finish_connect( - table: &mut WasiImpl, - socket: &Resource, - explicit: bool, - ) -> wasmtime::Result> { - let state = table.table().get_mut(socket)?; - let (new_socket, addr) = match mem::replace(state, UdpSocket::Dummy) { - // Implicit finishes will call `stream` for sockets in the initial - // state. - UdpSocket::Initial(socket) if !explicit => (socket, None), - // Implicit finishes won't try to reconnect a socket. - UdpSocket::Connected { .. } if !explicit => return Ok(Ok(())), - // Only explicit finishes can transition from the `Connecting` state. - UdpSocket::Connecting(socket, addr) if explicit => (socket, Some(addr)), - _ => return Ok(Err(SocketErrorCode::ConcurrencyConflict)), - }; - let borrow = Resource::new_borrow(new_socket.rep()); - let result = convert_result( - latest::sockets::udp::HostUdpSocket::stream(table, borrow, addr.map(|a| a.into())) - .await, - )?; - let (incoming, outgoing) = match result { - Ok(pair) => pair, - Err(e) => return Ok(Err(e)), - }; - *table.table().get_mut(socket)? = UdpSocket::Connected { - socket: new_socket, - incoming, - outgoing, - }; - Ok(Ok(())) - } - - fn inner(&self) -> wasmtime::Result> { - let r = match self { - UdpSocket::Initial(r) => r, - UdpSocket::Connecting(r, _) => r, - UdpSocket::Connected { socket, .. } => socket, - UdpSocket::Dummy => anyhow::bail!("invalid udp socket state"), - }; - Ok(Resource::new_borrow(r.rep())) - } -} - -#[async_trait] -impl wasi::sockets::udp::HostUdpSocket for WasiImpl -where - T: WasiView, -{ - async fn start_bind( - &mut self, - self_: Resource, - network: Resource, - local_address: IpSocketAddress, - ) -> wasmtime::Result> { - let socket = self.table().get(&self_)?.inner()?; - convert_result( - latest::sockets::udp::HostUdpSocket::start_bind( - self, - socket, - network, - local_address.into(), - ) - .await, - ) - } - - fn finish_bind( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - let socket = self.table().get(&self_)?.inner()?; - convert_result(latest::sockets::udp::HostUdpSocket::finish_bind( - self, socket, - )) - } - - fn start_connect( - &mut self, - self_: Resource, - _network: Resource, - remote_address: IpSocketAddress, - ) -> wasmtime::Result> { - let socket = self.table().get_mut(&self_)?; - let (new_state, result) = match mem::replace(socket, UdpSocket::Dummy) { - UdpSocket::Initial(socket) => (UdpSocket::Connecting(socket, remote_address), Ok(())), - other => (other, Err(SocketErrorCode::ConcurrencyConflict)), - }; - *socket = new_state; - Ok(result) - } - - async fn finish_connect( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - UdpSocket::finish_connect(self, &self_, true).await - } - - async fn receive( - &mut self, - self_: Resource, - max_results: u64, - ) -> wasmtime::Result, SocketErrorCode>> { - // If the socket is in the `initial` state then complete the connect, - // otherwise verify we're connected. - if let Err(e) = UdpSocket::finish_connect(self, &self_, true).await? { - return Ok(Err(e)); - } - - // Use our connected state to acquire the `incoming-datagram-stream` - // resource, then receive some datagrams. - let incoming = match self.table().get(&self_)? { - UdpSocket::Connected { incoming, .. } => Resource::new_borrow(incoming.rep()), - _ => return Ok(Err(SocketErrorCode::ConcurrencyConflict)), - }; - let result: Result, _> = convert_result( - latest::sockets::udp::HostIncomingDatagramStream::receive(self, incoming, max_results), - )?; - match result { - Ok(datagrams) => Ok(Ok(datagrams - .into_iter() - .map(|datagram| datagram.into()) - .collect())), - Err(e) => Ok(Err(e)), - } - } - - async fn send( - &mut self, - self_: Resource, - mut datagrams: Vec, - ) -> wasmtime::Result> { - // If the socket is in the `initial` state then complete the connect, - // otherwise verify we're connected. - if let Err(e) = UdpSocket::finish_connect(self, &self_, true).await? { - return Ok(Err(e)); - } - - // Use our connected state to acquire the `outgoing-datagram-stream` - // resource. - let outgoing = match self.table().get(&self_)? { - UdpSocket::Connected { outgoing, .. } => Resource::new_borrow(outgoing.rep()), - _ => return Ok(Err(SocketErrorCode::ConcurrencyConflict)), - }; - - // Acquire a sending permit for some datagrams, truncating our list to - // that size if we have one. - let outgoing2 = Resource::new_borrow(outgoing.rep()); - match convert_result( - latest::sockets::udp::HostOutgoingDatagramStream::check_send(self, outgoing2), - )? { - Ok(n) => { - if datagrams.len() as u64 > n { - datagrams.truncate(n as usize); - } - } - Err(e) => return Ok(Err(e)), - } - - // Send off the datagrams. - convert_result( - latest::sockets::udp::HostOutgoingDatagramStream::send( - self, - outgoing, - datagrams - .into_iter() - .map(|d| latest::sockets::udp::OutgoingDatagram { - data: d.data, - remote_address: Some(d.remote_address.into()), - }) - .collect(), - ) - .await, - ) - } - - fn local_address( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - let socket = self.table().get(&self_)?.inner()?; - convert_result(latest::sockets::udp::HostUdpSocket::local_address( - self, socket, - )) - } - - fn remote_address( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - let socket = self.table().get(&self_)?.inner()?; - convert_result(latest::sockets::udp::HostUdpSocket::remote_address( - self, socket, - )) - } - - fn address_family(&mut self, self_: Resource) -> wasmtime::Result { - let socket = self.table().get(&self_)?.inner()?; - latest::sockets::udp::HostUdpSocket::address_family(self, socket).map(|e| e.into()) - } - - fn ipv6_only( - &mut self, - _self_: Resource, - ) -> wasmtime::Result> { - anyhow::bail!("ipv6-only API no longer supported") - } - - fn set_ipv6_only( - &mut self, - _self_: Resource, - _value: bool, - ) -> wasmtime::Result> { - anyhow::bail!("ipv6-only API no longer supported") - } - - fn unicast_hop_limit( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - let socket = self.table().get(&self_)?.inner()?; - convert_result(latest::sockets::udp::HostUdpSocket::unicast_hop_limit( - self, socket, - )) - } - - fn set_unicast_hop_limit( - &mut self, - self_: Resource, - value: u8, - ) -> wasmtime::Result> { - let socket = self.table().get(&self_)?.inner()?; - convert_result(latest::sockets::udp::HostUdpSocket::set_unicast_hop_limit( - self, socket, value, - )) - } - - fn receive_buffer_size( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - let socket = self.table().get(&self_)?.inner()?; - convert_result(latest::sockets::udp::HostUdpSocket::receive_buffer_size( - self, socket, - )) - } - - fn set_receive_buffer_size( - &mut self, - self_: Resource, - value: u64, - ) -> wasmtime::Result> { - let socket = self.table().get(&self_)?.inner()?; - convert_result( - latest::sockets::udp::HostUdpSocket::set_receive_buffer_size(self, socket, value), - ) - } - - fn send_buffer_size( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - let socket = self.table().get(&self_)?.inner()?; - convert_result(latest::sockets::udp::HostUdpSocket::send_buffer_size( - self, socket, - )) - } - - fn set_send_buffer_size( - &mut self, - self_: Resource, - value: u64, - ) -> wasmtime::Result> { - let socket = self.table().get(&self_)?.inner()?; - convert_result(latest::sockets::udp::HostUdpSocket::set_send_buffer_size( - self, socket, value, - )) - } - - fn subscribe(&mut self, self_: Resource) -> wasmtime::Result> { - let socket = self.table().get(&self_)?.inner()?; - latest::sockets::udp::HostUdpSocket::subscribe(self, socket) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - let me = self.table().delete(rep)?; - let socket = match me { - UdpSocket::Initial(s) => s, - UdpSocket::Connecting(s, _) => s, - UdpSocket::Connected { - socket, - incoming, - outgoing, - } => { - latest::sockets::udp::HostIncomingDatagramStream::drop(self, incoming)?; - latest::sockets::udp::HostOutgoingDatagramStream::drop(self, outgoing)?; - socket - } - UdpSocket::Dummy => return Ok(()), - }; - latest::sockets::udp::HostUdpSocket::drop(self, socket) - } -} - -impl wasi::sockets::udp_create_socket::Host for WasiImpl -where - T: WasiView, -{ - fn create_udp_socket( - &mut self, - address_family: IpAddressFamily, - ) -> wasmtime::Result, SocketErrorCode>> { - let result = convert_result(latest::sockets::udp_create_socket::Host::create_udp_socket( - self, - address_family.into(), - ))?; - let socket = match result { - Ok(socket) => socket, - Err(e) => return Ok(Err(e)), - }; - let socket = self.table().push(UdpSocket::Initial(socket))?; - Ok(Ok(socket)) - } -} - -impl wasi::sockets::instance_network::Host for WasiImpl -where - T: WasiView, -{ - fn instance_network(&mut self) -> wasmtime::Result> { - latest::sockets::instance_network::Host::instance_network(self) - } -} - -impl wasi::sockets::network::Host for WasiImpl where T: WasiView {} - -impl wasi::sockets::network::HostNetwork for WasiImpl -where - T: WasiView, -{ - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::sockets::network::HostNetwork::drop(self, rep) - } -} - -impl wasi::sockets::ip_name_lookup::Host for WasiImpl -where - T: WasiView, -{ - fn resolve_addresses( - &mut self, - network: Resource, - name: String, - _address_family: Option, - _include_unavailable: bool, - ) -> wasmtime::Result, SocketErrorCode>> { - convert_result(latest::sockets::ip_name_lookup::Host::resolve_addresses( - self, network, name, - )) - } -} - -impl wasi::sockets::ip_name_lookup::HostResolveAddressStream for WasiImpl -where - T: WasiView, -{ - fn resolve_next_address( - &mut self, - self_: Resource, - ) -> wasmtime::Result, SocketErrorCode>> { - convert_result( - latest::sockets::ip_name_lookup::HostResolveAddressStream::resolve_next_address( - self, self_, - ) - .map(|e| e.map(|e| e.into())), - ) - } - - fn subscribe( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - latest::sockets::ip_name_lookup::HostResolveAddressStream::subscribe(self, self_) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::sockets::ip_name_lookup::HostResolveAddressStream::drop(self, rep) - } -} - -impl wasi::http::types::Host for WasiHttpImpl where T: WasiHttpView + Send {} - -impl wasi::http::types::HostFields for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn new( - &mut self, - entries: Vec<(String, Vec)>, - ) -> wasmtime::Result> { - match latest::http::types::HostFields::from_list(self, entries)? { - Ok(fields) => Ok(fields), - Err(e) => Err(e.into()), - } - } - - fn get( - &mut self, - self_: wasmtime::component::Resource, - name: String, - ) -> wasmtime::Result>> { - latest::http::types::HostFields::get(self, self_, name) - } - - fn set( - &mut self, - self_: wasmtime::component::Resource, - name: String, - value: Vec>, - ) -> wasmtime::Result<()> { - latest::http::types::HostFields::set(self, self_, name, value)??; - Ok(()) - } - - fn delete( - &mut self, - self_: wasmtime::component::Resource, - name: String, - ) -> wasmtime::Result<()> { - latest::http::types::HostFields::delete(self, self_, name)??; - Ok(()) - } - - fn append( - &mut self, - self_: wasmtime::component::Resource, - name: String, - value: Vec, - ) -> wasmtime::Result<()> { - latest::http::types::HostFields::append(self, self_, name, value)??; - Ok(()) - } - - fn entries( - &mut self, - self_: wasmtime::component::Resource, - ) -> wasmtime::Result)>> { - latest::http::types::HostFields::entries(self, self_) - } - - fn clone( - &mut self, - self_: wasmtime::component::Resource, - ) -> wasmtime::Result> { - latest::http::types::HostFields::clone(self, self_) - } - - fn drop(&mut self, rep: wasmtime::component::Resource) -> wasmtime::Result<()> { - latest::http::types::HostFields::drop(self, rep) - } -} - -impl wasi::http::types::HostIncomingRequest for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn method( - &mut self, - self_: wasmtime::component::Resource, - ) -> wasmtime::Result { - latest::http::types::HostIncomingRequest::method(self, self_).map(|e| e.into()) - } - - fn path_with_query( - &mut self, - self_: wasmtime::component::Resource, - ) -> wasmtime::Result> { - latest::http::types::HostIncomingRequest::path_with_query(self, self_) - } - - fn scheme( - &mut self, - self_: wasmtime::component::Resource, - ) -> wasmtime::Result> { - latest::http::types::HostIncomingRequest::scheme(self, self_).map(|e| e.map(|e| e.into())) - } - - fn authority( - &mut self, - self_: wasmtime::component::Resource, - ) -> wasmtime::Result> { - latest::http::types::HostIncomingRequest::authority(self, self_) - } - - fn headers( - &mut self, - self_: wasmtime::component::Resource, - ) -> wasmtime::Result> { - latest::http::types::HostIncomingRequest::headers(self, self_) - } - - fn consume( - &mut self, - self_: wasmtime::component::Resource, - ) -> wasmtime::Result, ()>> { - latest::http::types::HostIncomingRequest::consume(self, self_) - } - - fn drop( - &mut self, - rep: wasmtime::component::Resource, - ) -> wasmtime::Result<()> { - latest::http::types::HostIncomingRequest::drop(self, rep) - } -} - -impl wasi::http::types::HostIncomingResponse for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn status( - &mut self, - self_: wasmtime::component::Resource, - ) -> wasmtime::Result { - latest::http::types::HostIncomingResponse::status(self, self_) - } - - fn headers( - &mut self, - self_: wasmtime::component::Resource, - ) -> wasmtime::Result> { - latest::http::types::HostIncomingResponse::headers(self, self_) - } - - fn consume( - &mut self, - self_: wasmtime::component::Resource, - ) -> wasmtime::Result, ()>> { - latest::http::types::HostIncomingResponse::consume(self, self_) - } - - fn drop( - &mut self, - rep: wasmtime::component::Resource, - ) -> wasmtime::Result<()> { - latest::http::types::HostIncomingResponse::drop(self, rep) - } -} - -impl wasi::http::types::HostIncomingBody for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn stream( - &mut self, - self_: wasmtime::component::Resource, - ) -> wasmtime::Result, ()>> { - latest::http::types::HostIncomingBody::stream(self, self_) - } - - fn finish( - &mut self, - this: wasmtime::component::Resource, - ) -> wasmtime::Result> { - latest::http::types::HostIncomingBody::finish(self, this) - } - - fn drop(&mut self, rep: wasmtime::component::Resource) -> wasmtime::Result<()> { - latest::http::types::HostIncomingBody::drop(self, rep) - } -} - -impl wasi::http::types::HostOutgoingRequest for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn new( - &mut self, - method: Method, - path_with_query: Option, - scheme: Option, - authority: Option, - headers: wasmtime::component::Resource, - ) -> wasmtime::Result> { - let headers = latest::http::types::HostFields::clone(self, headers)?; - let request = latest::http::types::HostOutgoingRequest::new(self, headers)?; - let borrow = || Resource::new_borrow(request.rep()); - - if let Err(()) = - latest::http::types::HostOutgoingRequest::set_method(self, borrow(), method.into())? - { - latest::http::types::HostOutgoingRequest::drop(self, request)?; - anyhow::bail!("invalid method supplied"); - } - - if let Err(()) = latest::http::types::HostOutgoingRequest::set_path_with_query( - self, - borrow(), - path_with_query, - )? { - latest::http::types::HostOutgoingRequest::drop(self, request)?; - anyhow::bail!("invalid path-with-query supplied"); - } - - // Historical WASI would fill in an empty authority with a port which - // got just enough working to get things through. Current WASI requires - // the authority, though, so perform the translation manually here. - let authority = authority.unwrap_or_else(|| match &scheme { - Some(Scheme::Http) | Some(Scheme::Other(_)) => ":80".to_string(), - Some(Scheme::Https) | None => ":443".to_string(), - }); - if let Err(()) = latest::http::types::HostOutgoingRequest::set_scheme( - self, - borrow(), - scheme.map(|s| s.into()), - )? { - latest::http::types::HostOutgoingRequest::drop(self, request)?; - anyhow::bail!("invalid scheme supplied"); - } - - if let Err(()) = latest::http::types::HostOutgoingRequest::set_authority( - self, - borrow(), - Some(authority), - )? { - latest::http::types::HostOutgoingRequest::drop(self, request)?; - anyhow::bail!("invalid authority supplied"); - } - - Ok(request) - } - - fn write( - &mut self, - self_: wasmtime::component::Resource, - ) -> wasmtime::Result, ()>> { - latest::http::types::HostOutgoingRequest::body(self, self_) - } - - fn drop( - &mut self, - rep: wasmtime::component::Resource, - ) -> wasmtime::Result<()> { - latest::http::types::HostOutgoingRequest::drop(self, rep) - } -} - -impl wasi::http::types::HostOutgoingResponse for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn new( - &mut self, - status_code: StatusCode, - headers: wasmtime::component::Resource, - ) -> wasmtime::Result> { - let headers = latest::http::types::HostFields::clone(self, headers)?; - let response = latest::http::types::HostOutgoingResponse::new(self, headers)?; - let borrow = || Resource::new_borrow(response.rep()); - - if let Err(()) = - latest::http::types::HostOutgoingResponse::set_status_code(self, borrow(), status_code)? - { - latest::http::types::HostOutgoingResponse::drop(self, response)?; - anyhow::bail!("invalid status code supplied"); - } - - Ok(response) - } - - fn write( - &mut self, - self_: wasmtime::component::Resource, - ) -> wasmtime::Result, ()>> { - latest::http::types::HostOutgoingResponse::body(self, self_) - } - - fn drop( - &mut self, - rep: wasmtime::component::Resource, - ) -> wasmtime::Result<()> { - latest::http::types::HostOutgoingResponse::drop(self, rep) - } -} - -impl wasi::http::types::HostOutgoingBody for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn write( - &mut self, - self_: wasmtime::component::Resource, - ) -> wasmtime::Result, ()>> { - latest::http::types::HostOutgoingBody::write(self, self_) - } - - fn finish( - &mut self, - this: wasmtime::component::Resource, - trailers: Option>, - ) -> wasmtime::Result<()> { - latest::http::types::HostOutgoingBody::finish(self, this, trailers)?; - Ok(()) - } - - fn drop(&mut self, rep: wasmtime::component::Resource) -> wasmtime::Result<()> { - latest::http::types::HostOutgoingBody::drop(self, rep) - } -} - -impl wasi::http::types::HostResponseOutparam for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn set( - &mut self, - param: wasmtime::component::Resource, - response: Result, HttpError>, - ) -> wasmtime::Result<()> { - let response = response.map_err(|err| { - // TODO: probably need to figure out a better mapping between - // errors, but that seems like it would require string matching, - // which also seems not great. - let msg = match err { - HttpError::InvalidUrl(s) => format!("invalid url: {s}"), - HttpError::TimeoutError(s) => format!("timeout: {s}"), - HttpError::ProtocolError(s) => format!("protocol error: {s}"), - HttpError::UnexpectedError(s) => format!("unexpected error: {s}"), - }; - latest::http::types::ErrorCode::InternalError(Some(msg)) - }); - latest::http::types::HostResponseOutparam::set(self, param, response) - } - - fn drop( - &mut self, - rep: wasmtime::component::Resource, - ) -> wasmtime::Result<()> { - latest::http::types::HostResponseOutparam::drop(self, rep) - } -} - -impl wasi::http::types::HostFutureTrailers for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn subscribe( - &mut self, - self_: wasmtime::component::Resource, - ) -> wasmtime::Result> { - latest::http::types::HostFutureTrailers::subscribe(self, self_) - } - - fn get( - &mut self, - self_: wasmtime::component::Resource, - ) -> wasmtime::Result, HttpError>>> { - match latest::http::types::HostFutureTrailers::get(self, self_)? { - Some(Ok(Ok(Some(trailers)))) => Ok(Some(Ok(trailers))), - // Return an empty trailers if no trailers popped out since this - // version of WASI couldn't represent the lack of trailers. - Some(Ok(Ok(None))) => Ok(Some(Ok(latest::http::types::HostFields::new(self)?))), - Some(Ok(Err(e))) => Ok(Some(Err(e.into()))), - Some(Err(())) => Err(anyhow::anyhow!("trailers have already been retrieved")), - None => Ok(None), - } - } - - fn drop(&mut self, rep: wasmtime::component::Resource) -> wasmtime::Result<()> { - latest::http::types::HostFutureTrailers::drop(self, rep) - } -} - -impl wasi::http::types::HostFutureIncomingResponse for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn get( - &mut self, - self_: wasmtime::component::Resource, - ) -> wasmtime::Result< - Option, HttpError>, ()>>, - > { - match latest::http::types::HostFutureIncomingResponse::get(self, self_)? { - None => Ok(None), - Some(Ok(Ok(response))) => Ok(Some(Ok(Ok(response)))), - Some(Ok(Err(e))) => Ok(Some(Ok(Err(e.into())))), - Some(Err(())) => Ok(Some(Err(()))), - } - } - - fn subscribe( - &mut self, - self_: wasmtime::component::Resource, - ) -> wasmtime::Result> { - latest::http::types::HostFutureIncomingResponse::subscribe(self, self_) - } - - fn drop( - &mut self, - rep: wasmtime::component::Resource, - ) -> wasmtime::Result<()> { - latest::http::types::HostFutureIncomingResponse::drop(self, rep) - } -} - -impl wasi::http::outgoing_handler::Host for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn handle( - &mut self, - request: wasmtime::component::Resource, - options: Option, - ) -> wasmtime::Result, HttpError>> - { - let options = match options { - Some(RequestOptions { - connect_timeout_ms, - first_byte_timeout_ms, - between_bytes_timeout_ms, - }) => { - let options = latest::http::types::HostRequestOptions::new(self)?; - let borrow = || Resource::new_borrow(request.rep()); - - if let Some(ms) = connect_timeout_ms { - if let Err(()) = latest::http::types::HostRequestOptions::set_connect_timeout( - self, - borrow(), - Some(ms.into()), - )? { - latest::http::types::HostRequestOptions::drop(self, options)?; - anyhow::bail!("invalid connect timeout supplied"); - } - } - - if let Some(ms) = first_byte_timeout_ms { - if let Err(()) = - latest::http::types::HostRequestOptions::set_first_byte_timeout( - self, - borrow(), - Some(ms.into()), - )? - { - latest::http::types::HostRequestOptions::drop(self, options)?; - anyhow::bail!("invalid first byte timeout supplied"); - } - } - - if let Some(ms) = between_bytes_timeout_ms { - if let Err(()) = - latest::http::types::HostRequestOptions::set_between_bytes_timeout( - self, - borrow(), - Some(ms.into()), - )? - { - latest::http::types::HostRequestOptions::drop(self, options)?; - anyhow::bail!("invalid between bytes timeout supplied"); - } - } - - Some(options) - } - None => None, - }; - match latest::http::outgoing_handler::Host::handle(self, request, options) { - Ok(resp) => Ok(Ok(resp)), - Err(e) => Ok(Err(e.downcast()?.into())), - } - } -} - -pub fn convert_result( - result: Result>, -) -> wasmtime::Result> -where - T2: From, - E: std::error::Error + Send + Sync + 'static, - E2: From, -{ - match result { - Ok(e) => Ok(Ok(e.into())), - Err(e) => Ok(Err(e.downcast()?.into())), - } -} - -fn convert_stream_result( - mut view: impl WasiView, - result: Result, -) -> wasmtime::Result> -where - T2: From, -{ - match result { - Ok(e) => Ok(Ok(e.into())), - Err(wasmtime_wasi::StreamError::Closed) => Ok(Err(StreamError::Closed)), - Err(wasmtime_wasi::StreamError::LastOperationFailed(e)) => { - let e = view.table().push(e)?; - Ok(Err(StreamError::LastOperationFailed(e))) - } - Err(wasmtime_wasi::StreamError::Trap(e)) => Err(e), - } -} - -macro_rules! convert { - () => {}; - ($kind:ident $from:path [<=>] $to:path { $($body:tt)* } $($rest:tt)*) => { - convert!($kind $from => $to { $($body)* }); - convert!($kind $to => $from { $($body)* }); - - convert!($($rest)*); - }; - (struct $from:ty => $to:path { $($field:ident,)* } $($rest:tt)*) => { - impl From<$from> for $to { - fn from(e: $from) -> $to { - $to { - $( $field: e.$field.into(), )* - } - } - } - - convert!($($rest)*); - }; - (enum $from:path => $to:path { $($variant:ident $(($e:ident))?,)* } $($rest:tt)*) => { - impl From<$from> for $to { - fn from(e: $from) -> $to { - use $from as A; - use $to as B; - match e { - $( - A::$variant $(($e))? => B::$variant $(($e.into()))?, - )* - } - } - } - - convert!($($rest)*); - }; - (flags $from:path => $to:path { $($flag:ident,)* } $($rest:tt)*) => { - impl From<$from> for $to { - fn from(e: $from) -> $to { - use $from as A; - use $to as B; - let mut out = B::empty(); - $( - if e.contains(A::$flag) { - out |= B::$flag; - } - )* - out - } - } - - convert!($($rest)*); - }; -} - -pub(crate) use convert; - -convert! { - struct latest::clocks::wall_clock::Datetime [<=>] Datetime { - seconds, - nanoseconds, - } - - enum latest::filesystem::types::ErrorCode => FsErrorCode { - Access, - WouldBlock, - Already, - BadDescriptor, - Busy, - Deadlock, - Quota, - Exist, - FileTooLarge, - IllegalByteSequence, - InProgress, - Interrupted, - Invalid, - Io, - IsDirectory, - Loop, - TooManyLinks, - MessageSize, - NameTooLong, - NoDevice, - NoEntry, - NoLock, - InsufficientMemory, - InsufficientSpace, - NotDirectory, - NotEmpty, - NotRecoverable, - Unsupported, - NoTty, - NoSuchDevice, - Overflow, - NotPermitted, - Pipe, - ReadOnly, - InvalidSeek, - TextFileBusy, - CrossDevice, - } - - enum Advice => latest::filesystem::types::Advice { - Normal, - Sequential, - Random, - WillNeed, - DontNeed, - NoReuse, - } - - flags DescriptorFlags [<=>] latest::filesystem::types::DescriptorFlags { - READ, - WRITE, - FILE_INTEGRITY_SYNC, - DATA_INTEGRITY_SYNC, - REQUESTED_WRITE_SYNC, - MUTATE_DIRECTORY, - } - - enum DescriptorType [<=>] latest::filesystem::types::DescriptorType { - Unknown, - BlockDevice, - CharacterDevice, - Directory, - Fifo, - SymbolicLink, - RegularFile, - Socket, - } - - enum NewTimestamp => latest::filesystem::types::NewTimestamp { - NoChange, - Now, - Timestamp(e), - } - - flags PathFlags => latest::filesystem::types::PathFlags { - SYMLINK_FOLLOW, - } - - flags OpenFlags => latest::filesystem::types::OpenFlags { - CREATE, - DIRECTORY, - EXCLUSIVE, - TRUNCATE, - } - - struct latest::filesystem::types::MetadataHashValue => MetadataHashValue { - lower, - upper, - } - - struct latest::filesystem::types::DirectoryEntry => DirectoryEntry { - type_, - name, - } - - enum latest::sockets::network::ErrorCode => SocketErrorCode { - Unknown, - AccessDenied, - NotSupported, - InvalidArgument, - OutOfMemory, - Timeout, - ConcurrencyConflict, - NotInProgress, - WouldBlock, - InvalidState, - NewSocketLimit, - AddressNotBindable, - AddressInUse, - RemoteUnreachable, - ConnectionRefused, - ConnectionReset, - ConnectionAborted, - DatagramTooLarge, - NameUnresolvable, - TemporaryResolverFailure, - PermanentResolverFailure, - } - - enum latest::sockets::network::IpAddress [<=>] IpAddress { - Ipv4(e), - Ipv6(e), - } - - enum latest::sockets::network::IpSocketAddress [<=>] IpSocketAddress { - Ipv4(e), - Ipv6(e), - } - - struct latest::sockets::network::Ipv4SocketAddress [<=>] Ipv4SocketAddress { - port, - address, - } - - struct latest::sockets::network::Ipv6SocketAddress [<=>] Ipv6SocketAddress { - port, - flow_info, - scope_id, - address, - } - - enum latest::sockets::network::IpAddressFamily [<=>] IpAddressFamily { - Ipv4, - Ipv6, - } - - enum ShutdownType => latest::sockets::tcp::ShutdownType { - Receive, - Send, - Both, - } - - struct latest::sockets::udp::IncomingDatagram => Datagram { - data, - remote_address, - } - - enum latest::http::types::Method [<=>] Method { - Get, - Head, - Post, - Put, - Delete, - Connect, - Options, - Trace, - Patch, - Other(e), - } - - enum latest::http::types::Scheme [<=>] Scheme { - Http, - Https, - Other(e), - } -} - -impl From for DescriptorStat { - fn from(e: latest::filesystem::types::DescriptorStat) -> DescriptorStat { - DescriptorStat { - type_: e.type_.into(), - link_count: e.link_count, - size: e.size, - data_access_timestamp: e.data_access_timestamp.map(|e| e.into()), - data_modification_timestamp: e.data_modification_timestamp.map(|e| e.into()), - status_change_timestamp: e.status_change_timestamp.map(|e| e.into()), - } - } -} - -impl From for HttpError { - fn from(e: latest::http::types::ErrorCode) -> HttpError { - // TODO: should probably categorize this better given the typed info - // we have in `e`. - HttpError::UnexpectedError(e.to_string()) - } -} diff --git a/crates/core/src/wasi_2023_11_10.rs b/crates/core/src/wasi_2023_11_10.rs deleted file mode 100644 index a7d554deb..000000000 --- a/crates/core/src/wasi_2023_11_10.rs +++ /dev/null @@ -1,2455 +0,0 @@ -#![doc(hidden)] // internal implementation detail used in tests and spin-trigger - -use super::wasi_2023_10_18::{convert, convert_result}; -use anyhow::Result; -use async_trait::async_trait; -use wasmtime::component::{Linker, Resource}; -use wasmtime_wasi::{WasiImpl, WasiView}; -use wasmtime_wasi_http::{WasiHttpImpl, WasiHttpView}; - -mod latest { - pub use wasmtime_wasi::bindings::*; - pub mod http { - pub use wasmtime_wasi_http::bindings::http::*; - } -} - -mod bindings { - use super::latest; - - wasmtime::component::bindgen!({ - path: "../../wit", - interfaces: r#" - include wasi:http/proxy@0.2.0-rc-2023-11-10; - - // NB: this is handling the historical behavior where Spin supported - // more than "just" this snapshot of the proxy world but additionally - // other CLI-related interfaces. - include wasi:cli/reactor@0.2.0-rc-2023-11-10; - "#, - async: { - only_imports: [ - "[method]descriptor.advise", - "[method]descriptor.create-directory-at", - "[method]descriptor.get-flags", - "[method]descriptor.get-type", - "[method]descriptor.is-same-object", - "[method]descriptor.link-at", - "[method]descriptor.metadata-hash", - "[method]descriptor.metadata-hash-at", - "[method]descriptor.open-at", - "[method]descriptor.read", - "[method]descriptor.read-directory", - "[method]descriptor.readlink-at", - "[method]descriptor.remove-directory-at", - "[method]descriptor.rename-at", - "[method]descriptor.set-size", - "[method]descriptor.set-times", - "[method]descriptor.set-times-at", - "[method]descriptor.stat", - "[method]descriptor.stat-at", - "[method]descriptor.symlink-at", - "[method]descriptor.sync", - "[method]descriptor.sync-data", - "[method]descriptor.unlink-file-at", - "[method]descriptor.write", - "[method]input-stream.read", - "[method]input-stream.blocking-read", - "[method]input-stream.blocking-skip", - "[method]input-stream.skip", - "[method]output-stream.splice", - "[method]output-stream.blocking-splice", - "[method]output-stream.blocking-flush", - "[method]output-stream.blocking-write", - "[method]output-stream.blocking-write-and-flush", - "[method]output-stream.blocking-write-zeroes-and-flush", - "[method]directory-entry-stream.read-directory-entry", - "[method]pollable.block", - "[method]pollable.ready", - "poll", - - "[method]tcp-socket.start-bind", - "[method]tcp-socket.start-connect", - "[method]udp-socket.start-bind", - "[method]udp-socket.stream", - "[method]outgoing-datagram-stream.send", - ] - }, - with: { - "wasi:io/poll/pollable": latest::io::poll::Pollable, - "wasi:io/streams/input-stream": latest::io::streams::InputStream, - "wasi:io/streams/output-stream": latest::io::streams::OutputStream, - "wasi:io/error/error": latest::io::error::Error, - "wasi:filesystem/types/directory-entry-stream": latest::filesystem::types::DirectoryEntryStream, - "wasi:filesystem/types/descriptor": latest::filesystem::types::Descriptor, - "wasi:cli/terminal-input/terminal-input": latest::cli::terminal_input::TerminalInput, - "wasi:cli/terminal-output/terminal-output": latest::cli::terminal_output::TerminalOutput, - "wasi:sockets/tcp/tcp-socket": latest::sockets::tcp::TcpSocket, - "wasi:sockets/udp/udp-socket": latest::sockets::udp::UdpSocket, - "wasi:sockets/udp/outgoing-datagram-stream": latest::sockets::udp::OutgoingDatagramStream, - "wasi:sockets/udp/incoming-datagram-stream": latest::sockets::udp::IncomingDatagramStream, - "wasi:sockets/network/network": latest::sockets::network::Network, - "wasi:sockets/ip-name-lookup/resolve-address-stream": latest::sockets::ip_name_lookup::ResolveAddressStream, - "wasi:http/types/incoming-response": latest::http::types::IncomingResponse, - "wasi:http/types/incoming-request": latest::http::types::IncomingRequest, - "wasi:http/types/incoming-body": latest::http::types::IncomingBody, - "wasi:http/types/outgoing-response": latest::http::types::OutgoingResponse, - "wasi:http/types/outgoing-request": latest::http::types::OutgoingRequest, - "wasi:http/types/outgoing-body": latest::http::types::OutgoingBody, - "wasi:http/types/fields": latest::http::types::Fields, - "wasi:http/types/response-outparam": latest::http::types::ResponseOutparam, - "wasi:http/types/future-incoming-response": latest::http::types::FutureIncomingResponse, - "wasi:http/types/future-trailers": latest::http::types::FutureTrailers, - "wasi:http/types/request-options": latest::http::types::RequestOptions, - }, - trappable_imports: true, - }); -} - -mod wasi { - pub use super::bindings::wasi::{ - cli0_2_0_rc_2023_11_10 as cli, clocks0_2_0_rc_2023_11_10 as clocks, - filesystem0_2_0_rc_2023_11_10 as filesystem, http0_2_0_rc_2023_11_10 as http, - io0_2_0_rc_2023_11_10 as io, random0_2_0_rc_2023_11_10 as random, - sockets0_2_0_rc_2023_11_10 as sockets, - }; -} - -pub mod exports { - pub mod wasi { - pub use super::super::bindings::exports::wasi::http0_2_0_rc_2023_11_10 as http; - } -} - -use wasi::cli::terminal_input::TerminalInput; -use wasi::cli::terminal_output::TerminalOutput; -use wasi::clocks::monotonic_clock::{Duration, Instant}; -use wasi::clocks::wall_clock::Datetime; -use wasi::filesystem::types::{ - Advice, Descriptor, DescriptorFlags, DescriptorStat, DescriptorType, DirectoryEntry, - DirectoryEntryStream, ErrorCode as FsErrorCode, Filesize, MetadataHashValue, NewTimestamp, - OpenFlags, PathFlags, -}; -use wasi::http::types::{ - DnsErrorPayload, ErrorCode as HttpErrorCode, FieldSizePayload, Fields, FutureIncomingResponse, - FutureTrailers, HeaderError, Headers, IncomingBody, IncomingRequest, IncomingResponse, Method, - OutgoingBody, OutgoingRequest, OutgoingResponse, RequestOptions, ResponseOutparam, Scheme, - StatusCode, TlsAlertReceivedPayload, Trailers, -}; -use wasi::io::poll::Pollable; -use wasi::io::streams::{Error as IoError, InputStream, OutputStream, StreamError}; -use wasi::sockets::ip_name_lookup::{IpAddress, ResolveAddressStream}; -use wasi::sockets::network::{Ipv4SocketAddress, Ipv6SocketAddress}; -use wasi::sockets::tcp::{ - ErrorCode as SocketErrorCode, IpAddressFamily, IpSocketAddress, Network, ShutdownType, - TcpSocket, -}; -use wasi::sockets::udp::{ - IncomingDatagram, IncomingDatagramStream, OutgoingDatagram, OutgoingDatagramStream, UdpSocket, -}; - -pub fn add_to_linker(linker: &mut Linker) -> Result<()> -where - T: WasiView + WasiHttpView, -{ - // interfaces from the "command" world - fn type_annotate_wasi(f: F) -> F - where - F: Fn(&mut T) -> WasiImpl<&mut T>, - { - f - } - let closure = type_annotate_wasi::(|t| WasiImpl(t)); - wasi::clocks::monotonic_clock::add_to_linker_get_host(linker, closure)?; - wasi::clocks::wall_clock::add_to_linker_get_host(linker, closure)?; - wasi::filesystem::types::add_to_linker_get_host(linker, closure)?; - wasi::filesystem::preopens::add_to_linker_get_host(linker, closure)?; - wasi::io::error::add_to_linker_get_host(linker, closure)?; - wasi::io::poll::add_to_linker_get_host(linker, closure)?; - wasi::io::streams::add_to_linker_get_host(linker, closure)?; - wasi::random::random::add_to_linker_get_host(linker, closure)?; - wasi::random::insecure::add_to_linker_get_host(linker, closure)?; - wasi::random::insecure_seed::add_to_linker_get_host(linker, closure)?; - wasi::cli::exit::add_to_linker_get_host(linker, closure)?; - wasi::cli::environment::add_to_linker_get_host(linker, closure)?; - wasi::cli::stdin::add_to_linker_get_host(linker, closure)?; - wasi::cli::stdout::add_to_linker_get_host(linker, closure)?; - wasi::cli::stderr::add_to_linker_get_host(linker, closure)?; - wasi::cli::terminal_input::add_to_linker_get_host(linker, closure)?; - wasi::cli::terminal_output::add_to_linker_get_host(linker, closure)?; - wasi::cli::terminal_stdin::add_to_linker_get_host(linker, closure)?; - wasi::cli::terminal_stdout::add_to_linker_get_host(linker, closure)?; - wasi::cli::terminal_stderr::add_to_linker_get_host(linker, closure)?; - wasi::sockets::tcp::add_to_linker_get_host(linker, closure)?; - wasi::sockets::tcp_create_socket::add_to_linker_get_host(linker, closure)?; - wasi::sockets::udp::add_to_linker_get_host(linker, closure)?; - wasi::sockets::udp_create_socket::add_to_linker_get_host(linker, closure)?; - wasi::sockets::instance_network::add_to_linker_get_host(linker, closure)?; - wasi::sockets::network::add_to_linker_get_host(linker, closure)?; - wasi::sockets::ip_name_lookup::add_to_linker_get_host(linker, closure)?; - - fn type_annotate_http(f: F) -> F - where - F: Fn(&mut T) -> WasiHttpImpl<&mut T>, - { - f - } - let closure = type_annotate_http::(|t| WasiHttpImpl(t)); - wasi::http::types::add_to_linker_get_host(linker, closure)?; - wasi::http::outgoing_handler::add_to_linker_get_host(linker, closure)?; - Ok(()) -} - -impl wasi::clocks::monotonic_clock::Host for WasiImpl -where - T: WasiView, -{ - fn now(&mut self) -> wasmtime::Result { - latest::clocks::monotonic_clock::Host::now(self) - } - - fn resolution(&mut self) -> wasmtime::Result { - latest::clocks::monotonic_clock::Host::resolution(self) - } - - fn subscribe_instant(&mut self, when: Instant) -> wasmtime::Result> { - latest::clocks::monotonic_clock::Host::subscribe_instant(self, when) - } - - fn subscribe_duration(&mut self, when: Duration) -> wasmtime::Result> { - latest::clocks::monotonic_clock::Host::subscribe_duration(self, when) - } -} - -impl wasi::clocks::wall_clock::Host for WasiImpl -where - T: WasiView, -{ - fn now(&mut self) -> wasmtime::Result { - Ok(latest::clocks::wall_clock::Host::now(self)?.into()) - } - - fn resolution(&mut self) -> wasmtime::Result { - Ok(latest::clocks::wall_clock::Host::resolution(self)?.into()) - } -} - -impl wasi::filesystem::types::Host for WasiImpl -where - T: WasiView, -{ - fn filesystem_error_code( - &mut self, - err: Resource, - ) -> wasmtime::Result> { - Ok(latest::filesystem::types::Host::filesystem_error_code(self, err)?.map(|e| e.into())) - } -} - -#[async_trait] -impl wasi::filesystem::types::HostDescriptor for WasiImpl -where - T: WasiView, -{ - fn read_via_stream( - &mut self, - self_: Resource, - offset: Filesize, - ) -> wasmtime::Result, FsErrorCode>> { - convert_result(latest::filesystem::types::HostDescriptor::read_via_stream( - self, self_, offset, - )) - } - - fn write_via_stream( - &mut self, - self_: Resource, - offset: Filesize, - ) -> wasmtime::Result, FsErrorCode>> { - convert_result(latest::filesystem::types::HostDescriptor::write_via_stream( - self, self_, offset, - )) - } - - fn append_via_stream( - &mut self, - self_: Resource, - ) -> wasmtime::Result, FsErrorCode>> { - convert_result(latest::filesystem::types::HostDescriptor::append_via_stream(self, self_)) - } - - async fn advise( - &mut self, - self_: Resource, - offset: Filesize, - length: Filesize, - advice: Advice, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::advise( - self, - self_, - offset, - length, - advice.into(), - ) - .await, - ) - } - - async fn sync_data( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::filesystem::types::HostDescriptor::sync_data(self, self_).await) - } - - async fn get_flags( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::filesystem::types::HostDescriptor::get_flags(self, self_).await) - } - - async fn get_type( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::filesystem::types::HostDescriptor::get_type(self, self_).await) - } - - async fn set_size( - &mut self, - self_: Resource, - size: Filesize, - ) -> wasmtime::Result> { - convert_result(latest::filesystem::types::HostDescriptor::set_size(self, self_, size).await) - } - - async fn set_times( - &mut self, - self_: Resource, - data_access_timestamp: NewTimestamp, - data_modification_timestamp: NewTimestamp, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::set_times( - self, - self_, - data_access_timestamp.into(), - data_modification_timestamp.into(), - ) - .await, - ) - } - - async fn read( - &mut self, - self_: Resource, - length: Filesize, - offset: Filesize, - ) -> wasmtime::Result, bool), FsErrorCode>> { - convert_result( - latest::filesystem::types::HostDescriptor::read(self, self_, length, offset).await, - ) - } - - async fn write( - &mut self, - self_: Resource, - buffer: Vec, - offset: Filesize, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::write(self, self_, buffer, offset).await, - ) - } - - async fn read_directory( - &mut self, - self_: Resource, - ) -> wasmtime::Result, FsErrorCode>> { - convert_result(latest::filesystem::types::HostDescriptor::read_directory(self, self_).await) - } - - async fn sync( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::filesystem::types::HostDescriptor::sync(self, self_).await) - } - - async fn create_directory_at( - &mut self, - self_: Resource, - path: String, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::create_directory_at(self, self_, path).await, - ) - } - - async fn stat( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::filesystem::types::HostDescriptor::stat(self, self_).await) - } - - async fn stat_at( - &mut self, - self_: Resource, - path_flags: PathFlags, - path: String, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::stat_at( - self, - self_, - path_flags.into(), - path, - ) - .await, - ) - } - - async fn set_times_at( - &mut self, - self_: Resource, - path_flags: PathFlags, - path: String, - data_access_timestamp: NewTimestamp, - data_modification_timestamp: NewTimestamp, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::set_times_at( - self, - self_, - path_flags.into(), - path, - data_access_timestamp.into(), - data_modification_timestamp.into(), - ) - .await, - ) - } - - async fn link_at( - &mut self, - self_: Resource, - old_path_flags: PathFlags, - old_path: String, - new_descriptor: Resource, - new_path: String, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::link_at( - self, - self_, - old_path_flags.into(), - old_path, - new_descriptor, - new_path, - ) - .await, - ) - } - - async fn open_at( - &mut self, - self_: Resource, - path_flags: PathFlags, - path: String, - open_flags: OpenFlags, - flags: DescriptorFlags, - ) -> wasmtime::Result, FsErrorCode>> { - convert_result( - latest::filesystem::types::HostDescriptor::open_at( - self, - self_, - path_flags.into(), - path, - open_flags.into(), - flags.into(), - ) - .await, - ) - } - - async fn readlink_at( - &mut self, - self_: Resource, - path: String, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::readlink_at(self, self_, path).await, - ) - } - - async fn remove_directory_at( - &mut self, - self_: Resource, - path: String, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::remove_directory_at(self, self_, path).await, - ) - } - - async fn rename_at( - &mut self, - self_: Resource, - old_path: String, - new_descriptor: Resource, - new_path: String, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::rename_at( - self, - self_, - old_path, - new_descriptor, - new_path, - ) - .await, - ) - } - - async fn symlink_at( - &mut self, - self_: Resource, - old_path: String, - new_path: String, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::symlink_at(self, self_, old_path, new_path) - .await, - ) - } - - async fn unlink_file_at( - &mut self, - self_: Resource, - path: String, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::unlink_file_at(self, self_, path).await, - ) - } - - async fn is_same_object( - &mut self, - self_: Resource, - other: Resource, - ) -> wasmtime::Result { - latest::filesystem::types::HostDescriptor::is_same_object(self, self_, other).await - } - - async fn metadata_hash( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::filesystem::types::HostDescriptor::metadata_hash(self, self_).await) - } - - async fn metadata_hash_at( - &mut self, - self_: Resource, - path_flags: PathFlags, - path: String, - ) -> wasmtime::Result> { - convert_result( - latest::filesystem::types::HostDescriptor::metadata_hash_at( - self, - self_, - path_flags.into(), - path, - ) - .await, - ) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::filesystem::types::HostDescriptor::drop(self, rep) - } -} - -#[async_trait] -impl wasi::filesystem::types::HostDirectoryEntryStream for WasiImpl -where - T: WasiView, -{ - async fn read_directory_entry( - &mut self, - self_: Resource, - ) -> wasmtime::Result, FsErrorCode>> { - convert_result( - latest::filesystem::types::HostDirectoryEntryStream::read_directory_entry(self, self_) - .await - .map(|e| e.map(DirectoryEntry::from)), - ) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::filesystem::types::HostDirectoryEntryStream::drop(self, rep) - } -} - -impl wasi::filesystem::preopens::Host for WasiImpl -where - T: WasiView, -{ - fn get_directories(&mut self) -> wasmtime::Result, String)>> { - latest::filesystem::preopens::Host::get_directories(self) - } -} - -#[async_trait] -impl wasi::io::poll::Host for WasiImpl -where - T: WasiView, -{ - async fn poll(&mut self, list: Vec>) -> wasmtime::Result> { - latest::io::poll::Host::poll(self, list).await - } -} - -#[async_trait] -impl wasi::io::poll::HostPollable for WasiImpl -where - T: WasiView, -{ - async fn block(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::io::poll::HostPollable::block(self, rep).await - } - - async fn ready(&mut self, rep: Resource) -> wasmtime::Result { - latest::io::poll::HostPollable::ready(self, rep).await - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::io::poll::HostPollable::drop(self, rep) - } -} - -impl wasi::io::error::Host for WasiImpl where T: WasiView {} - -impl wasi::io::error::HostError for WasiImpl -where - T: WasiView, -{ - fn to_debug_string(&mut self, self_: Resource) -> wasmtime::Result { - latest::io::error::HostError::to_debug_string(self, self_) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::io::error::HostError::drop(self, rep) - } -} - -fn convert_stream_result( - mut view: impl WasiView, - result: Result, -) -> wasmtime::Result> -where - T2: From, -{ - match result { - Ok(e) => Ok(Ok(e.into())), - Err(wasmtime_wasi::StreamError::Closed) => Ok(Err(StreamError::Closed)), - Err(wasmtime_wasi::StreamError::LastOperationFailed(e)) => { - let e = view.table().push(e)?; - Ok(Err(StreamError::LastOperationFailed(e))) - } - Err(wasmtime_wasi::StreamError::Trap(e)) => Err(e), - } -} - -impl wasi::io::streams::Host for WasiImpl where T: WasiView {} - -#[async_trait] -impl wasi::io::streams::HostInputStream for WasiImpl -where - T: WasiView, -{ - async fn read( - &mut self, - self_: Resource, - len: u64, - ) -> wasmtime::Result, StreamError>> { - let result = latest::io::streams::HostInputStream::read(self, self_, len).await; - convert_stream_result(self, result) - } - - async fn blocking_read( - &mut self, - self_: Resource, - len: u64, - ) -> wasmtime::Result, StreamError>> { - let result = latest::io::streams::HostInputStream::blocking_read(self, self_, len).await; - convert_stream_result(self, result) - } - - async fn skip( - &mut self, - self_: Resource, - len: u64, - ) -> wasmtime::Result> { - let result = latest::io::streams::HostInputStream::skip(self, self_, len).await; - convert_stream_result(self, result) - } - - async fn blocking_skip( - &mut self, - self_: Resource, - len: u64, - ) -> wasmtime::Result> { - let result = latest::io::streams::HostInputStream::blocking_skip(self, self_, len).await; - convert_stream_result(self, result) - } - - fn subscribe(&mut self, self_: Resource) -> wasmtime::Result> { - latest::io::streams::HostInputStream::subscribe(self, self_) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::io::streams::HostInputStream::drop(self, rep) - } -} - -#[async_trait] -impl wasi::io::streams::HostOutputStream for WasiImpl -where - T: WasiView, -{ - fn check_write( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - let result = latest::io::streams::HostOutputStream::check_write(self, self_); - convert_stream_result(self, result) - } - - fn write( - &mut self, - self_: Resource, - contents: Vec, - ) -> wasmtime::Result> { - let result = latest::io::streams::HostOutputStream::write(self, self_, contents); - convert_stream_result(self, result) - } - - async fn blocking_write_and_flush( - &mut self, - self_: Resource, - contents: Vec, - ) -> wasmtime::Result> { - let result = - latest::io::streams::HostOutputStream::blocking_write_and_flush(self, self_, contents) - .await; - convert_stream_result(self, result) - } - - fn flush( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - let result = latest::io::streams::HostOutputStream::flush(self, self_); - convert_stream_result(self, result) - } - - async fn blocking_flush( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - let result = latest::io::streams::HostOutputStream::blocking_flush(self, self_).await; - convert_stream_result(self, result) - } - - fn subscribe(&mut self, self_: Resource) -> wasmtime::Result> { - latest::io::streams::HostOutputStream::subscribe(self, self_) - } - - fn write_zeroes( - &mut self, - self_: Resource, - len: u64, - ) -> wasmtime::Result> { - let result = latest::io::streams::HostOutputStream::write_zeroes(self, self_, len); - convert_stream_result(self, result) - } - - async fn blocking_write_zeroes_and_flush( - &mut self, - self_: Resource, - len: u64, - ) -> wasmtime::Result> { - let result = latest::io::streams::HostOutputStream::blocking_write_zeroes_and_flush( - self, self_, len, - ) - .await; - convert_stream_result(self, result) - } - - async fn splice( - &mut self, - self_: Resource, - src: Resource, - len: u64, - ) -> wasmtime::Result> { - let result = latest::io::streams::HostOutputStream::splice(self, self_, src, len).await; - convert_stream_result(self, result) - } - - async fn blocking_splice( - &mut self, - self_: Resource, - src: Resource, - len: u64, - ) -> wasmtime::Result> { - let result = - latest::io::streams::HostOutputStream::blocking_splice(self, self_, src, len).await; - convert_stream_result(self, result) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::io::streams::HostOutputStream::drop(self, rep) - } -} - -impl wasi::random::random::Host for WasiImpl -where - T: WasiView, -{ - fn get_random_bytes(&mut self, len: u64) -> wasmtime::Result> { - latest::random::random::Host::get_random_bytes(self, len) - } - - fn get_random_u64(&mut self) -> wasmtime::Result { - latest::random::random::Host::get_random_u64(self) - } -} - -impl wasi::random::insecure::Host for WasiImpl -where - T: WasiView, -{ - fn get_insecure_random_bytes(&mut self, len: u64) -> wasmtime::Result> { - latest::random::insecure::Host::get_insecure_random_bytes(self, len) - } - - fn get_insecure_random_u64(&mut self) -> wasmtime::Result { - latest::random::insecure::Host::get_insecure_random_u64(self) - } -} - -impl wasi::random::insecure_seed::Host for WasiImpl -where - T: WasiView, -{ - fn insecure_seed(&mut self) -> wasmtime::Result<(u64, u64)> { - latest::random::insecure_seed::Host::insecure_seed(self) - } -} - -impl wasi::cli::exit::Host for WasiImpl -where - T: WasiView, -{ - fn exit(&mut self, status: Result<(), ()>) -> wasmtime::Result<()> { - latest::cli::exit::Host::exit(self, status) - } -} - -impl wasi::cli::environment::Host for WasiImpl -where - T: WasiView, -{ - fn get_environment(&mut self) -> wasmtime::Result> { - latest::cli::environment::Host::get_environment(self) - } - - fn get_arguments(&mut self) -> wasmtime::Result> { - latest::cli::environment::Host::get_arguments(self) - } - - fn initial_cwd(&mut self) -> wasmtime::Result> { - latest::cli::environment::Host::initial_cwd(self) - } -} - -impl wasi::cli::stdin::Host for WasiImpl -where - T: WasiView, -{ - fn get_stdin(&mut self) -> wasmtime::Result> { - latest::cli::stdin::Host::get_stdin(self) - } -} - -impl wasi::cli::stdout::Host for WasiImpl -where - T: WasiView, -{ - fn get_stdout(&mut self) -> wasmtime::Result> { - latest::cli::stdout::Host::get_stdout(self) - } -} - -impl wasi::cli::stderr::Host for WasiImpl -where - T: WasiView, -{ - fn get_stderr(&mut self) -> wasmtime::Result> { - latest::cli::stderr::Host::get_stderr(self) - } -} - -impl wasi::cli::terminal_stdin::Host for WasiImpl -where - T: WasiView, -{ - fn get_terminal_stdin(&mut self) -> wasmtime::Result>> { - latest::cli::terminal_stdin::Host::get_terminal_stdin(self) - } -} - -impl wasi::cli::terminal_stdout::Host for WasiImpl -where - T: WasiView, -{ - fn get_terminal_stdout(&mut self) -> wasmtime::Result>> { - latest::cli::terminal_stdout::Host::get_terminal_stdout(self) - } -} - -impl wasi::cli::terminal_stderr::Host for WasiImpl -where - T: WasiView, -{ - fn get_terminal_stderr(&mut self) -> wasmtime::Result>> { - latest::cli::terminal_stderr::Host::get_terminal_stderr(self) - } -} - -impl wasi::cli::terminal_input::Host for WasiImpl where T: WasiView {} - -impl wasi::cli::terminal_input::HostTerminalInput for WasiImpl -where - T: WasiView, -{ - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::cli::terminal_input::HostTerminalInput::drop(self, rep) - } -} - -impl wasi::cli::terminal_output::Host for WasiImpl where T: WasiView {} - -impl wasi::cli::terminal_output::HostTerminalOutput for WasiImpl -where - T: WasiView, -{ - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::cli::terminal_output::HostTerminalOutput::drop(self, rep) - } -} - -impl wasi::sockets::tcp::Host for WasiImpl where T: WasiView {} - -#[async_trait] -impl wasi::sockets::tcp::HostTcpSocket for WasiImpl -where - T: WasiView, -{ - async fn start_bind( - &mut self, - self_: Resource, - network: Resource, - local_address: IpSocketAddress, - ) -> wasmtime::Result> { - convert_result( - latest::sockets::tcp::HostTcpSocket::start_bind( - self, - self_, - network, - local_address.into(), - ) - .await, - ) - } - - fn finish_bind( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::finish_bind( - self, self_, - )) - } - - async fn start_connect( - &mut self, - self_: Resource, - network: Resource, - remote_address: IpSocketAddress, - ) -> wasmtime::Result> { - convert_result( - latest::sockets::tcp::HostTcpSocket::start_connect( - self, - self_, - network, - remote_address.into(), - ) - .await, - ) - } - - fn finish_connect( - &mut self, - self_: Resource, - ) -> wasmtime::Result, Resource), SocketErrorCode>> - { - convert_result(latest::sockets::tcp::HostTcpSocket::finish_connect( - self, self_, - )) - } - - fn start_listen( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::start_listen( - self, self_, - )) - } - - fn finish_listen( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::finish_listen( - self, self_, - )) - } - - fn accept( - &mut self, - self_: Resource, - ) -> wasmtime::Result< - Result< - ( - Resource, - Resource, - Resource, - ), - SocketErrorCode, - >, - > { - convert_result(latest::sockets::tcp::HostTcpSocket::accept(self, self_)) - } - - fn local_address( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::local_address( - self, self_, - )) - } - - fn remote_address( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::remote_address( - self, self_, - )) - } - - fn address_family(&mut self, self_: Resource) -> wasmtime::Result { - latest::sockets::tcp::HostTcpSocket::address_family(self, self_).map(|e| e.into()) - } - - fn ipv6_only( - &mut self, - _self_: Resource, - ) -> wasmtime::Result> { - anyhow::bail!("ipv6-only API no longer supported") - } - - fn set_ipv6_only( - &mut self, - _self_: Resource, - _value: bool, - ) -> wasmtime::Result> { - anyhow::bail!("ipv6-only API no longer supported") - } - - fn set_listen_backlog_size( - &mut self, - self_: Resource, - value: u64, - ) -> wasmtime::Result> { - convert_result( - latest::sockets::tcp::HostTcpSocket::set_listen_backlog_size(self, self_, value), - ) - } - - fn is_listening(&mut self, self_: Resource) -> wasmtime::Result { - latest::sockets::tcp::HostTcpSocket::is_listening(self, self_) - } - - fn keep_alive_enabled( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::keep_alive_enabled( - self, self_, - )) - } - - fn set_keep_alive_enabled( - &mut self, - self_: Resource, - value: bool, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::set_keep_alive_enabled( - self, self_, value, - )) - } - - fn keep_alive_idle_time( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::keep_alive_idle_time( - self, self_, - )) - } - - fn set_keep_alive_idle_time( - &mut self, - self_: Resource, - value: Duration, - ) -> wasmtime::Result> { - convert_result( - latest::sockets::tcp::HostTcpSocket::set_keep_alive_idle_time(self, self_, value), - ) - } - - fn keep_alive_interval( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::keep_alive_interval( - self, self_, - )) - } - - fn set_keep_alive_interval( - &mut self, - self_: Resource, - value: Duration, - ) -> wasmtime::Result> { - convert_result( - latest::sockets::tcp::HostTcpSocket::set_keep_alive_interval(self, self_, value), - ) - } - - fn keep_alive_count( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::keep_alive_count( - self, self_, - )) - } - - fn set_keep_alive_count( - &mut self, - self_: Resource, - value: u32, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::set_keep_alive_count( - self, self_, value, - )) - } - - fn hop_limit( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::hop_limit(self, self_)) - } - - fn set_hop_limit( - &mut self, - self_: Resource, - value: u8, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::set_hop_limit( - self, self_, value, - )) - } - - fn receive_buffer_size( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::receive_buffer_size( - self, self_, - )) - } - - fn set_receive_buffer_size( - &mut self, - self_: Resource, - value: u64, - ) -> wasmtime::Result> { - convert_result( - latest::sockets::tcp::HostTcpSocket::set_receive_buffer_size(self, self_, value), - ) - } - - fn send_buffer_size( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::send_buffer_size( - self, self_, - )) - } - - fn set_send_buffer_size( - &mut self, - self_: Resource, - value: u64, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::set_send_buffer_size( - self, self_, value, - )) - } - - fn subscribe(&mut self, self_: Resource) -> wasmtime::Result> { - latest::sockets::tcp::HostTcpSocket::subscribe(self, self_) - } - - fn shutdown( - &mut self, - self_: Resource, - shutdown_type: ShutdownType, - ) -> wasmtime::Result> { - convert_result(latest::sockets::tcp::HostTcpSocket::shutdown( - self, - self_, - shutdown_type.into(), - )) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::sockets::tcp::HostTcpSocket::drop(self, rep) - } -} - -impl wasi::sockets::tcp_create_socket::Host for WasiImpl -where - T: WasiView, -{ - fn create_tcp_socket( - &mut self, - address_family: IpAddressFamily, - ) -> wasmtime::Result, SocketErrorCode>> { - convert_result(latest::sockets::tcp_create_socket::Host::create_tcp_socket( - self, - address_family.into(), - )) - } -} - -impl wasi::sockets::udp::Host for WasiImpl where T: WasiView {} - -#[async_trait] -impl wasi::sockets::udp::HostUdpSocket for WasiImpl -where - T: WasiView, -{ - async fn start_bind( - &mut self, - self_: Resource, - network: Resource, - local_address: IpSocketAddress, - ) -> wasmtime::Result> { - convert_result( - latest::sockets::udp::HostUdpSocket::start_bind( - self, - self_, - network, - local_address.into(), - ) - .await, - ) - } - - fn finish_bind( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::udp::HostUdpSocket::finish_bind( - self, self_, - )) - } - - fn local_address( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::udp::HostUdpSocket::local_address( - self, self_, - )) - } - - fn remote_address( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::udp::HostUdpSocket::remote_address( - self, self_, - )) - } - - fn address_family(&mut self, self_: Resource) -> wasmtime::Result { - latest::sockets::udp::HostUdpSocket::address_family(self, self_).map(|e| e.into()) - } - - fn ipv6_only( - &mut self, - _self_: Resource, - ) -> wasmtime::Result> { - anyhow::bail!("ipv6-only API no longer supported") - } - - fn set_ipv6_only( - &mut self, - _self_: Resource, - _value: bool, - ) -> wasmtime::Result> { - anyhow::bail!("ipv6-only API no longer supported") - } - - fn unicast_hop_limit( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::udp::HostUdpSocket::unicast_hop_limit( - self, self_, - )) - } - - fn set_unicast_hop_limit( - &mut self, - self_: Resource, - value: u8, - ) -> wasmtime::Result> { - convert_result(latest::sockets::udp::HostUdpSocket::set_unicast_hop_limit( - self, self_, value, - )) - } - - fn receive_buffer_size( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::udp::HostUdpSocket::receive_buffer_size( - self, self_, - )) - } - - fn set_receive_buffer_size( - &mut self, - self_: Resource, - value: u64, - ) -> wasmtime::Result> { - convert_result( - latest::sockets::udp::HostUdpSocket::set_receive_buffer_size(self, self_, value), - ) - } - - fn send_buffer_size( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::udp::HostUdpSocket::send_buffer_size( - self, self_, - )) - } - - fn set_send_buffer_size( - &mut self, - self_: Resource, - value: u64, - ) -> wasmtime::Result> { - convert_result(latest::sockets::udp::HostUdpSocket::set_send_buffer_size( - self, self_, value, - )) - } - - async fn stream( - &mut self, - self_: Resource, - remote_address: Option, - ) -> wasmtime::Result< - Result< - ( - Resource, - Resource, - ), - SocketErrorCode, - >, - > { - convert_result( - latest::sockets::udp::HostUdpSocket::stream( - self, - self_, - remote_address.map(|a| a.into()), - ) - .await, - ) - } - - fn subscribe(&mut self, self_: Resource) -> wasmtime::Result> { - latest::sockets::udp::HostUdpSocket::subscribe(self, self_) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::sockets::udp::HostUdpSocket::drop(self, rep) - } -} - -#[async_trait] -impl wasi::sockets::udp::HostOutgoingDatagramStream for WasiImpl -where - T: WasiView, -{ - fn check_send( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - convert_result(latest::sockets::udp::HostOutgoingDatagramStream::check_send(self, self_)) - } - - async fn send( - &mut self, - self_: Resource, - datagrams: Vec, - ) -> wasmtime::Result> { - convert_result( - latest::sockets::udp::HostOutgoingDatagramStream::send( - self, - self_, - datagrams.into_iter().map(|d| d.into()).collect(), - ) - .await, - ) - } - - fn subscribe( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - latest::sockets::udp::HostOutgoingDatagramStream::subscribe(self, self_) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::sockets::udp::HostOutgoingDatagramStream::drop(self, rep) - } -} - -impl wasi::sockets::udp::HostIncomingDatagramStream for WasiImpl -where - T: WasiView, -{ - fn receive( - &mut self, - self_: Resource, - max_results: u64, - ) -> wasmtime::Result, SocketErrorCode>> { - convert_result(latest::sockets::udp::HostIncomingDatagramStream::receive( - self, - self_, - max_results, - )) - .map(|r| r.map(|r: Vec<_>| r.into_iter().map(|d| d.into()).collect())) - } - - fn subscribe( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - latest::sockets::udp::HostIncomingDatagramStream::subscribe(self, self_) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::sockets::udp::HostIncomingDatagramStream::drop(self, rep) - } -} - -impl wasi::sockets::udp_create_socket::Host for WasiImpl -where - T: WasiView, -{ - fn create_udp_socket( - &mut self, - address_family: IpAddressFamily, - ) -> wasmtime::Result, SocketErrorCode>> { - convert_result(latest::sockets::udp_create_socket::Host::create_udp_socket( - self, - address_family.into(), - )) - } -} - -impl wasi::sockets::instance_network::Host for WasiImpl -where - T: WasiView, -{ - fn instance_network(&mut self) -> wasmtime::Result> { - latest::sockets::instance_network::Host::instance_network(self) - } -} - -impl wasi::sockets::network::Host for WasiImpl where T: WasiView {} - -impl wasi::sockets::network::HostNetwork for WasiImpl -where - T: WasiView, -{ - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::sockets::network::HostNetwork::drop(self, rep) - } -} - -impl wasi::sockets::ip_name_lookup::Host for WasiImpl -where - T: WasiView, -{ - fn resolve_addresses( - &mut self, - network: Resource, - name: String, - ) -> wasmtime::Result, SocketErrorCode>> { - convert_result(latest::sockets::ip_name_lookup::Host::resolve_addresses( - self, network, name, - )) - } -} - -impl wasi::sockets::ip_name_lookup::HostResolveAddressStream for WasiImpl -where - T: WasiView, -{ - fn resolve_next_address( - &mut self, - self_: Resource, - ) -> wasmtime::Result, SocketErrorCode>> { - convert_result( - latest::sockets::ip_name_lookup::HostResolveAddressStream::resolve_next_address( - self, self_, - ) - .map(|e| e.map(|e| e.into())), - ) - } - - fn subscribe( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - latest::sockets::ip_name_lookup::HostResolveAddressStream::subscribe(self, self_) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::sockets::ip_name_lookup::HostResolveAddressStream::drop(self, rep) - } -} - -impl wasi::http::types::Host for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn http_error_code( - &mut self, - error: Resource, - ) -> wasmtime::Result> { - latest::http::types::Host::http_error_code(self, error).map(|e| e.map(|e| e.into())) - } -} - -impl wasi::http::types::HostRequestOptions for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn new(&mut self) -> wasmtime::Result> { - latest::http::types::HostRequestOptions::new(self) - } - - fn connect_timeout_ms( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - latest::http::types::HostRequestOptions::connect_timeout(self, self_) - } - - fn set_connect_timeout_ms( - &mut self, - self_: Resource, - duration: Option, - ) -> wasmtime::Result> { - latest::http::types::HostRequestOptions::set_connect_timeout(self, self_, duration) - } - - fn first_byte_timeout_ms( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - latest::http::types::HostRequestOptions::first_byte_timeout(self, self_) - } - - fn set_first_byte_timeout_ms( - &mut self, - self_: Resource, - duration: Option, - ) -> wasmtime::Result> { - latest::http::types::HostRequestOptions::set_first_byte_timeout(self, self_, duration) - } - - fn between_bytes_timeout_ms( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - latest::http::types::HostRequestOptions::between_bytes_timeout(self, self_) - } - - fn set_between_bytes_timeout_ms( - &mut self, - self_: Resource, - duration: Option, - ) -> wasmtime::Result> { - latest::http::types::HostRequestOptions::set_between_bytes_timeout(self, self_, duration) - } - - fn drop(&mut self, self_: Resource) -> wasmtime::Result<()> { - latest::http::types::HostRequestOptions::drop(self, self_) - } -} - -impl wasi::http::types::HostFields for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn new(&mut self) -> wasmtime::Result> { - latest::http::types::HostFields::new(self) - } - - fn from_list( - &mut self, - entries: Vec<(String, Vec)>, - ) -> wasmtime::Result, HeaderError>> { - latest::http::types::HostFields::from_list(self, entries).map(|r| r.map_err(|e| e.into())) - } - - fn get(&mut self, self_: Resource, name: String) -> wasmtime::Result>> { - latest::http::types::HostFields::get(self, self_, name) - } - - fn set( - &mut self, - self_: Resource, - name: String, - value: Vec>, - ) -> wasmtime::Result> { - latest::http::types::HostFields::set(self, self_, name, value) - .map(|r| r.map_err(|e| e.into())) - } - - fn delete( - &mut self, - self_: Resource, - name: String, - ) -> wasmtime::Result> { - latest::http::types::HostFields::delete(self, self_, name).map(|r| r.map_err(|e| e.into())) - } - - fn append( - &mut self, - self_: Resource, - name: String, - value: Vec, - ) -> wasmtime::Result> { - latest::http::types::HostFields::append(self, self_, name, value) - .map(|r| r.map_err(|e| e.into())) - } - - fn entries(&mut self, self_: Resource) -> wasmtime::Result)>> { - latest::http::types::HostFields::entries(self, self_) - } - - fn clone(&mut self, self_: Resource) -> wasmtime::Result> { - latest::http::types::HostFields::clone(self, self_) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::http::types::HostFields::drop(self, rep) - } -} - -impl wasi::http::types::HostIncomingRequest for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn method(&mut self, self_: Resource) -> wasmtime::Result { - latest::http::types::HostIncomingRequest::method(self, self_).map(|e| e.into()) - } - - fn path_with_query( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - latest::http::types::HostIncomingRequest::path_with_query(self, self_) - } - - fn scheme(&mut self, self_: Resource) -> wasmtime::Result> { - latest::http::types::HostIncomingRequest::scheme(self, self_).map(|e| e.map(|e| e.into())) - } - - fn authority(&mut self, self_: Resource) -> wasmtime::Result> { - latest::http::types::HostIncomingRequest::authority(self, self_) - } - - fn headers(&mut self, self_: Resource) -> wasmtime::Result> { - latest::http::types::HostIncomingRequest::headers(self, self_) - } - - fn consume( - &mut self, - self_: Resource, - ) -> wasmtime::Result, ()>> { - latest::http::types::HostIncomingRequest::consume(self, self_) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::http::types::HostIncomingRequest::drop(self, rep) - } -} - -impl wasi::http::types::HostIncomingResponse for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn status(&mut self, self_: Resource) -> wasmtime::Result { - latest::http::types::HostIncomingResponse::status(self, self_) - } - - fn headers( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - latest::http::types::HostIncomingResponse::headers(self, self_) - } - - fn consume( - &mut self, - self_: Resource, - ) -> wasmtime::Result, ()>> { - latest::http::types::HostIncomingResponse::consume(self, self_) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::http::types::HostIncomingResponse::drop(self, rep) - } -} - -impl wasi::http::types::HostIncomingBody for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn stream( - &mut self, - self_: Resource, - ) -> wasmtime::Result, ()>> { - latest::http::types::HostIncomingBody::stream(self, self_) - } - - fn finish( - &mut self, - this: Resource, - ) -> wasmtime::Result> { - latest::http::types::HostIncomingBody::finish(self, this) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::http::types::HostIncomingBody::drop(self, rep) - } -} - -impl wasi::http::types::HostOutgoingRequest for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn new(&mut self, headers: Resource) -> wasmtime::Result> { - latest::http::types::HostOutgoingRequest::new(self, headers) - } - - fn method(&mut self, self_: Resource) -> wasmtime::Result { - latest::http::types::HostOutgoingRequest::method(self, self_).map(|m| m.into()) - } - - fn set_method( - &mut self, - self_: Resource, - method: Method, - ) -> wasmtime::Result> { - latest::http::types::HostOutgoingRequest::set_method(self, self_, method.into()) - } - - fn path_with_query( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - latest::http::types::HostOutgoingRequest::path_with_query(self, self_) - } - - fn set_path_with_query( - &mut self, - self_: Resource, - path_with_query: Option, - ) -> wasmtime::Result> { - latest::http::types::HostOutgoingRequest::set_path_with_query(self, self_, path_with_query) - } - - fn scheme(&mut self, self_: Resource) -> wasmtime::Result> { - latest::http::types::HostOutgoingRequest::scheme(self, self_).map(|s| s.map(|s| s.into())) - } - - fn set_scheme( - &mut self, - self_: Resource, - scheme: Option, - ) -> wasmtime::Result> { - latest::http::types::HostOutgoingRequest::set_scheme(self, self_, scheme.map(|s| s.into())) - } - - fn authority(&mut self, self_: Resource) -> wasmtime::Result> { - latest::http::types::HostOutgoingRequest::authority(self, self_) - } - - fn set_authority( - &mut self, - self_: Resource, - authority: Option, - ) -> wasmtime::Result> { - latest::http::types::HostOutgoingRequest::set_authority(self, self_, authority) - } - - fn headers(&mut self, self_: Resource) -> wasmtime::Result> { - latest::http::types::HostOutgoingRequest::headers(self, self_) - } - - fn body( - &mut self, - self_: Resource, - ) -> wasmtime::Result, ()>> { - latest::http::types::HostOutgoingRequest::body(self, self_) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::http::types::HostOutgoingRequest::drop(self, rep) - } -} - -impl wasi::http::types::HostOutgoingResponse for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn new(&mut self, headers: Resource) -> wasmtime::Result> { - let headers = latest::http::types::HostFields::clone(self, headers)?; - latest::http::types::HostOutgoingResponse::new(self, headers) - } - - fn status_code(&mut self, self_: Resource) -> wasmtime::Result { - latest::http::types::HostOutgoingResponse::status_code(self, self_) - } - - fn set_status_code( - &mut self, - self_: Resource, - status_code: StatusCode, - ) -> wasmtime::Result> { - latest::http::types::HostOutgoingResponse::set_status_code(self, self_, status_code) - } - - fn headers( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - latest::http::types::HostOutgoingResponse::headers(self, self_) - } - - fn body( - &mut self, - self_: Resource, - ) -> wasmtime::Result, ()>> { - latest::http::types::HostOutgoingResponse::body(self, self_) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::http::types::HostOutgoingResponse::drop(self, rep) - } -} - -impl wasi::http::types::HostOutgoingBody for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn write( - &mut self, - self_: Resource, - ) -> wasmtime::Result, ()>> { - latest::http::types::HostOutgoingBody::write(self, self_) - } - - fn finish( - &mut self, - this: Resource, - trailers: Option>, - ) -> wasmtime::Result> { - match latest::http::types::HostOutgoingBody::finish(self, this, trailers) { - Ok(()) => Ok(Ok(())), - Err(e) => Ok(Err(e.downcast()?.into())), - } - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::http::types::HostOutgoingBody::drop(self, rep) - } -} - -impl wasi::http::types::HostResponseOutparam for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn set( - &mut self, - param: Resource, - response: Result, HttpErrorCode>, - ) -> wasmtime::Result<()> { - latest::http::types::HostResponseOutparam::set(self, param, response.map_err(|e| e.into())) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::http::types::HostResponseOutparam::drop(self, rep) - } -} - -impl wasi::http::types::HostFutureTrailers for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn subscribe( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - latest::http::types::HostFutureTrailers::subscribe(self, self_) - } - - fn get( - &mut self, - self_: Resource, - ) -> wasmtime::Result>, HttpErrorCode>>> { - match latest::http::types::HostFutureTrailers::get(self, self_)? { - Some(Ok(Ok(trailers))) => Ok(Some(Ok(trailers))), - Some(Ok(Err(e))) => Ok(Some(Err(e.into()))), - Some(Err(())) => Err(anyhow::anyhow!("trailers have already been retrieved")), - None => Ok(None), - } - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::http::types::HostFutureTrailers::drop(self, rep) - } -} - -impl wasi::http::types::HostFutureIncomingResponse for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn get( - &mut self, - self_: Resource, - ) -> wasmtime::Result, HttpErrorCode>, ()>>> - { - match latest::http::types::HostFutureIncomingResponse::get(self, self_)? { - None => Ok(None), - Some(Ok(Ok(response))) => Ok(Some(Ok(Ok(response)))), - Some(Ok(Err(e))) => Ok(Some(Ok(Err(e.into())))), - Some(Err(())) => Ok(Some(Err(()))), - } - } - - fn subscribe( - &mut self, - self_: Resource, - ) -> wasmtime::Result> { - latest::http::types::HostFutureIncomingResponse::subscribe(self, self_) - } - - fn drop(&mut self, rep: Resource) -> wasmtime::Result<()> { - latest::http::types::HostFutureIncomingResponse::drop(self, rep) - } -} - -impl wasi::http::outgoing_handler::Host for WasiHttpImpl -where - T: WasiHttpView + Send, -{ - fn handle( - &mut self, - request: Resource, - options: Option>, - ) -> wasmtime::Result, HttpErrorCode>> { - match latest::http::outgoing_handler::Host::handle(self, request, options) { - Ok(resp) => Ok(Ok(resp)), - Err(e) => Ok(Err(e.downcast()?.into())), - } - } -} - -convert! { - struct latest::clocks::wall_clock::Datetime [<=>] Datetime { - seconds, - nanoseconds, - } - - enum latest::filesystem::types::ErrorCode => FsErrorCode { - Access, - WouldBlock, - Already, - BadDescriptor, - Busy, - Deadlock, - Quota, - Exist, - FileTooLarge, - IllegalByteSequence, - InProgress, - Interrupted, - Invalid, - Io, - IsDirectory, - Loop, - TooManyLinks, - MessageSize, - NameTooLong, - NoDevice, - NoEntry, - NoLock, - InsufficientMemory, - InsufficientSpace, - NotDirectory, - NotEmpty, - NotRecoverable, - Unsupported, - NoTty, - NoSuchDevice, - Overflow, - NotPermitted, - Pipe, - ReadOnly, - InvalidSeek, - TextFileBusy, - CrossDevice, - } - - enum Advice => latest::filesystem::types::Advice { - Normal, - Sequential, - Random, - WillNeed, - DontNeed, - NoReuse, - } - - flags DescriptorFlags [<=>] latest::filesystem::types::DescriptorFlags { - READ, - WRITE, - FILE_INTEGRITY_SYNC, - DATA_INTEGRITY_SYNC, - REQUESTED_WRITE_SYNC, - MUTATE_DIRECTORY, - } - - enum DescriptorType [<=>] latest::filesystem::types::DescriptorType { - Unknown, - BlockDevice, - CharacterDevice, - Directory, - Fifo, - SymbolicLink, - RegularFile, - Socket, - } - - enum NewTimestamp => latest::filesystem::types::NewTimestamp { - NoChange, - Now, - Timestamp(e), - } - - flags PathFlags => latest::filesystem::types::PathFlags { - SYMLINK_FOLLOW, - } - - flags OpenFlags => latest::filesystem::types::OpenFlags { - CREATE, - DIRECTORY, - EXCLUSIVE, - TRUNCATE, - } - - struct latest::filesystem::types::MetadataHashValue => MetadataHashValue { - lower, - upper, - } - - struct latest::filesystem::types::DirectoryEntry => DirectoryEntry { - type_, - name, - } - - - enum latest::sockets::network::ErrorCode => SocketErrorCode { - Unknown, - AccessDenied, - NotSupported, - InvalidArgument, - OutOfMemory, - Timeout, - ConcurrencyConflict, - NotInProgress, - WouldBlock, - InvalidState, - NewSocketLimit, - AddressNotBindable, - AddressInUse, - RemoteUnreachable, - ConnectionRefused, - ConnectionReset, - ConnectionAborted, - DatagramTooLarge, - NameUnresolvable, - TemporaryResolverFailure, - PermanentResolverFailure, - } - - enum latest::sockets::network::IpAddress [<=>] IpAddress { - Ipv4(e), - Ipv6(e), - } - - enum latest::sockets::network::IpSocketAddress [<=>] IpSocketAddress { - Ipv4(e), - Ipv6(e), - } - - struct latest::sockets::network::Ipv4SocketAddress [<=>] Ipv4SocketAddress { - port, - address, - } - - struct latest::sockets::network::Ipv6SocketAddress [<=>] Ipv6SocketAddress { - port, - flow_info, - scope_id, - address, - } - - enum latest::sockets::network::IpAddressFamily [<=>] IpAddressFamily { - Ipv4, - Ipv6, - } - - enum ShutdownType => latest::sockets::tcp::ShutdownType { - Receive, - Send, - Both, - } - - struct latest::sockets::udp::IncomingDatagram => IncomingDatagram { - data, - remote_address, - } - - enum latest::http::types::Method [<=>] Method { - Get, - Head, - Post, - Put, - Delete, - Connect, - Options, - Trace, - Patch, - Other(e), - } - - enum latest::http::types::Scheme [<=>] Scheme { - Http, - Https, - Other(e), - } - - enum latest::http::types::HeaderError => HeaderError { - InvalidSyntax, - Forbidden, - Immutable, - } - - struct latest::http::types::DnsErrorPayload [<=>] DnsErrorPayload { - rcode, - info_code, - } - - struct latest::http::types::TlsAlertReceivedPayload [<=>] TlsAlertReceivedPayload { - alert_id, - alert_message, - } - - struct latest::http::types::FieldSizePayload [<=>] FieldSizePayload { - field_name, - field_size, - } -} - -impl From for DescriptorStat { - fn from(e: latest::filesystem::types::DescriptorStat) -> DescriptorStat { - DescriptorStat { - type_: e.type_.into(), - link_count: e.link_count, - size: e.size, - data_access_timestamp: e.data_access_timestamp.map(|e| e.into()), - data_modification_timestamp: e.data_modification_timestamp.map(|e| e.into()), - status_change_timestamp: e.status_change_timestamp.map(|e| e.into()), - } - } -} - -impl From for latest::sockets::udp::OutgoingDatagram { - fn from(d: OutgoingDatagram) -> Self { - Self { - data: d.data, - remote_address: d.remote_address.map(|a| a.into()), - } - } -} - -impl From for HttpErrorCode { - fn from(e: latest::http::types::ErrorCode) -> Self { - match e { - latest::http::types::ErrorCode::DnsTimeout => HttpErrorCode::DnsTimeout, - latest::http::types::ErrorCode::DnsError(e) => HttpErrorCode::DnsError(e.into()), - latest::http::types::ErrorCode::DestinationNotFound => { - HttpErrorCode::DestinationNotFound - } - latest::http::types::ErrorCode::DestinationUnavailable => { - HttpErrorCode::DestinationUnavailable - } - latest::http::types::ErrorCode::DestinationIpProhibited => { - HttpErrorCode::DestinationIpProhibited - } - latest::http::types::ErrorCode::DestinationIpUnroutable => { - HttpErrorCode::DestinationIpUnroutable - } - latest::http::types::ErrorCode::ConnectionRefused => HttpErrorCode::ConnectionRefused, - latest::http::types::ErrorCode::ConnectionTerminated => { - HttpErrorCode::ConnectionTerminated - } - latest::http::types::ErrorCode::ConnectionTimeout => HttpErrorCode::ConnectionTimeout, - latest::http::types::ErrorCode::ConnectionReadTimeout => { - HttpErrorCode::ConnectionReadTimeout - } - latest::http::types::ErrorCode::ConnectionWriteTimeout => { - HttpErrorCode::ConnectionWriteTimeout - } - latest::http::types::ErrorCode::ConnectionLimitReached => { - HttpErrorCode::ConnectionLimitReached - } - latest::http::types::ErrorCode::TlsProtocolError => HttpErrorCode::TlsProtocolError, - latest::http::types::ErrorCode::TlsCertificateError => { - HttpErrorCode::TlsCertificateError - } - latest::http::types::ErrorCode::TlsAlertReceived(e) => { - HttpErrorCode::TlsAlertReceived(e.into()) - } - latest::http::types::ErrorCode::HttpRequestDenied => HttpErrorCode::HttpRequestDenied, - latest::http::types::ErrorCode::HttpRequestLengthRequired => { - HttpErrorCode::HttpRequestLengthRequired - } - latest::http::types::ErrorCode::HttpRequestBodySize(e) => { - HttpErrorCode::HttpRequestBodySize(e) - } - latest::http::types::ErrorCode::HttpRequestMethodInvalid => { - HttpErrorCode::HttpRequestMethodInvalid - } - latest::http::types::ErrorCode::HttpRequestUriInvalid => { - HttpErrorCode::HttpRequestUriInvalid - } - latest::http::types::ErrorCode::HttpRequestUriTooLong => { - HttpErrorCode::HttpRequestUriTooLong - } - latest::http::types::ErrorCode::HttpRequestHeaderSectionSize(e) => { - HttpErrorCode::HttpRequestHeaderSectionSize(e) - } - latest::http::types::ErrorCode::HttpRequestHeaderSize(e) => { - HttpErrorCode::HttpRequestHeaderSize(e.map(|e| e.into())) - } - latest::http::types::ErrorCode::HttpRequestTrailerSectionSize(e) => { - HttpErrorCode::HttpRequestTrailerSectionSize(e) - } - latest::http::types::ErrorCode::HttpRequestTrailerSize(e) => { - HttpErrorCode::HttpRequestTrailerSize(e.into()) - } - latest::http::types::ErrorCode::HttpResponseIncomplete => { - HttpErrorCode::HttpResponseIncomplete - } - latest::http::types::ErrorCode::HttpResponseHeaderSectionSize(e) => { - HttpErrorCode::HttpResponseHeaderSectionSize(e) - } - latest::http::types::ErrorCode::HttpResponseHeaderSize(e) => { - HttpErrorCode::HttpResponseHeaderSize(e.into()) - } - latest::http::types::ErrorCode::HttpResponseBodySize(e) => { - HttpErrorCode::HttpResponseBodySize(e) - } - latest::http::types::ErrorCode::HttpResponseTrailerSectionSize(e) => { - HttpErrorCode::HttpResponseTrailerSectionSize(e) - } - latest::http::types::ErrorCode::HttpResponseTrailerSize(e) => { - HttpErrorCode::HttpResponseTrailerSize(e.into()) - } - latest::http::types::ErrorCode::HttpResponseTransferCoding(e) => { - HttpErrorCode::HttpResponseTransferCoding(e) - } - latest::http::types::ErrorCode::HttpResponseContentCoding(e) => { - HttpErrorCode::HttpResponseContentCoding(e) - } - latest::http::types::ErrorCode::HttpResponseTimeout => { - HttpErrorCode::HttpResponseTimeout - } - latest::http::types::ErrorCode::HttpUpgradeFailed => HttpErrorCode::HttpUpgradeFailed, - latest::http::types::ErrorCode::HttpProtocolError => HttpErrorCode::HttpProtocolError, - latest::http::types::ErrorCode::LoopDetected => HttpErrorCode::LoopDetected, - latest::http::types::ErrorCode::ConfigurationError => HttpErrorCode::ConfigurationError, - latest::http::types::ErrorCode::InternalError(e) => HttpErrorCode::InternalError(e), - } - } -} - -impl From for latest::http::types::ErrorCode { - fn from(e: HttpErrorCode) -> Self { - match e { - HttpErrorCode::DnsTimeout => latest::http::types::ErrorCode::DnsTimeout, - HttpErrorCode::DnsError(e) => latest::http::types::ErrorCode::DnsError(e.into()), - HttpErrorCode::DestinationNotFound => { - latest::http::types::ErrorCode::DestinationNotFound - } - HttpErrorCode::DestinationUnavailable => { - latest::http::types::ErrorCode::DestinationUnavailable - } - HttpErrorCode::DestinationIpProhibited => { - latest::http::types::ErrorCode::DestinationIpProhibited - } - HttpErrorCode::DestinationIpUnroutable => { - latest::http::types::ErrorCode::DestinationIpUnroutable - } - HttpErrorCode::ConnectionRefused => latest::http::types::ErrorCode::ConnectionRefused, - HttpErrorCode::ConnectionTerminated => { - latest::http::types::ErrorCode::ConnectionTerminated - } - HttpErrorCode::ConnectionTimeout => latest::http::types::ErrorCode::ConnectionTimeout, - HttpErrorCode::ConnectionReadTimeout => { - latest::http::types::ErrorCode::ConnectionReadTimeout - } - HttpErrorCode::ConnectionWriteTimeout => { - latest::http::types::ErrorCode::ConnectionWriteTimeout - } - HttpErrorCode::ConnectionLimitReached => { - latest::http::types::ErrorCode::ConnectionLimitReached - } - HttpErrorCode::TlsProtocolError => latest::http::types::ErrorCode::TlsProtocolError, - HttpErrorCode::TlsCertificateError => { - latest::http::types::ErrorCode::TlsCertificateError - } - HttpErrorCode::TlsAlertReceived(e) => { - latest::http::types::ErrorCode::TlsAlertReceived(e.into()) - } - HttpErrorCode::HttpRequestDenied => latest::http::types::ErrorCode::HttpRequestDenied, - HttpErrorCode::HttpRequestLengthRequired => { - latest::http::types::ErrorCode::HttpRequestLengthRequired - } - HttpErrorCode::HttpRequestBodySize(e) => { - latest::http::types::ErrorCode::HttpRequestBodySize(e) - } - HttpErrorCode::HttpRequestMethodInvalid => { - latest::http::types::ErrorCode::HttpRequestMethodInvalid - } - HttpErrorCode::HttpRequestUriInvalid => { - latest::http::types::ErrorCode::HttpRequestUriInvalid - } - HttpErrorCode::HttpRequestUriTooLong => { - latest::http::types::ErrorCode::HttpRequestUriTooLong - } - HttpErrorCode::HttpRequestHeaderSectionSize(e) => { - latest::http::types::ErrorCode::HttpRequestHeaderSectionSize(e) - } - HttpErrorCode::HttpRequestHeaderSize(e) => { - latest::http::types::ErrorCode::HttpRequestHeaderSize(e.map(|e| e.into())) - } - HttpErrorCode::HttpRequestTrailerSectionSize(e) => { - latest::http::types::ErrorCode::HttpRequestTrailerSectionSize(e) - } - HttpErrorCode::HttpRequestTrailerSize(e) => { - latest::http::types::ErrorCode::HttpRequestTrailerSize(e.into()) - } - HttpErrorCode::HttpResponseIncomplete => { - latest::http::types::ErrorCode::HttpResponseIncomplete - } - HttpErrorCode::HttpResponseHeaderSectionSize(e) => { - latest::http::types::ErrorCode::HttpResponseHeaderSectionSize(e) - } - HttpErrorCode::HttpResponseHeaderSize(e) => { - latest::http::types::ErrorCode::HttpResponseHeaderSize(e.into()) - } - HttpErrorCode::HttpResponseBodySize(e) => { - latest::http::types::ErrorCode::HttpResponseBodySize(e) - } - HttpErrorCode::HttpResponseTrailerSectionSize(e) => { - latest::http::types::ErrorCode::HttpResponseTrailerSectionSize(e) - } - HttpErrorCode::HttpResponseTrailerSize(e) => { - latest::http::types::ErrorCode::HttpResponseTrailerSize(e.into()) - } - HttpErrorCode::HttpResponseTransferCoding(e) => { - latest::http::types::ErrorCode::HttpResponseTransferCoding(e) - } - HttpErrorCode::HttpResponseContentCoding(e) => { - latest::http::types::ErrorCode::HttpResponseContentCoding(e) - } - HttpErrorCode::HttpResponseTimeout => { - latest::http::types::ErrorCode::HttpResponseTimeout - } - HttpErrorCode::HttpUpgradeFailed => latest::http::types::ErrorCode::HttpUpgradeFailed, - HttpErrorCode::HttpProtocolError => latest::http::types::ErrorCode::HttpProtocolError, - HttpErrorCode::LoopDetected => latest::http::types::ErrorCode::LoopDetected, - HttpErrorCode::ConfigurationError => latest::http::types::ErrorCode::ConfigurationError, - HttpErrorCode::InternalError(e) => latest::http::types::ErrorCode::InternalError(e), - } - } -} diff --git a/crates/core/tests/core-wasi-test/src/main.rs b/crates/core/tests/core-wasi-test/src/main.rs index a1bc0ed28..77a76c2a1 100644 --- a/crates/core/tests/core-wasi-test/src/main.rs +++ b/crates/core/tests/core-wasi-test/src/main.rs @@ -5,11 +5,6 @@ use std::time::Duration; -wit_bindgen::generate!({ - world: "multiplier", - path: "wit/multiplier.wit" -}); - type Result = std::result::Result<(), Box>; fn main() -> Result { @@ -44,12 +39,6 @@ fn main() -> Result { eprintln!("write {path}"); std::fs::write(path, "content")?; } - "multiply" => { - let input: i32 = args.next().expect("input").parse().expect("i32"); - eprintln!("multiply {input}"); - let output = imports::multiply(input); - println!("{output}"); - } "sleep" => { let duration = Duration::from_millis(args.next().expect("duration_ms").parse().expect("u64")); diff --git a/crates/core/tests/integration_test.rs b/crates/core/tests/integration_test.rs index 726f9aa59..a442bc2dd 100644 --- a/crates/core/tests/integration_test.rs +++ b/crates/core/tests/integration_test.rs @@ -1,86 +1,28 @@ use std::{ - io::Cursor, path::PathBuf, time::{Duration, Instant}, }; use anyhow::Context; -use spin_core::{ - Component, Config, Engine, HostComponent, I32Exit, Store, StoreBuilder, Trap, WasiVersion, -}; -use tempfile::TempDir; +use serde_json::json; +use spin_core::{Component, Config, Engine, State, Store, StoreBuilder, Trap}; +use spin_factor_wasi::{DummyFilesMounter, WasiFactor}; +use spin_factors::{App, RuntimeFactors}; +use spin_locked_app::locked::LockedApp; use tokio::{fs, io::AsyncWrite}; - -#[tokio::test(flavor = "multi_thread")] -async fn test_stdio() { - let stdout = run_core_wasi_test(["echo"], |store_builder| { - store_builder.stdin_pipe(Cursor::new(b"DATA")); - }) - .await - .unwrap(); - - assert_eq!(stdout, "DATA"); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_read_only_preopened_dir() { - let filename = "test_file"; - let tempdir = TempDir::new().unwrap(); - std::fs::write(tempdir.path().join(filename), "x").unwrap(); - - run_core_wasi_test(["read", filename], |store_builder| { - store_builder - .read_only_preopened_dir(&tempdir, "/".into()) - .unwrap(); - }) - .await - .unwrap(); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_read_only_preopened_dir_write_fails() { - let filename = "test_file"; - let tempdir = TempDir::new().unwrap(); - std::fs::write(tempdir.path().join(filename), "x").unwrap(); - - let err = run_core_wasi_test(["write", filename], |store_builder| { - store_builder - .read_only_preopened_dir(&tempdir, "/".into()) - .unwrap(); - }) - .await - .unwrap_err(); - let trap = err - .root_cause() // The error returned is a backtrace. We need the root cause. - .downcast_ref::() - .expect("trap error was not an I32Exit"); - assert_eq!(trap.0, 1); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_read_write_preopened_dir() { - let filename = "test_file"; - let tempdir = TempDir::new().unwrap(); - - run_core_wasi_test(["write", filename], |store_builder| { - store_builder - .read_write_preopened_dir(&tempdir, "/".into()) - .unwrap(); - }) - .await - .unwrap(); - - let content = std::fs::read(tempdir.path().join(filename)).unwrap(); - assert_eq!(content, b"content"); -} +use wasmtime_wasi::I32Exit; #[tokio::test(flavor = "multi_thread")] async fn test_max_memory_size_obeyed() { let max = 10_000_000; let alloc = max / 10; - run_core_wasi_test(["alloc", &format!("{alloc}")], |store_builder| { - store_builder.max_memory_size(max); - }) + run_test( + ["alloc", &format!("{alloc}")], + |store_builder| { + store_builder.max_memory_size(max); + }, + |_| {}, + ) .await .unwrap(); } @@ -89,9 +31,13 @@ async fn test_max_memory_size_obeyed() { async fn test_max_memory_size_violated() { let max = 10_000_000; let alloc = max * 2; - let err = run_core_wasi_test(["alloc", &format!("{alloc}")], |store_builder| { - store_builder.max_memory_size(max); - }) + let err = run_test( + ["alloc", &format!("{alloc}")], + |store_builder| { + store_builder.max_memory_size(max); + }, + |_| {}, + ) .await .unwrap_err(); let trap = err @@ -101,14 +47,14 @@ async fn test_max_memory_size_violated() { assert_eq!(trap.0, 1); } +// FIXME: racy timing test #[tokio::test(flavor = "multi_thread")] async fn test_set_deadline_obeyed() { - run_core_wasi_test_engine( - &test_engine(), + run_test( ["sleep", "20"], |_| {}, |store| { - store.set_deadline(Instant::now() + Duration::from_millis(1000)); + store.set_deadline(Instant::now() + Duration::from_millis(10000)); }, ) .await @@ -117,8 +63,7 @@ async fn test_set_deadline_obeyed() { #[tokio::test(flavor = "multi_thread")] async fn test_set_deadline_violated() { - let err = run_core_wasi_test_engine( - &test_engine(), + let err = run_test( ["sleep", "100"], |_| {}, |store| { @@ -131,83 +76,82 @@ async fn test_set_deadline_violated() { assert_eq!(trap, Trap::Interrupt); } -#[tokio::test(flavor = "multi_thread")] -async fn test_host_component() { - let stdout = run_core_wasi_test(["multiply", "5"], |_| {}).await.unwrap(); - assert_eq!(stdout, "10"); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_host_component_data_update() { - let engine = test_engine(); - let multiplier_handle = engine - .find_host_component_handle::() - .unwrap(); - - let stdout = run_core_wasi_test_engine( - &engine, - ["multiply", "5"], - |store_builder| { - store_builder - .host_components_data() - .set(multiplier_handle, Multiplier(100)); - }, - |_| {}, - ) - .await - .unwrap(); - assert_eq!(stdout, "500"); -} - #[tokio::test(flavor = "multi_thread")] #[cfg(not(tarpaulin))] async fn test_panic() { - let err = run_core_wasi_test(["panic"], |_| {}).await.unwrap_err(); + let err = run_test(["panic"], |_| {}, |_| {}).await.unwrap_err(); let trap = err.downcast::().expect("trap"); assert_eq!(trap, Trap::UnreachableCodeReached); } -fn test_config() -> Config { - let mut config = Config::default(); - config - .wasmtime_config() - .wasm_backtrace_details(wasmtime::WasmBacktraceDetails::Enable); - config +#[derive(RuntimeFactors)] +struct TestFactors { + wasi: WasiFactor, +} + +struct TestState { + core: State, + factors: TestFactorsInstanceState, } -fn test_engine() -> Engine<()> { - let mut builder = Engine::builder(&test_config()).unwrap(); - builder.add_host_component(MultiplierHostComponent).unwrap(); - builder - .link_import(|l, _| wasmtime_wasi::add_to_linker_async(l)) - .unwrap(); - builder - .link_import(|l, _| spin_core::wasi_2023_10_18::add_to_linker(l)) - .unwrap(); - builder.build() +impl AsMut for TestState { + fn as_mut(&mut self) -> &mut State { + &mut self.core + } } -async fn run_core_wasi_test<'a>( - args: impl IntoIterator, - f: impl FnOnce(&mut StoreBuilder), -) -> anyhow::Result { - run_core_wasi_test_engine(&test_engine(), args, f, |_| {}).await +impl AsMut for TestState { + fn as_mut(&mut self) -> &mut TestFactorsInstanceState { + &mut self.factors + } } -async fn run_core_wasi_test_engine<'a>( - engine: &Engine<()>, - args: impl IntoIterator, +async fn run_test( + args: impl IntoIterator, update_store_builder: impl FnOnce(&mut StoreBuilder), - update_store: impl FnOnce(&mut Store<()>), -) -> anyhow::Result { - let mut store_builder: StoreBuilder = engine.store_builder(WasiVersion::Preview2); - let stdout_buf = store_builder.stdout_buffered()?; - store_builder.stderr_pipe(TestWriter(tokio::io::stdout())); - store_builder.args(args)?; + update_store: impl FnOnce(&mut Store), +) -> anyhow::Result<()> { + let mut factors = TestFactors { + wasi: WasiFactor::new(DummyFilesMounter), + }; + let mut config = Config::default(); + config + .wasmtime_config() + .wasm_backtrace_details(wasmtime::WasmBacktraceDetails::Enable); + + let mut builder = Engine::builder(&config).unwrap(); + factors.init(builder.linker())?; + let engine = builder.build(); + + let mut store_builder = engine.store_builder(); update_store_builder(&mut store_builder); - let mut store = store_builder.build()?; + let locked: LockedApp = serde_json::from_value(json!({ + "spin_lock_version": 1, + "triggers": [], + "components": [{ + "id": "test-component", + "source": { + "content_type": "application/wasm", + "content": {}, + }, + }] + }))?; + let app = App::new("test-app", locked); + let configured_app = factors.configure_app(app, ())?; + let mut builders = factors.prepare(&configured_app, "test-component")?; + // FIXME: it is unfortunate that we have to unwrap here... + builders.wasi.as_mut().unwrap().args(args); + let instance_state = factors.build_instance_state(builders)?; + let state = TestState { + core: State::default(), + factors: instance_state, + }; + + let mut store = store_builder.build(state)?; + update_store(&mut store); + let module_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("../../target/test-programs/core-wasi-test.wasm"); let component = spin_componentize::componentize_command(&fs::read(module_path).await?)?; @@ -222,48 +166,11 @@ async fn run_core_wasi_test_engine<'a>( .context("missing the expected 'wasi:cli/run@0.2.0' instance")?; instance.typed_func::<(), (Result<(), ()>,)>("run")? }; - update_store(&mut store); func.call_async(&mut store, ()) .await? .0 - .map_err(|()| anyhow::anyhow!("command failed"))?; - - let stdout = String::from_utf8(stdout_buf.contents().to_vec())? - .trim_end() - .into(); - Ok(stdout) -} - -// Simple test HostComponent; multiplies the input by the configured factor -#[derive(Clone)] -struct MultiplierHostComponent; - -mod multiplier { - wasmtime::component::bindgen!("multiplier" in "tests/core-wasi-test/wit"); -} - -impl HostComponent for MultiplierHostComponent { - type Data = Multiplier; - - fn add_to_linker( - linker: &mut spin_core::Linker, - get: impl Fn(&mut spin_core::Data) -> &mut Self::Data + Send + Sync + Copy + 'static, - ) -> anyhow::Result<()> { - multiplier::imports::add_to_linker(linker, get) - } - - fn build_data(&self) -> Self::Data { - Multiplier(2) - } -} - -struct Multiplier(i32); - -impl multiplier::imports::Host for Multiplier { - fn multiply(&mut self, a: i32) -> i32 { - self.0 * a - } + .map_err(|()| anyhow::anyhow!("command failed")) } // Write with `print!`, required for test output capture diff --git a/crates/factor-wasi/Cargo.toml b/crates/factor-wasi/Cargo.toml index 6fb2dfc8e..3995da46f 100644 --- a/crates/factor-wasi/Cargo.toml +++ b/crates/factor-wasi/Cargo.toml @@ -7,6 +7,7 @@ edition = { workspace = true } [dependencies] async-trait = "0.1" cap-primitives = "3.0.0" +spin-app = { path = "../app" } spin-factors = { path = "../factors" } tokio = { version = "1" } wasmtime = { workspace = true } diff --git a/crates/factor-wasi/src/lib.rs b/crates/factor-wasi/src/lib.rs index 62f98c146..983b18dea 100644 --- a/crates/factor-wasi/src/lib.rs +++ b/crates/factor-wasi/src/lib.rs @@ -3,9 +3,10 @@ mod wasi_2023_11_10; use std::{future::Future, net::SocketAddr, path::Path}; +use spin_app::AppComponent; use spin_factors::{ - anyhow, AppComponent, Factor, FactorInstanceBuilder, InitContext, InstanceBuilders, - PrepareContext, RuntimeFactors, RuntimeFactorsInstanceState, + anyhow, Factor, FactorInstanceBuilder, InitContext, InstanceBuilders, PrepareContext, + RuntimeFactors, RuntimeFactorsInstanceState, }; use tokio::io::{AsyncRead, AsyncWrite}; use wasmtime_wasi::{ @@ -43,10 +44,7 @@ impl Factor for WasiFactor { type AppState = (); type InstanceBuilder = InstanceBuilder; - fn init( - &mut self, - mut ctx: InitContext, - ) -> anyhow::Result<()> { + fn init(&mut self, mut ctx: InitContext) -> anyhow::Result<()> { fn type_annotate(f: F) -> F where F: Fn(&mut T) -> WasiImpl, diff --git a/crates/factors-test/src/lib.rs b/crates/factors-test/src/lib.rs index 103671dfe..7e9c78232 100644 --- a/crates/factors-test/src/lib.rs +++ b/crates/factors-test/src/lib.rs @@ -58,13 +58,13 @@ impl TestEnvironment { mut factors: T, ) -> anyhow::Result { let mut linker = Self::new_linker::(); - factors.init::(&mut linker)?; + factors.init(&mut linker)?; let locked_app = self .build_locked_app() .await .context("failed to build locked app")?; - let app = App::inert(locked_app); + let app = App::new("test-app", locked_app); let runtime_config = TomlRuntimeConfig(&self.runtime_config); let configured_app = factors.configure_app(app, runtime_config)?; diff --git a/crates/factors/src/lib.rs b/crates/factors/src/lib.rs index 569b76e9b..074468809 100644 --- a/crates/factors/src/lib.rs +++ b/crates/factors/src/lib.rs @@ -7,6 +7,7 @@ pub use anyhow; pub use serde; pub use wasmtime; +pub use spin_app::App; pub use spin_factors_derive::RuntimeFactors; pub use crate::{ @@ -17,9 +18,6 @@ pub use crate::{ }; // Temporary wrappers while refactoring -pub type App = spin_app::App<'static, spin_app::InertLoader>; -pub type AppComponent<'a> = spin_app::AppComponent<'a, spin_app::InertLoader>; - pub type Result = std::result::Result; #[derive(Debug, thiserror::Error)] diff --git a/crates/factors/src/prepare.rs b/crates/factors/src/prepare.rs index 1c66d7568..318bb15b0 100644 --- a/crates/factors/src/prepare.rs +++ b/crates/factors/src/prepare.rs @@ -1,6 +1,8 @@ use std::any::Any; -use crate::{AppComponent, Error, Factor, RuntimeFactors}; +use spin_app::AppComponent; + +use crate::{Error, Factor, RuntimeFactors}; /// A builder for a [`Factor`]'s per instance state. pub trait FactorInstanceBuilder: Any { diff --git a/crates/factors/tests/smoke.rs b/crates/factors/tests/smoke.rs index 7ec8cc059..0a4cbde32 100644 --- a/crates/factors/tests/smoke.rs +++ b/crates/factors/tests/smoke.rs @@ -69,7 +69,7 @@ async fn smoke_test_works() -> anyhow::Result<()> { let engine = wasmtime::Engine::new(wasmtime::Config::new().async_support(true))?; let mut linker = wasmtime::component::Linker::new(&engine); - factors.init::(&mut linker).unwrap(); + factors.init(&mut linker).unwrap(); let configured_app = factors.configure_app(app, TestSource)?; let builders = factors.prepare(&configured_app, "smoke-app")?; From 3b66505be3c1e21eb57e0a4333b90ef84d41e8ce Mon Sep 17 00:00:00 2001 From: Lann Martin Date: Fri, 19 Jul 2024 09:35:40 -0400 Subject: [PATCH 2/3] Resolve PR feedback Signed-off-by: Lann Martin --- Cargo.lock | 1 - crates/factor-wasi/Cargo.toml | 1 - crates/factor-wasi/src/lib.rs | 5 ++--- crates/factors/src/lib.rs | 4 ++-- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4fbcc3c94..dd8ec4bd0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7663,7 +7663,6 @@ version = "2.7.0-pre0" dependencies = [ "async-trait", "cap-primitives 3.0.0", - "spin-app", "spin-factors", "spin-factors-test", "tokio", diff --git a/crates/factor-wasi/Cargo.toml b/crates/factor-wasi/Cargo.toml index 3995da46f..6fb2dfc8e 100644 --- a/crates/factor-wasi/Cargo.toml +++ b/crates/factor-wasi/Cargo.toml @@ -7,7 +7,6 @@ edition = { workspace = true } [dependencies] async-trait = "0.1" cap-primitives = "3.0.0" -spin-app = { path = "../app" } spin-factors = { path = "../factors" } tokio = { version = "1" } wasmtime = { workspace = true } diff --git a/crates/factor-wasi/src/lib.rs b/crates/factor-wasi/src/lib.rs index 983b18dea..82fdd802b 100644 --- a/crates/factor-wasi/src/lib.rs +++ b/crates/factor-wasi/src/lib.rs @@ -3,10 +3,9 @@ mod wasi_2023_11_10; use std::{future::Future, net::SocketAddr, path::Path}; -use spin_app::AppComponent; use spin_factors::{ - anyhow, Factor, FactorInstanceBuilder, InitContext, InstanceBuilders, PrepareContext, - RuntimeFactors, RuntimeFactorsInstanceState, + anyhow, AppComponent, Factor, FactorInstanceBuilder, InitContext, InstanceBuilders, + PrepareContext, RuntimeFactors, RuntimeFactorsInstanceState, }; use tokio::io::{AsyncRead, AsyncWrite}; use wasmtime_wasi::{ diff --git a/crates/factors/src/lib.rs b/crates/factors/src/lib.rs index 074468809..69f5c20b8 100644 --- a/crates/factors/src/lib.rs +++ b/crates/factors/src/lib.rs @@ -7,7 +7,7 @@ pub use anyhow; pub use serde; pub use wasmtime; -pub use spin_app::App; +pub use spin_app::{App, AppComponent}; pub use spin_factors_derive::RuntimeFactors; pub use crate::{ @@ -17,7 +17,7 @@ pub use crate::{ runtime_factors::{RuntimeFactors, RuntimeFactorsInstanceState}, }; -// Temporary wrappers while refactoring +/// Result wrapper type defaulting to use [`Error`]. pub type Result = std::result::Result; #[derive(Debug, thiserror::Error)] From e2334e7dc5513a90a996a023938b9bc0fc26e676 Mon Sep 17 00:00:00 2001 From: Lann Martin Date: Fri, 19 Jul 2024 09:45:16 -0400 Subject: [PATCH 3/3] Remove ouroboros Signed-off-by: Lann Martin --- Cargo.lock | 51 ------------------- crates/locked-app/Cargo.toml | 1 - examples/spin-timer/Cargo.lock | 93 +--------------------------------- supply-chain/config.toml | 8 --- 4 files changed, 1 insertion(+), 152 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dd8ec4bd0..aa48f93f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -64,12 +64,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "aliasable" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" - [[package]] name = "allocator-api2" version = "0.2.16" @@ -5298,31 +5292,6 @@ version = "6.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" -[[package]] -name = "ouroboros" -version = "0.18.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b7be5a8a3462b752f4be3ff2b2bf2f7f1d00834902e46be2a4d68b87b0573c" -dependencies = [ - "aliasable", - "ouroboros_macro", - "static_assertions", -] - -[[package]] -name = "ouroboros_macro" -version = "0.18.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b645dcde5f119c2c454a92d0dfa271a2a3b205da92e4292a68ead4bdbfde1f33" -dependencies = [ - "heck 0.4.1", - "itertools 0.12.1", - "proc-macro2", - "proc-macro2-diagnostics", - "quote", - "syn 2.0.58", -] - [[package]] name = "outbound-http" version = "2.7.0-pre0" @@ -5930,19 +5899,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "proc-macro2-diagnostics" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", - "version_check", - "yansi", -] - [[package]] name = "proc-quote" version = "0.4.0" @@ -7896,7 +7852,6 @@ version = "2.7.0-pre0" dependencies = [ "anyhow", "async-trait", - "ouroboros", "serde 1.0.197", "serde_json", "spin-serde", @@ -10896,12 +10851,6 @@ dependencies = [ "linked-hash-map", ] -[[package]] -name = "yansi" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" - [[package]] name = "zbus" version = "3.15.2" diff --git a/crates/locked-app/Cargo.toml b/crates/locked-app/Cargo.toml index 44b25fee5..d0531c52a 100644 --- a/crates/locked-app/Cargo.toml +++ b/crates/locked-app/Cargo.toml @@ -7,7 +7,6 @@ edition = { workspace = true } [dependencies] anyhow = "1.0" async-trait = "0.1" -ouroboros = "0.18.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" spin-serde = { path = "../serde" } diff --git a/examples/spin-timer/Cargo.lock b/examples/spin-timer/Cargo.lock index e78d13851..e26adced5 100644 --- a/examples/spin-timer/Cargo.lock +++ b/examples/spin-timer/Cargo.lock @@ -58,12 +58,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "aliasable" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" - [[package]] name = "allocator-api2" version = "0.2.16" @@ -3953,31 +3947,6 @@ version = "6.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" -[[package]] -name = "ouroboros" -version = "0.18.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b7be5a8a3462b752f4be3ff2b2bf2f7f1d00834902e46be2a4d68b87b0573c" -dependencies = [ - "aliasable", - "ouroboros_macro", - "static_assertions", -] - -[[package]] -name = "ouroboros_macro" -version = "0.18.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b645dcde5f119c2c454a92d0dfa271a2a3b205da92e4292a68ead4bdbfde1f33" -dependencies = [ - "heck 0.4.1", - "itertools 0.12.1", - "proc-macro2", - "proc-macro2-diagnostics", - "quote", - "syn 2.0.48", -] - [[package]] name = "outbound-http" version = "2.7.0-pre0" @@ -4500,19 +4469,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "proc-macro2-diagnostics" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", - "version_check", - "yansi", -] - [[package]] name = "prost" version = "0.12.6" @@ -5674,10 +5630,8 @@ version = "2.7.0-pre0" dependencies = [ "anyhow", "async-trait", - "ouroboros", "serde 1.0.203", "serde_json", - "spin-core", "spin-locked-app", "spin-serde", "thiserror", @@ -5714,21 +5668,9 @@ version = "2.7.0-pre0" dependencies = [ "anyhow", "async-trait", - "bytes", - "cap-primitives", - "cap-std", "crossbeam-channel", - "http 1.1.0", - "io-extras", - "rustix 0.37.27", - "spin-telemetry", - "system-interface", - "tokio", "tracing", - "wasi-common", "wasmtime", - "wasmtime-wasi", - "wasmtime-wasi-http", ] [[package]] @@ -5875,7 +5817,6 @@ version = "2.7.0-pre0" dependencies = [ "anyhow", "async-trait", - "ouroboros", "serde 1.0.203", "serde_json", "spin-serde", @@ -6063,6 +6004,7 @@ dependencies = [ name = "spin-world" version = "2.7.0-pre0" dependencies = [ + "async-trait", "wasmtime", ] @@ -7163,33 +7105,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasi-common" -version = "22.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b86fd41e1e26ff6af9451c6a332a5ce5f5283ca51e87d875cdd9a05305598ee3" -dependencies = [ - "anyhow", - "bitflags 2.4.2", - "cap-fs-ext", - "cap-rand", - "cap-std", - "cap-time-ext", - "fs-set-times", - "io-extras", - "io-lifetimes 2.0.3", - "log", - "once_cell", - "rustix 0.38.31", - "system-interface", - "thiserror", - "tokio", - "tracing", - "wasmtime", - "wiggle", - "windows-sys 0.52.0", -] - [[package]] name = "wasite" version = "0.1.0" @@ -8249,12 +8164,6 @@ dependencies = [ "linked-hash-map", ] -[[package]] -name = "yansi" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" - [[package]] name = "zbus" version = "3.15.2" diff --git a/supply-chain/config.toml b/supply-chain/config.toml index 142f4441c..27eaaba2c 100644 --- a/supply-chain/config.toml +++ b/supply-chain/config.toml @@ -1104,14 +1104,6 @@ criteria = "safe-to-deploy" version = "6.3.0" criteria = "safe-to-deploy" -[[exemptions.ouroboros]] -version = "0.15.6" -criteria = "safe-to-deploy" - -[[exemptions.ouroboros_macro]] -version = "0.15.6" -criteria = "safe-to-deploy" - [[exemptions.overload]] version = "0.1.1" criteria = "safe-to-deploy"