Skip to main content

wasmedge_sys/instance/
module.rs

1//! Defines WasmEdge Instance and other relevant types.
2use crate::{
3    ffi::{self},
4    instance::{global::InnerGlobal, memory::InnerMemory, table::InnerTable},
5    types::WasmEdgeString,
6    FuncRef, Function, Global, Memory, Table, WasmEdgeResult,
7};
8
9use wasmedge_types::error::{InstanceError, WasmEdgeError};
10
11use super::{function::AsFunc, InnerRef};
12
13/// An [Instance] represents an instantiated module. In the instantiation process, An [Instance] is created from al[Module](crate::Module). From an [Instance] the exported [functions](crate::Function), [tables](crate::Table), [memories](crate::Memory), and [globals](crate::Global) can be fetched.
14#[derive(Debug)]
15pub struct Instance {
16    pub(crate) inner: InnerInstance,
17}
18impl Drop for Instance {
19    fn drop(&mut self) {
20        unsafe {
21            ffi::WasmEdge_ModuleInstanceDelete(self.inner.0);
22        }
23    }
24}
25impl AsInstance for Instance {
26    unsafe fn as_ptr(&self) -> *const ffi::WasmEdge_ModuleInstanceContext {
27        self.inner.0
28    }
29}
30
31impl<Inst: Sized> AsInstance for Inst
32where
33    Inst: AsMut<Instance> + AsRef<Instance>,
34{
35    unsafe fn as_ptr(&self) -> *const ffi::WasmEdge_ModuleInstanceContext {
36        self.as_ref().as_ptr()
37    }
38}
39
40#[derive(Debug, Clone)]
41pub(crate) struct InnerInstance(pub(crate) *mut ffi::WasmEdge_ModuleInstanceContext);
42unsafe impl Send for InnerInstance {}
43unsafe impl Sync for InnerInstance {}
44
45/// The object as an module instance is required to implement this trait.
46pub trait AsInstance {
47    /// Returns the name of this exported [module instance](crate::Instance).
48    ///
49    /// If this module instance is an active module instance, then None is returned.
50    fn name(&self) -> Option<String> {
51        let name = unsafe { ffi::WasmEdge_ModuleInstanceGetModuleName(self.as_ptr()) };
52
53        let name: String = (&name).into();
54        if name.is_empty() {
55            return None;
56        }
57
58        Some(name)
59    }
60
61    /// Returns the exported [table instance](crate::Table) by name.
62    ///
63    /// # Argument
64    ///
65    /// * `name` - The name of the target exported [table instance](crate::Table).
66    ///
67    /// # Error
68    ///
69    /// If fail to find the target [table instance](crate::Table), then an error is returned.
70    fn get_table(&self, name: impl AsRef<str>) -> WasmEdgeResult<InnerRef<Table, &Self>>
71    where
72        Self: Sized,
73    {
74        let table_name: WasmEdgeString = name.as_ref().into();
75        let ctx =
76            unsafe { ffi::WasmEdge_ModuleInstanceFindTable(self.as_ptr(), table_name.as_raw()) };
77        match ctx.is_null() {
78            true => Err(Box::new(WasmEdgeError::Instance(
79                InstanceError::NotFoundTable(name.as_ref().to_string()),
80            ))),
81            false => {
82                let table = std::mem::ManuallyDrop::new(Table {
83                    inner: InnerTable(ctx),
84                });
85                Ok(unsafe { InnerRef::create_from_ref(table, self) })
86            }
87        }
88    }
89
90    /// Returns the exported [memory instance](crate::Memory) by name.
91    ///
92    /// # Argument
93    ///
94    /// * `name` - The name of the target exported [memory instance](crate::Memory).
95    ///
96    /// # Error
97    ///
98    /// If fail to find the target [memory instance](crate::Memory), then an error is returned.
99    fn get_memory_ref(&self, name: impl AsRef<str>) -> WasmEdgeResult<InnerRef<Memory, &Self>>
100    where
101        Self: Sized,
102    {
103        unsafe {
104            let mem_name: WasmEdgeString = name.as_ref().into();
105            let ctx = ffi::WasmEdge_ModuleInstanceFindMemory(self.as_ptr(), mem_name.as_raw());
106
107            if ctx.is_null() {
108                Err(Box::new(WasmEdgeError::Instance(
109                    InstanceError::NotFoundMem(name.as_ref().to_string()),
110                )))
111            } else {
112                let mem = Memory {
113                    inner: InnerMemory(ctx),
114                };
115
116                Ok(InnerRef::create_from_ref(
117                    std::mem::ManuallyDrop::new(mem),
118                    self,
119                ))
120            }
121        }
122    }
123
124    fn get_memory_mut(
125        &mut self,
126        name: impl AsRef<str>,
127    ) -> WasmEdgeResult<InnerRef<Memory, &mut Self>>
128    where
129        Self: Sized,
130    {
131        unsafe {
132            let mem_name: WasmEdgeString = name.as_ref().into();
133            let ctx = ffi::WasmEdge_ModuleInstanceFindMemory(self.as_ptr(), mem_name.as_raw());
134
135            if ctx.is_null() {
136                Err(Box::new(WasmEdgeError::Instance(
137                    InstanceError::NotFoundMem(name.as_ref().to_string()),
138                )))
139            } else {
140                let mem = Memory {
141                    inner: InnerMemory(ctx),
142                };
143
144                Ok(InnerRef::create_from_mut(
145                    std::mem::ManuallyDrop::new(mem),
146                    self,
147                ))
148            }
149        }
150    }
151
152    /// Returns the exported [global instance](crate::Global) by name.
153    ///
154    /// # Argument
155    ///
156    /// * `name` - The name of the target exported [global instance](crate::Global).
157    ///
158    /// # Error
159    ///
160    /// If fail to find the target [global instance](crate::Global), then an error is returned.
161    fn get_global(&self, name: impl AsRef<str>) -> WasmEdgeResult<InnerRef<Global, &Self>>
162    where
163        Self: Sized,
164    {
165        let global_name: WasmEdgeString = name.as_ref().into();
166        let ctx =
167            unsafe { ffi::WasmEdge_ModuleInstanceFindGlobal(self.as_ptr(), global_name.as_raw()) };
168        match ctx.is_null() {
169            true => Err(Box::new(WasmEdgeError::Instance(
170                InstanceError::NotFoundGlobal(name.as_ref().to_string()),
171            ))),
172            false => {
173                let value = std::mem::ManuallyDrop::new(Global {
174                    inner: InnerGlobal(ctx),
175                });
176                Ok(unsafe { InnerRef::create_from_ref(value, self) })
177            }
178        }
179    }
180
181    fn get_global_mut(
182        &mut self,
183        name: impl AsRef<str>,
184    ) -> WasmEdgeResult<InnerRef<Global, &mut Self>>
185    where
186        Self: Sized,
187    {
188        let global_name: WasmEdgeString = name.as_ref().into();
189        let ctx =
190            unsafe { ffi::WasmEdge_ModuleInstanceFindGlobal(self.as_ptr(), global_name.as_raw()) };
191        match ctx.is_null() {
192            true => Err(Box::new(WasmEdgeError::Instance(
193                InstanceError::NotFoundGlobal(name.as_ref().to_string()),
194            ))),
195            false => {
196                let value = std::mem::ManuallyDrop::new(Global {
197                    inner: InnerGlobal(ctx),
198                });
199                Ok(unsafe { InnerRef::create_from_mut(value, self) })
200            }
201        }
202    }
203
204    /// Returns the length of the exported [function instances](crate::Function) in this module instance.
205    fn func_len(&self) -> u32 {
206        unsafe { ffi::WasmEdge_ModuleInstanceListFunctionLength(self.as_ptr()) }
207    }
208
209    /// Returns the names of the exported [function instances](crate::Function) in this module instance.
210    fn func_names(&self) -> Option<Vec<String>> {
211        let len_func_names = self.func_len();
212        match len_func_names > 0 {
213            true => {
214                let mut func_names = Vec::with_capacity(len_func_names as usize);
215                unsafe {
216                    ffi::WasmEdge_ModuleInstanceListFunction(
217                        self.as_ptr(),
218                        func_names.as_mut_ptr(),
219                        len_func_names,
220                    );
221                    func_names.set_len(len_func_names as usize);
222                }
223
224                let names = func_names
225                    .into_iter()
226                    .map(|x| x.into())
227                    .collect::<Vec<String>>();
228                Some(names)
229            }
230            false => None,
231        }
232    }
233
234    /// Returns the exported [function instance](crate::Function) by name.
235    ///
236    /// # Argument
237    ///
238    /// * `name` - The name of the target exported [function instance](crate::Function).
239    ///
240    /// # Error
241    ///
242    /// If fail to find the target [function](crate::Function), then an error is returned.
243    fn get_func(&self, name: &str) -> WasmEdgeResult<FuncRef<&Instance>> {
244        unsafe {
245            let func_name: WasmEdgeString = name.into();
246            let func_ctx =
247                ffi::WasmEdge_ModuleInstanceFindFunction(self.as_ptr(), func_name.as_raw());
248
249            if func_ctx.is_null() {
250                Err(Box::new(WasmEdgeError::Instance(
251                    InstanceError::NotFoundFunc(name.to_string()),
252                )))
253            } else {
254                let value = Function::from_raw(func_ctx);
255                Ok(FuncRef::create_ref(std::mem::ManuallyDrop::new(value)))
256            }
257        }
258    }
259
260    /// Returns the exported [function instance](crate::Function) by name.
261    ///
262    /// # Argument
263    ///
264    /// * `name` - The name of the target exported [function instance](crate::Function).
265    ///
266    /// # Error
267    ///
268    /// If fail to find the target [function](crate::Function), then an error is returned.
269    fn get_func_mut(&mut self, name: &str) -> WasmEdgeResult<FuncRef<&mut Instance>> {
270        unsafe {
271            let func_name: WasmEdgeString = name.into();
272            let func_ctx =
273                ffi::WasmEdge_ModuleInstanceFindFunction(self.as_ptr(), func_name.as_raw());
274
275            if func_ctx.is_null() {
276                Err(Box::new(WasmEdgeError::Instance(
277                    InstanceError::NotFoundFunc(name.to_string()),
278                )))
279            } else {
280                let value = Function::from_raw(func_ctx);
281                Ok(FuncRef::create_mut(std::mem::ManuallyDrop::new(value)))
282            }
283        }
284    }
285
286    /// Returns the length of the exported [table instances](crate::Table) in this module instance.
287    fn table_len(&self) -> u32 {
288        unsafe { ffi::WasmEdge_ModuleInstanceListTableLength(self.as_ptr()) }
289    }
290
291    /// Returns the names of the exported [table instances](crate::Table) in this module instance.
292    fn table_names(&self) -> Option<Vec<String>> {
293        let len_table_names = self.table_len();
294        match len_table_names > 0 {
295            true => {
296                let mut table_names = Vec::with_capacity(len_table_names as usize);
297                unsafe {
298                    ffi::WasmEdge_ModuleInstanceListTable(
299                        self.as_ptr(),
300                        table_names.as_mut_ptr(),
301                        len_table_names,
302                    );
303                    table_names.set_len(len_table_names as usize);
304                }
305
306                let names = table_names
307                    .into_iter()
308                    .map(|x| x.into())
309                    .collect::<Vec<String>>();
310                Some(names)
311            }
312            false => None,
313        }
314    }
315
316    /// Returns the length of the exported [memory instances](crate::Memory) in this module instance.
317    fn mem_len(&self) -> u32 {
318        unsafe { ffi::WasmEdge_ModuleInstanceListMemoryLength(self.as_ptr()) }
319    }
320
321    /// Returns the names of all exported [memory instances](crate::Memory) in this module instance.
322    fn mem_names(&self) -> Option<Vec<String>> {
323        let len_mem_names = self.mem_len();
324        match len_mem_names > 0 {
325            true => {
326                let mut mem_names = Vec::with_capacity(len_mem_names as usize);
327                unsafe {
328                    ffi::WasmEdge_ModuleInstanceListMemory(
329                        self.as_ptr(),
330                        mem_names.as_mut_ptr(),
331                        len_mem_names,
332                    );
333                    mem_names.set_len(len_mem_names as usize);
334                }
335
336                let names = mem_names
337                    .into_iter()
338                    .map(|x| x.into())
339                    .collect::<Vec<String>>();
340                Some(names)
341            }
342            false => None,
343        }
344    }
345
346    /// Returns the length of the exported [global instances](crate::Global) in this module instance.
347    fn global_len(&self) -> u32 {
348        unsafe { ffi::WasmEdge_ModuleInstanceListGlobalLength(self.as_ptr()) }
349    }
350
351    /// Returns the names of the exported [global instances](crate::Global) in this module instance.
352    fn global_names(&self) -> Option<Vec<String>> {
353        let len_global_names = self.global_len();
354        match len_global_names > 0 {
355            true => {
356                let mut global_names = Vec::with_capacity(len_global_names as usize);
357                unsafe {
358                    ffi::WasmEdge_ModuleInstanceListGlobal(
359                        self.as_ptr(),
360                        global_names.as_mut_ptr(),
361                        len_global_names,
362                    );
363                    global_names.set_len(len_global_names as usize);
364                }
365
366                let names = global_names
367                    .into_iter()
368                    .map(|x| x.into())
369                    .collect::<Vec<String>>();
370                Some(names)
371            }
372            false => None,
373        }
374    }
375
376    /// # Safety
377    ///
378    /// Provides a raw pointer to the inner module instance context.
379    /// The lifetime of the returned pointer must not exceed that of the object itself.
380    unsafe fn as_ptr(&self) -> *const ffi::WasmEdge_ModuleInstanceContext;
381}
382
383/// An [ImportModule] represents a host module with a name. A host module consists of one or more host [function](crate::Function), [table](crate::Table), [memory](crate::Memory), and [global](crate::Global) instances,  which are defined outside wasm modules and fed into wasm modules as imports.
384#[derive(Debug)]
385pub struct ImportModule<T: ?Sized> {
386    pub(crate) inner: InnerInstance,
387    name: String,
388    _data: std::marker::PhantomData<T>,
389}
390impl<T: ?Sized> Drop for ImportModule<T> {
391    fn drop(&mut self) {
392        unsafe {
393            ffi::WasmEdge_ModuleInstanceDelete(self.inner.0);
394        }
395    }
396}
397
398unsafe extern "C" fn import_data_finalizer<T>(ptr: *mut std::os::raw::c_void) {
399    let box_data: Box<T> = Box::from_raw(ptr as _);
400    std::mem::drop(box_data)
401}
402
403impl<T: Sized> ImportModule<T> {
404    /// Creates a module instance which is used to import host functions, tables, memories, and globals into a wasm module.
405    ///
406    /// # Argument
407    ///
408    /// * `name` - The name of the import module instance.
409    ///
410    /// * `data` - The host context data used in this function.
411    ///
412    /// # Error
413    ///
414    /// If fail to create the import module instance, then an error is returned.
415    pub fn create(name: impl AsRef<str>, data: Box<T>) -> WasmEdgeResult<Self> {
416        let raw_name = WasmEdgeString::from(name.as_ref());
417
418        // ffi::WasmEdge_ModuleInstanceGetModuleName(Cxt)
419
420        let ctx = unsafe {
421            ffi::WasmEdge_ModuleInstanceCreateWithData(
422                raw_name.as_raw(),
423                Box::leak(data) as *mut _ as *mut std::ffi::c_void,
424                Some(import_data_finalizer::<T>),
425            )
426        };
427
428        let import = Self {
429            inner: InnerInstance(ctx),
430            name: name.as_ref().to_string(),
431            _data: Default::default(),
432        };
433
434        Ok(import)
435    }
436
437    /// # Safety
438    ///
439    /// Provides a raw pointer to the inner module instance context.
440    /// The lifetime of the returned pointer must not exceed that of the object itself.
441    pub unsafe fn as_raw(&self) -> *mut ffi::WasmEdge_ModuleInstanceContext {
442        self.inner.0
443    }
444
445    /// # Safety
446    ///
447    /// This function will take over the lifetime management of `ctx`, so do not call `ffi::WasmEdge_ModuleInstanceDelete` on `ctx` after this.
448    pub unsafe fn from_raw(ctx: *mut ffi::WasmEdge_ModuleInstanceContext) -> Self {
449        let wasmedge_s = WasmEdgeString::from_raw(ffi::WasmEdge_ModuleInstanceGetModuleName(ctx));
450        let name = (&wasmedge_s).into();
451        Self {
452            inner: InnerInstance(ctx),
453            name,
454            _data: Default::default(),
455        }
456    }
457
458    pub fn get_host_data(&self) -> &T {
459        unsafe { &*(ffi::WasmEdge_ModuleInstanceGetHostData(self.as_ptr()) as *mut T) }
460    }
461
462    pub fn get_host_data_mut(&mut self) -> &mut T {
463        unsafe { &mut *(ffi::WasmEdge_ModuleInstanceGetHostData(self.as_ptr()) as *mut T) }
464    }
465}
466impl<T: Sized> AsInstance for ImportModule<T> {
467    unsafe fn as_ptr(&self) -> *const ffi::WasmEdge_ModuleInstanceContext {
468        self.inner.0
469    }
470
471    fn name(&self) -> Option<String> {
472        Some(self.name.clone())
473    }
474}
475impl<T: Sized> ImportModule<T> {
476    pub fn add_func(&mut self, name: impl AsRef<str>, func: Function) {
477        let func_name: WasmEdgeString = name.into();
478        unsafe {
479            ffi::WasmEdge_ModuleInstanceAddFunction(
480                self.inner.0,
481                func_name.as_raw(),
482                func.get_func_raw(),
483            );
484        }
485        std::mem::forget(func);
486    }
487
488    pub fn add_table(&mut self, name: impl AsRef<str>, table: Table) {
489        let table_name: WasmEdgeString = name.as_ref().into();
490        unsafe {
491            ffi::WasmEdge_ModuleInstanceAddTable(self.inner.0, table_name.as_raw(), table.inner.0);
492        }
493        std::mem::forget(table);
494    }
495
496    pub fn add_memory(&mut self, name: impl AsRef<str>, memory: Memory) {
497        let mem_name: WasmEdgeString = name.as_ref().into();
498        unsafe {
499            ffi::WasmEdge_ModuleInstanceAddMemory(self.inner.0, mem_name.as_raw(), memory.inner.0);
500        }
501        std::mem::forget(memory);
502    }
503
504    pub fn add_global(&mut self, name: impl AsRef<str>, global: Global) {
505        let global_name: WasmEdgeString = name.as_ref().into();
506        unsafe {
507            ffi::WasmEdge_ModuleInstanceAddGlobal(
508                self.inner.0,
509                global_name.as_raw(),
510                global.inner.0,
511            );
512        }
513        std::mem::forget(global);
514    }
515}
516
517/// A [WasiModule] is a module instance for the WASI specification.
518#[derive(Debug)]
519pub struct WasiModule(Instance);
520
521impl AsRef<Instance> for WasiModule {
522    fn as_ref(&self) -> &Instance {
523        &self.0
524    }
525}
526impl AsMut<Instance> for WasiModule {
527    fn as_mut(&mut self) -> &mut Instance {
528        &mut self.0
529    }
530}
531
532impl WasiModule {
533    /// Creates a WASI host module which contains the WASI host functions, and initializes it with the given parameters.
534    ///
535    /// # Arguments
536    ///
537    /// * `args` - The commandline arguments. The first argument is the program name.
538    ///
539    /// * `envs` - The environment variables in the format `ENV_VAR_NAME=VALUE`.
540    ///
541    /// * `preopens` - The directories to pre-open. The required format is `GUEST_PATH:HOST_PATH`.
542    ///
543    /// # Error
544    ///
545    /// If fail to create a host module, then an error is returned.
546    pub fn create(
547        args: Option<Vec<&str>>,
548        envs: Option<Vec<&str>>,
549        preopens: Option<Vec<&str>>,
550    ) -> WasmEdgeResult<Self> {
551        // parse args
552        let cstr_args: Vec<_> = match args {
553            Some(args) => args
554                .iter()
555                .map(|&x| std::ffi::CString::new(x).unwrap())
556                .collect(),
557            None => vec![],
558        };
559        let mut p_args: Vec<_> = cstr_args.iter().map(|x| x.as_ptr()).collect();
560        let p_args_len = p_args.len();
561        p_args.push(std::ptr::null());
562
563        // parse envs
564        let cstr_envs: Vec<_> = match envs {
565            Some(envs) => envs
566                .iter()
567                .map(|&x| std::ffi::CString::new(x).unwrap())
568                .collect(),
569            None => vec![],
570        };
571        let mut p_envs: Vec<_> = cstr_envs.iter().map(|x| x.as_ptr()).collect();
572        let p_envs_len = p_envs.len();
573        p_envs.push(std::ptr::null());
574
575        // parse preopens
576        let cstr_preopens: Vec<_> = match preopens {
577            Some(preopens) => preopens
578                .iter()
579                .map(|&x| std::ffi::CString::new(x).unwrap())
580                .collect(),
581            None => vec![],
582        };
583        let mut p_preopens: Vec<_> = cstr_preopens.iter().map(|x| x.as_ptr()).collect();
584        let p_preopens_len = p_preopens.len();
585        p_preopens.push(std::ptr::null());
586
587        let ctx = unsafe {
588            ffi::WasmEdge_ModuleInstanceCreateWASI(
589                p_args.as_ptr(),
590                p_args_len as u32,
591                p_envs.as_ptr(),
592                p_envs_len as u32,
593                p_preopens.as_ptr(),
594                p_preopens_len as u32,
595            )
596        };
597        match ctx.is_null() {
598            true => Err(Box::new(WasmEdgeError::ImportObjCreate)),
599            false => Ok(Self(Instance {
600                inner: InnerInstance(ctx),
601            })),
602        }
603    }
604
605    /// Returns the name of the module instance.
606    pub fn name(&self) -> &str {
607        "wasi_snapshot_preview1"
608    }
609
610    /// Initializes the WASI host module with the given parameters.
611    ///
612    /// # Arguments
613    ///
614    /// * `args` - The commandline arguments. The first argument is the program name.
615    ///
616    /// * `envs` - The environment variables in the format `ENV_VAR_NAME=VALUE`.
617    ///
618    /// * `preopens` - The directories to pre-open. The required format is `GUEST_PATH:HOST_PATH`.
619    pub fn init_wasi(
620        &mut self,
621        args: Option<Vec<&str>>,
622        envs: Option<Vec<&str>>,
623        preopens: Option<Vec<&str>>,
624    ) {
625        // parse args
626        let cstr_args: Vec<_> = match args {
627            Some(args) => args
628                .iter()
629                .map(|&x| std::ffi::CString::new(x).unwrap())
630                .collect(),
631            None => vec![],
632        };
633        let mut p_args: Vec<_> = cstr_args.iter().map(|x| x.as_ptr()).collect();
634        let p_args_len = p_args.len();
635        p_args.push(std::ptr::null());
636
637        // parse envs
638        let cstr_envs: Vec<_> = match envs {
639            Some(envs) => envs
640                .iter()
641                .map(|&x| std::ffi::CString::new(x).unwrap())
642                .collect(),
643            None => vec![],
644        };
645        let mut p_envs: Vec<_> = cstr_envs.iter().map(|x| x.as_ptr()).collect();
646        let p_envs_len = p_envs.len();
647        p_envs.push(std::ptr::null());
648
649        // parse preopens
650        let cstr_preopens: Vec<_> = match preopens {
651            Some(preopens) => preopens
652                .iter()
653                .map(|&x| std::ffi::CString::new(x).unwrap())
654                .collect(),
655            None => vec![],
656        };
657        let mut p_preopens: Vec<_> = cstr_preopens.iter().map(|x| x.as_ptr()).collect();
658        let p_preopens_len = p_preopens.len();
659        p_preopens.push(std::ptr::null());
660
661        unsafe {
662            ffi::WasmEdge_ModuleInstanceInitWASI(
663                self.0.as_ptr() as *mut _,
664                p_args.as_ptr(),
665                p_args_len as u32,
666                p_envs.as_ptr(),
667                p_envs_len as u32,
668                p_preopens.as_ptr(),
669                p_preopens_len as u32,
670            )
671        };
672    }
673
674    /// Returns the WASI exit code.
675    ///
676    /// The WASI exit code can be accessed after running the "_start" function of a `wasm32-wasi` program.
677    pub fn exit_code(&self) -> u32 {
678        unsafe { ffi::WasmEdge_ModuleInstanceWASIGetExitCode(self.0.as_ptr()) }
679    }
680
681    /// Returns the native handler from the mapped FD/Handler.
682    ///
683    /// # Argument
684    ///
685    /// * `fd` - The WASI mapped Fd.
686    ///
687    /// # Error
688    ///
689    /// If fail to get the native handler, then an error is returned.
690    pub fn get_native_handler(&self, fd: i32) -> WasmEdgeResult<u64> {
691        let mut handler: u64 = 0;
692        let code: u32 = unsafe {
693            ffi::WasmEdge_ModuleInstanceWASIGetNativeHandler(
694                self.0.as_ptr(),
695                fd,
696                &mut handler as *mut u64,
697            )
698        };
699
700        match code {
701            0 => Ok(handler),
702            _ => Err(Box::new(WasmEdgeError::Instance(
703                InstanceError::NotFoundMappedFdHandler,
704            ))),
705        }
706    }
707}
708
709#[cfg(test)]
710mod tests {
711    use super::*;
712    use crate::{CallingFrame, Executor, GlobalType, ImportModule, Store, TableType, WasmValue};
713
714    use wasmedge_types::{
715        error::{CoreError, CoreExecutionError},
716        FuncType, MemoryType, Mutability, RefType, ValType,
717    };
718
719    #[test]
720    #[allow(clippy::assertions_on_result_states)]
721    fn test_instance_add_instance() {
722        let host_name = "extern";
723
724        // create an import module
725        let result = ImportModule::<()>::create(host_name, Box::new(()));
726        assert!(result.is_ok());
727        let mut import = result.unwrap();
728
729        // create a host function
730        let func_ty = wasmedge_types::FuncType::new(
731            vec![ValType::ExternRef, ValType::I32],
732            vec![ValType::I32],
733        );
734
735        let result = unsafe {
736            Function::create_sync_func(&func_ty, real_add, import.get_host_data_mut(), 0)
737        };
738        assert!(result.is_ok());
739
740        let host_func = result.unwrap();
741        // add the host function
742        import.add_func("func-add", host_func);
743
744        // create a table
745        let table_ty = TableType::new(RefType::FuncRef, 10, Some(20));
746        let result = Table::create(table_ty);
747        assert!(result.is_ok());
748        let host_table = result.unwrap();
749        // add the table
750        import.add_table("table", host_table);
751
752        // create a memory
753        let result = MemoryType::new(1, Some(2), false);
754        assert!(result.is_ok());
755        let mem_ty = result.unwrap();
756        let result = Memory::create(&mem_ty);
757        assert!(result.is_ok());
758        let host_memory = result.unwrap();
759        // add the memory
760        import.add_memory("memory", host_memory);
761
762        // create a global
763        let global_ty = GlobalType::new(ValType::I32, Mutability::Const);
764        let result = Global::create(&global_ty, WasmValue::from_i32(666));
765        assert!(result.is_ok());
766        let host_global = result.unwrap();
767        // add the global
768        import.add_global("global_i32", host_global);
769    }
770
771    #[cfg(target_family = "unix")]
772    #[test]
773    fn test_instance_wasi() {
774        // create a wasi module instance
775        {
776            let result = WasiModule::create(None, None, None);
777            assert!(result.is_ok());
778
779            let result = WasiModule::create(
780                Some(vec!["arg1", "arg2"]),
781                Some(vec!["ENV1=VAL1", "ENV1=VAL2", "ENV3=VAL3"]),
782                Some(vec![
783                    "apiTestData",
784                    "Makefile",
785                    "CMakeFiles",
786                    "ssvmAPICoreTests",
787                    ".:.",
788                ]),
789            );
790            assert!(result.is_ok());
791
792            let result = WasiModule::create(
793                None,
794                Some(vec!["ENV1=VAL1", "ENV1=VAL2", "ENV3=VAL3"]),
795                Some(vec![
796                    "apiTestData",
797                    "Makefile",
798                    "CMakeFiles",
799                    "ssvmAPICoreTests",
800                    ".:.",
801                ]),
802            );
803            assert!(result.is_ok());
804            let wasi_import = result.unwrap();
805            assert_eq!(wasi_import.exit_code(), 0);
806        }
807    }
808
809    #[test]
810    #[allow(clippy::assertions_on_result_states)]
811    fn test_instance_find_xxx() -> Result<(), Box<dyn std::error::Error>> {
812        let module_name = "extern_module";
813
814        // create ImportModule instance
815        let result = ImportModule::create(module_name, Box::new(()));
816        assert!(result.is_ok());
817        let mut import = result.unwrap();
818
819        // add host function
820        let func_ty = FuncType::new(vec![ValType::I32; 2], vec![ValType::I32]);
821        let result = unsafe {
822            Function::create_sync_func(&func_ty, real_add, import.get_host_data_mut(), 0)
823        };
824        assert!(result.is_ok());
825        let host_func = result.unwrap();
826        import.add_func("add", host_func);
827
828        // add table
829        let ty = TableType::new(RefType::FuncRef, 0, Some(u32::MAX));
830        let result = Table::create(ty);
831        assert!(result.is_ok());
832        let table = result.unwrap();
833        import.add_table("table", table);
834
835        // add memory
836        let result = MemoryType::new(0, Some(u32::MAX), false);
837        assert!(result.is_ok());
838        let mem_ty = result.unwrap();
839        let result = Memory::create(&mem_ty);
840        assert!(result.is_ok());
841        let memory = result.unwrap();
842        import.add_memory("mem", memory);
843
844        // add global
845        let ty = GlobalType::new(ValType::F32, Mutability::Const);
846        let result = Global::create(&ty, WasmValue::from_f32(3.5));
847        assert!(result.is_ok());
848        let global = result.unwrap();
849        import.add_global("global", global);
850
851        // create an executor
852        let mut executor = Executor::create(None, None)?;
853
854        // create a store
855        let mut store = Store::create()?;
856
857        executor.register_import_module(&mut store, &import)?;
858
859        // get the module named "extern"
860        let result = store.module("extern_module");
861        assert!(result.is_ok());
862        let instance = result.unwrap();
863
864        // check the name of the module
865        assert!(instance.name().is_some());
866        assert_eq!(instance.name().unwrap(), "extern_module");
867
868        // get the exported function named "fib"
869        let result = instance.get_func("add");
870        assert!(result.is_ok());
871        let func = result.unwrap();
872
873        // check the type of the function
874        let result = func.ty();
875        assert!(result.is_some());
876        let ty = result.unwrap();
877
878        // check the parameter types
879        assert_eq!(ty.args(), &[ValType::I32, ValType::I32]);
880
881        // check the return types
882        assert_eq!(ty.returns(), &[ValType::I32]);
883
884        // get the exported table named "table"
885        let result = instance.get_table("table");
886        assert!(result.is_ok());
887        let table = result.unwrap();
888
889        // check the type of the table
890        let result = table.ty();
891        assert!(result.is_ok());
892        let ty = result.unwrap();
893        assert_eq!(ty.elem_ty(), RefType::FuncRef);
894        assert_eq!(ty.minimum(), 0);
895        assert_eq!(ty.maximum(), Some(u32::MAX));
896
897        // get the exported memory named "mem"
898        let result = instance.get_memory_ref("mem");
899        assert!(result.is_ok());
900        let memory = result.unwrap();
901
902        // check the type of the memory
903        let result = memory.ty();
904        assert!(result.is_ok());
905        let ty = result.unwrap();
906        assert_eq!(ty.minimum(), 0);
907        assert_eq!(ty.maximum(), Some(u32::MAX));
908
909        // get the exported global named "global"
910        let result = instance.get_global("global");
911        assert!(result.is_ok());
912        let global = result.unwrap();
913
914        // check the type of the global
915        let result = global.ty();
916        assert!(result.is_ok());
917        let global = result.unwrap();
918        assert_eq!(global.value_ty(), ValType::F32);
919        assert_eq!(global.mutability(), Mutability::Const);
920
921        Ok(())
922    }
923
924    #[test]
925    #[allow(clippy::assertions_on_result_states)]
926    fn test_instance_find_names() -> Result<(), Box<dyn std::error::Error>> {
927        let module_name = "extern_module";
928
929        // create ImportModule instance
930        let result = ImportModule::create(module_name, Box::new(()));
931        assert!(result.is_ok());
932        let mut import = result.unwrap();
933
934        // add host function
935        let func_ty = FuncType::new(vec![ValType::I32; 2], vec![ValType::I32]);
936        let result = unsafe {
937            Function::create_sync_func(&func_ty, real_add, import.get_host_data_mut(), 0)
938        };
939        assert!(result.is_ok());
940        let host_func = result.unwrap();
941        import.add_func("add", host_func);
942
943        // add table
944        let ty = TableType::new(RefType::FuncRef, 0, Some(u32::MAX));
945        let result = Table::create(ty);
946        assert!(result.is_ok());
947        let table = result.unwrap();
948        import.add_table("table", table);
949
950        // add memory
951        let result = MemoryType::new(0, Some(u32::MAX), false);
952        assert!(result.is_ok());
953        let mem_ty = result.unwrap();
954        let result = Memory::create(&mem_ty);
955        assert!(result.is_ok());
956        let memory = result.unwrap();
957        import.add_memory("mem", memory);
958
959        // add global
960        let ty = GlobalType::new(ValType::F32, Mutability::Const);
961        let result = Global::create(&ty, WasmValue::from_f32(3.5));
962        assert!(result.is_ok());
963        let global = result.unwrap();
964        import.add_global("global", global);
965
966        // create an executor
967        let mut executor = Executor::create(None, None)?;
968
969        // create a store
970        let mut store = Store::create()?;
971
972        executor.register_import_module(&mut store, &import)?;
973
974        // get the module named "extern"
975        let result = store.module("extern_module");
976        assert!(result.is_ok());
977        let instance = result.unwrap();
978
979        // check the name of the module
980        assert!(instance.name().is_some());
981        assert_eq!(instance.name().unwrap(), "extern_module");
982
983        assert_eq!(instance.func_len(), 1);
984        let result = instance.func_names();
985        assert!(result.is_some());
986        assert_eq!(result.unwrap(), ["add"]);
987
988        assert_eq!(instance.table_len(), 1);
989        let result = instance.table_names();
990        assert!(result.is_some());
991        assert_eq!(result.unwrap(), ["table"]);
992
993        assert_eq!(instance.mem_len(), 1);
994        let result = instance.mem_names();
995        assert!(result.is_some());
996        assert_eq!(result.unwrap(), ["mem"]);
997
998        assert_eq!(instance.global_len(), 1);
999        let result = instance.global_names();
1000        assert!(result.is_some());
1001        assert_eq!(result.unwrap(), ["global"]);
1002
1003        Ok(())
1004    }
1005
1006    fn real_add(
1007        _data: &mut (),
1008        _inst: &mut Instance,
1009        _frame: &mut CallingFrame,
1010        inputs: Vec<WasmValue>,
1011    ) -> Result<Vec<WasmValue>, CoreError> {
1012        if inputs.len() != 2 {
1013            return Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch));
1014        }
1015
1016        let a = if inputs[0].ty() == ValType::I32 {
1017            inputs[0].to_i32()
1018        } else {
1019            return Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch));
1020        };
1021
1022        let b = if inputs[1].ty() == ValType::I32 {
1023            inputs[1].to_i32()
1024        } else {
1025            return Err(CoreError::Execution(CoreExecutionError::FuncSigMismatch));
1026        };
1027
1028        let c = a + b;
1029
1030        Ok(vec![WasmValue::from_i32(c)])
1031    }
1032}