Skip to main content

wasmedge_sys/async/
module.rs

1use crate::{
2    instance::function::SyncFn, AsInstance, CallingFrame, FuncType, Function, ImportModule,
3    Instance, Memory, WasmEdgeResult, WasmValue,
4};
5use async_wasi::snapshots::{
6    common::{
7        error::Errno,
8        memory::WasmPtr,
9        types::{__wasi_ciovec_t, __wasi_size_t},
10    },
11    preview_1 as p, WasiCtx,
12};
13use std::{
14    future::Future,
15    ops::{Deref, DerefMut},
16};
17use wasmedge_types::{
18    error::{CoreCommonError, CoreError, CoreExecutionError},
19    ValType,
20};
21
22use super::function::{AsyncFn, AsyncFunction};
23
24#[derive(Debug)]
25pub struct AsyncInstance(pub(crate) Instance);
26
27impl AsRef<Instance> for AsyncInstance {
28    fn as_ref(&self) -> &Instance {
29        &self.0
30    }
31}
32
33impl AsMut<Instance> for AsyncInstance {
34    fn as_mut(&mut self) -> &mut Instance {
35        &mut self.0
36    }
37}
38
39#[derive(Debug)]
40pub struct AsyncImportObject<T: Send>(ImportModule<T>);
41impl<T: Send> Deref for AsyncImportObject<T> {
42    type Target = ImportModule<T>;
43    fn deref(&self) -> &Self::Target {
44        &self.0
45    }
46}
47impl<T: Send> DerefMut for AsyncImportObject<T> {
48    fn deref_mut(&mut self) -> &mut Self::Target {
49        &mut self.0
50    }
51}
52
53impl<T: Send> AsyncImportObject<T> {
54    pub fn create(name: impl AsRef<str>, data: Box<T>) -> WasmEdgeResult<Self> {
55        let inner = ImportModule::create(name, data)?;
56        Ok(AsyncImportObject(inner))
57    }
58
59    pub fn add_async_func(&mut self, name: impl AsRef<str>, func: AsyncFunction) {
60        self.0.add_func(name, func.0);
61    }
62}
63impl<T: Send> AsRef<ImportModule<T>> for AsyncImportObject<T> {
64    fn as_ref(&self) -> &ImportModule<T> {
65        &self.0
66    }
67}
68impl<T: Send> AsMut<ImportModule<T>> for AsyncImportObject<T> {
69    fn as_mut(&mut self) -> &mut ImportModule<T> {
70        &mut self.0
71    }
72}
73
74impl<T: Send> AsInstance for AsyncImportObject<T> {
75    unsafe fn as_ptr(&self) -> *const crate::ffi::WasmEdge_ModuleInstanceContext {
76        self.0.as_ptr()
77    }
78}
79
80/// A [AsyncWasiModule] is a module instance for the WASI specification and used in the `async` scenario.
81#[derive(Debug)]
82pub struct AsyncWasiModule(AsyncImportObject<WasiCtx>);
83
84impl AsRef<AsyncImportObject<WasiCtx>> for AsyncWasiModule {
85    fn as_ref(&self) -> &AsyncImportObject<WasiCtx> {
86        &self.0
87    }
88}
89
90impl AsMut<AsyncImportObject<WasiCtx>> for AsyncWasiModule {
91    fn as_mut(&mut self) -> &mut AsyncImportObject<WasiCtx> {
92        &mut self.0
93    }
94}
95
96impl AsyncWasiModule {
97    /// Creates a [AsyncWasiModule] instance.
98    ///
99    /// # Arguments
100    ///
101    /// * `args` - The commandline arguments. The first argument is the program name.
102    ///
103    /// * `envs` - The environment variables.
104    ///
105    /// # Error
106    ///
107    /// If fail to create a [AsyncWasiModule] instance, then an error is returned.
108    pub fn create(
109        args: Option<Vec<impl AsRef<str>>>,
110        envs: Option<Vec<(impl AsRef<str>, impl AsRef<str>)>>,
111    ) -> WasmEdgeResult<Self> {
112        // create wasi context
113        let mut wasi_ctx = WasiCtx::new();
114
115        // push args, envs and preopens
116        if let Some(args) = args {
117            wasi_ctx.push_args(args.iter().map(|x| x.as_ref().to_string()).collect());
118        }
119        if let Some(envs) = envs {
120            wasi_ctx.push_envs(
121                envs.iter()
122                    .map(|(k, v)| format!("{}={}", k.as_ref(), v.as_ref()))
123                    .collect(),
124            );
125        }
126
127        Self::create_from_wasi_context(wasi_ctx)
128    }
129
130    /// Creates a [AsyncWasiModule] instance with the given wasi context.
131    ///
132    /// # Arguments
133    ///
134    /// * `wasi_ctx` - The [WasiCtx](async_wasi::snapshots::WasiCtx) instance.
135    ///
136    /// # Error
137    ///
138    /// If fail to create [AsyncWasiModule] instance, then an error is returned.
139    pub fn create_from_wasi_context(wasi_ctx: WasiCtx) -> WasmEdgeResult<Self> {
140        // create wasi module
141        let name = "wasi_snapshot_preview1";
142
143        let mut async_wasi_module = Self(AsyncImportObject::create(name, Box::new(wasi_ctx))?);
144
145        // add sync/async host functions to the module
146        for wasi_func in wasi_impls() {
147            match wasi_func {
148                WasiFunc::SyncFn(name, (ty_args, ty_rets), real_fn) => {
149                    let func_ty = FuncType::new(ty_args, ty_rets);
150
151                    let func = unsafe {
152                        Function::create_sync_func(
153                            &func_ty,
154                            real_fn,
155                            async_wasi_module.0.get_host_data_mut(),
156                            0,
157                        )
158                    }?;
159
160                    async_wasi_module.0.add_func(&name, func);
161                }
162                WasiFunc::AsyncFn(name, (ty_args, ty_rets), real_async_fn) => {
163                    let func_ty = FuncType::new(ty_args, ty_rets);
164
165                    let func = AsyncFunction::create_async_func(
166                        &func_ty,
167                        real_async_fn,
168                        async_wasi_module.0.get_host_data_mut(),
169                        0,
170                    )?;
171
172                    async_wasi_module.0.add_async_func(&name, func);
173                }
174            }
175        }
176
177        Ok(async_wasi_module)
178    }
179
180    /// Returns the name of the module instance.
181    pub fn name(&self) -> &str {
182        "wasi_snapshot_preview1"
183    }
184
185    /// Returns the WASI exit code.
186    ///
187    /// The WASI exit code can be accessed after running the "_start" function of a `wasm32-wasi` program.
188    pub fn exit_code(&self) -> u32 {
189        self.0.get_host_data().exit_code
190    }
191}
192
193// ============== wasi host functions ==============
194
195fn args_get(
196    data: &mut WasiCtx,
197    _inst: &mut Instance,
198    frame: &mut CallingFrame,
199    args: Vec<WasmValue>,
200) -> Result<Vec<WasmValue>, CoreError> {
201    let mut mem = frame
202        .memory_mut(0)
203        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
204
205    if let Some([argv, argv_buf]) = args.get(0..2) {
206        let argv = argv.to_i32() as usize;
207        let argv_buf = argv_buf.to_i32() as usize;
208        Ok(to_wasm_return(p::args_get(
209            data,
210            &mut *mem,
211            WasmPtr::from(argv),
212            WasmPtr::from(argv_buf),
213        )))
214    } else {
215        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
216    }
217}
218
219fn args_sizes_get(
220    data: &mut WasiCtx,
221    _inst: &mut Instance,
222    frame: &mut CallingFrame,
223    args: Vec<WasmValue>,
224) -> Result<Vec<WasmValue>, CoreError> {
225    let mut mem = frame
226        .memory_mut(0)
227        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
228
229    if let Some([argc, argv_buf_size]) = args.get(0..2) {
230        let argc = argc.to_i32() as usize;
231        let argv_buf_size = argv_buf_size.to_i32() as usize;
232        Ok(to_wasm_return(p::args_sizes_get(
233            data,
234            &mut mem as &mut Memory,
235            WasmPtr::from(argc),
236            WasmPtr::from(argv_buf_size),
237        )))
238    } else {
239        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
240    }
241}
242
243fn environ_get(
244    data: &mut WasiCtx,
245    _inst: &mut Instance,
246    frame: &mut CallingFrame,
247    args: Vec<WasmValue>,
248) -> Result<Vec<WasmValue>, CoreError> {
249    let mut mem = frame
250        .memory_mut(0)
251        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
252
253    if let Some([p1, p2]) = args.get(0..2) {
254        let environ = p1.to_i32() as usize;
255        let environ_buf = p2.to_i32() as usize;
256        Ok(to_wasm_return(p::environ_get(
257            data,
258            &mut mem as &mut Memory,
259            WasmPtr::from(environ),
260            WasmPtr::from(environ_buf),
261        )))
262    } else {
263        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
264    }
265}
266
267fn environ_sizes_get(
268    data: &mut WasiCtx,
269    _inst: &mut Instance,
270    frame: &mut CallingFrame,
271    args: Vec<WasmValue>,
272) -> Result<Vec<WasmValue>, CoreError> {
273    let mut mem = frame
274        .memory_mut(0)
275        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
276
277    if let Some([p1, p2]) = args.get(0..2) {
278        let environ_count = p1.to_i32() as usize;
279        let environ_buf_size = p2.to_i32() as usize;
280        Ok(to_wasm_return(p::environ_sizes_get(
281            data,
282            &mut mem as &mut Memory,
283            WasmPtr::from(environ_count),
284            WasmPtr::from(environ_buf_size),
285        )))
286    } else {
287        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
288    }
289}
290
291fn clock_res_get(
292    data: &mut WasiCtx,
293    _inst: &mut Instance,
294    frame: &mut CallingFrame,
295    args: Vec<WasmValue>,
296) -> Result<Vec<WasmValue>, CoreError> {
297    let mut mem = frame
298        .memory_mut(0)
299        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
300
301    if let Some([p1, p2]) = args.get(0..2) {
302        let clock_id = p1.to_i32() as u32;
303        let resolution_ptr = p2.to_i32() as usize;
304        Ok(to_wasm_return(p::clock_res_get(
305            data,
306            &mut mem as &mut Memory,
307            clock_id,
308            WasmPtr::from(resolution_ptr),
309        )))
310    } else {
311        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
312    }
313}
314
315fn clock_time_get(
316    data: &mut WasiCtx,
317    _inst: &mut Instance,
318    frame: &mut CallingFrame,
319    args: Vec<WasmValue>,
320) -> Result<Vec<WasmValue>, CoreError> {
321    let mut mem = frame
322        .memory_mut(0)
323        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
324
325    if let Some([p1, p2, p3]) = args.get(0..3) {
326        let clock_id = p1.to_i32() as u32;
327        let precision = p2.to_i64() as u64;
328        let time_ptr = p3.to_i32() as usize;
329
330        Ok(to_wasm_return(p::clock_time_get(
331            data,
332            &mut mem as &mut Memory,
333            clock_id,
334            precision,
335            WasmPtr::from(time_ptr),
336        )))
337    } else {
338        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
339    }
340}
341
342fn random_get(
343    data: &mut WasiCtx,
344    _inst: &mut Instance,
345    frame: &mut CallingFrame,
346    args: Vec<WasmValue>,
347) -> Result<Vec<WasmValue>, CoreError> {
348    let mut mem = frame
349        .memory_mut(0)
350        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
351
352    if let Some([p1, p2]) = args.get(0..2) {
353        let buf = p1.to_i32() as usize;
354        let buf_len = p2.to_i32() as u32;
355
356        Ok(to_wasm_return(p::random_get(
357            data,
358            &mut mem as &mut Memory,
359            WasmPtr::from(buf),
360            buf_len,
361        )))
362    } else {
363        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
364    }
365}
366
367fn fd_prestat_get(
368    data: &mut WasiCtx,
369    _inst: &mut Instance,
370    frame: &mut CallingFrame,
371    args: Vec<WasmValue>,
372) -> Result<Vec<WasmValue>, CoreError> {
373    let mut mem = frame
374        .memory_mut(0)
375        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
376
377    if let Some([p1, p2]) = args.get(0..2) {
378        let fd = p1.to_i32();
379        let prestat_ptr = p2.to_i32() as usize;
380
381        Ok(to_wasm_return(p::fd_prestat_get(
382            data,
383            &mut mem as &mut Memory,
384            fd,
385            WasmPtr::from(prestat_ptr),
386        )))
387    } else {
388        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
389    }
390}
391
392fn fd_prestat_dir_name(
393    data: &mut WasiCtx,
394    _inst: &mut Instance,
395    frame: &mut CallingFrame,
396    args: Vec<WasmValue>,
397) -> Result<Vec<WasmValue>, CoreError> {
398    let mut mem = frame
399        .memory_mut(0)
400        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
401
402    if let Some([p1, p2, p3]) = args.get(0..3) {
403        let fd = p1.to_i32();
404        let path_buf_ptr = p2.to_i32() as usize;
405        let path_max_len = p3.to_i32() as u32;
406
407        Ok(to_wasm_return(p::fd_prestat_dir_name(
408            data,
409            &mut mem as &mut Memory,
410            fd,
411            WasmPtr::from(path_buf_ptr),
412            path_max_len,
413        )))
414    } else {
415        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
416    }
417}
418
419fn fd_renumber(
420    data: &mut WasiCtx,
421    _inst: &mut Instance,
422    frame: &mut CallingFrame,
423    args: Vec<WasmValue>,
424) -> Result<Vec<WasmValue>, CoreError> {
425    let mut mem = frame
426        .memory_mut(0)
427        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
428
429    if let Some([p1, p2]) = args.get(0..2) {
430        let from = p1.to_i32();
431        let to = p2.to_i32();
432
433        Ok(to_wasm_return(p::fd_renumber(
434            data,
435            &mut mem as &mut Memory,
436            from,
437            to,
438        )))
439    } else {
440        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
441    }
442}
443
444fn fd_advise(
445    data: &mut WasiCtx,
446    _inst: &mut Instance,
447    frame: &mut CallingFrame,
448    args: Vec<WasmValue>,
449) -> Result<Vec<WasmValue>, CoreError> {
450    let mut mem = frame
451        .memory_mut(0)
452        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
453
454    if let Some([p1, p2, p3, p4]) = args.get(0..4) {
455        let fd = p1.to_i32();
456        let offset = p2.to_i64() as u64;
457        let len = p3.to_i64() as u64;
458        let advice = p4.to_i32() as u8;
459
460        Ok(to_wasm_return(p::fd_advise(
461            data,
462            &mut mem as &mut Memory,
463            fd,
464            offset,
465            len,
466            advice,
467        )))
468    } else {
469        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
470    }
471}
472
473fn fd_allocate(
474    data: &mut WasiCtx,
475    _inst: &mut Instance,
476    frame: &mut CallingFrame,
477    args: Vec<WasmValue>,
478) -> Result<Vec<WasmValue>, CoreError> {
479    let mut mem = frame
480        .memory_mut(0)
481        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
482
483    if let Some([p1, p2, p3]) = args.get(0..3) {
484        let fd = p1.to_i32();
485        let offset = p2.to_i64() as u64;
486        let len = p3.to_i64() as u64;
487
488        Ok(to_wasm_return(p::fd_allocate(
489            data,
490            &mut mem as &mut Memory,
491            fd,
492            offset,
493            len,
494        )))
495    } else {
496        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
497    }
498}
499
500fn fd_close(
501    data: &mut WasiCtx,
502    _inst: &mut Instance,
503    frame: &mut CallingFrame,
504    args: Vec<WasmValue>,
505) -> Result<Vec<WasmValue>, CoreError> {
506    let mut mem = frame
507        .memory_mut(0)
508        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
509
510    if let Some([p1]) = args.get(0..1) {
511        let fd = p1.to_i32();
512
513        Ok(to_wasm_return(p::fd_close(
514            data,
515            &mut mem as &mut Memory,
516            fd,
517        )))
518    } else {
519        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
520    }
521}
522
523fn fd_seek(
524    data: &mut WasiCtx,
525    _inst: &mut Instance,
526    frame: &mut CallingFrame,
527    args: Vec<WasmValue>,
528) -> Result<Vec<WasmValue>, CoreError> {
529    let mut mem = frame
530        .memory_mut(0)
531        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
532
533    if let Some([p1, p2, p3, p4]) = args.get(0..4) {
534        let fd = p1.to_i32();
535        let offset = p2.to_i64();
536        let whence = p3.to_i32() as u8;
537        let newoffset_ptr = p4.to_i32() as usize;
538
539        Ok(to_wasm_return(p::fd_seek(
540            data,
541            &mut mem as &mut Memory,
542            fd,
543            offset,
544            whence,
545            WasmPtr::from(newoffset_ptr),
546        )))
547    } else {
548        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
549    }
550}
551
552fn fd_sync(
553    data: &mut WasiCtx,
554    _inst: &mut Instance,
555    frame: &mut CallingFrame,
556    args: Vec<WasmValue>,
557) -> Result<Vec<WasmValue>, CoreError> {
558    let mut mem = frame
559        .memory_mut(0)
560        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
561
562    if let Some([p1]) = args.get(0..1) {
563        let fd = p1.to_i32();
564
565        Ok(to_wasm_return(p::fd_sync(
566            data,
567            &mut mem as &mut Memory,
568            fd,
569        )))
570    } else {
571        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
572    }
573}
574
575fn fd_datasync(
576    data: &mut WasiCtx,
577    _inst: &mut Instance,
578    frame: &mut CallingFrame,
579    args: Vec<WasmValue>,
580) -> Result<Vec<WasmValue>, CoreError> {
581    let mut mem = frame
582        .memory_mut(0)
583        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
584
585    if let Some([p1]) = args.get(0..1) {
586        let fd = p1.to_i32();
587
588        Ok(to_wasm_return(p::fd_datasync(
589            data,
590            &mut mem as &mut Memory,
591            fd,
592        )))
593    } else {
594        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
595    }
596}
597
598fn fd_tell(
599    data: &mut WasiCtx,
600    _inst: &mut Instance,
601    frame: &mut CallingFrame,
602    args: Vec<WasmValue>,
603) -> Result<Vec<WasmValue>, CoreError> {
604    let mut mem = frame
605        .memory_mut(0)
606        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
607
608    if let Some([p1, p2]) = args.get(0..2) {
609        let fd = p1.to_i32();
610        let offset = p2.to_i32() as usize;
611
612        Ok(to_wasm_return(p::fd_tell(
613            data,
614            &mut mem as &mut Memory,
615            fd,
616            WasmPtr::from(offset),
617        )))
618    } else {
619        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
620    }
621}
622
623fn fd_fdstat_get(
624    data: &mut WasiCtx,
625    _inst: &mut Instance,
626    frame: &mut CallingFrame,
627    args: Vec<WasmValue>,
628) -> Result<Vec<WasmValue>, CoreError> {
629    let mut mem = frame
630        .memory_mut(0)
631        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
632
633    if let Some([p1, p2]) = args.get(0..2) {
634        let fd = p1.to_i32();
635        let buf_ptr = p2.to_i32() as usize;
636
637        Ok(to_wasm_return(p::fd_fdstat_get(
638            data,
639            &mut mem as &mut Memory,
640            fd,
641            WasmPtr::from(buf_ptr),
642        )))
643    } else {
644        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
645    }
646}
647
648fn fd_fdstat_set_flags(
649    data: &mut WasiCtx,
650    _inst: &mut Instance,
651    frame: &mut CallingFrame,
652    args: Vec<WasmValue>,
653) -> Result<Vec<WasmValue>, CoreError> {
654    let mut mem = frame
655        .memory_mut(0)
656        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
657
658    if let Some([p1, p2]) = args.get(0..2) {
659        let fd = p1.to_i32();
660        let flags = p2.to_i32() as u16;
661
662        Ok(to_wasm_return(p::fd_fdstat_set_flags(
663            data,
664            &mut mem as &mut Memory,
665            fd,
666            flags,
667        )))
668    } else {
669        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
670    }
671}
672
673fn fd_fdstat_set_rights(
674    data: &mut WasiCtx,
675    _inst: &mut Instance,
676    frame: &mut CallingFrame,
677    args: Vec<WasmValue>,
678) -> Result<Vec<WasmValue>, CoreError> {
679    let mut mem = frame
680        .memory_mut(0)
681        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
682
683    if let Some([p1, p2, p3]) = args.get(0..3) {
684        let fd = p1.to_i32();
685        let fs_rights_base = p2.to_i64() as u64;
686        let fs_rights_inheriting = p3.to_i64() as u64;
687
688        Ok(to_wasm_return(p::fd_fdstat_set_rights(
689            data,
690            &mut mem as &mut Memory,
691            fd,
692            fs_rights_base,
693            fs_rights_inheriting,
694        )))
695    } else {
696        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
697    }
698}
699
700fn fd_filestat_get(
701    data: &mut WasiCtx,
702    _inst: &mut Instance,
703    frame: &mut CallingFrame,
704    args: Vec<WasmValue>,
705) -> Result<Vec<WasmValue>, CoreError> {
706    let mut mem = frame
707        .memory_mut(0)
708        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
709
710    if let Some([p1, p2]) = args.get(0..2) {
711        let fd = p1.to_i32();
712        let buf = p2.to_i32() as usize;
713
714        Ok(to_wasm_return(p::fd_filestat_get(
715            data,
716            &mut mem as &mut Memory,
717            fd,
718            WasmPtr::from(buf),
719        )))
720    } else {
721        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
722    }
723}
724
725fn fd_filestat_set_size(
726    data: &mut WasiCtx,
727    _inst: &mut Instance,
728    frame: &mut CallingFrame,
729    args: Vec<WasmValue>,
730) -> Result<Vec<WasmValue>, CoreError> {
731    let mut mem = frame
732        .memory_mut(0)
733        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
734
735    if let Some([p1, p2]) = args.get(0..2) {
736        let fd = p1.to_i32();
737        let buf = p2.to_i32() as usize;
738
739        Ok(to_wasm_return(p::fd_filestat_get(
740            data,
741            &mut mem as &mut Memory,
742            fd,
743            WasmPtr::from(buf),
744        )))
745    } else {
746        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
747    }
748}
749
750fn fd_filestat_set_times(
751    data: &mut WasiCtx,
752    _inst: &mut Instance,
753    frame: &mut CallingFrame,
754    args: Vec<WasmValue>,
755) -> Result<Vec<WasmValue>, CoreError> {
756    let mut mem = frame
757        .memory_mut(0)
758        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
759
760    if let Some([p1, p2, p3, p4]) = args.get(0..4) {
761        let fd = p1.to_i32();
762        let st_atim = p2.to_i64() as u64;
763        let st_mtim = p3.to_i64() as u64;
764        let fst_flags = p4.to_i32() as u16;
765
766        Ok(to_wasm_return(p::fd_filestat_set_times(
767            data,
768            &mut mem as &mut Memory,
769            fd,
770            st_atim,
771            st_mtim,
772            fst_flags,
773        )))
774    } else {
775        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
776    }
777}
778
779fn fd_read(
780    data: &mut WasiCtx,
781    _inst: &mut Instance,
782    frame: &mut CallingFrame,
783    args: Vec<WasmValue>,
784) -> Result<Vec<WasmValue>, CoreError> {
785    let mut mem = frame
786        .memory_mut(0)
787        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
788
789    if let Some([p1, p2, p3, p4]) = args.get(0..4) {
790        let fd = p1.to_i32();
791        let iovs = p2.to_i32() as usize;
792        let iovs_len = p3.to_i32() as u32;
793        let nread = p4.to_i32() as usize;
794
795        Ok(to_wasm_return(p::fd_read(
796            data,
797            &mut mem as &mut Memory,
798            fd,
799            WasmPtr::from(iovs),
800            iovs_len,
801            WasmPtr::from(nread),
802        )))
803    } else {
804        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
805    }
806}
807
808fn fd_pread(
809    data: &mut WasiCtx,
810    _inst: &mut Instance,
811    frame: &mut CallingFrame,
812    args: Vec<WasmValue>,
813) -> Result<Vec<WasmValue>, CoreError> {
814    let mut mem = frame
815        .memory_mut(0)
816        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
817
818    if let Some([p1, p2, p3, p4, p5]) = args.get(0..5) {
819        let fd = p1.to_i32();
820        let iovs = p2.to_i32() as usize;
821        let iovs_len = p3.to_i32() as u32;
822        let offset = p4.to_i64() as u64;
823        let nread = p5.to_i32() as usize;
824
825        Ok(to_wasm_return(p::fd_pread(
826            data,
827            &mut mem as &mut Memory,
828            fd,
829            WasmPtr::from(iovs),
830            iovs_len,
831            offset,
832            WasmPtr::from(nread),
833        )))
834    } else {
835        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
836    }
837}
838
839fn fd_write(
840    data: &mut WasiCtx,
841    _inst: &mut Instance,
842    frame: &mut CallingFrame,
843    args: Vec<WasmValue>,
844) -> Result<Vec<WasmValue>, CoreError> {
845    let mut mem = frame
846        .memory_mut(0)
847        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
848
849    if let Some([p1, p2, p3, p4]) = args.get(0..4) {
850        let fd = p1.to_i32();
851        let iovs = p2.to_i32() as usize;
852        let iovs_len = p3.to_i32() as u32;
853        let nwritten = p4.to_i32() as usize;
854
855        Ok(to_wasm_return(p::fd_write(
856            data,
857            &mut mem as &mut Memory,
858            fd,
859            WasmPtr::from(iovs),
860            iovs_len,
861            WasmPtr::from(nwritten),
862        )))
863    } else {
864        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
865    }
866}
867
868fn fd_pwrite(
869    data: &mut WasiCtx,
870    _inst: &mut Instance,
871    frame: &mut CallingFrame,
872    args: Vec<WasmValue>,
873) -> Result<Vec<WasmValue>, CoreError> {
874    let mut mem = frame
875        .memory_mut(0)
876        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
877
878    if let Some([p1, p2, p3, p4, p5]) = args.get(0..5) {
879        let fd = p1.to_i32();
880        let iovs = p2.to_i32() as usize;
881        let iovs_len = p3.to_i32() as u32;
882        let offset = p4.to_i64() as u64;
883        let nwritten = p5.to_i32() as usize;
884
885        Ok(to_wasm_return(p::fd_pwrite(
886            data,
887            &mut mem as &mut Memory,
888            fd,
889            WasmPtr::from(iovs),
890            iovs_len,
891            offset,
892            WasmPtr::from(nwritten),
893        )))
894    } else {
895        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
896    }
897}
898
899fn fd_readdir(
900    data: &mut WasiCtx,
901    _inst: &mut Instance,
902    frame: &mut CallingFrame,
903    args: Vec<WasmValue>,
904) -> Result<Vec<WasmValue>, CoreError> {
905    let mut mem = frame
906        .memory_mut(0)
907        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
908
909    if let Some([p1, p2, p3, p4, p5]) = args.get(0..5) {
910        let fd = p1.to_i32();
911        let buf = p2.to_i32() as usize;
912        let buf_len = p3.to_i32() as u32;
913        let cookie = p4.to_i64() as u64;
914        let bufused_ptr = p5.to_i32() as usize;
915
916        Ok(to_wasm_return(p::fd_readdir(
917            data,
918            &mut mem as &mut Memory,
919            fd,
920            WasmPtr::from(buf),
921            buf_len,
922            cookie,
923            WasmPtr::from(bufused_ptr),
924        )))
925    } else {
926        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
927    }
928}
929
930fn path_create_directory(
931    data: &mut WasiCtx,
932    _inst: &mut Instance,
933    frame: &mut CallingFrame,
934    args: Vec<WasmValue>,
935) -> Result<Vec<WasmValue>, CoreError> {
936    let mem = frame
937        .memory_mut(0)
938        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
939
940    if let Some([p1, p2, p3]) = args.get(0..3) {
941        let dirfd = p1.to_i32();
942        let path_ptr = p2.to_i32() as usize;
943        let path_len = p3.to_i32() as u32;
944
945        Ok(to_wasm_return(p::path_create_directory(
946            data,
947            &mem as &Memory,
948            dirfd,
949            WasmPtr::from(path_ptr),
950            path_len,
951        )))
952    } else {
953        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
954    }
955}
956
957fn path_filestat_get(
958    data: &mut WasiCtx,
959    _inst: &mut Instance,
960    frame: &mut CallingFrame,
961    args: Vec<WasmValue>,
962) -> Result<Vec<WasmValue>, CoreError> {
963    let mut mem = frame
964        .memory_mut(0)
965        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
966
967    if let Some([p1, p2, p3, p4, p5]) = args.get(0..5) {
968        let fd = p1.to_i32();
969        let flags = p2.to_i32() as u32;
970        let path_ptr = p3.to_i32() as usize;
971        let path_len = p4.to_i32() as u32;
972        let file_stat_ptr = p5.to_i32() as usize;
973
974        Ok(to_wasm_return(p::path_filestat_get(
975            data,
976            &mut mem as &mut Memory,
977            fd,
978            flags,
979            WasmPtr::from(path_ptr),
980            path_len,
981            WasmPtr::from(file_stat_ptr),
982        )))
983    } else {
984        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
985    }
986}
987
988fn path_filestat_set_times(
989    _data: &mut WasiCtx,
990    _inst: &mut Instance,
991    _frame: &mut CallingFrame,
992    _args: Vec<WasmValue>,
993) -> Result<Vec<WasmValue>, CoreError> {
994    Ok(vec![WasmValue::from_i32(
995        Errno::__WASI_ERRNO_NOSYS.0 as i32,
996    )])
997}
998
999fn path_link(
1000    _data: &mut WasiCtx,
1001    _inst: &mut Instance,
1002    _frame: &mut CallingFrame,
1003    _args: Vec<WasmValue>,
1004) -> Result<Vec<WasmValue>, CoreError> {
1005    Ok(vec![WasmValue::from_i32(
1006        Errno::__WASI_ERRNO_NOSYS.0 as i32,
1007    )])
1008}
1009
1010fn path_open(
1011    data: &mut WasiCtx,
1012    _inst: &mut Instance,
1013    frame: &mut CallingFrame,
1014    args: Vec<WasmValue>,
1015) -> Result<Vec<WasmValue>, CoreError> {
1016    let mut mem = frame
1017        .memory_mut(0)
1018        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
1019
1020    if let Some([p1, p2, p3, p4, p5, p6, p7, p8, p9]) = args.get(0..9) {
1021        let dirfd = p1.to_i32();
1022        let dirflags = p2.to_i32() as u32;
1023        let path = p3.to_i32() as usize;
1024        let path_len = p4.to_i32() as u32;
1025        let o_flags = p5.to_i32() as u16;
1026        let fs_rights_base = p6.to_i64() as u64;
1027        let fs_rights_inheriting = p7.to_i64() as u64;
1028        let fs_flags = p8.to_i32() as u16;
1029        let fd_ptr = p9.to_i32() as usize;
1030
1031        Ok(to_wasm_return(p::path_open(
1032            data,
1033            &mut mem as &mut Memory,
1034            dirfd,
1035            dirflags,
1036            WasmPtr::from(path),
1037            path_len,
1038            o_flags,
1039            fs_rights_base,
1040            fs_rights_inheriting,
1041            fs_flags,
1042            WasmPtr::from(fd_ptr),
1043        )))
1044    } else {
1045        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
1046    }
1047}
1048
1049fn path_readlink(
1050    _data: &mut WasiCtx,
1051    _inst: &mut Instance,
1052    _frame: &mut CallingFrame,
1053    _args: Vec<WasmValue>,
1054) -> Result<Vec<WasmValue>, CoreError> {
1055    Ok(vec![WasmValue::from_i32(
1056        Errno::__WASI_ERRNO_NOSYS.0 as i32,
1057    )])
1058}
1059
1060fn path_remove_directory(
1061    data: &mut WasiCtx,
1062    _inst: &mut Instance,
1063    frame: &mut CallingFrame,
1064    args: Vec<WasmValue>,
1065) -> Result<Vec<WasmValue>, CoreError> {
1066    let mem = frame
1067        .memory_mut(0)
1068        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
1069
1070    if let Some([p1, p2, p3]) = args.get(0..3) {
1071        let fd = p1.to_i32();
1072        let path_ptr = p2.to_i32() as usize;
1073        let path_len = p3.to_i32() as u32;
1074
1075        Ok(to_wasm_return(p::path_remove_directory(
1076            data,
1077            &mem as &Memory,
1078            fd,
1079            WasmPtr::from(path_ptr),
1080            path_len,
1081        )))
1082    } else {
1083        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
1084    }
1085}
1086
1087fn path_rename(
1088    data: &mut WasiCtx,
1089    _inst: &mut Instance,
1090    frame: &mut CallingFrame,
1091    args: Vec<WasmValue>,
1092) -> Result<Vec<WasmValue>, CoreError> {
1093    let mem = frame
1094        .memory_mut(0)
1095        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
1096
1097    if let Some([p1, p2, p3, p4, p5, p6]) = args.get(0..6) {
1098        let old_fd = p1.to_i32();
1099        let old_path = p2.to_i32() as usize;
1100        let old_path_len = p3.to_i32() as u32;
1101        let new_fd = p4.to_i32();
1102        let new_path = p5.to_i32() as usize;
1103        let new_path_len = p6.to_i32() as u32;
1104
1105        Ok(to_wasm_return(p::path_rename(
1106            data,
1107            &mem as &Memory,
1108            old_fd,
1109            WasmPtr::from(old_path),
1110            old_path_len,
1111            new_fd,
1112            WasmPtr::from(new_path),
1113            new_path_len,
1114        )))
1115    } else {
1116        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
1117    }
1118}
1119
1120fn path_symlink(
1121    _data: &mut WasiCtx,
1122    _inst: &mut Instance,
1123    _frame: &mut CallingFrame,
1124    _args: Vec<WasmValue>,
1125) -> Result<Vec<WasmValue>, CoreError> {
1126    Ok(vec![WasmValue::from_i32(
1127        Errno::__WASI_ERRNO_NOSYS.0 as i32,
1128    )])
1129}
1130
1131fn path_unlink_file(
1132    data: &mut WasiCtx,
1133    _inst: &mut Instance,
1134    frame: &mut CallingFrame,
1135    args: Vec<WasmValue>,
1136) -> Result<Vec<WasmValue>, CoreError> {
1137    let mem = frame
1138        .memory_mut(0)
1139        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
1140
1141    if let Some([p1, p2, p3]) = args.get(0..3) {
1142        let fd = p1.to_i32();
1143        let path_ptr = p2.to_i32() as usize;
1144        let path_len = p3.to_i32() as u32;
1145
1146        Ok(to_wasm_return(p::path_unlink_file(
1147            data,
1148            &mem as &Memory,
1149            fd,
1150            WasmPtr::from(path_ptr),
1151            path_len,
1152        )))
1153    } else {
1154        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
1155    }
1156}
1157
1158fn proc_exit(
1159    data: &mut WasiCtx,
1160    _inst: &mut Instance,
1161    frame: &mut CallingFrame,
1162    args: Vec<WasmValue>,
1163) -> Result<Vec<WasmValue>, CoreError> {
1164    let mut mem = frame
1165        .memory_mut(0)
1166        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
1167
1168    if let Some([p1]) = args.get(0..1) {
1169        let code = p1.to_i32() as u32;
1170        p::proc_exit(data, &mut mem as &mut Memory, code);
1171        Err(CoreError::Common(CoreCommonError::Terminated))
1172    } else {
1173        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
1174    }
1175}
1176
1177fn proc_raise(
1178    _data: &mut WasiCtx,
1179    _inst: &mut Instance,
1180    _frame: &mut CallingFrame,
1181    _args: Vec<WasmValue>,
1182) -> Result<Vec<WasmValue>, CoreError> {
1183    Ok(vec![WasmValue::from_i32(
1184        Errno::__WASI_ERRNO_NOSYS.0 as i32,
1185    )])
1186}
1187
1188// todo: ld asyncify yield
1189
1190fn sched_yield(
1191    _data: &mut WasiCtx,
1192    _inst: &mut Instance,
1193    _frame: &mut CallingFrame,
1194    _args: Vec<WasmValue>,
1195) -> Result<Vec<WasmValue>, CoreError> {
1196    Ok(vec![WasmValue::from_i32(
1197        Errno::__WASI_ERRNO_NOSYS.0 as i32,
1198    )])
1199}
1200
1201//socket
1202
1203fn sock_open(
1204    data: &mut WasiCtx,
1205    _inst: &mut Instance,
1206    frame: &mut CallingFrame,
1207    args: Vec<WasmValue>,
1208) -> Result<Vec<WasmValue>, CoreError> {
1209    let mut mem = frame
1210        .memory_mut(0)
1211        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
1212
1213    if let Some([p1, p2, p3]) = args.get(0..3) {
1214        let af = p1.to_i32() as u8;
1215        let ty = p2.to_i32() as u8;
1216        let ro_fd_ptr = p3.to_i32() as usize;
1217
1218        Ok(to_wasm_return(p::async_socket::sock_open(
1219            data,
1220            &mut mem as &mut Memory,
1221            af,
1222            ty,
1223            WasmPtr::from(ro_fd_ptr),
1224        )))
1225    } else {
1226        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
1227    }
1228}
1229
1230fn sock_bind(
1231    data: &mut WasiCtx,
1232    _inst: &mut Instance,
1233    frame: &mut CallingFrame,
1234    args: Vec<WasmValue>,
1235) -> Result<Vec<WasmValue>, CoreError> {
1236    let mem = frame
1237        .memory_mut(0)
1238        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
1239
1240    if let Some([p1, p2, p3]) = args.get(0..3) {
1241        let fd = p1.to_i32();
1242        let addr_ptr = p2.to_i32() as usize;
1243        let port = p3.to_i32() as u32;
1244        Ok(to_wasm_return(p::async_socket::sock_bind(
1245            data,
1246            &mem as &Memory,
1247            fd,
1248            WasmPtr::from(addr_ptr),
1249            port,
1250        )))
1251    } else {
1252        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
1253    }
1254}
1255
1256fn sock_listen(
1257    data: &mut WasiCtx,
1258    _inst: &mut Instance,
1259    frame: &mut CallingFrame,
1260    args: Vec<WasmValue>,
1261) -> Result<Vec<WasmValue>, CoreError> {
1262    let mut mem = frame
1263        .memory_mut(0)
1264        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
1265
1266    if let Some([p1, p2]) = args.get(0..2) {
1267        let fd = p1.to_i32();
1268        let backlog = p2.to_i32() as u32;
1269
1270        Ok(to_wasm_return(p::async_socket::sock_listen(
1271            data,
1272            &mut mem as &mut Memory,
1273            fd,
1274            backlog,
1275        )))
1276    } else {
1277        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
1278    }
1279}
1280
1281fn sock_accept<'data, 'inst, 'frame, 'fut>(
1282    data: &'data mut WasiCtx,
1283    _inst: &'inst mut AsyncInstance,
1284    frame: &'frame mut CallingFrame,
1285    args: Vec<WasmValue>,
1286) -> Box<dyn Future<Output = Result<Vec<WasmValue>, CoreError>> + Send + 'fut>
1287where
1288    'data: 'fut,
1289    'frame: 'fut,
1290    'inst: 'fut,
1291{
1292    Box::new(async move {
1293        let mut mem = frame
1294            .memory_mut(0)
1295            .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
1296
1297        if let Some([p1, p2]) = args.get(0..2) {
1298            let fd = p1.to_i32();
1299            let ro_fd_ptr = p2.to_i32() as usize;
1300
1301            Ok(to_wasm_return(
1302                p::async_socket::sock_accept(
1303                    data,
1304                    &mut mem as &mut Memory,
1305                    fd,
1306                    WasmPtr::from(ro_fd_ptr),
1307                )
1308                .await,
1309            ))
1310        } else {
1311            Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
1312        }
1313    })
1314}
1315
1316async fn sock_connect(
1317    data: &mut WasiCtx,
1318    _inst: &mut AsyncInstance,
1319    frame: &mut CallingFrame,
1320    args: Vec<WasmValue>,
1321) -> Result<Vec<WasmValue>, CoreError> {
1322    let mem = frame
1323        .memory_mut(0)
1324        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
1325
1326    if let Some([p1, p2, p3]) = args.get(0..3) {
1327        let fd = p1.to_i32();
1328        let addr_ptr = p2.to_i32() as usize;
1329        let port = p3.to_i32() as u32;
1330
1331        Ok(to_wasm_return(
1332            p::async_socket::sock_connect(data, &mem as &Memory, fd, WasmPtr::from(addr_ptr), port)
1333                .await,
1334        ))
1335    } else {
1336        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
1337    }
1338}
1339
1340async fn sock_recv(
1341    data: &mut WasiCtx,
1342    _inst: &mut AsyncInstance,
1343    frame: &mut CallingFrame,
1344    args: Vec<WasmValue>,
1345) -> Result<Vec<WasmValue>, CoreError> {
1346    let mut mem = frame
1347        .memory_mut(0)
1348        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
1349
1350    if let Some([p1, p2, p3, p4, p5, p6]) = args.get(0..6) {
1351        let fd = p1.to_i32();
1352        let buf_ptr = p2.to_i32() as usize;
1353        let buf_len = p3.to_i32() as u32;
1354        let flags = p4.to_i32() as u16;
1355        let ro_data_len_ptr = p5.to_i32() as usize;
1356        let ro_flags_ptr = p6.to_i32() as usize;
1357
1358        Ok(to_wasm_return(
1359            p::async_socket::sock_recv(
1360                data,
1361                &mut mem as &mut Memory,
1362                fd,
1363                WasmPtr::from(buf_ptr),
1364                buf_len,
1365                flags,
1366                WasmPtr::from(ro_data_len_ptr),
1367                WasmPtr::from(ro_flags_ptr),
1368            )
1369            .await,
1370        ))
1371    } else {
1372        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
1373    }
1374}
1375
1376async fn sock_recv_from(
1377    data: &mut WasiCtx,
1378    _inst: &mut AsyncInstance,
1379    frame: &mut CallingFrame,
1380    args: Vec<WasmValue>,
1381) -> Result<Vec<WasmValue>, CoreError> {
1382    let mut mem = frame
1383        .memory_mut(0)
1384        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
1385
1386    if let Some([p1, p2, p3, p4, p5, p6, p7, p8]) = args.get(0..8) {
1387        let fd = p1.to_i32();
1388        let buf_ptr = p2.to_i32() as usize;
1389        let buf_len = p3.to_i32() as u32;
1390        let wasi_addr_ptr = p4.to_i32() as usize;
1391        let flags = p5.to_i32() as u16;
1392        let port_ptr = p6.to_i32() as usize;
1393        let ro_data_len_ptr = p7.to_i32() as usize;
1394        let ro_flags_ptr = p8.to_i32() as usize;
1395
1396        Ok(to_wasm_return(
1397            p::async_socket::sock_recv_from(
1398                data,
1399                &mut mem as &mut Memory,
1400                fd,
1401                WasmPtr::from(buf_ptr),
1402                buf_len,
1403                WasmPtr::from(wasi_addr_ptr),
1404                flags,
1405                WasmPtr::from(port_ptr),
1406                WasmPtr::from(ro_data_len_ptr),
1407                WasmPtr::from(ro_flags_ptr),
1408            )
1409            .await,
1410        ))
1411    } else {
1412        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
1413    }
1414}
1415
1416async fn sock_send(
1417    data: &mut WasiCtx,
1418    _inst: &mut AsyncInstance,
1419    frame: &mut CallingFrame,
1420    args: Vec<WasmValue>,
1421) -> Result<Vec<WasmValue>, CoreError> {
1422    let mut mem = frame
1423        .memory_mut(0)
1424        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
1425
1426    if let Some([p1, p2, p3, p4, p5]) = args.get(0..5) {
1427        let fd = p1.to_i32();
1428        let buf_ptr = p2.to_i32() as usize;
1429        let buf_len = p3.to_i32() as u32;
1430        let flags = p4.to_i32() as u16;
1431        let send_len_ptr = p5.to_i32() as usize;
1432
1433        Ok(to_wasm_return(
1434            p::async_socket::sock_send(
1435                data,
1436                &mut mem as &mut Memory,
1437                fd,
1438                WasmPtr::from(buf_ptr),
1439                buf_len,
1440                flags,
1441                WasmPtr::from(send_len_ptr),
1442            )
1443            .await,
1444        ))
1445    } else {
1446        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
1447    }
1448}
1449
1450async fn sock_send_to(
1451    data: &mut WasiCtx,
1452    _inst: &mut AsyncInstance,
1453    frame: &mut CallingFrame,
1454    args: Vec<WasmValue>,
1455) -> Result<Vec<WasmValue>, CoreError> {
1456    let mut mem = frame
1457        .memory_mut(0)
1458        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
1459
1460    if let Some([p1, p2, p3, p4, p5, p6, p7]) = args.get(0..7) {
1461        let fd = p1.to_i32();
1462        let buf_ptr = p2.to_i32() as usize;
1463        let buf_len = p3.to_i32() as u32;
1464        let wasi_addr_ptr = p4.to_i32() as usize;
1465        let port = p5.to_i32() as u32;
1466        let flags = p6.to_i32() as u16;
1467        let send_len_ptr = p7.to_i32() as usize;
1468
1469        Ok(to_wasm_return(
1470            p::async_socket::sock_send_to(
1471                data,
1472                &mut mem as &mut Memory,
1473                fd,
1474                WasmPtr::from(buf_ptr),
1475                buf_len,
1476                WasmPtr::from(wasi_addr_ptr),
1477                port,
1478                flags,
1479                WasmPtr::from(send_len_ptr),
1480            )
1481            .await,
1482        ))
1483    } else {
1484        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
1485    }
1486}
1487
1488fn sock_shutdown(
1489    data: &mut WasiCtx,
1490    _inst: &mut Instance,
1491    frame: &mut CallingFrame,
1492    args: Vec<WasmValue>,
1493) -> Result<Vec<WasmValue>, CoreError> {
1494    let mut mem = frame
1495        .memory_mut(0)
1496        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
1497
1498    if let Some([p1, p2]) = args.get(0..2) {
1499        let fd = p1.to_i32();
1500        let how = p2.to_i32() as u8;
1501        Ok(to_wasm_return(p::async_socket::sock_shutdown(
1502            data,
1503            &mut mem as &mut Memory,
1504            fd,
1505            how,
1506        )))
1507    } else {
1508        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
1509    }
1510}
1511
1512fn sock_getpeeraddr(
1513    data: &mut WasiCtx,
1514    _inst: &mut Instance,
1515    frame: &mut CallingFrame,
1516    args: Vec<WasmValue>,
1517) -> Result<Vec<WasmValue>, CoreError> {
1518    let mut mem = frame
1519        .memory_mut(0)
1520        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
1521
1522    if let Some([p1, p2, p3, p4]) = args.get(0..4) {
1523        let fd = p1.to_i32();
1524        let wasi_addr_ptr = p2.to_i32() as usize;
1525        let addr_type = p3.to_i32() as usize;
1526        let port_ptr = p4.to_i32() as usize;
1527        Ok(to_wasm_return(p::async_socket::sock_getpeeraddr(
1528            data,
1529            &mut mem as &mut Memory,
1530            fd,
1531            WasmPtr::from(wasi_addr_ptr),
1532            WasmPtr::from(addr_type),
1533            WasmPtr::from(port_ptr),
1534        )))
1535    } else {
1536        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
1537    }
1538}
1539
1540fn sock_getlocaladdr(
1541    data: &mut WasiCtx,
1542    _inst: &mut Instance,
1543    frame: &mut CallingFrame,
1544    args: Vec<WasmValue>,
1545) -> Result<Vec<WasmValue>, CoreError> {
1546    let mut mem = frame
1547        .memory_mut(0)
1548        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
1549
1550    if let Some([p1, p2, p3, p4]) = args.get(0..4) {
1551        let fd = p1.to_i32();
1552        let wasi_addr_ptr = p2.to_i32() as usize;
1553        let addr_type = p3.to_i32() as usize;
1554        let port_ptr = p4.to_i32() as usize;
1555        Ok(to_wasm_return(p::async_socket::sock_getlocaladdr(
1556            data,
1557            &mut mem as &mut Memory,
1558            fd,
1559            WasmPtr::from(wasi_addr_ptr),
1560            WasmPtr::from(addr_type),
1561            WasmPtr::from(port_ptr),
1562        )))
1563    } else {
1564        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
1565    }
1566}
1567
1568fn sock_getsockopt(
1569    data: &mut WasiCtx,
1570    _inst: &mut Instance,
1571    frame: &mut CallingFrame,
1572    args: Vec<WasmValue>,
1573) -> Result<Vec<WasmValue>, CoreError> {
1574    let mut mem = frame
1575        .memory_mut(0)
1576        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
1577
1578    if let Some([p1, p2, p3, p4, p5]) = args.get(0..5) {
1579        let fd = p1.to_i32();
1580        let level = p2.to_i32() as u32;
1581        let name = p3.to_i32() as u32;
1582        let flag = p4.to_i32() as usize;
1583        let flag_size_ptr = p5.to_i32() as usize;
1584        Ok(to_wasm_return(p::async_socket::sock_getsockopt(
1585            data,
1586            &mut mem as &mut Memory,
1587            fd,
1588            level,
1589            name,
1590            WasmPtr::from(flag),
1591            WasmPtr::from(flag_size_ptr),
1592        )))
1593    } else {
1594        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
1595    }
1596}
1597
1598fn sock_setsockopt(
1599    data: &mut WasiCtx,
1600    _inst: &mut Instance,
1601    frame: &mut CallingFrame,
1602    args: Vec<WasmValue>,
1603) -> Result<Vec<WasmValue>, CoreError> {
1604    let mem = frame
1605        .memory_mut(0)
1606        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
1607
1608    if let Some([p1, p2, p3, p4, p5]) = args.get(0..5) {
1609        let fd = p1.to_i32();
1610        let level = p2.to_i32() as u32;
1611        let name = p3.to_i32() as u32;
1612        let flag = p4.to_i32() as usize;
1613        let flag_size = p5.to_i32() as u32;
1614        Ok(to_wasm_return(p::async_socket::sock_setsockopt(
1615            data,
1616            &mem as &Memory,
1617            fd,
1618            level,
1619            name,
1620            WasmPtr::from(flag),
1621            flag_size,
1622        )))
1623    } else {
1624        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
1625    }
1626}
1627
1628fn sock_getaddrinfo(
1629    data: &mut WasiCtx,
1630    _inst: &mut Instance,
1631    frame: &mut CallingFrame,
1632    args: Vec<WasmValue>,
1633) -> Result<Vec<WasmValue>, CoreError> {
1634    let mut mem = frame
1635        .memory_mut(0)
1636        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
1637
1638    if let Some([p1, p2, p3, p4, p5, p6, p7, p8]) = args.get(0..8) {
1639        let node = p1.to_i32() as usize;
1640        let node_len = p2.to_i32() as u32;
1641        let server = p3.to_i32() as usize;
1642        let server_len = p4.to_i32() as u32;
1643        let hint = p5.to_i32() as usize;
1644        let res = p6.to_i32() as usize;
1645        let max_len = p7.to_i32() as u32;
1646        let res_len = p8.to_i32() as usize;
1647
1648        Ok(to_wasm_return(p::async_socket::addrinfo::sock_getaddrinfo(
1649            data,
1650            &mut mem as &mut Memory,
1651            WasmPtr::from(node),
1652            node_len,
1653            WasmPtr::from(server),
1654            server_len,
1655            WasmPtr::from(hint),
1656            WasmPtr::from(res),
1657            max_len,
1658            WasmPtr::from(res_len),
1659        )))
1660    } else {
1661        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
1662    }
1663}
1664
1665async fn poll_oneoff(
1666    data: &mut WasiCtx,
1667    _inst: &mut AsyncInstance,
1668    frame: &mut CallingFrame,
1669    args: Vec<WasmValue>,
1670) -> Result<Vec<WasmValue>, CoreError> {
1671    let mut mem = frame
1672        .memory_mut(0)
1673        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
1674
1675    if let Some([p1, p2, p3, p4]) = args.get(0..4) {
1676        let in_ptr = p1.to_i32() as usize;
1677        let out_ptr = p2.to_i32() as usize;
1678        let nsubscriptions = p3.to_i32() as u32;
1679        let revents_num_ptr = p4.to_i32() as usize;
1680
1681        Ok(to_wasm_return(
1682            p::async_poll::poll_oneoff(
1683                data,
1684                &mut mem as &mut Memory,
1685                WasmPtr::from(in_ptr),
1686                WasmPtr::from(out_ptr),
1687                nsubscriptions,
1688                WasmPtr::from(revents_num_ptr),
1689            )
1690            .await,
1691        ))
1692    } else {
1693        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
1694    }
1695}
1696
1697async fn sock_lookup_ip(
1698    data: &mut WasiCtx,
1699    _inst: &mut AsyncInstance,
1700    frame: &mut CallingFrame,
1701    args: Vec<WasmValue>,
1702) -> Result<Vec<WasmValue>, CoreError> {
1703    let mut mem = frame
1704        .memory_mut(0)
1705        .ok_or(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds))?;
1706
1707    if let Some([p1, p2, p3, p4, p5, p6]) = args.get(0..6) {
1708        let host_name_ptr = p1.to_i32() as usize;
1709        let host_name_len = p2.to_i32() as u32;
1710        let lookup_type = p3.to_i32() as u8;
1711        let addr_buf = p4.to_i32() as usize;
1712        let addr_buf_max_len = p5.to_i32() as u32;
1713        let raddr_num_ptr = p6.to_i32() as usize;
1714        Ok(to_wasm_return(
1715            p::async_socket::sock_lookup_ip(
1716                data,
1717                &mut mem as &mut Memory,
1718                WasmPtr::from(host_name_ptr),
1719                host_name_len,
1720                lookup_type,
1721                WasmPtr::from(addr_buf),
1722                addr_buf_max_len,
1723                WasmPtr::from(raddr_num_ptr),
1724            )
1725            .await,
1726        ))
1727    } else {
1728        Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch))
1729    }
1730}
1731
1732#[inline]
1733fn box_future<
1734    'data,
1735    'inst,
1736    'frame,
1737    'fut,
1738    Data: Send,
1739    Fut: Future<Output = Result<Vec<WasmValue>, CoreError>> + Send + 'fut,
1740    F: FnOnce(
1741        &'data mut Data,
1742        &'inst mut AsyncInstance,
1743        &'frame mut CallingFrame,
1744        Vec<WasmValue>,
1745    ) -> Fut,
1746>(
1747    data: &'data mut Data,
1748    inst: &'inst mut AsyncInstance,
1749    frame: &'frame mut CallingFrame,
1750    args: Vec<WasmValue>,
1751) -> Box<dyn Future<Output = Result<Vec<WasmValue>, CoreError>> + Send + 'fut>
1752where
1753    'data: 'fut,
1754    'inst: 'fut,
1755    'frame: 'fut,
1756{
1757    let f: F = unsafe { std::mem::zeroed() };
1758    Box::new(f(data, inst, frame, args))
1759}
1760
1761#[allow(clippy::complexity)]
1762fn wrap_future<
1763    'data,
1764    'inst,
1765    'frame,
1766    'fut,
1767    Data: Send + 'data,
1768    Fut: Future<Output = Result<Vec<WasmValue>, CoreError>> + Send + 'fut,
1769    F: FnOnce(
1770        &'data mut Data,
1771        &'inst mut AsyncInstance,
1772        &'frame mut CallingFrame,
1773        Vec<WasmValue>,
1774    ) -> Fut,
1775>(
1776    _f: F,
1777) -> fn(
1778    data: &'data mut Data,
1779    inst: &'inst mut AsyncInstance,
1780    frame: &'frame mut CallingFrame,
1781    args: Vec<WasmValue>,
1782) -> Box<dyn Future<Output = Result<Vec<WasmValue>, CoreError>> + Send + 'fut>
1783where
1784    'data: 'fut,
1785    'inst: 'fut,
1786    'frame: 'fut,
1787{
1788    box_future::<Data, Fut, F>
1789}
1790
1791enum WasiFunc<'data, 'inst, 'frame, 'fut, T: Sized>
1792where
1793    'data: 'fut,
1794    'inst: 'fut,
1795    'frame: 'fut,
1796{
1797    SyncFn(String, (Vec<ValType>, Vec<ValType>), SyncFn<T>),
1798    AsyncFn(
1799        String,
1800        (Vec<ValType>, Vec<ValType>),
1801        AsyncFn<'data, 'inst, 'frame, 'fut, T>,
1802    ),
1803}
1804
1805fn wasi_impls<'data, 'inst, 'frame, 'fut>() -> Vec<WasiFunc<'data, 'inst, 'frame, 'fut, WasiCtx>> {
1806    macro_rules! sync_fn {
1807        ($name:expr, $ty:expr, $f:ident) => {
1808            WasiFunc::SyncFn($name.into(), $ty, $f)
1809        };
1810    }
1811    macro_rules! async_fn {
1812        ($name:expr, $ty:expr, $f:expr) => {
1813            WasiFunc::AsyncFn($name.into(), $ty, $f)
1814        };
1815    }
1816    vec![
1817        sync_fn!(
1818            "args_get",
1819            (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
1820            args_get
1821        ),
1822        sync_fn!(
1823            "args_sizes_get",
1824            (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
1825            args_sizes_get
1826        ),
1827        sync_fn!(
1828            "environ_get",
1829            (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
1830            environ_get
1831        ),
1832        sync_fn!(
1833            "environ_sizes_get",
1834            (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
1835            environ_sizes_get
1836        ),
1837        sync_fn!(
1838            "clock_res_get",
1839            (vec![ValType::I32, ValType::I64], vec![ValType::I32]),
1840            clock_res_get
1841        ),
1842        sync_fn!(
1843            "clock_time_get",
1844            (
1845                vec![ValType::I32, ValType::I64, ValType::I32],
1846                vec![ValType::I32],
1847            ),
1848            clock_time_get
1849        ),
1850        sync_fn!(
1851            "random_get",
1852            (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
1853            random_get
1854        ),
1855        sync_fn!(
1856            "fd_prestat_get",
1857            (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
1858            fd_prestat_get
1859        ),
1860        sync_fn!(
1861            "fd_prestat_dir_name",
1862            (
1863                vec![ValType::I32, ValType::I32, ValType::I32],
1864                vec![ValType::I32],
1865            ),
1866            fd_prestat_dir_name
1867        ),
1868        sync_fn!(
1869            "fd_renumber",
1870            (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
1871            fd_renumber
1872        ),
1873        sync_fn!(
1874            "fd_advise",
1875            (
1876                vec![ValType::I32, ValType::I64, ValType::I64, ValType::I32],
1877                vec![ValType::I32],
1878            ),
1879            fd_advise
1880        ),
1881        sync_fn!(
1882            "fd_allocate",
1883            (
1884                vec![ValType::I32, ValType::I64, ValType::I64],
1885                vec![ValType::I32],
1886            ),
1887            fd_allocate
1888        ),
1889        sync_fn!(
1890            "fd_close",
1891            (vec![ValType::I32], vec![ValType::I32]),
1892            fd_close
1893        ),
1894        sync_fn!(
1895            "fd_seek",
1896            (
1897                vec![ValType::I32, ValType::I64, ValType::I32, ValType::I32],
1898                vec![ValType::I32],
1899            ),
1900            fd_seek
1901        ),
1902        sync_fn!("fd_sync", (vec![ValType::I32], vec![ValType::I32]), fd_sync),
1903        sync_fn!(
1904            "fd_datasync",
1905            (vec![ValType::I32], vec![ValType::I32]),
1906            fd_datasync
1907        ),
1908        sync_fn!(
1909            "fd_tell",
1910            (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
1911            fd_tell
1912        ),
1913        sync_fn!(
1914            "fd_fdstat_get",
1915            (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
1916            fd_fdstat_get
1917        ),
1918        sync_fn!(
1919            "fd_fdstat_set_flags",
1920            (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
1921            fd_fdstat_set_flags
1922        ),
1923        sync_fn!(
1924            "fd_fdstat_set_rights",
1925            (
1926                vec![ValType::I32, ValType::I64, ValType::I64],
1927                vec![ValType::I32],
1928            ),
1929            fd_fdstat_set_rights
1930        ),
1931        sync_fn!(
1932            "fd_filestat_get",
1933            (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
1934            fd_filestat_get
1935        ),
1936        sync_fn!(
1937            "fd_filestat_set_size",
1938            (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
1939            fd_filestat_set_size
1940        ),
1941        sync_fn!(
1942            "fd_filestat_set_times",
1943            (
1944                vec![ValType::I32, ValType::I64, ValType::I64, ValType::I32],
1945                vec![ValType::I32],
1946            ),
1947            fd_filestat_set_times
1948        ),
1949        sync_fn!(
1950            "fd_read",
1951            (
1952                vec![ValType::I32, ValType::I32, ValType::I32, ValType::I32],
1953                vec![ValType::I32],
1954            ),
1955            fd_read
1956        ),
1957        sync_fn!(
1958            "fd_pread",
1959            (
1960                vec![
1961                    ValType::I32,
1962                    ValType::I32,
1963                    ValType::I32,
1964                    ValType::I64,
1965                    ValType::I32,
1966                ],
1967                vec![ValType::I32],
1968            ),
1969            fd_pread
1970        ),
1971        sync_fn!(
1972            "fd_write",
1973            (
1974                vec![ValType::I32, ValType::I32, ValType::I32, ValType::I32],
1975                vec![ValType::I32],
1976            ),
1977            fd_write
1978        ),
1979        sync_fn!(
1980            "fd_pwrite",
1981            (
1982                vec![
1983                    ValType::I32,
1984                    ValType::I32,
1985                    ValType::I32,
1986                    ValType::I64,
1987                    ValType::I32,
1988                ],
1989                vec![ValType::I32],
1990            ),
1991            fd_pwrite
1992        ),
1993        sync_fn!(
1994            "fd_readdir",
1995            (
1996                vec![
1997                    ValType::I32,
1998                    ValType::I32,
1999                    ValType::I32,
2000                    ValType::I64,
2001                    ValType::I32,
2002                ],
2003                vec![ValType::I32],
2004            ),
2005            fd_readdir
2006        ),
2007        sync_fn!(
2008            "path_create_directory",
2009            (
2010                vec![ValType::I32, ValType::I32, ValType::I32],
2011                vec![ValType::I32],
2012            ),
2013            path_create_directory
2014        ),
2015        sync_fn!(
2016            "path_filestat_get",
2017            (
2018                vec![
2019                    ValType::I32,
2020                    ValType::I32,
2021                    ValType::I32,
2022                    ValType::I32,
2023                    ValType::I32,
2024                ],
2025                vec![ValType::I32],
2026            ),
2027            path_filestat_get
2028        ),
2029        sync_fn!(
2030            "path_filestat_set_times",
2031            (
2032                vec![
2033                    ValType::I32,
2034                    ValType::I32,
2035                    ValType::I32,
2036                    ValType::I32,
2037                    ValType::I64,
2038                    ValType::I64,
2039                    ValType::I32,
2040                ],
2041                vec![ValType::I32],
2042            ),
2043            path_filestat_set_times
2044        ),
2045        sync_fn!(
2046            "path_link",
2047            (
2048                vec![
2049                    ValType::I32,
2050                    ValType::I32,
2051                    ValType::I32,
2052                    ValType::I32,
2053                    ValType::I32,
2054                    ValType::I32,
2055                    ValType::I32,
2056                ],
2057                vec![ValType::I32],
2058            ),
2059            path_link
2060        ),
2061        sync_fn!(
2062            "path_open",
2063            (
2064                vec![
2065                    ValType::I32,
2066                    ValType::I32,
2067                    ValType::I32,
2068                    ValType::I32,
2069                    ValType::I32,
2070                    ValType::I64,
2071                    ValType::I64,
2072                    ValType::I32,
2073                    ValType::I32,
2074                ],
2075                vec![ValType::I32],
2076            ),
2077            path_open
2078        ),
2079        sync_fn!(
2080            "path_readlink",
2081            (
2082                vec![
2083                    ValType::I32,
2084                    ValType::I32,
2085                    ValType::I32,
2086                    ValType::I32,
2087                    ValType::I32,
2088                    ValType::I32,
2089                ],
2090                vec![ValType::I32],
2091            ),
2092            path_readlink
2093        ),
2094        sync_fn!(
2095            "path_remove_directory",
2096            (
2097                vec![ValType::I32, ValType::I32, ValType::I32],
2098                vec![ValType::I32],
2099            ),
2100            path_remove_directory
2101        ),
2102        sync_fn!(
2103            "path_rename",
2104            (
2105                vec![
2106                    ValType::I32,
2107                    ValType::I32,
2108                    ValType::I32,
2109                    ValType::I32,
2110                    ValType::I32,
2111                    ValType::I32,
2112                ],
2113                vec![ValType::I32],
2114            ),
2115            path_rename
2116        ),
2117        sync_fn!(
2118            "path_symlink",
2119            (
2120                vec![
2121                    ValType::I32,
2122                    ValType::I32,
2123                    ValType::I32,
2124                    ValType::I32,
2125                    ValType::I32,
2126                ],
2127                vec![ValType::I32],
2128            ),
2129            path_symlink
2130        ),
2131        sync_fn!(
2132            "path_unlink_file",
2133            (
2134                vec![ValType::I32, ValType::I32, ValType::I32],
2135                vec![ValType::I32],
2136            ),
2137            path_unlink_file
2138        ),
2139        sync_fn!("proc_exit", (vec![ValType::I32], vec![]), proc_exit),
2140        sync_fn!(
2141            "proc_raise",
2142            (vec![ValType::I32], vec![ValType::I32]),
2143            proc_raise
2144        ),
2145        sync_fn!("sched_yield", (vec![], vec![ValType::I32]), sched_yield),
2146        sync_fn!(
2147            "sock_open",
2148            (
2149                vec![ValType::I32, ValType::I32, ValType::I32],
2150                vec![ValType::I32],
2151            ),
2152            sock_open
2153        ),
2154        sync_fn!(
2155            "sock_bind",
2156            (
2157                vec![ValType::I32, ValType::I32, ValType::I32],
2158                vec![ValType::I32],
2159            ),
2160            sock_bind
2161        ),
2162        sync_fn!(
2163            "sock_listen",
2164            (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
2165            sock_listen
2166        ),
2167        async_fn!(
2168            "sock_accept",
2169            (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
2170            sock_accept
2171        ),
2172        async_fn!(
2173            "sock_connect",
2174            (
2175                vec![ValType::I32, ValType::I32, ValType::I32],
2176                vec![ValType::I32],
2177            ),
2178            wrap_future(sock_connect)
2179        ),
2180        async_fn!(
2181            "sock_recv",
2182            (
2183                vec![
2184                    ValType::I32,
2185                    ValType::I32,
2186                    ValType::I32,
2187                    ValType::I32,
2188                    ValType::I32,
2189                    ValType::I32,
2190                ],
2191                vec![ValType::I32],
2192            ),
2193            wrap_future(sock_recv)
2194        ),
2195        async_fn!(
2196            "sock_recv_from",
2197            (
2198                vec![
2199                    ValType::I32,
2200                    ValType::I32,
2201                    ValType::I32,
2202                    ValType::I32,
2203                    ValType::I32,
2204                    ValType::I32,
2205                    ValType::I32,
2206                    ValType::I32,
2207                ],
2208                vec![ValType::I32],
2209            ),
2210            wrap_future(sock_recv_from)
2211        ),
2212        async_fn!(
2213            "sock_send",
2214            (
2215                vec![
2216                    ValType::I32,
2217                    ValType::I32,
2218                    ValType::I32,
2219                    ValType::I32,
2220                    ValType::I32,
2221                ],
2222                vec![ValType::I32],
2223            ),
2224            wrap_future(sock_send)
2225        ),
2226        async_fn!(
2227            "sock_send_to",
2228            (
2229                vec![
2230                    ValType::I32,
2231                    ValType::I32,
2232                    ValType::I32,
2233                    ValType::I32,
2234                    ValType::I32,
2235                    ValType::I32,
2236                    ValType::I32,
2237                ],
2238                vec![ValType::I32],
2239            ),
2240            wrap_future(sock_send_to)
2241        ),
2242        sync_fn!(
2243            "sock_shutdown",
2244            (vec![ValType::I32, ValType::I32], vec![ValType::I32]),
2245            sock_shutdown
2246        ),
2247        sync_fn!(
2248            "sock_getpeeraddr",
2249            (
2250                vec![ValType::I32, ValType::I32, ValType::I32, ValType::I32],
2251                vec![ValType::I32],
2252            ),
2253            sock_getpeeraddr
2254        ),
2255        sync_fn!(
2256            "sock_getlocaladdr",
2257            (
2258                vec![ValType::I32, ValType::I32, ValType::I32, ValType::I32],
2259                vec![ValType::I32],
2260            ),
2261            sock_getlocaladdr
2262        ),
2263        sync_fn!(
2264            "sock_getsockopt",
2265            (
2266                vec![
2267                    ValType::I32,
2268                    ValType::I32,
2269                    ValType::I32,
2270                    ValType::I32,
2271                    ValType::I32,
2272                ],
2273                vec![ValType::I32],
2274            ),
2275            sock_getsockopt
2276        ),
2277        sync_fn!(
2278            "sock_setsockopt",
2279            (
2280                vec![
2281                    ValType::I32,
2282                    ValType::I32,
2283                    ValType::I32,
2284                    ValType::I32,
2285                    ValType::I32,
2286                ],
2287                vec![ValType::I32],
2288            ),
2289            sock_setsockopt
2290        ),
2291        async_fn!(
2292            "poll_oneoff",
2293            (
2294                vec![ValType::I32, ValType::I32, ValType::I32, ValType::I32],
2295                vec![ValType::I32],
2296            ),
2297            wrap_future(poll_oneoff)
2298        ),
2299        async_fn!(
2300            "epoll_oneoff",
2301            (
2302                vec![ValType::I32, ValType::I32, ValType::I32, ValType::I32],
2303                vec![ValType::I32],
2304            ),
2305            wrap_future(poll_oneoff)
2306        ),
2307        async_fn!(
2308            "sock_lookup_ip",
2309            (
2310                vec![
2311                    ValType::I32,
2312                    ValType::I32,
2313                    ValType::I32,
2314                    ValType::I32,
2315                    ValType::I32,
2316                    ValType::I32,
2317                ],
2318                vec![ValType::I32],
2319            ),
2320            wrap_future(sock_lookup_ip)
2321        ),
2322        sync_fn!(
2323            "sock_getaddrinfo",
2324            (
2325                vec![
2326                    ValType::I32,
2327                    ValType::I32,
2328                    ValType::I32,
2329                    ValType::I32,
2330                    ValType::I32,
2331                    ValType::I32,
2332                    ValType::I32,
2333                    ValType::I32,
2334                ],
2335                vec![ValType::I32],
2336            ),
2337            sock_getaddrinfo
2338        ),
2339    ]
2340}
2341
2342fn to_wasm_return(r: Result<(), Errno>) -> Vec<WasmValue> {
2343    let code = if let Err(e) = r { e.0 } else { 0 };
2344    log::trace!("wasi return {code}");
2345    vec![WasmValue::from_i32(code as i32)]
2346}
2347
2348impl async_wasi::snapshots::common::memory::Memory for Memory {
2349    fn get_data<T: Sized>(&self, offset: WasmPtr<T>) -> Result<&T, Errno> {
2350        unsafe {
2351            let r = std::mem::size_of::<T>();
2352            let ptr = self
2353                .data_pointer(offset.0 as u32, r as u32)
2354                .map_err(|_| Errno::__WASI_ERRNO_FAULT)?;
2355            Ok(ptr.cast::<T>().as_ref().unwrap())
2356        }
2357    }
2358
2359    fn get_slice<T: Sized>(&self, offset: WasmPtr<T>, len: usize) -> Result<&[T], Errno> {
2360        unsafe {
2361            let r = std::mem::size_of::<T>() * len;
2362            let ptr = self
2363                .data_pointer(offset.0 as u32, r as u32)
2364                .map_err(|_| Errno::__WASI_ERRNO_FAULT)? as *const T;
2365            Ok(std::slice::from_raw_parts(ptr, len))
2366        }
2367    }
2368
2369    fn get_iovec<'a>(
2370        &self,
2371        iovec_ptr: WasmPtr<__wasi_ciovec_t>,
2372        iovec_len: __wasi_size_t,
2373    ) -> Result<Vec<std::io::IoSlice<'a>>, Errno> {
2374        unsafe {
2375            let iovec = self.get_slice(iovec_ptr, iovec_len as usize)?.to_vec();
2376            let mut result = Vec::with_capacity(iovec.len());
2377            for i in iovec {
2378                let ptr = self
2379                    .data_pointer(i.buf, i.buf_len)
2380                    .map_err(|_| Errno::__WASI_ERRNO_FAULT)?;
2381                let s = std::io::IoSlice::new(std::slice::from_raw_parts(ptr, i.buf_len as usize));
2382                result.push(s);
2383            }
2384            Ok(result)
2385        }
2386    }
2387
2388    fn mut_data<T: Sized>(&mut self, offset: WasmPtr<T>) -> Result<&mut T, Errno> {
2389        unsafe {
2390            let r = std::mem::size_of::<T>();
2391            let ptr = self
2392                .data_pointer_mut(offset.0 as u32, r as u32)
2393                .map_err(|_| Errno::__WASI_ERRNO_FAULT)?;
2394            Ok(ptr.cast::<T>().as_mut().unwrap())
2395        }
2396    }
2397
2398    fn mut_slice<T: Sized>(&mut self, offset: WasmPtr<T>, len: usize) -> Result<&mut [T], Errno> {
2399        unsafe {
2400            let r = std::mem::size_of::<T>() * len;
2401            let ptr = self
2402                .data_pointer_mut(offset.0 as u32, r as u32)
2403                .map_err(|_| Errno::__WASI_ERRNO_FAULT)? as *mut T;
2404            Ok(std::slice::from_raw_parts_mut(ptr, len))
2405        }
2406    }
2407
2408    fn mut_iovec(
2409        &mut self,
2410        iovec_ptr: WasmPtr<async_wasi::snapshots::env::wasi_types::__wasi_iovec_t>,
2411        iovec_len: async_wasi::snapshots::env::wasi_types::__wasi_size_t,
2412    ) -> Result<Vec<std::io::IoSliceMut<'_>>, Errno> {
2413        unsafe {
2414            let iovec = self.get_slice(iovec_ptr, iovec_len as usize)?.to_vec();
2415            let mut result = Vec::with_capacity(iovec.len());
2416            for i in iovec {
2417                let ptr = self
2418                    .data_pointer_mut(i.buf, i.buf_len)
2419                    .map_err(|_| Errno::__WASI_ERRNO_FAULT)?;
2420                let s = std::io::IoSliceMut::new(std::slice::from_raw_parts_mut(
2421                    ptr,
2422                    i.buf_len as usize,
2423                ));
2424                result.push(s);
2425            }
2426            Ok(result)
2427        }
2428    }
2429
2430    fn write_data<T: Sized>(&mut self, offset: WasmPtr<T>, data: T) -> Result<(), Errno> {
2431        let p = self.mut_data(offset)?;
2432        *p = data;
2433        Ok(())
2434    }
2435}
2436
2437#[cfg(test)]
2438mod tests {
2439    use super::*;
2440    use crate::{r#async::fiber::AsyncState, Executor, Loader, Store, Validator};
2441
2442    #[tokio::test]
2443    async fn test_async_wasi_module() -> Result<(), Box<dyn std::error::Error>> {
2444        // create an Executor
2445        let result = Executor::create(None, None);
2446        assert!(result.is_ok());
2447        let mut executor = result.unwrap();
2448        assert!(!executor.inner.0.is_null());
2449
2450        // create a Store
2451        let result = Store::create();
2452        assert!(result.is_ok());
2453        let mut store = result.unwrap();
2454
2455        // create an AsyncWasiModule
2456        let result = AsyncWasiModule::create(Some(vec!["abc"]), Some(vec![("ENV", "1")]));
2457        assert!(result.is_ok());
2458        let mut async_wasi_module = result.unwrap();
2459
2460        // register async_wasi module into the store
2461        let result = executor.register_import_module(&mut store, async_wasi_module.as_mut());
2462        assert!(result.is_ok());
2463
2464        let wasm_file = std::env::current_dir()
2465            .unwrap()
2466            .ancestors()
2467            .nth(2)
2468            .unwrap()
2469            .join("examples/wasmedge-sys/async_hello.wasm");
2470        let module = Loader::create(None)?.from_file(&wasm_file)?;
2471        Validator::create(None)?.validate(&module)?;
2472        let mut instance = executor.register_active_module(&mut store, &module)?;
2473        let mut fn_start = instance.get_func_mut("_start")?;
2474
2475        async fn tick() {
2476            let mut i = 0;
2477            loop {
2478                println!("[tick] i={i}");
2479                tokio::time::sleep(std::time::Duration::from_millis(500)).await;
2480                i += 1;
2481            }
2482        }
2483        tokio::spawn(tick());
2484
2485        let async_state = AsyncState::new();
2486        let _ = executor
2487            .call_func_async(&async_state, &mut fn_start, [])
2488            .await?;
2489
2490        Ok(())
2491    }
2492}