use alloc::format;
use alloc::string::ToString;
use core::any::type_name;
use core::slice::from_raw_parts_mut;
use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode;
use tracing::instrument;
use super::handle::GuestHandle;
use crate::error::{HyperlightGuestError, Result};
impl GuestHandle {
#[instrument(skip_all, level = "Trace")]
pub fn try_pop_shared_input_data_into<T>(&self) -> Result<T>
where
T: for<'a> TryFrom<&'a [u8]>,
{
let peb_ptr = self.peb().unwrap();
let input_stack_size = unsafe { (*peb_ptr).input_stack.size as usize };
let input_stack_ptr = unsafe { (*peb_ptr).input_stack.ptr as *mut u8 };
let idb = unsafe { from_raw_parts_mut(input_stack_ptr, input_stack_size) };
if idb.is_empty() {
return Err(HyperlightGuestError::new(
ErrorCode::GuestError,
"Got a 0-size buffer in pop_shared_input_data_into".to_string(),
));
}
let stack_ptr_rel: u64 =
u64::from_le_bytes(idb[..8].try_into().expect("Shared input buffer too small"));
if stack_ptr_rel as usize > input_stack_size || stack_ptr_rel < 16 {
return Err(HyperlightGuestError::new(
ErrorCode::GuestError,
format!(
"Invalid stack pointer: {} in pop_shared_input_data_into",
stack_ptr_rel
),
));
}
let last_element_offset_rel = u64::from_le_bytes(
idb[stack_ptr_rel as usize - 8..stack_ptr_rel as usize]
.try_into()
.expect("Invalid stack pointer in pop_shared_input_data_into"),
);
let buffer = &idb[last_element_offset_rel as usize..];
let type_t = match T::try_from(buffer) {
Ok(t) => Ok(t),
Err(_e) => {
return Err(HyperlightGuestError::new(
ErrorCode::GuestError,
format!("Unable to convert buffer to {}", type_name::<T>()),
));
}
};
idb[..8].copy_from_slice(&last_element_offset_rel.to_le_bytes());
idb[last_element_offset_rel as usize..stack_ptr_rel as usize].fill(0);
type_t
}
pub fn push_shared_output_data(&self, data: &[u8]) -> Result<()> {
let peb_ptr = self.peb().unwrap();
let output_stack_size = unsafe { (*peb_ptr).output_stack.size as usize };
let output_stack_ptr = unsafe { (*peb_ptr).output_stack.ptr as *mut u8 };
let odb = unsafe { from_raw_parts_mut(output_stack_ptr, output_stack_size) };
if odb.is_empty() {
return Err(HyperlightGuestError::new(
ErrorCode::GuestError,
"Got a 0-size buffer in push_shared_output_data".to_string(),
));
}
let stack_ptr_rel: u64 =
u64::from_le_bytes(odb[..8].try_into().expect("Shared output buffer too small"));
if stack_ptr_rel as usize > output_stack_size || stack_ptr_rel < 8 {
return Err(HyperlightGuestError::new(
ErrorCode::GuestError,
format!(
"Invalid stack pointer: {} in push_shared_output_data",
stack_ptr_rel
),
));
}
let size_required = data.len() + 8; let size_available = output_stack_size - stack_ptr_rel as usize;
if size_required > size_available {
return Err(HyperlightGuestError::new(
ErrorCode::GuestError,
format!(
"Not enough space in shared output buffer. Required: {}, Available: {}",
size_required, size_available
),
));
}
odb[stack_ptr_rel as usize..stack_ptr_rel as usize + data.len()].copy_from_slice(data);
let bytes: [u8; 8] = stack_ptr_rel.to_le_bytes();
odb[stack_ptr_rel as usize + data.len()..stack_ptr_rel as usize + data.len() + 8]
.copy_from_slice(&bytes);
let new_stack_ptr_rel: u64 = (stack_ptr_rel as usize + data.len() + 8) as u64;
odb[0..8].copy_from_slice(&(new_stack_ptr_rel).to_le_bytes());
Ok(())
}
}