@@ -18,8 +18,14 @@ use alloc::format;
1818use alloc:: string:: String ;
1919use alloc:: vec:: Vec ;
2020
21+ use hyperlight_common:: flatbuffer_wrappers:: function_call:: FunctionCall ;
2122use hyperlight_common:: flatbuffer_wrappers:: function_types:: { ParameterType , ReturnType } ;
2223use hyperlight_common:: flatbuffer_wrappers:: guest_error:: ErrorCode ;
24+ use hyperlight_common:: flatbuffer_wrappers:: util:: get_flatbuffer_result;
25+ use hyperlight_common:: for_each_tuple;
26+ use hyperlight_common:: func:: {
27+ Function , ParameterTuple , ResultType , ReturnValue , SupportedReturnType ,
28+ } ;
2329use hyperlight_guest:: error:: { HyperlightGuestError , Result } ;
2430
2531/// The definition of a function exposed from the guest to the host
@@ -35,6 +41,104 @@ pub struct GuestFunctionDefinition {
3541 pub function_pointer : usize ,
3642}
3743
44+ /// Trait for functions that can be converted to a `fn(&FunctionCall) -> Result<Vec<u8>>`
45+ #[ doc( hidden) ]
46+ pub trait IntoGuestFunction < Output , Args >
47+ where
48+ Self : Function < Output , Args , HyperlightGuestError > ,
49+ Self : Copy + ' static ,
50+ Output : SupportedReturnType ,
51+ Args : ParameterTuple ,
52+ {
53+ #[ doc( hidden) ]
54+ const ASSERT_ZERO_SIZED : ( ) ;
55+
56+ /// Convert the function into a `fn(&FunctionCall) -> Result<Vec<u8>>`
57+ fn into_guest_function ( self ) -> fn ( & FunctionCall ) -> Result < Vec < u8 > > ;
58+ }
59+
60+ /// Trait for functions that can be converted to a `GuestFunctionDefinition`
61+ pub trait AsGuestFunctionDefinition < Output , Args >
62+ where
63+ Self : Function < Output , Args , HyperlightGuestError > ,
64+ Self : IntoGuestFunction < Output , Args > ,
65+ Output : SupportedReturnType ,
66+ Args : ParameterTuple ,
67+ {
68+ /// Get the `GuestFunctionDefinition` for this function
69+ fn as_guest_function_definition ( & self , name : impl Into < String > ) -> GuestFunctionDefinition ;
70+ }
71+
72+ fn into_flatbuffer_result ( value : ReturnValue ) -> Vec < u8 > {
73+ match value {
74+ ReturnValue :: Void ( ( ) ) => get_flatbuffer_result ( ( ) ) ,
75+ ReturnValue :: Int ( i) => get_flatbuffer_result ( i) ,
76+ ReturnValue :: UInt ( u) => get_flatbuffer_result ( u) ,
77+ ReturnValue :: Long ( l) => get_flatbuffer_result ( l) ,
78+ ReturnValue :: ULong ( ul) => get_flatbuffer_result ( ul) ,
79+ ReturnValue :: Float ( f) => get_flatbuffer_result ( f) ,
80+ ReturnValue :: Double ( d) => get_flatbuffer_result ( d) ,
81+ ReturnValue :: Bool ( b) => get_flatbuffer_result ( b) ,
82+ ReturnValue :: String ( s) => get_flatbuffer_result ( s. as_str ( ) ) ,
83+ ReturnValue :: VecBytes ( v) => get_flatbuffer_result ( v. as_slice ( ) ) ,
84+ }
85+ }
86+
87+ macro_rules! impl_host_function {
88+ ( [ $N: expr] ( $( $p: ident: $P: ident) ,* ) ) => {
89+ impl <F , R , $( $P) ,* > IntoGuestFunction <R :: ReturnType , ( $( $P, ) * ) > for F
90+ where
91+ F : Fn ( $( $P) ,* ) -> R ,
92+ F : Function <R :: ReturnType , ( $( $P, ) * ) , HyperlightGuestError >,
93+ F : Copy + ' static , // Copy implies that F has no Drop impl
94+ ( $( $P, ) * ) : ParameterTuple ,
95+ R : ResultType <HyperlightGuestError >,
96+ {
97+ #[ doc( hidden) ]
98+ const ASSERT_ZERO_SIZED : ( ) = const {
99+ assert!( core:: mem:: size_of:: <Self >( ) == 0 )
100+ } ;
101+
102+ fn into_guest_function( self ) -> fn ( & FunctionCall ) -> Result <Vec <u8 >> {
103+ |fc: & FunctionCall | {
104+ // SAFETY: This is safe because:
105+ // 1. F is zero-sized (enforced by the ASSERT_ZERO_SIZED const).
106+ // 2. F has no Drop impl (enforced by the Copy bound).
107+ // Therefore, creating an instance of F is safe.
108+ let this = unsafe { core:: mem:: zeroed:: <F >( ) } ;
109+ let params = fc. parameters. clone( ) . unwrap_or_default( ) ;
110+ let params = <( $( $P, ) * ) as ParameterTuple >:: from_value( params) ?;
111+ let result = Function :: <R :: ReturnType , ( $( $P, ) * ) , HyperlightGuestError >:: call( & this, params) ?;
112+ Ok ( into_flatbuffer_result( result. into_value( ) ) )
113+ }
114+ }
115+ }
116+ } ;
117+ }
118+
119+ impl < F , Args , Output > AsGuestFunctionDefinition < Output , Args > for F
120+ where
121+ F : IntoGuestFunction < Output , Args > ,
122+ Args : ParameterTuple ,
123+ Output : SupportedReturnType ,
124+ {
125+ fn as_guest_function_definition ( & self , name : impl Into < String > ) -> GuestFunctionDefinition {
126+ let parameter_types = Args :: TYPE . to_vec ( ) ;
127+ let return_type = Output :: TYPE ;
128+ let function_pointer = self . into_guest_function ( ) ;
129+ let function_pointer = function_pointer as usize ;
130+
131+ GuestFunctionDefinition {
132+ function_name : name. into ( ) ,
133+ parameter_types,
134+ return_type,
135+ function_pointer,
136+ }
137+ }
138+ }
139+
140+ for_each_tuple ! ( impl_host_function) ;
141+
38142impl GuestFunctionDefinition {
39143 /// Create a new `GuestFunctionDefinition`.
40144 pub fn new (
@@ -51,6 +155,19 @@ impl GuestFunctionDefinition {
51155 }
52156 }
53157
158+ /// Create a new `GuestFunctionDefinition` from a function that implements
159+ /// `AsGuestFunctionDefinition`.
160+ pub fn from_fn < Output , Args > (
161+ function_name : String ,
162+ function : impl AsGuestFunctionDefinition < Output , Args > ,
163+ ) -> Self
164+ where
165+ Args : ParameterTuple ,
166+ Output : SupportedReturnType ,
167+ {
168+ function. as_guest_function_definition ( function_name)
169+ }
170+
54171 /// Verify that `self` has same signature as the provided `parameter_types`.
55172 pub fn verify_parameters ( & self , parameter_types : & [ ParameterType ] ) -> Result < ( ) > {
56173 // Verify that the function does not have more than `MAX_PARAMETERS` parameters.
0 commit comments