hyperlight_host/func/
host_functions.rs1use std::sync::{Arc, Mutex};
18
19use hyperlight_common::flatbuffer_wrappers::function_types::{ParameterValue, ReturnValue};
20
21use super::utils::for_each_tuple;
22use super::{ParameterTuple, ResultType, SupportedReturnType};
23use crate::sandbox::UninitializedSandbox;
24use crate::sandbox::host_funcs::FunctionEntry;
25use crate::{Result, new_error};
26
27pub trait Registerable {
30 fn register_host_function<Args: ParameterTuple, Output: SupportedReturnType>(
32 &mut self,
33 name: &str,
34 hf: impl Into<HostFunction<Output, Args>>,
35 ) -> Result<()>;
36}
37impl Registerable for UninitializedSandbox {
38 fn register_host_function<Args: ParameterTuple, Output: SupportedReturnType>(
39 &mut self,
40 name: &str,
41 hf: impl Into<HostFunction<Output, Args>>,
42 ) -> Result<()> {
43 let mut hfs = self
44 .host_funcs
45 .try_lock()
46 .map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))?;
47
48 let entry = FunctionEntry {
49 function: hf.into().into(),
50 parameter_types: Args::TYPE,
51 return_type: Output::TYPE,
52 };
53
54 (*hfs).register_host_function(name.to_string(), entry, &mut self.mgr)
55 }
56}
57
58#[derive(Clone)]
61pub struct HostFunction<Output, Args>
62where
63 Args: ParameterTuple,
64 Output: SupportedReturnType,
65{
66 func: Arc<dyn Fn(Args) -> Result<Output> + Send + Sync + 'static>,
91}
92
93pub(crate) struct TypeErasedHostFunction {
94 func: Box<dyn Fn(Vec<ParameterValue>) -> Result<ReturnValue> + Send + Sync + 'static>,
95}
96
97impl<Args, Output> HostFunction<Output, Args>
98where
99 Args: ParameterTuple,
100 Output: SupportedReturnType,
101{
102 pub fn call(&self, args: Args) -> Result<Output> {
104 (self.func)(args)
105 }
106}
107
108impl TypeErasedHostFunction {
109 pub(crate) fn call(&self, args: Vec<ParameterValue>) -> Result<ReturnValue> {
110 (self.func)(args)
111 }
112}
113
114impl<Args, Output> From<HostFunction<Output, Args>> for TypeErasedHostFunction
115where
116 Args: ParameterTuple,
117 Output: SupportedReturnType,
118{
119 fn from(func: HostFunction<Output, Args>) -> TypeErasedHostFunction {
120 TypeErasedHostFunction {
121 func: Box::new(move |args: Vec<ParameterValue>| {
122 let args = Args::from_value(args)?;
123 Ok(func.call(args)?.into_value())
124 }),
125 }
126 }
127}
128
129macro_rules! impl_host_function {
130 ([$N:expr] ($($p:ident: $P:ident),*)) => {
131 impl<F, R, $($P),*> From<F> for HostFunction<R::ReturnType, ($($P,)*)>
139 where
140 F: FnMut($($P),*) -> R + Send + 'static,
141 ($($P,)*): ParameterTuple,
142 R: ResultType,
143 {
144 fn from(mut func: F) -> HostFunction<R::ReturnType, ($($P,)*)> {
145 let func = move |($($p,)*): ($($P,)*)| -> Result<R::ReturnType> {
146 func($($p),*).into_result()
147 };
148 let func = Mutex::new(func);
149 HostFunction {
150 func: Arc::new(move |args: ($($P,)*)| {
151 func.try_lock()
152 .map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))?
153 (args)
154 })
155 }
156 }
157 }
158 };
159}
160
161for_each_tuple!(impl_host_function);
162
163pub(crate) fn register_host_function<Args: ParameterTuple, Output: SupportedReturnType>(
164 func: impl Into<HostFunction<Output, Args>>,
165 sandbox: &mut UninitializedSandbox,
166 name: &str,
167) -> Result<()> {
168 let func = func.into().into();
169
170 let entry = FunctionEntry {
171 function: func,
172 parameter_types: Args::TYPE,
173 return_type: Output::TYPE,
174 };
175
176 sandbox
177 .host_funcs
178 .try_lock()
179 .map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))?
180 .register_host_function(name.to_string(), entry, &mut sandbox.mgr)?;
181
182 Ok(())
183}