@@ -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,101 @@ 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 of the safety comment on the function.
105+ let this = unsafe { core:: mem:: zeroed:: <F >( ) } ;
106+ let params = fc. parameters. clone( ) . unwrap_or_default( ) ;
107+ let params = <( $( $P, ) * ) as ParameterTuple >:: from_value( params) ?;
108+ let result = Function :: <R :: ReturnType , ( $( $P, ) * ) , HyperlightGuestError >:: call( & this, params) ?;
109+ Ok ( into_flatbuffer_result( result. into_value( ) ) )
110+ }
111+ }
112+ }
113+ } ;
114+ }
115+
116+ impl < F , Args , Output > AsGuestFunctionDefinition < Output , Args > for F
117+ where
118+ F : IntoGuestFunction < Output , Args > ,
119+ Args : ParameterTuple ,
120+ Output : SupportedReturnType ,
121+ {
122+ fn as_guest_function_definition ( & self , name : impl Into < String > ) -> GuestFunctionDefinition {
123+ let parameter_types = Args :: TYPE . to_vec ( ) ;
124+ let return_type = Output :: TYPE ;
125+ let function_pointer = self . into_guest_function ( ) ;
126+ let function_pointer = function_pointer as usize ;
127+
128+ GuestFunctionDefinition {
129+ function_name : name. into ( ) ,
130+ parameter_types,
131+ return_type,
132+ function_pointer,
133+ }
134+ }
135+ }
136+
137+ for_each_tuple ! ( impl_host_function) ;
138+
38139impl GuestFunctionDefinition {
39140 /// Create a new `GuestFunctionDefinition`.
40141 pub fn new (
@@ -51,6 +152,19 @@ impl GuestFunctionDefinition {
51152 }
52153 }
53154
155+ /// Create a new `GuestFunctionDefinition` from a function that implements
156+ /// `AsGuestFunctionDefinition`.
157+ pub fn from_fn < Output , Args > (
158+ function_name : String ,
159+ function : impl AsGuestFunctionDefinition < Output , Args > ,
160+ ) -> Self
161+ where
162+ Args : ParameterTuple ,
163+ Output : SupportedReturnType ,
164+ {
165+ function. as_guest_function_definition ( function_name)
166+ }
167+
54168 /// Verify that `self` has same signature as the provided `parameter_types`.
55169 pub fn verify_parameters ( & self , parameter_types : & [ ParameterType ] ) -> Result < ( ) > {
56170 // Verify that the function does not have more than `MAX_PARAMETERS` parameters.
0 commit comments