use crate::{
+ instance::function::SyncFn, AsInstance, CallingFrame, FuncType, Function, ImportModule,
+ Instance, Memory, WasmEdgeResult, WasmValue,
+};
+use async_wasi::snapshots::{
+ common::{
+ error::Errno,
+ memory::WasmPtr,
+ types::{__wasi_ciovec_t, __wasi_size_t},
+ },
+ preview_1 as p, WasiCtx,
+};
+use std::{
+ future::Future,
+ ops::{Deref, DerefMut},
+};
+use wasmedge_types::{
+ error::{CoreCommonError, CoreError, CoreExecutionError},
+ ValType,
+};
+
+use super::function::{AsyncFn, AsyncFunction};
+
+#[derive(Debug)]
+pub struct AsyncInstance(pub(crate) Instance);
+
+impl AsRef<Instance> for AsyncInstance {
+ fn as_ref(&self) -> &Instance {
+ &self.0
+ }
+}
+
+impl AsMut<Instance> for AsyncInstance {
+ fn as_mut(&mut self) -> &mut Instance {
+ &mut self.0
+ }
+}
+
+#[derive(Debug)]
+pub struct AsyncImportObject<T: Send>(ImportModule<T>);
+impl<T: Send> Deref for AsyncImportObject<T> {
+ type Target = ImportModule<T>;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+impl<T: Send> DerefMut for AsyncImportObject<T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.0
+ }
+}
+
+impl<T: Send> AsyncImportObject<T> {
+ pub fn create(name: impl AsRef<str>, data: Box<T>) -> WasmEdgeResult<Self> {
+ let inner = ImportModule::create(name, data)?;
+ Ok(AsyncImportObject(inner))
+ }
+
+ pub fn add_async_func(&mut self, name: impl AsRef<str>, func: AsyncFunction) {
+ self.0.add_func(name, func.0);
+ }
+}
+impl<T: Send> AsRef<ImportModule<T>> for AsyncImportObject<T> {
+ fn as_ref(&self) -> &ImportModule<T> {
+ &self.0
+ }
+}
+impl<T: Send> AsMut<ImportModule<T>> for AsyncImportObject<T> {
+ fn as_mut(&mut self) -> &mut ImportModule<T> {
+ &mut self.0
+ }
+}
+
+impl<T: Send> AsInstance for AsyncImportObject<T> {
+ unsafe fn as_ptr(&self) -> *const crate::ffi::WasmEdge_ModuleInstanceContext {
+ self.0.as_ptr()
+ }
+}
+
+#[derive(Debug)]
+pub struct AsyncWasiModule(AsyncImportObject<WasiCtx>);
+
+impl AsRef<AsyncImportObject<WasiCtx>> for AsyncWasiModule {
+ fn as_ref(&self) -> &AsyncImportObject<WasiCtx> {
+ &self.0
+ }
+}
+
+impl AsMut<AsyncImportObject<WasiCtx>> for AsyncWasiModule {
+ fn as_mut(&mut self) -> &mut AsyncImportObject<WasiCtx> {
+ &mut self.0
+ }
+}
+
+impl AsyncWasiModule {
+ pub fn create(
+ args: Option<Vec<impl AsRef<str>>>,
+ envs: Option<Vec<(impl AsRef<str>, impl AsRef<str>)>>,
+ ) -> WasmEdgeResult<Self> {
+ let mut wasi_ctx = WasiCtx::new();
+
+ if let Some(args) = args {
+ wasi_ctx.push_args(args.iter().map(|x| x.as_ref().to_string()).collect());
+ }
+ if let Some(envs) = envs {
+ wasi_ctx.push_envs(
+ envs.iter()
+ .map(|(k, v)| format!("{}={}", k.as_ref(), v.as_ref()))
+ .collect(),
+ );
+ }
+
+ Self::create_from_wasi_context(wasi_ctx)
+ }
+
+ pub fn create_from_wasi_context(wasi_ctx: WasiCtx) -> WasmEdgeResult<Self> {
+ let name = "wasi_snapshot_preview1";
+
+ let mut async_wasi_module = Self(AsyncImportObject::create(name, Box::new(wasi_ctx))?);
+
+ for wasi_func in wasi_impls() {
+ match wasi_func {
+ WasiFunc::SyncFn(name, (ty_args, ty_rets), real_fn) => {
+ let func_ty = FuncType::new(ty_args, ty_rets);
+
+ let func = unsafe {
+ Function::create_sync_func(
+ &func_ty,
+ real_fn,
+ async_wasi_module.0.get_host_data_mut(),
+ 0,
+ )
+ }?;
+
+ async_wasi_module.0.add_func(&name, func);
+ }
+ WasiFunc::AsyncFn(name, (ty_args, ty_rets), real_async_fn) => {
+ let func_ty = FuncType::new(ty_args, ty_rets);
+
+ let func = AsyncFunction::create_async_func(
+ &func_ty,
+ real_async_fn,
+ async_wasi_module.0.get_host_data_mut(),
+ 0,
+ )?;
+
+ async_wasi_module.0.add_async_func(&name, func);
+ }
+ }
+ }
+
+ Ok(async_wasi_module)
+ }
+
+ pub fn name(&self) -> &str {
+ "wasi_snapshot_preview1"
+ }
+
+ pub fn exit_code(&self) -> u32 {
+ self.0.get_host_data().exit_code
+ }
+}
+
+fn args_get(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([argv, argv_buf]) = args.get(0..2) {
+ let argv = argv.to_i32() as usize;
+ let argv_buf = argv_buf.to_i32() as usize;
+ Ok(to_wasm_return(p::args_get(
+ data,
+ &mut *mem,
+ WasmPtr::from(argv),
+ WasmPtr::from(argv_buf),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn args_sizes_get(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([argc, argv_buf_size]) = args.get(0..2) {
+ let argc = argc.to_i32() as usize;
+ let argv_buf_size = argv_buf_size.to_i32() as usize;
+ Ok(to_wasm_return(p::args_sizes_get(
+ data,
+ &mut mem as &mut Memory,
+ WasmPtr::from(argc),
+ WasmPtr::from(argv_buf_size),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn environ_get(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2]) = args.get(0..2) {
+ let environ = p1.to_i32() as usize;
+ let environ_buf = p2.to_i32() as usize;
+ Ok(to_wasm_return(p::environ_get(
+ data,
+ &mut mem as &mut Memory,
+ WasmPtr::from(environ),
+ WasmPtr::from(environ_buf),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn environ_sizes_get(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2]) = args.get(0..2) {
+ let environ_count = p1.to_i32() as usize;
+ let environ_buf_size = p2.to_i32() as usize;
+ Ok(to_wasm_return(p::environ_sizes_get(
+ data,
+ &mut mem as &mut Memory,
+ WasmPtr::from(environ_count),
+ WasmPtr::from(environ_buf_size),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn clock_res_get(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2]) = args.get(0..2) {
+ let clock_id = p1.to_i32() as u32;
+ let resolution_ptr = p2.to_i32() as usize;
+ Ok(to_wasm_return(p::clock_res_get(
+ data,
+ &mut mem as &mut Memory,
+ clock_id,
+ WasmPtr::from(resolution_ptr),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn clock_time_get(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3]) = args.get(0..3) {
+ let clock_id = p1.to_i32() as u32;
+ let precision = p2.to_i64() as u64;
+ let time_ptr = p3.to_i32() as usize;
+
+ Ok(to_wasm_return(p::clock_time_get(
+ data,
+ &mut mem as &mut Memory,
+ clock_id,
+ precision,
+ WasmPtr::from(time_ptr),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn random_get(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2]) = args.get(0..2) {
+ let buf = p1.to_i32() as usize;
+ let buf_len = p2.to_i32() as u32;
+
+ Ok(to_wasm_return(p::random_get(
+ data,
+ &mut mem as &mut Memory,
+ WasmPtr::from(buf),
+ buf_len,
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn fd_prestat_get(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2]) = args.get(0..2) {
+ let fd = p1.to_i32();
+ let prestat_ptr = p2.to_i32() as usize;
+
+ Ok(to_wasm_return(p::fd_prestat_get(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ WasmPtr::from(prestat_ptr),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn fd_prestat_dir_name(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3]) = args.get(0..3) {
+ let fd = p1.to_i32();
+ let path_buf_ptr = p2.to_i32() as usize;
+ let path_max_len = p3.to_i32() as u32;
+
+ Ok(to_wasm_return(p::fd_prestat_dir_name(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ WasmPtr::from(path_buf_ptr),
+ path_max_len,
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn fd_renumber(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2]) = args.get(0..2) {
+ let from = p1.to_i32();
+ let to = p2.to_i32();
+
+ Ok(to_wasm_return(p::fd_renumber(
+ data,
+ &mut mem as &mut Memory,
+ from,
+ to,
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn fd_advise(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3, p4]) = args.get(0..4) {
+ let fd = p1.to_i32();
+ let offset = p2.to_i64() as u64;
+ let len = p3.to_i64() as u64;
+ let advice = p4.to_i32() as u8;
+
+ Ok(to_wasm_return(p::fd_advise(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ offset,
+ len,
+ advice,
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn fd_allocate(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3]) = args.get(0..3) {
+ let fd = p1.to_i32();
+ let offset = p2.to_i64() as u64;
+ let len = p3.to_i64() as u64;
+
+ Ok(to_wasm_return(p::fd_allocate(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ offset,
+ len,
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn fd_close(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1]) = args.get(0..1) {
+ let fd = p1.to_i32();
+
+ Ok(to_wasm_return(p::fd_close(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn fd_seek(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3, p4]) = args.get(0..4) {
+ let fd = p1.to_i32();
+ let offset = p2.to_i64();
+ let whence = p3.to_i32() as u8;
+ let newoffset_ptr = p4.to_i32() as usize;
+
+ Ok(to_wasm_return(p::fd_seek(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ offset,
+ whence,
+ WasmPtr::from(newoffset_ptr),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn fd_sync(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1]) = args.get(0..1) {
+ let fd = p1.to_i32();
+
+ Ok(to_wasm_return(p::fd_sync(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn fd_datasync(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1]) = args.get(0..1) {
+ let fd = p1.to_i32();
+
+ Ok(to_wasm_return(p::fd_datasync(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn fd_tell(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2]) = args.get(0..2) {
+ let fd = p1.to_i32();
+ let offset = p2.to_i32() as usize;
+
+ Ok(to_wasm_return(p::fd_tell(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ WasmPtr::from(offset),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn fd_fdstat_get(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2]) = args.get(0..2) {
+ let fd = p1.to_i32();
+ let buf_ptr = p2.to_i32() as usize;
+
+ Ok(to_wasm_return(p::fd_fdstat_get(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ WasmPtr::from(buf_ptr),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn fd_fdstat_set_flags(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2]) = args.get(0..2) {
+ let fd = p1.to_i32();
+ let flags = p2.to_i32() as u16;
+
+ Ok(to_wasm_return(p::fd_fdstat_set_flags(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ flags,
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn fd_fdstat_set_rights(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3]) = args.get(0..3) {
+ let fd = p1.to_i32();
+ let fs_rights_base = p2.to_i64() as u64;
+ let fs_rights_inheriting = p3.to_i64() as u64;
+
+ Ok(to_wasm_return(p::fd_fdstat_set_rights(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ fs_rights_base,
+ fs_rights_inheriting,
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn fd_filestat_get(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2]) = args.get(0..2) {
+ let fd = p1.to_i32();
+ let buf = p2.to_i32() as usize;
+
+ Ok(to_wasm_return(p::fd_filestat_get(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ WasmPtr::from(buf),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn fd_filestat_set_size(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2]) = args.get(0..2) {
+ let fd = p1.to_i32();
+ let buf = p2.to_i32() as usize;
+
+ Ok(to_wasm_return(p::fd_filestat_get(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ WasmPtr::from(buf),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn fd_filestat_set_times(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3, p4]) = args.get(0..4) {
+ let fd = p1.to_i32();
+ let st_atim = p2.to_i64() as u64;
+ let st_mtim = p3.to_i64() as u64;
+ let fst_flags = p4.to_i32() as u16;
+
+ Ok(to_wasm_return(p::fd_filestat_set_times(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ st_atim,
+ st_mtim,
+ fst_flags,
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn fd_read(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3, p4]) = args.get(0..4) {
+ let fd = p1.to_i32();
+ let iovs = p2.to_i32() as usize;
+ let iovs_len = p3.to_i32() as u32;
+ let nread = p4.to_i32() as usize;
+
+ Ok(to_wasm_return(p::fd_read(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ WasmPtr::from(iovs),
+ iovs_len,
+ WasmPtr::from(nread),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn fd_pread(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3, p4, p5]) = args.get(0..5) {
+ let fd = p1.to_i32();
+ let iovs = p2.to_i32() as usize;
+ let iovs_len = p3.to_i32() as u32;
+ let offset = p4.to_i64() as u64;
+ let nread = p5.to_i32() as usize;
+
+ Ok(to_wasm_return(p::fd_pread(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ WasmPtr::from(iovs),
+ iovs_len,
+ offset,
+ WasmPtr::from(nread),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn fd_write(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3, p4]) = args.get(0..4) {
+ let fd = p1.to_i32();
+ let iovs = p2.to_i32() as usize;
+ let iovs_len = p3.to_i32() as u32;
+ let nwritten = p4.to_i32() as usize;
+
+ Ok(to_wasm_return(p::fd_write(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ WasmPtr::from(iovs),
+ iovs_len,
+ WasmPtr::from(nwritten),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn fd_pwrite(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3, p4, p5]) = args.get(0..5) {
+ let fd = p1.to_i32();
+ let iovs = p2.to_i32() as usize;
+ let iovs_len = p3.to_i32() as u32;
+ let offset = p4.to_i64() as u64;
+ let nwritten = p5.to_i32() as usize;
+
+ Ok(to_wasm_return(p::fd_pwrite(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ WasmPtr::from(iovs),
+ iovs_len,
+ offset,
+ WasmPtr::from(nwritten),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn fd_readdir(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3, p4, p5]) = args.get(0..5) {
+ let fd = p1.to_i32();
+ let buf = p2.to_i32() as usize;
+ let buf_len = p3.to_i32() as u32;
+ let cookie = p4.to_i64() as u64;
+ let bufused_ptr = p5.to_i32() as usize;
+
+ Ok(to_wasm_return(p::fd_readdir(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ WasmPtr::from(buf),
+ buf_len,
+ cookie,
+ WasmPtr::from(bufused_ptr),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn path_create_directory(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3]) = args.get(0..3) {
+ let dirfd = p1.to_i32();
+ let path_ptr = p2.to_i32() as usize;
+ let path_len = p3.to_i32() as u32;
+
+ Ok(to_wasm_return(p::path_create_directory(
+ data,
+ &mem as &Memory,
+ dirfd,
+ WasmPtr::from(path_ptr),
+ path_len,
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn path_filestat_get(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3, p4, p5]) = args.get(0..5) {
+ let fd = p1.to_i32();
+ let flags = p2.to_i32() as u32;
+ let path_ptr = p3.to_i32() as usize;
+ let path_len = p4.to_i32() as u32;
+ let file_stat_ptr = p5.to_i32() as usize;
+
+ Ok(to_wasm_return(p::path_filestat_get(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ flags,
+ WasmPtr::from(path_ptr),
+ path_len,
+ WasmPtr::from(file_stat_ptr),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn path_filestat_set_times(
+ _data: &mut WasiCtx,
+ _inst: &mut Instance,
+ _frame: &mut CallingFrame,
+ _args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ Ok(vec![WasmValue::from_i32(
+ Errno::__WASI_ERRNO_NOSYS.0 as i32,
+ )])
+}
+
+fn path_link(
+ _data: &mut WasiCtx,
+ _inst: &mut Instance,
+ _frame: &mut CallingFrame,
+ _args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ Ok(vec![WasmValue::from_i32(
+ Errno::__WASI_ERRNO_NOSYS.0 as i32,
+ )])
+}
+
+fn path_open(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3, p4, p5, p6, p7, p8, p9]) = args.get(0..9) {
+ let dirfd = p1.to_i32();
+ let dirflags = p2.to_i32() as u32;
+ let path = p3.to_i32() as usize;
+ let path_len = p4.to_i32() as u32;
+ let o_flags = p5.to_i32() as u16;
+ let fs_rights_base = p6.to_i64() as u64;
+ let fs_rights_inheriting = p7.to_i64() as u64;
+ let fs_flags = p8.to_i32() as u16;
+ let fd_ptr = p9.to_i32() as usize;
+
+ Ok(to_wasm_return(p::path_open(
+ data,
+ &mut mem as &mut Memory,
+ dirfd,
+ dirflags,
+ WasmPtr::from(path),
+ path_len,
+ o_flags,
+ fs_rights_base,
+ fs_rights_inheriting,
+ fs_flags,
+ WasmPtr::from(fd_ptr),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn path_readlink(
+ _data: &mut WasiCtx,
+ _inst: &mut Instance,
+ _frame: &mut CallingFrame,
+ _args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ Ok(vec![WasmValue::from_i32(
+ Errno::__WASI_ERRNO_NOSYS.0 as i32,
+ )])
+}
+
+fn path_remove_directory(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3]) = args.get(0..3) {
+ let fd = p1.to_i32();
+ let path_ptr = p2.to_i32() as usize;
+ let path_len = p3.to_i32() as u32;
+
+ Ok(to_wasm_return(p::path_remove_directory(
+ data,
+ &mem as &Memory,
+ fd,
+ WasmPtr::from(path_ptr),
+ path_len,
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn path_rename(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3, p4, p5, p6]) = args.get(0..6) {
+ let old_fd = p1.to_i32();
+ let old_path = p2.to_i32() as usize;
+ let old_path_len = p3.to_i32() as u32;
+ let new_fd = p4.to_i32();
+ let new_path = p5.to_i32() as usize;
+ let new_path_len = p6.to_i32() as u32;
+
+ Ok(to_wasm_return(p::path_rename(
+ data,
+ &mem as &Memory,
+ old_fd,
+ WasmPtr::from(old_path),
+ old_path_len,
+ new_fd,
+ WasmPtr::from(new_path),
+ new_path_len,
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn path_symlink(
+ _data: &mut WasiCtx,
+ _inst: &mut Instance,
+ _frame: &mut CallingFrame,
+ _args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ Ok(vec![WasmValue::from_i32(
+ Errno::__WASI_ERRNO_NOSYS.0 as i32,
+ )])
+}
+
+fn path_unlink_file(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3]) = args.get(0..3) {
+ let fd = p1.to_i32();
+ let path_ptr = p2.to_i32() as usize;
+ let path_len = p3.to_i32() as u32;
+
+ Ok(to_wasm_return(p::path_unlink_file(
+ data,
+ &mem as &Memory,
+ fd,
+ WasmPtr::from(path_ptr),
+ path_len,
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn proc_exit(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1]) = args.get(0..1) {
+ let code = p1.to_i32() as u32;
+ p::proc_exit(data, &mut mem as &mut Memory, code);
+ Err(CoreError::Common(CoreCommonError::Terminated))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn proc_raise(
+ _data: &mut WasiCtx,
+ _inst: &mut Instance,
+ _frame: &mut CallingFrame,
+ _args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ Ok(vec![WasmValue::from_i32(
+ Errno::__WASI_ERRNO_NOSYS.0 as i32,
+ )])
+}
+
+fn sched_yield(
+ _data: &mut WasiCtx,
+ _inst: &mut Instance,
+ _frame: &mut CallingFrame,
+ _args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ Ok(vec![WasmValue::from_i32(
+ Errno::__WASI_ERRNO_NOSYS.0 as i32,
+ )])
+}
+
+fn sock_open(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3]) = args.get(0..3) {
+ let af = p1.to_i32() as u8;
+ let ty = p2.to_i32() as u8;
+ let ro_fd_ptr = p3.to_i32() as usize;
+
+ Ok(to_wasm_return(p::async_socket::sock_open(
+ data,
+ &mut mem as &mut Memory,
+ af,
+ ty,
+ WasmPtr::from(ro_fd_ptr),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn sock_bind(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3]) = args.get(0..3) {
+ let fd = p1.to_i32();
+ let addr_ptr = p2.to_i32() as usize;
+ let port = p3.to_i32() as u32;
+ Ok(to_wasm_return(p::async_socket::sock_bind(
+ data,
+ &mem as &Memory,
+ fd,
+ WasmPtr::from(addr_ptr),
+ port,
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn sock_listen(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2]) = args.get(0..2) {
+ let fd = p1.to_i32();
+ let backlog = p2.to_i32() as u32;
+
+ Ok(to_wasm_return(p::async_socket::sock_listen(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ backlog,
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn sock_accept<'data, 'inst, 'frame, 'fut>(
+ data: &'data mut WasiCtx,
+ _inst: &'inst mut AsyncInstance,
+ frame: &'frame mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Box<dyn Future<Output = Result<Vec<WasmValue>, CoreError>> + Send + 'fut>
+where
+ 'data: 'fut,
+ 'frame: 'fut,
+ 'inst: 'fut,
+{
+ Box::new(async move {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2]) = args.get(0..2) {
+ let fd = p1.to_i32();
+ let ro_fd_ptr = p2.to_i32() as usize;
+
+ Ok(to_wasm_return(
+ p::async_socket::sock_accept(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ WasmPtr::from(ro_fd_ptr),
+ )
+ .await,
+ ))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+ })
+}
+
+async fn sock_connect(
+ data: &mut WasiCtx,
+ _inst: &mut AsyncInstance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3]) = args.get(0..3) {
+ let fd = p1.to_i32();
+ let addr_ptr = p2.to_i32() as usize;
+ let port = p3.to_i32() as u32;
+
+ Ok(to_wasm_return(
+ p::async_socket::sock_connect(data, &mem as &Memory, fd, WasmPtr::from(addr_ptr), port)
+ .await,
+ ))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+async fn sock_recv(
+ data: &mut WasiCtx,
+ _inst: &mut AsyncInstance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3, p4, p5, p6]) = args.get(0..6) {
+ let fd = p1.to_i32();
+ let buf_ptr = p2.to_i32() as usize;
+ let buf_len = p3.to_i32() as u32;
+ let flags = p4.to_i32() as u16;
+ let ro_data_len_ptr = p5.to_i32() as usize;
+ let ro_flags_ptr = p6.to_i32() as usize;
+
+ Ok(to_wasm_return(
+ p::async_socket::sock_recv(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ WasmPtr::from(buf_ptr),
+ buf_len,
+ flags,
+ WasmPtr::from(ro_data_len_ptr),
+ WasmPtr::from(ro_flags_ptr),
+ )
+ .await,
+ ))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+async fn sock_recv_from(
+ data: &mut WasiCtx,
+ _inst: &mut AsyncInstance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3, p4, p5, p6, p7, p8]) = args.get(0..8) {
+ let fd = p1.to_i32();
+ let buf_ptr = p2.to_i32() as usize;
+ let buf_len = p3.to_i32() as u32;
+ let wasi_addr_ptr = p4.to_i32() as usize;
+ let flags = p5.to_i32() as u16;
+ let port_ptr = p6.to_i32() as usize;
+ let ro_data_len_ptr = p7.to_i32() as usize;
+ let ro_flags_ptr = p8.to_i32() as usize;
+
+ Ok(to_wasm_return(
+ p::async_socket::sock_recv_from(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ WasmPtr::from(buf_ptr),
+ buf_len,
+ WasmPtr::from(wasi_addr_ptr),
+ flags,
+ WasmPtr::from(port_ptr),
+ WasmPtr::from(ro_data_len_ptr),
+ WasmPtr::from(ro_flags_ptr),
+ )
+ .await,
+ ))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+async fn sock_send(
+ data: &mut WasiCtx,
+ _inst: &mut AsyncInstance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3, p4, p5]) = args.get(0..5) {
+ let fd = p1.to_i32();
+ let buf_ptr = p2.to_i32() as usize;
+ let buf_len = p3.to_i32() as u32;
+ let flags = p4.to_i32() as u16;
+ let send_len_ptr = p5.to_i32() as usize;
+
+ Ok(to_wasm_return(
+ p::async_socket::sock_send(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ WasmPtr::from(buf_ptr),
+ buf_len,
+ flags,
+ WasmPtr::from(send_len_ptr),
+ )
+ .await,
+ ))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+async fn sock_send_to(
+ data: &mut WasiCtx,
+ _inst: &mut AsyncInstance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3, p4, p5, p6, p7]) = args.get(0..7) {
+ let fd = p1.to_i32();
+ let buf_ptr = p2.to_i32() as usize;
+ let buf_len = p3.to_i32() as u32;
+ let wasi_addr_ptr = p4.to_i32() as usize;
+ let port = p5.to_i32() as u32;
+ let flags = p6.to_i32() as u16;
+ let send_len_ptr = p7.to_i32() as usize;
+
+ Ok(to_wasm_return(
+ p::async_socket::sock_send_to(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ WasmPtr::from(buf_ptr),
+ buf_len,
+ WasmPtr::from(wasi_addr_ptr),
+ port,
+ flags,
+ WasmPtr::from(send_len_ptr),
+ )
+ .await,
+ ))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn sock_shutdown(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2]) = args.get(0..2) {
+ let fd = p1.to_i32();
+ let how = p2.to_i32() as u8;
+ Ok(to_wasm_return(p::async_socket::sock_shutdown(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ how,
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn sock_getpeeraddr(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3, p4]) = args.get(0..4) {
+ let fd = p1.to_i32();
+ let wasi_addr_ptr = p2.to_i32() as usize;
+ let addr_type = p3.to_i32() as usize;
+ let port_ptr = p4.to_i32() as usize;
+ Ok(to_wasm_return(p::async_socket::sock_getpeeraddr(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ WasmPtr::from(wasi_addr_ptr),
+ WasmPtr::from(addr_type),
+ WasmPtr::from(port_ptr),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn sock_getlocaladdr(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3, p4]) = args.get(0..4) {
+ let fd = p1.to_i32();
+ let wasi_addr_ptr = p2.to_i32() as usize;
+ let addr_type = p3.to_i32() as usize;
+ let port_ptr = p4.to_i32() as usize;
+ Ok(to_wasm_return(p::async_socket::sock_getlocaladdr(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ WasmPtr::from(wasi_addr_ptr),
+ WasmPtr::from(addr_type),
+ WasmPtr::from(port_ptr),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn sock_getsockopt(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3, p4, p5]) = args.get(0..5) {
+ let fd = p1.to_i32();
+ let level = p2.to_i32() as u32;
+ let name = p3.to_i32() as u32;
+ let flag = p4.to_i32() as usize;
+ let flag_size_ptr = p5.to_i32() as usize;
+ Ok(to_wasm_return(p::async_socket::sock_getsockopt(
+ data,
+ &mut mem as &mut Memory,
+ fd,
+ level,
+ name,
+ WasmPtr::from(flag),
+ WasmPtr::from(flag_size_ptr),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn sock_setsockopt(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3, p4, p5]) = args.get(0..5) {
+ let fd = p1.to_i32();
+ let level = p2.to_i32() as u32;
+ let name = p3.to_i32() as u32;
+ let flag = p4.to_i32() as usize;
+ let flag_size = p5.to_i32() as u32;
+ Ok(to_wasm_return(p::async_socket::sock_setsockopt(
+ data,
+ &mem as &Memory,
+ fd,
+ level,
+ name,
+ WasmPtr::from(flag),
+ flag_size,
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+fn sock_getaddrinfo(
+ data: &mut WasiCtx,
+ _inst: &mut Instance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3, p4, p5, p6, p7, p8]) = args.get(0..8) {
+ let node = p1.to_i32() as usize;
+ let node_len = p2.to_i32() as u32;
+ let server = p3.to_i32() as usize;
+ let server_len = p4.to_i32() as u32;
+ let hint = p5.to_i32() as usize;
+ let res = p6.to_i32() as usize;
+ let max_len = p7.to_i32() as u32;
+ let res_len = p8.to_i32() as usize;
+
+ Ok(to_wasm_return(p::async_socket::addrinfo::sock_getaddrinfo(
+ data,
+ &mut mem as &mut Memory,
+ WasmPtr::from(node),
+ node_len,
+ WasmPtr::from(server),
+ server_len,
+ WasmPtr::from(hint),
+ WasmPtr::from(res),
+ max_len,
+ WasmPtr::from(res_len),
+ )))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+async fn poll_oneoff(
+ data: &mut WasiCtx,
+ _inst: &mut AsyncInstance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3, p4]) = args.get(0..4) {
+ let in_ptr = p1.to_i32() as usize;
+ let out_ptr = p2.to_i32() as usize;
+ let nsubscriptions = p3.to_i32() as u32;
+ let revents_num_ptr = p4.to_i32() as usize;
+
+ Ok(to_wasm_return(
+ p::async_poll::poll_oneoff(
+ data,
+ &mut mem as &mut Memory,
+ WasmPtr::from(in_ptr),
+ WasmPtr::from(out_ptr),
+ nsubscriptions,
+ WasmPtr::from(revents_num_ptr),
+ )
+ .await,
+ ))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+async fn sock_lookup_ip(
+ data: &mut WasiCtx,
+ _inst: &mut AsyncInstance,
+ frame: &mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Result<Vec<WasmValue>, CoreError> {
+ let mut mem = frame
+ .memory_mut(0)
+ .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
+
+ if let Some([p1, p2, p3, p4, p5, p6]) = args.get(0..6) {
+ let host_name_ptr = p1.to_i32() as usize;
+ let host_name_len = p2.to_i32() as u32;
+ let lookup_type = p3.to_i32() as u8;
+ let addr_buf = p4.to_i32() as usize;
+ let addr_buf_max_len = p5.to_i32() as u32;
+ let raddr_num_ptr = p6.to_i32() as usize;
+ Ok(to_wasm_return(
+ p::async_socket::sock_lookup_ip(
+ data,
+ &mut mem as &mut Memory,
+ WasmPtr::from(host_name_ptr),
+ host_name_len,
+ lookup_type,
+ WasmPtr::from(addr_buf),
+ addr_buf_max_len,
+ WasmPtr::from(raddr_num_ptr),
+ )
+ .await,
+ ))
+ } else {
+ Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
+ }
+}
+
+#[inline]
+fn box_future<
+ 'data,
+ 'inst,
+ 'frame,
+ 'fut,
+ Data: Send,
+ Fut: Future<Output = Result<Vec<WasmValue>, CoreError>> + Send + 'fut,
+ F: FnOnce(
+ &'data mut Data,
+ &'inst mut AsyncInstance,
+ &'frame mut CallingFrame,
+ Vec<WasmValue>,
+ ) -> Fut,
+>(
+ data: &'data mut Data,
+ inst: &'inst mut AsyncInstance,
+ frame: &'frame mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Box<dyn Future<Output = Result<Vec<WasmValue>, CoreError>> + Send + 'fut>
+where
+ 'data: 'fut,
+ 'inst: 'fut,
+ 'frame: 'fut,
+{
+ let f: F = unsafe { std::mem::zeroed() };
+ Box::new(f(data, inst, frame, args))
+}
+
+#[allow(clippy::complexity)]
+fn wrap_future<
+ 'data,
+ 'inst,
+ 'frame,
+ 'fut,
+ Data: Send + 'data,
+ Fut: Future<Output = Result<Vec<WasmValue>, CoreError>> + Send + 'fut,
+ F: FnOnce(
+ &'data mut Data,
+ &'inst mut AsyncInstance,
+ &'frame mut CallingFrame,
+ Vec<WasmValue>,
+ ) -> Fut,
+>(
+ _f: F,
+) -> fn(
+ data: &'data mut Data,
+ inst: &'inst mut AsyncInstance,
+ frame: &'frame mut CallingFrame,
+ args: Vec<WasmValue>,
+) -> Box<dyn Future<Output = Result<Vec<WasmValue>, CoreError>> + Send + 'fut>
+where
+ 'data: 'fut,
+ 'inst: 'fut,
+ 'frame: 'fut,
+{
+ box_future::<Data, Fut, F>
+}
+
+enum WasiFunc<'data, 'inst, 'frame, 'fut, T: Sized>
+where
+ 'data: 'fut,
+ 'inst: 'fut,
+ 'frame: 'fut,
+{
+ SyncFn(String, (Vec<ValType>, Vec<ValType>), SyncFn<T>),
+ AsyncFn(
+ String,
+ (Vec<ValType>, Vec<ValType>),
+ AsyncFn<'data, 'inst, 'frame, 'fut, T>,
+ ),
+}
+
+fn wasi_impls<'data, 'inst, 'frame, 'fut>() -> Vec<WasiFunc<'data, 'inst, 'frame, 'fut, WasiCtx>> {
+ macro_rules! sync_fn {
+ ($name:expr, $ty:expr, $f:ident) => {
+ WasiFunc::SyncFn($name.into(), $ty, $f)
+ };
+ }
+ macro_rules! async_fn {
+ ($name:expr, $ty:expr, $f:expr) => {
+ WasiFunc::AsyncFn($name.into(), $ty, $f)
+ };
+ }
+ vec![
+ sync_fn!(
+ "args_get",
+ (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
+ args_get
+ ),
+ sync_fn!(
+ "args_sizes_get",
+ (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
+ args_sizes_get
+ ),
+ sync_fn!(
+ "environ_get",
+ (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
+ environ_get
+ ),
+ sync_fn!(
+ "environ_sizes_get",
+ (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
+ environ_sizes_get
+ ),
+ sync_fn!(
+ "clock_res_get",
+ (vec![ValType::I32, ValType::I64], vec![ValType::I32]),
+ clock_res_get
+ ),
+ sync_fn!(
+ "clock_time_get",
+ (
+ vec![ValType::I32, ValType::I64, ValType::I32],
+ vec![ValType::I32],
+ ),
+ clock_time_get
+ ),
+ sync_fn!(
+ "random_get",
+ (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
+ random_get
+ ),
+ sync_fn!(
+ "fd_prestat_get",
+ (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
+ fd_prestat_get
+ ),
+ sync_fn!(
+ "fd_prestat_dir_name",
+ (
+ vec![ValType::I32, ValType::I32, ValType::I32],
+ vec![ValType::I32],
+ ),
+ fd_prestat_dir_name
+ ),
+ sync_fn!(
+ "fd_renumber",
+ (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
+ fd_renumber
+ ),
+ sync_fn!(
+ "fd_advise",
+ (
+ vec![ValType::I32, ValType::I64, ValType::I64, ValType::I32],
+ vec![ValType::I32],
+ ),
+ fd_advise
+ ),
+ sync_fn!(
+ "fd_allocate",
+ (
+ vec![ValType::I32, ValType::I64, ValType::I64],
+ vec![ValType::I32],
+ ),
+ fd_allocate
+ ),
+ sync_fn!(
+ "fd_close",
+ (vec![ValType::I32], vec![ValType::I32]),
+ fd_close
+ ),
+ sync_fn!(
+ "fd_seek",
+ (
+ vec![ValType::I32, ValType::I64, ValType::I32, ValType::I32],
+ vec![ValType::I32],
+ ),
+ fd_seek
+ ),
+ sync_fn!("fd_sync", (vec![ValType::I32], vec![ValType::I32]), fd_sync),
+ sync_fn!(
+ "fd_datasync",
+ (vec![ValType::I32], vec![ValType::I32]),
+ fd_datasync
+ ),
+ sync_fn!(
+ "fd_tell",
+ (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
+ fd_tell
+ ),
+ sync_fn!(
+ "fd_fdstat_get",
+ (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
+ fd_fdstat_get
+ ),
+ sync_fn!(
+ "fd_fdstat_set_flags",
+ (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
+ fd_fdstat_set_flags
+ ),
+ sync_fn!(
+ "fd_fdstat_set_rights",
+ (
+ vec![ValType::I32, ValType::I64, ValType::I64],
+ vec![ValType::I32],
+ ),
+ fd_fdstat_set_rights
+ ),
+ sync_fn!(
+ "fd_filestat_get",
+ (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
+ fd_filestat_get
+ ),
+ sync_fn!(
+ "fd_filestat_set_size",
+ (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
+ fd_filestat_set_size
+ ),
+ sync_fn!(
+ "fd_filestat_set_times",
+ (
+ vec![ValType::I32, ValType::I64, ValType::I64, ValType::I32],
+ vec![ValType::I32],
+ ),
+ fd_filestat_set_times
+ ),
+ sync_fn!(
+ "fd_read",
+ (
+ vec![ValType::I32, ValType::I32, ValType::I32, ValType::I32],
+ vec![ValType::I32],
+ ),
+ fd_read
+ ),
+ sync_fn!(
+ "fd_pread",
+ (
+ vec![
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I64,
+ ValType::I32,
+ ],
+ vec![ValType::I32],
+ ),
+ fd_pread
+ ),
+ sync_fn!(
+ "fd_write",
+ (
+ vec![ValType::I32, ValType::I32, ValType::I32, ValType::I32],
+ vec![ValType::I32],
+ ),
+ fd_write
+ ),
+ sync_fn!(
+ "fd_pwrite",
+ (
+ vec![
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I64,
+ ValType::I32,
+ ],
+ vec![ValType::I32],
+ ),
+ fd_pwrite
+ ),
+ sync_fn!(
+ "fd_readdir",
+ (
+ vec![
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I64,
+ ValType::I32,
+ ],
+ vec![ValType::I32],
+ ),
+ fd_readdir
+ ),
+ sync_fn!(
+ "path_create_directory",
+ (
+ vec![ValType::I32, ValType::I32, ValType::I32],
+ vec![ValType::I32],
+ ),
+ path_create_directory
+ ),
+ sync_fn!(
+ "path_filestat_get",
+ (
+ vec![
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ],
+ vec![ValType::I32],
+ ),
+ path_filestat_get
+ ),
+ sync_fn!(
+ "path_filestat_set_times",
+ (
+ vec![
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I64,
+ ValType::I64,
+ ValType::I32,
+ ],
+ vec![ValType::I32],
+ ),
+ path_filestat_set_times
+ ),
+ sync_fn!(
+ "path_link",
+ (
+ vec![
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ],
+ vec![ValType::I32],
+ ),
+ path_link
+ ),
+ sync_fn!(
+ "path_open",
+ (
+ vec![
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I64,
+ ValType::I64,
+ ValType::I32,
+ ValType::I32,
+ ],
+ vec![ValType::I32],
+ ),
+ path_open
+ ),
+ sync_fn!(
+ "path_readlink",
+ (
+ vec![
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ],
+ vec![ValType::I32],
+ ),
+ path_readlink
+ ),
+ sync_fn!(
+ "path_remove_directory",
+ (
+ vec![ValType::I32, ValType::I32, ValType::I32],
+ vec![ValType::I32],
+ ),
+ path_remove_directory
+ ),
+ sync_fn!(
+ "path_rename",
+ (
+ vec![
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ],
+ vec![ValType::I32],
+ ),
+ path_rename
+ ),
+ sync_fn!(
+ "path_symlink",
+ (
+ vec![
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ],
+ vec![ValType::I32],
+ ),
+ path_symlink
+ ),
+ sync_fn!(
+ "path_unlink_file",
+ (
+ vec![ValType::I32, ValType::I32, ValType::I32],
+ vec![ValType::I32],
+ ),
+ path_unlink_file
+ ),
+ sync_fn!("proc_exit", (vec![ValType::I32], vec![]), proc_exit),
+ sync_fn!(
+ "proc_raise",
+ (vec![ValType::I32], vec![ValType::I32]),
+ proc_raise
+ ),
+ sync_fn!("sched_yield", (vec![], vec![ValType::I32]), sched_yield),
+ sync_fn!(
+ "sock_open",
+ (
+ vec![ValType::I32, ValType::I32, ValType::I32],
+ vec![ValType::I32],
+ ),
+ sock_open
+ ),
+ sync_fn!(
+ "sock_bind",
+ (
+ vec![ValType::I32, ValType::I32, ValType::I32],
+ vec![ValType::I32],
+ ),
+ sock_bind
+ ),
+ sync_fn!(
+ "sock_listen",
+ (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
+ sock_listen
+ ),
+ async_fn!(
+ "sock_accept",
+ (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
+ sock_accept
+ ),
+ async_fn!(
+ "sock_connect",
+ (
+ vec![ValType::I32, ValType::I32, ValType::I32],
+ vec![ValType::I32],
+ ),
+ wrap_future(sock_connect)
+ ),
+ async_fn!(
+ "sock_recv",
+ (
+ vec![
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ],
+ vec![ValType::I32],
+ ),
+ wrap_future(sock_recv)
+ ),
+ async_fn!(
+ "sock_recv_from",
+ (
+ vec![
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ],
+ vec![ValType::I32],
+ ),
+ wrap_future(sock_recv_from)
+ ),
+ async_fn!(
+ "sock_send",
+ (
+ vec![
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ],
+ vec![ValType::I32],
+ ),
+ wrap_future(sock_send)
+ ),
+ async_fn!(
+ "sock_send_to",
+ (
+ vec![
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ],
+ vec![ValType::I32],
+ ),
+ wrap_future(sock_send_to)
+ ),
+ sync_fn!(
+ "sock_shutdown",
+ (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
+ sock_shutdown
+ ),
+ sync_fn!(
+ "sock_getpeeraddr",
+ (
+ vec![ValType::I32, ValType::I32, ValType::I32, ValType::I32],
+ vec![ValType::I32],
+ ),
+ sock_getpeeraddr
+ ),
+ sync_fn!(
+ "sock_getlocaladdr",
+ (
+ vec![ValType::I32, ValType::I32, ValType::I32, ValType::I32],
+ vec![ValType::I32],
+ ),
+ sock_getlocaladdr
+ ),
+ sync_fn!(
+ "sock_getsockopt",
+ (
+ vec![
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ],
+ vec![ValType::I32],
+ ),
+ sock_getsockopt
+ ),
+ sync_fn!(
+ "sock_setsockopt",
+ (
+ vec![
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ],
+ vec![ValType::I32],
+ ),
+ sock_setsockopt
+ ),
+ async_fn!(
+ "poll_oneoff",
+ (
+ vec![ValType::I32, ValType::I32, ValType::I32, ValType::I32],
+ vec![ValType::I32],
+ ),
+ wrap_future(poll_oneoff)
+ ),
+ async_fn!(
+ "epoll_oneoff",
+ (
+ vec![ValType::I32, ValType::I32, ValType::I32, ValType::I32],
+ vec![ValType::I32],
+ ),
+ wrap_future(poll_oneoff)
+ ),
+ async_fn!(
+ "sock_lookup_ip",
+ (
+ vec![
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ],
+ vec![ValType::I32],
+ ),
+ wrap_future(sock_lookup_ip)
+ ),
+ sync_fn!(
+ "sock_getaddrinfo",
+ (
+ vec![
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ValType::I32,
+ ],
+ vec![ValType::I32],
+ ),
+ sock_getaddrinfo
+ ),
+ ]
+}
+
+fn to_wasm_return(r: Result<(), Errno>) -> Vec<WasmValue> {
+ let code = if let Err(e) = r { e.0 } else { 0 };
+ log::trace!("wasi return {code}");
+ vec![WasmValue::from_i32(code as i32)]
+}
+
+impl async_wasi::snapshots::common::memory::Memory for Memory {
+ fn get_data<T: Sized>(&self, offset: WasmPtr<T>) -> Result<&T, Errno> {
+ unsafe {
+ let r = std::mem::size_of::<T>();
+ let ptr = self
+ .data_pointer(offset.0 as u32, r as u32)
+ .map_err(|_| Errno::__WASI_ERRNO_FAULT)?;
+ Ok(ptr.cast::<T>().as_ref().unwrap())
+ }
+ }
+
+ fn get_slice<T: Sized>(&self, offset: WasmPtr<T>, len: usize) -> Result<&[T], Errno> {
+ unsafe {
+ let r = std::mem::size_of::<T>() * len;
+ let ptr = self
+ .data_pointer(offset.0 as u32, r as u32)
+ .map_err(|_| Errno::__WASI_ERRNO_FAULT)? as *const T;
+ Ok(std::slice::from_raw_parts(ptr, len))
+ }
+ }
+
+ fn get_iovec<'a>(
+ &self,
+ iovec_ptr: WasmPtr<__wasi_ciovec_t>,
+ iovec_len: __wasi_size_t,
+ ) -> Result<Vec<std::io::IoSlice<'a>>, Errno> {
+ unsafe {
+ let iovec = self.get_slice(iovec_ptr, iovec_len as usize)?.to_vec();
+ let mut result = Vec::with_capacity(iovec.len());
+ for i in iovec {
+ let ptr = self
+ .data_pointer(i.buf, i.buf_len)
+ .map_err(|_| Errno::__WASI_ERRNO_FAULT)?;
+ let s = std::io::IoSlice::new(std::slice::from_raw_parts(ptr, i.buf_len as usize));
+ result.push(s);
+ }
+ Ok(result)
+ }
+ }
+
+ fn mut_data<T: Sized>(&mut self, offset: WasmPtr<T>) -> Result<&mut T, Errno> {
+ unsafe {
+ let r = std::mem::size_of::<T>();
+ let ptr = self
+ .data_pointer_mut(offset.0 as u32, r as u32)
+ .map_err(|_| Errno::__WASI_ERRNO_FAULT)?;
+ Ok(ptr.cast::<T>().as_mut().unwrap())
+ }
+ }
+
+ fn mut_slice<T: Sized>(&mut self, offset: WasmPtr<T>, len: usize) -> Result<&mut [T], Errno> {
+ unsafe {
+ let r = std::mem::size_of::<T>() * len;
+ let ptr = self
+ .data_pointer_mut(offset.0 as u32, r as u32)
+ .map_err(|_| Errno::__WASI_ERRNO_FAULT)? as *mut T;
+ Ok(std::slice::from_raw_parts_mut(ptr, len))
+ }
+ }
+
+ fn mut_iovec(
+ &mut self,
+ iovec_ptr: WasmPtr<async_wasi::snapshots::env::wasi_types::__wasi_iovec_t>,
+ iovec_len: async_wasi::snapshots::env::wasi_types::__wasi_size_t,
+ ) -> Result<Vec<std::io::IoSliceMut<'_>>, Errno> {
+ unsafe {
+ let iovec = self.get_slice(iovec_ptr, iovec_len as usize)?.to_vec();
+ let mut result = Vec::with_capacity(iovec.len());
+ for i in iovec {
+ let ptr = self
+ .data_pointer_mut(i.buf, i.buf_len)
+ .map_err(|_| Errno::__WASI_ERRNO_FAULT)?;
+ let s = std::io::IoSliceMut::new(std::slice::from_raw_parts_mut(
+ ptr,
+ i.buf_len as usize,
+ ));
+ result.push(s);
+ }
+ Ok(result)
+ }
+ }
+
+ fn write_data<T: Sized>(&mut self, offset: WasmPtr<T>, data: T) -> Result<(), Errno> {
+ let p = self.mut_data(offset)?;
+ *p = data;
+ Ok(())
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::{r#async::fiber::AsyncState, Executor, Loader, Store, Validator};
+
+ #[tokio::test]
+ async fn test_async_wasi_module() -> Result<(), Box<dyn std::error::Error>> {
+ let result = Executor::create(None, None);
+ assert!(result.is_ok());
+ let mut executor = result.unwrap();
+ assert!(!executor.inner.0.is_null());
+
+ let result = Store::create();
+ assert!(result.is_ok());
+ let mut store = result.unwrap();
+
+ let result = AsyncWasiModule::create(Some(vec!["abc"]), Some(vec![("ENV", "1")]));
+ assert!(result.is_ok());
+ let mut async_wasi_module = result.unwrap();
+
+ let result = executor.register_import_module(&mut store, async_wasi_module.as_mut());
+ assert!(result.is_ok());
+
+ let wasm_file = std::env::current_dir()
+ .unwrap()
+ .ancestors()
+ .nth(2)
+ .unwrap()
+ .join("examples/wasmedge-sys/async_hello.wasm");
+ let module = Loader::create(None)?.from_file(&wasm_file)?;
+ Validator::create(None)?.validate(&module)?;
+ let mut instance = executor.register_active_module(&mut store, &module)?;
+ let mut fn_start = instance.get_func_mut("_start")?;
+
+ async fn tick() {
+ let mut i = 0;
+ loop {
+ println!("[tick] i={i}");
+ tokio::time::sleep(std::time::Duration::from_millis(500)).await;
+ i += 1;
+ }
+ }
+ tokio::spawn(tick());
+
+ let async_state = AsyncState::new();
+ let _ = executor
+ .call_func_async(&async_state, &mut fn_start, [])
+ .await?;
+
+ Ok(())
+ }
+}
+