use anyhow::bail;
use wasi_common::WasiCtx;
use wasmtime::{AsContext, AsContextMut, Caller, Extern};
pub fn read_mem(caller: &mut Caller<'_, WasiCtx>, ptr: i32, buf: &mut [u8]) -> anyhow::Result<()> {
let Some(Extern::Memory(mem)) = caller.get_export("memory") else {
bail!("no mem");
};
mem.read(caller.as_context_mut(), usize::try_from(ptr)?, buf)?;
Ok(())
}
pub fn write_mem(caller: &mut Caller<'_, WasiCtx>, bytes: &[u8]) -> Option<i64> {
let alloc = match caller.get_export("alloc") {
Some(Extern::Func(malloc)) => match malloc.typed::<i32, i32>(caller.as_context()) {
Ok(malloc) => malloc,
Err(_) => return None,
},
_ => return None,
};
let len = bytes.len();
let Ok(params) = i32::try_from(len) else {
return None;
};
let Ok(ptr) = alloc.call(caller.as_context_mut(), params) else {
return None;
};
let Some(Extern::Memory(mem)) = caller.get_export("memory") else {
return None;
};
let Ok(usize_ptr) = usize::try_from(ptr) else {
return None;
};
if mem
.write(caller.as_context_mut(), usize_ptr, bytes)
.is_err()
{
return None;
}
let i64_ptr = i64::from(ptr) << 32;
let Ok(i64_len) = i64::try_from(len) else {
return None;
};
Some(i64_ptr | i64_len)
}