diff --git a/crates/factor-key-value/src/lib.rs b/crates/factor-key-value/src/lib.rs index f893263af9..0cc97281c3 100644 --- a/crates/factor-key-value/src/lib.rs +++ b/crates/factor-key-value/src/lib.rs @@ -38,7 +38,7 @@ impl Factor for KeyValueFactor { type AppState = AppState; type InstanceBuilder = InstanceBuilder; - fn init(&mut self, mut ctx: InitContext) -> anyhow::Result<()> { + fn init(&mut self, ctx: &mut impl InitContext) -> anyhow::Result<()> { ctx.link_bindings(spin_world::v1::key_value::add_to_linker)?; ctx.link_bindings(spin_world::v2::key_value::add_to_linker)?; ctx.link_bindings(spin_world::wasi::keyvalue::store::add_to_linker)?; diff --git a/crates/factor-llm/src/lib.rs b/crates/factor-llm/src/lib.rs index 6491d9afcd..c0442c5de1 100644 --- a/crates/factor-llm/src/lib.rs +++ b/crates/factor-llm/src/lib.rs @@ -36,10 +36,7 @@ impl Factor for LlmFactor { type AppState = AppState; type InstanceBuilder = InstanceState; - fn init( - &mut self, - mut ctx: spin_factors::InitContext, - ) -> anyhow::Result<()> { + fn init(&mut self, ctx: &mut impl spin_factors::InitContext) -> anyhow::Result<()> { ctx.link_bindings(spin_world::v1::llm::add_to_linker)?; ctx.link_bindings(spin_world::v2::llm::add_to_linker)?; Ok(()) diff --git a/crates/factor-outbound-http/src/lib.rs b/crates/factor-outbound-http/src/lib.rs index cfcb167d5e..ed3e778feb 100644 --- a/crates/factor-outbound-http/src/lib.rs +++ b/crates/factor-outbound-http/src/lib.rs @@ -52,12 +52,9 @@ impl Factor for OutboundHttpFactor { type AppState = (); type InstanceBuilder = InstanceState; - fn init( - &mut self, - mut ctx: spin_factors::InitContext, - ) -> anyhow::Result<()> { + fn init(&mut self, ctx: &mut impl spin_factors::InitContext) -> anyhow::Result<()> { ctx.link_bindings(spin_world::v1::http::add_to_linker)?; - wasi::add_to_linker::(&mut ctx)?; + wasi::add_to_linker(ctx)?; Ok(()) } diff --git a/crates/factor-outbound-http/src/wasi.rs b/crates/factor-outbound-http/src/wasi.rs index 1376f07965..27c4097a16 100644 --- a/crates/factor-outbound-http/src/wasi.rs +++ b/crates/factor-outbound-http/src/wasi.rs @@ -23,26 +23,24 @@ use crate::{ wasi_2023_10_18, wasi_2023_11_10, InstanceState, OutboundHttpFactor, SelfRequestOrigin, }; -pub(crate) fn add_to_linker( - ctx: &mut spin_factors::InitContext, -) -> anyhow::Result<()> { - fn type_annotate(f: F) -> F +pub(crate) fn add_to_linker(ctx: &mut C) -> anyhow::Result<()> +where + C: spin_factors::InitContext, +{ + fn get_http(store: &mut C::StoreData) -> WasiHttpImpl> where - F: Fn(&mut T) -> WasiHttpImpl, + C: spin_factors::InitContext, { - f - } - let get_data_with_table = ctx.get_data_with_table_fn(); - let closure = type_annotate(move |data| { - let (state, table) = get_data_with_table(data); + let (state, table) = C::get_data_with_table(store); WasiHttpImpl(IoImpl(WasiHttpImplInner { state, table })) - }); + } + let get_http = get_http:: as fn(&mut C::StoreData) -> WasiHttpImpl>; let linker = ctx.linker(); - wasmtime_wasi_http::bindings::http::outgoing_handler::add_to_linker_get_host(linker, closure)?; - wasmtime_wasi_http::bindings::http::types::add_to_linker_get_host(linker, closure)?; + wasmtime_wasi_http::bindings::http::outgoing_handler::add_to_linker_get_host(linker, get_http)?; + wasmtime_wasi_http::bindings::http::types::add_to_linker_get_host(linker, get_http)?; - wasi_2023_10_18::add_to_linker(linker, closure)?; - wasi_2023_11_10::add_to_linker(linker, closure)?; + wasi_2023_10_18::add_to_linker(linker, get_http)?; + wasi_2023_11_10::add_to_linker(linker, get_http)?; Ok(()) } diff --git a/crates/factor-outbound-http/src/wasi_2023_10_18.rs b/crates/factor-outbound-http/src/wasi_2023_10_18.rs index 2f2790b766..d25ad432dd 100644 --- a/crates/factor-outbound-http/src/wasi_2023_10_18.rs +++ b/crates/factor-outbound-http/src/wasi_2023_10_18.rs @@ -54,10 +54,12 @@ use wasi::io::streams::{InputStream, OutputStream}; use crate::wasi::WasiHttpImplInner; -pub(crate) fn add_to_linker(linker: &mut Linker, closure: F) -> Result<()> +pub(crate) fn add_to_linker( + linker: &mut Linker, + closure: fn(&mut T) -> WasiHttpImpl>, +) -> Result<()> where - T: Send, - F: Fn(&mut T) -> WasiHttpImpl + Send + Sync + Copy + 'static, + T: Send + 'static, { wasi::http::types::add_to_linker_get_host(linker, closure)?; wasi::http::outgoing_handler::add_to_linker_get_host(linker, closure)?; diff --git a/crates/factor-outbound-http/src/wasi_2023_11_10.rs b/crates/factor-outbound-http/src/wasi_2023_11_10.rs index 3767163e02..ac964f1433 100644 --- a/crates/factor-outbound-http/src/wasi_2023_11_10.rs +++ b/crates/factor-outbound-http/src/wasi_2023_11_10.rs @@ -59,10 +59,12 @@ use wasi::io::streams::{Error as IoError, InputStream, OutputStream}; use crate::wasi::WasiHttpImplInner; -pub(crate) fn add_to_linker(linker: &mut Linker, closure: F) -> Result<()> +pub(crate) fn add_to_linker( + linker: &mut Linker, + closure: fn(&mut T) -> WasiHttpImpl>, +) -> Result<()> where - T: Send, - F: Fn(&mut T) -> WasiHttpImpl + Send + Sync + Copy + 'static, + T: Send + 'static, { wasi::http::types::add_to_linker_get_host(linker, closure)?; wasi::http::outgoing_handler::add_to_linker_get_host(linker, closure)?; diff --git a/crates/factor-outbound-mqtt/src/lib.rs b/crates/factor-outbound-mqtt/src/lib.rs index 79c5138e5c..3811348707 100644 --- a/crates/factor-outbound-mqtt/src/lib.rs +++ b/crates/factor-outbound-mqtt/src/lib.rs @@ -31,10 +31,7 @@ impl Factor for OutboundMqttFactor { type AppState = (); type InstanceBuilder = InstanceState; - fn init( - &mut self, - mut ctx: spin_factors::InitContext, - ) -> anyhow::Result<()> { + fn init(&mut self, ctx: &mut impl spin_factors::InitContext) -> anyhow::Result<()> { ctx.link_bindings(spin_world::v2::mqtt::add_to_linker)?; Ok(()) } diff --git a/crates/factor-outbound-mysql/src/lib.rs b/crates/factor-outbound-mysql/src/lib.rs index e666fff56c..80ac3d4d77 100644 --- a/crates/factor-outbound-mysql/src/lib.rs +++ b/crates/factor-outbound-mysql/src/lib.rs @@ -17,7 +17,7 @@ impl Factor for OutboundMysqlFactor { type AppState = (); type InstanceBuilder = InstanceState; - fn init(&mut self, mut ctx: InitContext) -> anyhow::Result<()> { + fn init(&mut self, ctx: &mut impl InitContext) -> anyhow::Result<()> { ctx.link_bindings(v1::add_to_linker)?; ctx.link_bindings(v2::add_to_linker)?; Ok(()) diff --git a/crates/factor-outbound-pg/src/lib.rs b/crates/factor-outbound-pg/src/lib.rs index 4ca3663531..b4e38829d1 100644 --- a/crates/factor-outbound-pg/src/lib.rs +++ b/crates/factor-outbound-pg/src/lib.rs @@ -17,10 +17,7 @@ impl Factor for OutboundPgFactor { type AppState = (); type InstanceBuilder = InstanceState; - fn init( - &mut self, - mut ctx: spin_factors::InitContext, - ) -> anyhow::Result<()> { + fn init(&mut self, ctx: &mut impl spin_factors::InitContext) -> anyhow::Result<()> { ctx.link_bindings(spin_world::v1::postgres::add_to_linker)?; ctx.link_bindings(spin_world::v2::postgres::add_to_linker)?; ctx.link_bindings(spin_world::spin::postgres::postgres::add_to_linker)?; diff --git a/crates/factor-outbound-redis/src/lib.rs b/crates/factor-outbound-redis/src/lib.rs index a818713334..b98c633b7d 100644 --- a/crates/factor-outbound-redis/src/lib.rs +++ b/crates/factor-outbound-redis/src/lib.rs @@ -23,10 +23,7 @@ impl Factor for OutboundRedisFactor { type AppState = (); type InstanceBuilder = InstanceState; - fn init( - &mut self, - mut ctx: spin_factors::InitContext, - ) -> anyhow::Result<()> { + fn init(&mut self, ctx: &mut impl spin_factors::InitContext) -> anyhow::Result<()> { ctx.link_bindings(spin_world::v1::redis::add_to_linker)?; ctx.link_bindings(spin_world::v2::redis::add_to_linker)?; Ok(()) diff --git a/crates/factor-sqlite/src/lib.rs b/crates/factor-sqlite/src/lib.rs index ca3240d607..2f62917e71 100644 --- a/crates/factor-sqlite/src/lib.rs +++ b/crates/factor-sqlite/src/lib.rs @@ -32,10 +32,7 @@ impl Factor for SqliteFactor { type AppState = AppState; type InstanceBuilder = InstanceState; - fn init( - &mut self, - mut ctx: spin_factors::InitContext, - ) -> anyhow::Result<()> { + fn init(&mut self, ctx: &mut impl spin_factors::InitContext) -> anyhow::Result<()> { ctx.link_bindings(v1::add_to_linker)?; ctx.link_bindings(v2::add_to_linker)?; ctx.link_bindings(v3::add_to_linker)?; diff --git a/crates/factor-variables/src/lib.rs b/crates/factor-variables/src/lib.rs index 0983696094..98f881b146 100644 --- a/crates/factor-variables/src/lib.rs +++ b/crates/factor-variables/src/lib.rs @@ -28,7 +28,7 @@ impl Factor for VariablesFactor { type AppState = AppState; type InstanceBuilder = InstanceState; - fn init(&mut self, mut ctx: InitContext) -> anyhow::Result<()> { + fn init(&mut self, ctx: &mut impl InitContext) -> anyhow::Result<()> { ctx.link_bindings(spin_world::v1::config::add_to_linker)?; ctx.link_bindings(spin_world::v2::variables::add_to_linker)?; ctx.link_bindings(spin_world::wasi::config::store::add_to_linker)?; diff --git a/crates/factor-wasi/src/lib.rs b/crates/factor-wasi/src/lib.rs index 0c57a0528a..cd867f55bf 100644 --- a/crates/factor-wasi/src/lib.rs +++ b/crates/factor-wasi/src/lib.rs @@ -44,70 +44,98 @@ impl WasiFactor { } } +/// Helper trait to extend `InitContext` with some more `link_*_bindings` +/// methods related to `wasmtime-wasi` and `wasmtime-wasi-io`-specific +/// signatures. +#[allow(clippy::type_complexity, reason = "sorry, blame alex")] +trait InitContextExt: InitContext { + fn get_io(data: &mut Self::StoreData) -> IoImpl> { + let (state, table) = Self::get_data_with_table(data); + IoImpl(WasiImplInner { + ctx: &mut state.ctx, + table, + }) + } + + fn link_io_bindings( + &mut self, + add_to_linker: fn( + &mut wasmtime::component::Linker, + fn(&mut Self::StoreData) -> IoImpl>, + ) -> anyhow::Result<()>, + ) -> anyhow::Result<()> { + add_to_linker(self.linker(), Self::get_io) + } + + fn get_wasi(data: &mut Self::StoreData) -> WasiImpl> { + WasiImpl(Self::get_io(data)) + } + + fn link_wasi_bindings( + &mut self, + add_to_linker: fn( + &mut wasmtime::component::Linker, + fn(&mut Self::StoreData) -> WasiImpl>, + ) -> anyhow::Result<()>, + ) -> anyhow::Result<()> { + add_to_linker(self.linker(), Self::get_wasi) + } + + fn link_wasi_default_bindings( + &mut self, + add_to_linker: fn( + &mut wasmtime::component::Linker, + &O, + fn(&mut Self::StoreData) -> WasiImpl>, + ) -> anyhow::Result<()>, + ) -> anyhow::Result<()> + where + O: Default, + { + add_to_linker(self.linker(), &O::default(), Self::get_wasi) + } +} + +impl InitContextExt for T where T: InitContext {} + impl Factor for WasiFactor { type RuntimeConfig = (); type AppState = (); type InstanceBuilder = InstanceBuilder; - fn init(&mut self, mut ctx: InitContext) -> anyhow::Result<()> { - fn type_annotate_wasi(f: F) -> F - where - F: Fn(&mut T) -> WasiImpl, - { - f - } - fn type_annotate_io(f: F) -> F - where - F: Fn(&mut T) -> IoImpl, - { - f - } - let get_data_with_table = ctx.get_data_with_table_fn(); - let io_closure = type_annotate_io(move |data| { - let (state, table) = get_data_with_table(data); - IoImpl(WasiImplInner { - ctx: &mut state.ctx, - table, - }) - }); - let wasi_closure = type_annotate_wasi(move |data| WasiImpl(io_closure(data))); - let linker = ctx.linker(); + fn init(&mut self, ctx: &mut impl InitContext) -> anyhow::Result<()> { use wasmtime_wasi::bindings; - bindings::clocks::wall_clock::add_to_linker_get_host(linker, wasi_closure)?; - bindings::clocks::monotonic_clock::add_to_linker_get_host(linker, wasi_closure)?; - bindings::filesystem::types::add_to_linker_get_host(linker, wasi_closure)?; - bindings::filesystem::preopens::add_to_linker_get_host(linker, wasi_closure)?; - bindings::io::error::add_to_linker_get_host(linker, io_closure)?; - bindings::io::poll::add_to_linker_get_host(linker, io_closure)?; - bindings::io::streams::add_to_linker_get_host(linker, io_closure)?; - bindings::random::random::add_to_linker_get_host(linker, wasi_closure)?; - bindings::random::insecure::add_to_linker_get_host(linker, wasi_closure)?; - bindings::random::insecure_seed::add_to_linker_get_host(linker, wasi_closure)?; - bindings::cli::exit::add_to_linker_get_host(linker, &Default::default(), wasi_closure)?; - bindings::cli::environment::add_to_linker_get_host(linker, wasi_closure)?; - bindings::cli::stdin::add_to_linker_get_host(linker, wasi_closure)?; - bindings::cli::stdout::add_to_linker_get_host(linker, wasi_closure)?; - bindings::cli::stderr::add_to_linker_get_host(linker, wasi_closure)?; - bindings::cli::terminal_input::add_to_linker_get_host(linker, wasi_closure)?; - bindings::cli::terminal_output::add_to_linker_get_host(linker, wasi_closure)?; - bindings::cli::terminal_stdin::add_to_linker_get_host(linker, wasi_closure)?; - bindings::cli::terminal_stdout::add_to_linker_get_host(linker, wasi_closure)?; - bindings::cli::terminal_stderr::add_to_linker_get_host(linker, wasi_closure)?; - bindings::sockets::tcp::add_to_linker_get_host(linker, wasi_closure)?; - bindings::sockets::tcp_create_socket::add_to_linker_get_host(linker, wasi_closure)?; - bindings::sockets::udp::add_to_linker_get_host(linker, wasi_closure)?; - bindings::sockets::udp_create_socket::add_to_linker_get_host(linker, wasi_closure)?; - bindings::sockets::instance_network::add_to_linker_get_host(linker, wasi_closure)?; - bindings::sockets::network::add_to_linker_get_host( - linker, - &Default::default(), - wasi_closure, - )?; - bindings::sockets::ip_name_lookup::add_to_linker_get_host(linker, wasi_closure)?; - - wasi_2023_10_18::add_to_linker(linker, wasi_closure)?; - wasi_2023_11_10::add_to_linker(linker, wasi_closure)?; + ctx.link_wasi_bindings(bindings::clocks::wall_clock::add_to_linker_get_host)?; + ctx.link_wasi_bindings(bindings::clocks::monotonic_clock::add_to_linker_get_host)?; + ctx.link_wasi_bindings(bindings::filesystem::types::add_to_linker_get_host)?; + ctx.link_wasi_bindings(bindings::filesystem::preopens::add_to_linker_get_host)?; + ctx.link_io_bindings(bindings::io::error::add_to_linker_get_host)?; + ctx.link_io_bindings(bindings::io::poll::add_to_linker_get_host)?; + ctx.link_io_bindings(bindings::io::streams::add_to_linker_get_host)?; + ctx.link_wasi_bindings(bindings::random::random::add_to_linker_get_host)?; + ctx.link_wasi_bindings(bindings::random::insecure::add_to_linker_get_host)?; + ctx.link_wasi_bindings(bindings::random::insecure_seed::add_to_linker_get_host)?; + ctx.link_wasi_default_bindings(bindings::cli::exit::add_to_linker_get_host)?; + ctx.link_wasi_bindings(bindings::cli::environment::add_to_linker_get_host)?; + ctx.link_wasi_bindings(bindings::cli::stdin::add_to_linker_get_host)?; + ctx.link_wasi_bindings(bindings::cli::stdout::add_to_linker_get_host)?; + ctx.link_wasi_bindings(bindings::cli::stderr::add_to_linker_get_host)?; + ctx.link_wasi_bindings(bindings::cli::terminal_input::add_to_linker_get_host)?; + ctx.link_wasi_bindings(bindings::cli::terminal_output::add_to_linker_get_host)?; + ctx.link_wasi_bindings(bindings::cli::terminal_stdin::add_to_linker_get_host)?; + ctx.link_wasi_bindings(bindings::cli::terminal_stdout::add_to_linker_get_host)?; + ctx.link_wasi_bindings(bindings::cli::terminal_stderr::add_to_linker_get_host)?; + ctx.link_wasi_bindings(bindings::sockets::tcp::add_to_linker_get_host)?; + ctx.link_wasi_bindings(bindings::sockets::tcp_create_socket::add_to_linker_get_host)?; + ctx.link_wasi_bindings(bindings::sockets::udp::add_to_linker_get_host)?; + ctx.link_wasi_bindings(bindings::sockets::udp_create_socket::add_to_linker_get_host)?; + ctx.link_wasi_bindings(bindings::sockets::instance_network::add_to_linker_get_host)?; + ctx.link_wasi_default_bindings(bindings::sockets::network::add_to_linker_get_host)?; + ctx.link_wasi_bindings(bindings::sockets::ip_name_lookup::add_to_linker_get_host)?; + + ctx.link_wasi_bindings(wasi_2023_10_18::add_to_linker)?; + ctx.link_wasi_bindings(wasi_2023_11_10::add_to_linker)?; Ok(()) } diff --git a/crates/factor-wasi/src/wasi_2023_10_18.rs b/crates/factor-wasi/src/wasi_2023_10_18.rs index e03baa3e87..f5ca3b67d4 100644 --- a/crates/factor-wasi/src/wasi_2023_10_18.rs +++ b/crates/factor-wasi/src/wasi_2023_10_18.rs @@ -118,10 +118,12 @@ use wasi::sockets::udp::Datagram; use crate::WasiImplInner; -pub fn add_to_linker(linker: &mut Linker, closure: F) -> Result<()> +pub fn add_to_linker( + linker: &mut Linker, + closure: fn(&mut T) -> WasiImpl>, +) -> Result<()> where - T: Send, - F: Fn(&mut T) -> WasiImpl + Send + Sync + Copy + 'static, + T: Send + 'static, { wasi::clocks::monotonic_clock::add_to_linker_get_host(linker, closure)?; wasi::clocks::wall_clock::add_to_linker_get_host(linker, closure)?; diff --git a/crates/factor-wasi/src/wasi_2023_11_10.rs b/crates/factor-wasi/src/wasi_2023_11_10.rs index e8a7db8bd4..2430f57245 100644 --- a/crates/factor-wasi/src/wasi_2023_11_10.rs +++ b/crates/factor-wasi/src/wasi_2023_11_10.rs @@ -111,10 +111,12 @@ use wasi::sockets::udp::{ use crate::WasiImplInner; -pub fn add_to_linker(linker: &mut Linker, closure: F) -> Result<()> +pub fn add_to_linker( + linker: &mut Linker, + closure: fn(&mut T) -> WasiImpl>, +) -> Result<()> where - T: Send, - F: Fn(&mut T) -> WasiImpl + Send + Sync + Copy + 'static, + T: Send + 'static, { wasi::clocks::monotonic_clock::add_to_linker_get_host(linker, closure)?; wasi::clocks::wall_clock::add_to_linker_get_host(linker, closure)?; diff --git a/crates/factors-derive/src/lib.rs b/crates/factors-derive/src/lib.rs index 8f6649d021..8002fe5642 100644 --- a/crates/factors-derive/src/lib.rs +++ b/crates/factors-derive/src/lib.rs @@ -94,16 +94,27 @@ fn expand_factors(input: &DeriveInput) -> syn::Result { } #( - #Factor::init::( + #[allow(non_camel_case_types)] + struct #factor_names; + + impl #factors_path::FactorField for #factor_names { + type State = #state_name; + type Factor = #factor_types; + + fn get(state: &mut #state_name) -> ( + &mut #factors_path::FactorInstanceState<#factor_types>, + &mut #wasmtime::component::ResourceTable, + ) { + (&mut state.#factor_names, &mut state.__table) + } + } + + #Factor::init( &mut self.#factor_names, - #factors_path::InitContext::::new( + &mut #factors_path::FactorInitContext::<'_, T, #factor_names> { linker, - |data| &mut data.as_instance_state().#factor_names, - |data| { - let state = data.as_instance_state(); - (&mut state.#factor_names, &mut state.__table) - }, - ) + _marker: std::marker::PhantomData, + }, ).map_err(#Error::factor_init_error::<#factor_types>)?; )* Ok(()) diff --git a/crates/factors/src/factor.rs b/crates/factors/src/factor.rs index 412ca86de8..a82babf3db 100644 --- a/crates/factors/src/factor.rs +++ b/crates/factors/src/factor.rs @@ -1,8 +1,11 @@ use std::any::Any; +use std::marker::PhantomData; use wasmtime::component::{Linker, ResourceTable}; -use crate::{prepare::FactorInstanceBuilder, App, Error, PrepareContext, RuntimeFactors}; +use crate::{ + prepare::FactorInstanceBuilder, App, AsInstanceState, Error, PrepareContext, RuntimeFactors, +}; /// A contained (i.e., "factored") piece of runtime functionality. pub trait Factor: Any + Sized { @@ -25,11 +28,8 @@ pub trait Factor: Any + Sized { /// This will be called at most once, before any call to /// [`Factor::prepare`]. `InitContext` provides access to a wasmtime /// `Linker`, so this is where any bindgen `add_to_linker` calls go. - /// - /// The type parameter `T` here is the same as the [`wasmtime::Store`] type - /// parameter `T`, which will contain the [`RuntimeFactors::InstanceState`]. - fn init(&mut self, mut ctx: InitContext) -> anyhow::Result<()> { - _ = &mut ctx; + fn init(&mut self, ctx: &mut impl InitContext) -> anyhow::Result<()> { + let _ = ctx; Ok(()) } @@ -70,58 +70,70 @@ pub trait Factor: Any + Sized { pub type FactorInstanceState = <::InstanceBuilder as FactorInstanceBuilder>::InstanceState; -pub(crate) type GetDataFn = fn(&mut T) -> &mut FactorInstanceState; - -pub(crate) type GetDataWithTableFn = - fn(&mut T) -> (&mut FactorInstanceState, &mut ResourceTable); - /// An InitContext is passed to [`Factor::init`], giving access to the global /// common [`wasmtime::component::Linker`]. -pub struct InitContext<'a, T, U: Factor> { - pub(crate) linker: &'a mut Linker, - pub(crate) get_data: GetDataFn, - pub(crate) get_data_with_table: GetDataWithTableFn, -} - -impl<'a, T, U: Factor> InitContext<'a, T, U> { - #[doc(hidden)] - pub fn new( - linker: &'a mut Linker, - get_data: GetDataFn, - get_data_with_table: GetDataWithTableFn, - ) -> Self { - Self { - linker, - get_data, - get_data_with_table, - } - } +pub trait InitContext { + /// The `T` in `Store`. + type StoreData: Send + 'static; /// Returns a mutable reference to the [`wasmtime::component::Linker`]. - pub fn linker(&mut self) -> &mut Linker { - self.linker - } + fn linker(&mut self) -> &mut Linker; - /// Returns a function that can be used to get the instance state for this factor. - pub fn get_data_fn(&self) -> GetDataFn { - self.get_data + /// Get the instance state for this factor from the store's state. + fn get_data(store: &mut Self::StoreData) -> &mut FactorInstanceState { + Self::get_data_with_table(store).0 } - /// Returns a function that can be used to get the instance state for this - /// factor along with the instance's [`ResourceTable`]. - pub fn get_data_with_table_fn(&self) -> GetDataWithTableFn { - self.get_data_with_table - } + /// Get the instance state for this factor from the store's state, with the + /// resource table as well. + fn get_data_with_table( + store: &mut Self::StoreData, + ) -> (&mut FactorInstanceState, &mut ResourceTable); /// Convenience method to link a binding to the linker. - pub fn link_bindings( + fn link_bindings( &mut self, add_to_linker: impl Fn( - &mut Linker, - fn(&mut T) -> &mut FactorInstanceState, + &mut Linker, + fn(&mut Self::StoreData) -> &mut FactorInstanceState, ) -> anyhow::Result<()>, ) -> anyhow::Result<()> { - add_to_linker(self.linker, self.get_data) + add_to_linker(self.linker(), Self::get_data) + } +} + +// used in #[derive(RuntimeFactor)] +#[doc(hidden)] +pub struct FactorInitContext<'a, T, G> { + pub linker: &'a mut Linker, + pub _marker: PhantomData, +} + +// used in #[derive(RuntimeFactor)] +#[doc(hidden)] +pub trait FactorField { + type State: crate::RuntimeFactorsInstanceState; + type Factor: Factor; + + fn get(field: &mut Self::State) + -> (&mut FactorInstanceState, &mut ResourceTable); +} + +impl InitContext for FactorInitContext<'_, T, G> +where + G: FactorField, + T: AsInstanceState + Send + 'static, +{ + type StoreData = T; + + fn linker(&mut self) -> &mut Linker { + self.linker + } + + fn get_data_with_table( + store: &mut Self::StoreData, + ) -> (&mut FactorInstanceState, &mut ResourceTable) { + G::get(store.as_instance_state()) } } diff --git a/crates/factors/src/lib.rs b/crates/factors/src/lib.rs index 3cff92c20f..abcb73f456 100644 --- a/crates/factors/src/lib.rs +++ b/crates/factors/src/lib.rs @@ -11,7 +11,10 @@ pub use spin_app::{App, AppComponent}; pub use spin_factors_derive::RuntimeFactors; pub use crate::{ - factor::{ConfigureAppContext, ConfiguredApp, Factor, FactorInstanceState, InitContext}, + factor::{ + ConfigureAppContext, ConfiguredApp, Factor, FactorField, FactorInitContext, + FactorInstanceState, InitContext, + }, prepare::{FactorInstanceBuilder, PrepareContext, SelfInstanceBuilder}, runtime_config::{FactorRuntimeConfigSource, RuntimeConfigSourceFinalizer}, runtime_factors::{