use std::alloc::{Layout, alloc as mem_alloc, dealloc as mem_dealloc};
#[must_use]
pub fn host_alloc(len: u32) -> u32 {
if len == 0 {
return 0;
}
let Ok(layout) = Layout::from_size_align(len as usize, 1) else {
return 0;
};
let ptr = unsafe { mem_alloc(layout) } as usize;
if ptr > u32::MAX as usize {
unsafe { mem_dealloc(ptr as *mut u8, layout) };
return 0;
}
ptr as u32
}
pub fn host_dealloc(ptr: u32, len: u32) {
if ptr == 0 || len == 0 {
return;
}
let Ok(layout) = Layout::from_size_align(len as usize, 1) else {
return;
};
unsafe { mem_dealloc(ptr as *mut u8, layout) }
}
#[must_use]
pub unsafe fn read_input<'a>(ptr: u32, len: u32) -> &'a [u8] {
if len == 0 || !cfg!(target_pointer_width = "32") {
return &[];
}
unsafe { std::slice::from_raw_parts(ptr as *const u8, len as usize) }
}
#[must_use]
pub fn write_output(bytes: Vec<u8>) -> u64 {
let mut boxed = bytes.into_boxed_slice();
let out_len = boxed.len() as u32;
let out_ptr = boxed.as_mut_ptr() as usize;
if out_ptr > u32::MAX as usize {
return u64::from(out_len);
}
std::mem::forget(boxed);
((out_ptr as u64) << 32) | u64::from(out_len)
}