use std::collections::HashMap;
use hyperlight_common::flatbuffer_wrappers::host_function_definition::HostFunctionDefinition;
use hyperlight_common::flatbuffer_wrappers::host_function_details::HostFunctionDetails;
use hyperlight_host::func::{HostFunction, ParameterTuple, Registerable, SupportedReturnType};
use hyperlight_host::sandbox::config::SandboxConfiguration;
use hyperlight_host::{GuestBinary, Result, UninitializedSandbox, new_error};
use super::metrics::{METRIC_ACTIVE_PROTO_WASM_SANDBOXES, METRIC_TOTAL_PROTO_WASM_SANDBOXES};
use super::sandbox_builder::SandboxBuilder;
use super::wasm_sandbox::WasmSandbox;
use crate::build_info::BuildInfo;
pub struct ProtoWasmSandbox {
pub(super) inner: Option<UninitializedSandbox>,
host_function_definitions: HashMap<String, HostFunctionDefinition>,
}
impl Registerable for ProtoWasmSandbox {
fn register_host_function<Args: ParameterTuple, Output: SupportedReturnType>(
&mut self,
name: &str,
hf: impl Into<HostFunction<Output, Args>>,
) -> Result<()> {
self.inner
.as_mut()
.ok_or(new_error!("inner sandbox was none"))
.and_then(|sb| sb.register(name, hf))?;
self.host_function_definitions.insert(
name.to_string(),
HostFunctionDefinition {
function_name: name.to_string(),
parameter_types: Some(Args::TYPE.to_vec()),
return_type: Output::TYPE,
},
);
Ok(())
}
}
impl ProtoWasmSandbox {
pub(super) fn new(
cfg: Option<SandboxConfiguration>,
guest_binary: GuestBinary,
) -> Result<Self> {
BuildInfo::log();
let inner = UninitializedSandbox::new(guest_binary, cfg)?;
metrics::gauge!(METRIC_ACTIVE_PROTO_WASM_SANDBOXES).increment(1);
metrics::counter!(METRIC_TOTAL_PROTO_WASM_SANDBOXES).increment(1);
let host_function_definitions = HashMap::new();
Ok(Self {
inner: Some(inner),
host_function_definitions,
})
}
pub fn load_runtime(mut self) -> Result<WasmSandbox> {
let host_function_definitions = HostFunctionDetails {
host_functions: Some(
std::mem::take(&mut self.host_function_definitions)
.into_values()
.collect(),
),
};
let host_function_definitions_bytes: Vec<u8> = (&host_function_definitions)
.try_into()
.map_err(|e| new_error!("Failed to serialize host function details: {:?}", e))?;
let mut sandbox = match self.inner.take() {
Some(s) => s.evolve()?,
None => return Err(new_error!("No inner sandbox found.")),
};
let res: i32 = sandbox.call("InitWasmRuntime", (host_function_definitions_bytes,))?;
if res != 0 {
return Err(new_error!(
"InitWasmRuntime Failed with error code {:?}",
res
));
}
WasmSandbox::new(sandbox)
}
pub fn register<Args: ParameterTuple, Output: SupportedReturnType>(
&mut self,
name: impl AsRef<str>,
host_func: impl Into<HostFunction<Output, Args>>,
) -> Result<()> {
self.register_host_function(name.as_ref(), host_func)
}
pub fn register_print(
&mut self,
print_func: impl Into<HostFunction<i32, (String,)>>,
) -> Result<()> {
self.inner
.as_mut()
.ok_or(new_error!("inner sandbox was none"))?
.register_print(print_func)
}
}
impl std::fmt::Debug for ProtoWasmSandbox {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ProtoWasmSandbox").finish()
}
}
impl Drop for ProtoWasmSandbox {
fn drop(&mut self) {
metrics::gauge!(METRIC_ACTIVE_PROTO_WASM_SANDBOXES).decrement(1);
}
}
impl Default for ProtoWasmSandbox {
fn default() -> Self {
SandboxBuilder::new().build().unwrap()
}
}