@ -17,32 +17,6 @@ use wasmtime_runtime::component::{
} ;
} ;
use wasmtime_runtime ::{ VMCallerCheckedAnyfunc , VMMemoryDefinition , VMOpaqueContext } ;
use wasmtime_runtime ::{ VMCallerCheckedAnyfunc , VMMemoryDefinition , VMOpaqueContext } ;
/// Trait representing host-defined functions that can be imported into a wasm
/// component.
///
/// For more information see the
/// [`func_wrap`](crate::component::LinkerInstance::func_wrap) documentation.
pub trait IntoComponentFunc < T , Params , Return > {
/// Host entrypoint from a cranelift-generated trampoline.
///
/// This function has type `VMLoweringCallee` and delegates to the shared
/// `call_host` function below.
#[ doc(hidden) ]
extern "C" fn entrypoint (
cx : * mut VMOpaqueContext ,
data : * mut u8 ,
flags : InstanceFlags ,
memory : * mut VMMemoryDefinition ,
realloc : * mut VMCallerCheckedAnyfunc ,
string_encoding : StringEncoding ,
storage : * mut ValRaw ,
storage_len : usize ,
) ;
#[ doc(hidden) ]
fn into_host_func ( self ) -> Arc < HostFunc > ;
}
pub struct HostFunc {
pub struct HostFunc {
entrypoint : VMLoweringCallee ,
entrypoint : VMLoweringCallee ,
typecheck : Box < dyn ( Fn ( TypeFuncIndex , & Arc < ComponentTypes > ) -> Result < ( ) > ) + Send + Sync > ,
typecheck : Box < dyn ( Fn ( TypeFuncIndex , & Arc < ComponentTypes > ) -> Result < ( ) > ) + Send + Sync > ,
@ -50,12 +24,13 @@ pub struct HostFunc {
}
}
impl HostFunc {
impl HostFunc {
fn new < F , P , R > ( func : F , entrypoint : VMLoweringCallee ) -> Arc < HostFunc >
pub ( crate ) fn from_closure < T , F , P , R > ( func : F ) -> Arc < HostFunc >
where
where
F : Send + Sync + 'static ,
F : Fn ( StoreContextMut < T > , P ) -> Result < R > + Send + Sync + 'static ,
P : ComponentNamedList + Lift + 'static ,
P : ComponentNamedList + Lift + 'static ,
R : ComponentNamedList + Lower + 'static ,
R : ComponentNamedList + Lower + 'static ,
{
{
let entrypoint = Self ::entrypoint ::< T , F , P , R > ;
Arc ::new ( HostFunc {
Arc ::new ( HostFunc {
entrypoint ,
entrypoint ,
typecheck : Box ::new ( typecheck ::< P , R > ) ,
typecheck : Box ::new ( typecheck ::< P , R > ) ,
@ -63,6 +38,36 @@ impl HostFunc {
} )
} )
}
}
extern "C" fn entrypoint < T , F , P , R > (
cx : * mut VMOpaqueContext ,
data : * mut u8 ,
flags : InstanceFlags ,
memory : * mut VMMemoryDefinition ,
realloc : * mut VMCallerCheckedAnyfunc ,
string_encoding : StringEncoding ,
storage : * mut ValRaw ,
storage_len : usize ,
) where
F : Fn ( StoreContextMut < T > , P ) -> Result < R > ,
P : ComponentNamedList + Lift + 'static ,
R : ComponentNamedList + Lower + 'static ,
{
let data = data as * const F ;
unsafe {
handle_result ( | | {
call_host ::< _ , _ , _ , _ > (
cx ,
flags ,
memory ,
realloc ,
string_encoding ,
std ::slice ::from_raw_parts_mut ( storage , storage_len ) ,
| store , args | ( * data ) ( store , args ) ,
)
} )
}
}
pub ( crate ) fn new_dynamic < T , F > (
pub ( crate ) fn new_dynamic < T , F > (
func : F ,
func : F ,
index : TypeFuncIndex ,
index : TypeFuncIndex ,
@ -122,10 +127,10 @@ where
/// The "meat" of calling a host function from wasm.
/// The "meat" of calling a host function from wasm.
///
///
/// This function is delegated to from implementations of `IntoComponentFunc`
/// This function is delegated to from implementations of
/// generated in the macro below. Most of the arguments from the `entrypoint`
/// `HostFunc::from_closure`. Most of the arguments from the `entrypoint` are
/// are forwarded here except for the `data` pointer which is encapsulated in
/// forwarded here except for the `data` pointer which is encapsulated in the
/// the `closure` argument here.
/// `closure` argument here.
///
///
/// This function is parameterized over:
/// This function is parameterized over:
///
///
@ -270,88 +275,6 @@ unsafe fn handle_result(func: impl FnOnce() -> Result<()>) {
}
}
}
}
macro_rules ! impl_into_component_func {
( $num :tt $( $args :ident ) * ) = > {
// Implement for functions without a leading `StoreContextMut` parameter
#[ allow(non_snake_case) ]
impl < T , F , $( $args , ) * R > IntoComponentFunc < T , ( $( $args , ) * ) , R > for F
where
F : Fn ( $( $args ) , * ) -> Result < R > + Send + Sync + 'static ,
( $( $args , ) * ) : ComponentNamedList + Lift + 'static ,
R : ComponentNamedList + Lower + 'static ,
{
extern "C" fn entrypoint (
cx : * mut VMOpaqueContext ,
data : * mut u8 ,
flags : InstanceFlags ,
memory : * mut VMMemoryDefinition ,
realloc : * mut VMCallerCheckedAnyfunc ,
string_encoding : StringEncoding ,
storage : * mut ValRaw ,
storage_len : usize ,
) {
let data = data as * const Self ;
unsafe {
handle_result ( | | call_host ::< T , _ , _ , _ > (
cx ,
flags ,
memory ,
realloc ,
string_encoding ,
std ::slice ::from_raw_parts_mut ( storage , storage_len ) ,
| _ , ( $( $args , ) * ) | ( * data ) ( $( $args ) , * ) ,
) )
}
}
fn into_host_func ( self ) -> Arc < HostFunc > {
let entrypoint = < Self as IntoComponentFunc < T , ( $( $args , ) * ) , R > > ::entrypoint ;
HostFunc ::new ::< _ , ( $( $args , ) * ) , R > ( self , entrypoint )
}
}
// Implement for functions with a leading `StoreContextMut` parameter
#[ allow(non_snake_case) ]
impl < T , F , $( $args , ) * R > IntoComponentFunc < T , ( StoreContextMut < '_ , T > , $( $args , ) * ) , R > for F
where
F : Fn ( StoreContextMut < '_ , T > , $( $args ) , * ) -> Result < R > + Send + Sync + 'static ,
( $( $args , ) * ) : ComponentNamedList + Lift + 'static ,
R : ComponentNamedList + Lower + 'static ,
{
extern "C" fn entrypoint (
cx : * mut VMOpaqueContext ,
data : * mut u8 ,
flags : InstanceFlags ,
memory : * mut VMMemoryDefinition ,
realloc : * mut VMCallerCheckedAnyfunc ,
string_encoding : StringEncoding ,
storage : * mut ValRaw ,
storage_len : usize ,
) {
let data = data as * const Self ;
unsafe {
handle_result ( | | call_host ::< T , _ , _ , _ > (
cx ,
flags ,
memory ,
realloc ,
string_encoding ,
std ::slice ::from_raw_parts_mut ( storage , storage_len ) ,
| store , ( $( $args , ) * ) | ( * data ) ( store , $( $args ) , * ) ,
) )
}
}
fn into_host_func ( self ) -> Arc < HostFunc > {
let entrypoint = < Self as IntoComponentFunc < T , ( StoreContextMut < '_ , T > , $( $args , ) * ) , R > > ::entrypoint ;
HostFunc ::new ::< _ , ( $( $args , ) * ) , R > ( self , entrypoint )
}
}
}
}
for_each_function_signature ! ( impl_into_component_func ) ;
unsafe fn call_host_dynamic < T , F > (
unsafe fn call_host_dynamic < T , F > (
Types { params , results } : & Types ,
Types { params , results } : & Types ,
cx : * mut VMOpaqueContext ,
cx : * mut VMOpaqueContext ,