@@ -35,8 +35,76 @@ pub struct FunctionRegistry {
3535 functions_map : HashMap < String , FunctionEntry > ,
3636}
3737
38- impl From < & mut FunctionRegistry > for HostFunctionDetails {
39- fn from ( registry : & mut FunctionRegistry ) -> Self {
38+ /// A collection of host functions that can be supplied to a sandbox
39+ /// constructor (e.g. [`crate::MultiUseSandbox::from_snapshot`]) to
40+ /// expose host-side functionality to the guest.
41+ ///
42+ /// Use [`HostFunctions::default`] to start with the standard
43+ /// `HostPrint` function pre-registered (matches the registry that the
44+ /// regular `UninitializedSandbox` → `evolve()` path constructs), or
45+ /// [`HostFunctions::new`] to start with an empty registry.
46+ ///
47+ /// Add additional host functions via the
48+ /// [`crate::func::Registerable`] trait, just as you would on an
49+ /// `UninitializedSandbox`.
50+ ///
51+ /// ```no_run
52+ /// # use hyperlight_host::{HostFunctions, Result};
53+ /// # use hyperlight_host::func::Registerable;
54+ /// # fn example() -> Result<()> {
55+ /// // Default: HostPrint already registered.
56+ /// let mut funcs = HostFunctions::default();
57+ /// funcs.register_host_function("Add", |a: i32, b: i32| Ok(a + b))?;
58+ /// # Ok(())
59+ /// # }
60+ /// ```
61+ pub struct HostFunctions ( FunctionRegistry ) ;
62+
63+ impl HostFunctions {
64+ /// Create an empty `HostFunctions` with no host functions
65+ /// registered.
66+ ///
67+ /// Most callers want [`HostFunctions::default`] instead, which
68+ /// pre-registers the standard `HostPrint` function.
69+ pub fn new ( ) -> Self {
70+ Self ( FunctionRegistry :: default ( ) )
71+ }
72+
73+ /// Consume this `HostFunctions` and return the inner registry.
74+ pub ( crate ) fn into_inner ( self ) -> FunctionRegistry {
75+ self . 0
76+ }
77+
78+ /// Borrow the inner registry mutably.
79+ pub ( crate ) fn inner_mut ( & mut self ) -> & mut FunctionRegistry {
80+ & mut self . 0
81+ }
82+
83+ /// Borrow the inner registry immutably.
84+ pub ( crate ) fn inner ( & self ) -> & FunctionRegistry {
85+ & self . 0
86+ }
87+ }
88+
89+ impl Default for HostFunctions {
90+ /// Create a `HostFunctions` pre-populated with the standard
91+ /// `HostPrint` function (writes UTF-8 strings to the host's
92+ /// stdout in green).
93+ ///
94+ /// This matches the default registry installed by
95+ /// `UninitializedSandbox::new()`, so a snapshot taken from a
96+ /// regular sandbox can be loaded with
97+ /// `MultiUseSandbox::from_snapshot(snap, HostFunctions::default())`
98+ /// without registering anything else.
99+ ///
100+ /// Use [`HostFunctions::new`] for an empty registry.
101+ fn default ( ) -> Self {
102+ Self ( FunctionRegistry :: with_default_host_print ( ) )
103+ }
104+ }
105+
106+ impl From < & FunctionRegistry > for HostFunctionDetails {
107+ fn from ( registry : & FunctionRegistry ) -> Self {
40108 let host_functions = registry
41109 . functions_map
42110 . iter ( )
@@ -61,15 +129,26 @@ pub struct FunctionEntry {
61129
62130impl FunctionRegistry {
63131 /// Register a host function with the sandbox.
64- #[ instrument( err( Debug ) , skip_all, parent = Span :: current( ) , level = "Trace" ) ]
65- pub ( crate ) fn register_host_function (
66- & mut self ,
67- name : String ,
68- func : FunctionEntry ,
69- ) -> Result < ( ) > {
132+ #[ instrument( skip_all, parent = Span :: current( ) , level = "Trace" ) ]
133+ pub ( crate ) fn register_host_function ( & mut self , name : String , func : FunctionEntry ) {
70134 self . functions_map . insert ( name, func) ;
135+ }
71136
72- Ok ( ( ) )
137+ /// Create a `FunctionRegistry` pre-populated with the default
138+ /// `HostPrint` function (writes to stdout with green text).
139+ pub ( crate ) fn with_default_host_print ( ) -> Self {
140+ use crate :: func:: host_functions:: HostFunction ;
141+ use crate :: func:: { ParameterTuple , SupportedReturnType } ;
142+
143+ let mut registry = Self :: default ( ) ;
144+ let hf: HostFunction < i32 , ( String , ) > = default_writer_func. into ( ) ;
145+ let entry = FunctionEntry {
146+ function : hf. into ( ) ,
147+ parameter_types : <( String , ) >:: TYPE ,
148+ return_type : <i32 as SupportedReturnType >:: TYPE ,
149+ } ;
150+ registry. register_host_function ( "HostPrint" . to_string ( ) , entry) ;
151+ registry
73152 }
74153
75154 /// Assuming a host function called `"HostPrint"` exists, and takes a
@@ -118,7 +197,7 @@ impl FunctionRegistry {
118197
119198/// The default writer function is to write to stdout with green text.
120199#[ instrument( err( Debug ) , skip_all, parent = Span :: current( ) , level = "Trace" ) ]
121- pub ( super ) fn default_writer_func ( s : String ) -> Result < i32 > {
200+ fn default_writer_func ( s : String ) -> Result < i32 > {
122201 match std:: io:: stdout ( ) . is_terminal ( ) {
123202 false => {
124203 print ! ( "{}" , s) ;
0 commit comments