Skip to main content

wasmedge_sys/
ast_module.rs

1//! Defines WasmEdge AST Module, Export, and Import structs.
2
3use super::ffi;
4use crate::{types::WasmEdgeLimit, WasmEdgeResult};
5use std::{borrow::Cow, ffi::CStr};
6use wasmedge_types::{
7    error::{ExportError, ImportError, WasmEdgeError},
8    ExternalInstanceType, FuncType, GlobalType, MemoryType, Mutability, RefType, TableType,
9    ValType,
10};
11
12/// Defines compiled in-memory representation of an input WASM binary.
13///
14/// [Module] is also called *AST Module* in WasmEdge terminology. A [Module] is a compiled in-memory
15/// representation of an input WebAssembly binary. In the instantiation process, a [Module] is used to create a
16/// [module stance](crate::instance), from which the exported [functions](crate::Function), [tables](crate::Table),
17/// [memories](crate::Memory), and [globals](crate::Global) can be fetched.
18#[derive(Debug)]
19pub struct Module {
20    pub(crate) inner: InnerModule,
21}
22impl Drop for Module {
23    fn drop(&mut self) {
24        unsafe { ffi::WasmEdge_ASTModuleDelete(self.inner.0) };
25    }
26}
27impl Module {
28    /// Returns the number of wasm imports in the [Module].
29    pub fn count_of_imports(&self) -> u32 {
30        unsafe { ffi::WasmEdge_ASTModuleListImportsLength(self.inner.0) }
31    }
32
33    /// Returns the types of wasm imports in the [Module].
34    pub fn imports(&self) -> Vec<ImportType<'_>> {
35        let size = self.count_of_imports();
36        let mut returns = Vec::with_capacity(size as usize);
37        unsafe {
38            ffi::WasmEdge_ASTModuleListImports(self.inner.0, returns.as_mut_ptr(), size);
39            returns.set_len(size as usize);
40        }
41
42        returns
43            .into_iter()
44            .map(|ctx| ImportType {
45                inner: InnerImportType(ctx),
46                module: self,
47            })
48            .collect()
49    }
50
51    /// Returns the count of wasm exports in the [Module].
52    pub fn count_of_exports(&self) -> u32 {
53        unsafe { ffi::WasmEdge_ASTModuleListExportsLength(self.inner.0) }
54    }
55
56    /// Returns the types of wasm exports in the [Module].
57    pub fn export(&self) -> Vec<ExportType<'_>> {
58        let size = self.count_of_exports();
59        let mut returns = Vec::with_capacity(size as usize);
60        unsafe {
61            ffi::WasmEdge_ASTModuleListExports(self.inner.0, returns.as_mut_ptr(), size);
62            returns.set_len(size as usize);
63        }
64
65        returns
66            .into_iter()
67            .map(|ctx| ExportType {
68                inner: InnerExportType(ctx),
69                module: self,
70            })
71            .collect()
72    }
73
74    pub unsafe fn from_raw(ptr: *mut ffi::WasmEdge_ASTModuleContext) -> Self {
75        Self {
76            inner: InnerModule(ptr),
77        }
78    }
79}
80
81#[derive(Debug, Clone, Copy)]
82pub(crate) struct InnerModule(pub(crate) *mut ffi::WasmEdge_ASTModuleContext);
83unsafe impl Send for InnerModule {}
84unsafe impl Sync for InnerModule {}
85
86/// Defines the types of the imported wasm value.
87#[derive(Debug)]
88pub struct ImportType<'module> {
89    pub(crate) inner: InnerImportType,
90    pub(crate) module: &'module Module,
91}
92impl Drop for ImportType<'_> {
93    fn drop(&mut self) {
94        if !self.inner.0.is_null() {
95            self.inner.0 = std::ptr::null();
96        }
97    }
98}
99impl ImportType<'_> {
100    /// Returns the type of this import.
101    pub fn ty(&self) -> WasmEdgeResult<ExternalInstanceType> {
102        let ty = unsafe { ffi::WasmEdge_ImportTypeGetExternalType(self.inner.0) };
103        let ty: ExternalInstanceType = ty.into();
104        match ty {
105            ExternalInstanceType::Func(_) => {
106                let ctx_func_ty = unsafe {
107                    ffi::WasmEdge_ImportTypeGetFunctionType(
108                        self.module.inner.0 as *const _,
109                        self.inner.0 as *const _,
110                    )
111                };
112                match ctx_func_ty.is_null() {
113                    true => Err(Box::new(WasmEdgeError::Import(ImportError::FuncType(
114                        "Fail to get the function type".into(),
115                    )))),
116                    false => {
117                        // get types of the arguments
118                        let args_len = unsafe {
119                            ffi::WasmEdge_FunctionTypeGetParametersLength(ctx_func_ty) as usize
120                        };
121                        let mut args = Vec::with_capacity(args_len);
122                        unsafe {
123                            ffi::WasmEdge_FunctionTypeGetParameters(
124                                ctx_func_ty,
125                                args.as_mut_ptr(),
126                                args_len as u32,
127                            );
128                            args.set_len(args_len);
129                        }
130                        let args: Vec<ValType> = args.into_iter().map(Into::into).collect();
131
132                        // get types of the returns
133                        let returns_len = unsafe {
134                            ffi::WasmEdge_FunctionTypeGetReturnsLength(ctx_func_ty) as usize
135                        };
136                        let mut returns = Vec::with_capacity(returns_len);
137                        unsafe {
138                            ffi::WasmEdge_FunctionTypeGetReturns(
139                                ctx_func_ty,
140                                returns.as_mut_ptr(),
141                                returns_len as u32,
142                            );
143                            returns.set_len(returns_len);
144                        }
145                        let returns: Vec<ValType> = returns.into_iter().map(Into::into).collect();
146
147                        Ok(ExternalInstanceType::Func(FuncType::new(args, returns)))
148                    }
149                }
150            }
151            ExternalInstanceType::Global(_) => {
152                let ctx_global_ty = unsafe {
153                    ffi::WasmEdge_ImportTypeGetGlobalType(self.module.inner.0, self.inner.0)
154                };
155                match ctx_global_ty.is_null() {
156                    true => Err(Box::new(WasmEdgeError::Import(ImportError::MemType(
157                        "Fail to get the global type".into(),
158                    )))),
159                    false => {
160                        // get the value type
161                        let val = unsafe { ffi::WasmEdge_GlobalTypeGetValType(ctx_global_ty) };
162                        let val_ty: ValType = val.into();
163
164                        // get mutability
165                        let val = unsafe { ffi::WasmEdge_GlobalTypeGetMutability(ctx_global_ty) };
166                        let mutability: Mutability = val.into();
167
168                        Ok(ExternalInstanceType::Global(GlobalType::new(
169                            val_ty, mutability,
170                        )))
171                    }
172                }
173            }
174            ExternalInstanceType::Memory(_) => {
175                let ctx_mem_ty = unsafe {
176                    ffi::WasmEdge_ImportTypeGetMemoryType(self.module.inner.0, self.inner.0)
177                };
178                match ctx_mem_ty.is_null() {
179                    true => Err(Box::new(WasmEdgeError::Import(ImportError::MemType(
180                        "Fail to get the memory type".into(),
181                    )))),
182                    false => {
183                        let limit = unsafe { ffi::WasmEdge_MemoryTypeGetLimit(ctx_mem_ty) };
184                        let limit = WasmEdgeLimit::from_context(limit);
185
186                        Ok(ExternalInstanceType::Memory(MemoryType::new(
187                            limit.min(),
188                            limit.max(),
189                            limit.shared(),
190                        )?))
191                    }
192                }
193            }
194            ExternalInstanceType::Table(_) => {
195                let ctx_tab_ty = unsafe {
196                    ffi::WasmEdge_ImportTypeGetTableType(self.module.inner.0, self.inner.0)
197                };
198                match ctx_tab_ty.is_null() {
199                    true => Err(Box::new(WasmEdgeError::Import(ImportError::TableType(
200                        "Fail to get the table type".into(),
201                    )))),
202                    false => {
203                        // get the element type
204                        let elem_ty = unsafe { ffi::WasmEdge_TableTypeGetRefType(ctx_tab_ty) };
205                        let elem_ty = RefType::from(ValType::from(elem_ty));
206
207                        // get the limit
208                        let limit = unsafe { ffi::WasmEdge_TableTypeGetLimit(ctx_tab_ty) };
209                        let limit = WasmEdgeLimit::from_context(limit);
210
211                        Ok(ExternalInstanceType::Table(TableType::new(
212                            elem_ty,
213                            limit.min(),
214                            limit.max(),
215                        )))
216                    }
217                }
218            }
219        }
220    }
221
222    /// Returns the field name of the module that this import is expected to come from.
223    pub fn name(&self) -> Cow<'_, str> {
224        let c_name = unsafe {
225            let raw_name = ffi::WasmEdge_ImportTypeGetExternalName(self.inner.0);
226            CStr::from_ptr(raw_name.Buf)
227        };
228        c_name.to_string_lossy()
229    }
230
231    /// Returns the module name that this import is expected to come from.
232    pub fn module_name(&self) -> Cow<'_, str> {
233        let c_name = unsafe {
234            let raw_name = ffi::WasmEdge_ImportTypeGetModuleName(self.inner.0);
235            CStr::from_ptr(raw_name.Buf)
236        };
237        c_name.to_string_lossy()
238    }
239
240    /// Provides a raw pointer to the inner ImportType context.
241    #[cfg(feature = "ffi")]
242    #[cfg_attr(docsrs, doc(cfg(feature = "ffi")))]
243    pub fn as_ptr(&self) -> *const ffi::WasmEdge_ImportTypeContext {
244        self.inner.0 as *const _
245    }
246}
247
248#[derive(Debug)]
249pub(crate) struct InnerImportType(pub(crate) *const ffi::WasmEdge_ImportTypeContext);
250unsafe impl Send for InnerImportType {}
251unsafe impl Sync for InnerImportType {}
252
253/// Defines the types of the exported wasm values.
254#[derive(Debug)]
255pub struct ExportType<'module> {
256    pub(crate) inner: InnerExportType,
257    pub(crate) module: &'module Module,
258}
259
260impl ExportType<'_> {
261    /// Returns the type of this export.
262    pub fn ty(&self) -> WasmEdgeResult<ExternalInstanceType> {
263        let ty = unsafe { ffi::WasmEdge_ExportTypeGetExternalType(self.inner.0) };
264        let ty: ExternalInstanceType = ty.into();
265        match ty {
266            ExternalInstanceType::Func(_) => {
267                let ctx_func_ty = unsafe {
268                    ffi::WasmEdge_ExportTypeGetFunctionType(self.module.inner.0, self.inner.0)
269                };
270                match ctx_func_ty.is_null() {
271                    true => Err(Box::new(WasmEdgeError::Export(ExportError::FuncType(
272                        "Fail to get the function type".into(),
273                    )))),
274                    false => {
275                        // get types of the arguments
276                        let args_len = unsafe {
277                            ffi::WasmEdge_FunctionTypeGetParametersLength(ctx_func_ty) as usize
278                        };
279                        let mut args = Vec::with_capacity(args_len);
280                        unsafe {
281                            ffi::WasmEdge_FunctionTypeGetParameters(
282                                ctx_func_ty,
283                                args.as_mut_ptr(),
284                                args_len as u32,
285                            );
286                            args.set_len(args_len);
287                        }
288                        let args: Vec<ValType> = args.into_iter().map(Into::into).collect();
289
290                        // get types of the returns
291                        let returns_len = unsafe {
292                            ffi::WasmEdge_FunctionTypeGetReturnsLength(ctx_func_ty) as usize
293                        };
294                        let mut returns = Vec::with_capacity(returns_len);
295                        unsafe {
296                            ffi::WasmEdge_FunctionTypeGetReturns(
297                                ctx_func_ty,
298                                returns.as_mut_ptr(),
299                                returns_len as u32,
300                            );
301                            returns.set_len(returns_len);
302                        }
303                        let returns: Vec<ValType> = returns.into_iter().map(Into::into).collect();
304
305                        Ok(ExternalInstanceType::Func(FuncType::new(args, returns)))
306                    }
307                }
308            }
309            ExternalInstanceType::Table(_) => {
310                let ctx_tab_ty = unsafe {
311                    ffi::WasmEdge_ExportTypeGetTableType(self.module.inner.0, self.inner.0)
312                };
313                match ctx_tab_ty.is_null() {
314                    true => Err(Box::new(WasmEdgeError::Export(ExportError::TableType(
315                        "Fail to get the function type".into(),
316                    )))),
317                    false => {
318                        // get the element type
319                        let elem_ty = unsafe { ffi::WasmEdge_TableTypeGetRefType(ctx_tab_ty) };
320                        let elem_ty = RefType::from(ValType::from(elem_ty));
321
322                        // get the limit
323                        let limit = unsafe { ffi::WasmEdge_TableTypeGetLimit(ctx_tab_ty) };
324                        let limit = WasmEdgeLimit::from_context(limit);
325
326                        Ok(ExternalInstanceType::Table(TableType::new(
327                            elem_ty,
328                            limit.min(),
329                            limit.max(),
330                        )))
331                    }
332                }
333            }
334            ExternalInstanceType::Memory(_) => {
335                let ctx_mem_ty = unsafe {
336                    ffi::WasmEdge_ExportTypeGetMemoryType(self.module.inner.0, self.inner.0)
337                };
338                match ctx_mem_ty.is_null() {
339                    true => Err(Box::new(WasmEdgeError::Export(ExportError::MemType(
340                        "Fail to get the function type".into(),
341                    )))),
342                    false => {
343                        let limit = unsafe { ffi::WasmEdge_MemoryTypeGetLimit(ctx_mem_ty) };
344                        let limit = WasmEdgeLimit::from_context(limit);
345
346                        Ok(ExternalInstanceType::Memory(MemoryType::new(
347                            limit.min(),
348                            limit.max(),
349                            limit.shared(),
350                        )?))
351                    }
352                }
353            }
354            ExternalInstanceType::Global(_) => {
355                let ctx_global_ty = unsafe {
356                    ffi::WasmEdge_ExportTypeGetGlobalType(self.module.inner.0, self.inner.0)
357                };
358                match ctx_global_ty.is_null() {
359                    true => Err(Box::new(WasmEdgeError::Export(ExportError::GlobalType(
360                        "Fail to get the function type".into(),
361                    )))),
362                    false => {
363                        // get the value type
364                        let val = unsafe { ffi::WasmEdge_GlobalTypeGetValType(ctx_global_ty) };
365                        let val_ty: ValType = val.into();
366
367                        // get mutability
368                        let val = unsafe { ffi::WasmEdge_GlobalTypeGetMutability(ctx_global_ty) };
369                        let mutability: Mutability = val.into();
370
371                        Ok(ExternalInstanceType::Global(GlobalType::new(
372                            val_ty, mutability,
373                        )))
374                    }
375                }
376            }
377        }
378    }
379
380    /// Returns the name by which this export is known by.
381    pub fn name(&self) -> Cow<'_, str> {
382        let c_name = unsafe {
383            let raw_name = ffi::WasmEdge_ExportTypeGetExternalName(self.inner.0);
384            CStr::from_ptr(raw_name.Buf)
385        };
386        c_name.to_string_lossy()
387    }
388}
389
390#[derive(Debug)]
391pub(crate) struct InnerExportType(pub(crate) *const ffi::WasmEdge_ExportTypeContext);
392unsafe impl Send for InnerExportType {}
393unsafe impl Sync for InnerExportType {}
394
395#[cfg(test)]
396mod tests {
397    use crate::{Config, Loader};
398    use std::{
399        sync::{Arc, Mutex},
400        thread,
401    };
402    use wasmedge_types::{ExternalInstanceType, Mutability, RefType, ValType};
403
404    #[ignore = "need to update `import.wat`"]
405    #[test]
406    fn test_module_import() {
407        let path = std::env::current_dir()
408            .unwrap()
409            .ancestors()
410            .nth(2)
411            .unwrap()
412            .join("examples/wasmedge-sys/data/import.wat");
413
414        let result = Config::create();
415        assert!(result.is_ok());
416        let mut config = result.unwrap();
417        config.bulk_memory_operations(true);
418        assert!(config.bulk_memory_operations_enabled());
419
420        // load module from file
421        let result = Loader::create(Some(&config));
422        assert!(result.is_ok());
423        let loader = result.unwrap();
424        let result = loader.from_file(path);
425        assert!(result.is_ok());
426        let module = result.unwrap();
427        assert!(!module.inner.0.is_null());
428
429        // check imports
430
431        assert_eq!(module.count_of_imports(), 14);
432        let imports = module.imports();
433
434        // check the ty, name, and module_name functions
435        let result = imports[0].ty();
436        assert!(result.is_ok());
437        let ty = result.unwrap();
438        matches!(ty, ExternalInstanceType::Func(_));
439        assert_eq!(imports[0].name(), "func-add");
440        assert_eq!(imports[0].module_name(), "extern");
441
442        let result = imports[1].ty();
443        assert!(result.is_ok());
444        matches!(result.unwrap(), ExternalInstanceType::Func(_));
445        assert_eq!(imports[1].name(), "func-sub");
446        assert_eq!(imports[1].module_name(), "extern");
447
448        let result = imports[2].ty();
449        assert!(result.is_ok());
450        matches!(result.unwrap(), ExternalInstanceType::Func(_));
451        assert_eq!(imports[2].name(), "func-mul");
452        assert_eq!(imports[2].module_name(), "extern");
453
454        let result = imports[3].ty();
455        assert!(result.is_ok());
456        matches!(result.unwrap(), ExternalInstanceType::Func(_));
457        assert_eq!(imports[3].name(), "func-div");
458        assert_eq!(imports[3].module_name(), "extern");
459
460        let result = imports[4].ty();
461        assert!(result.is_ok());
462        matches!(result.unwrap(), ExternalInstanceType::Func(_));
463        assert_eq!(imports[4].name(), "func-term");
464        assert_eq!(imports[4].module_name(), "extern");
465
466        let result = imports[5].ty();
467        assert!(result.is_ok());
468        matches!(result.unwrap(), ExternalInstanceType::Func(_));
469        assert_eq!(imports[5].name(), "func-fail");
470        assert_eq!(imports[5].module_name(), "extern");
471
472        let result = imports[6].ty();
473        assert!(result.is_ok());
474        matches!(result.unwrap(), ExternalInstanceType::Global(_));
475        assert_eq!(imports[6].name(), "glob-i32");
476        assert_eq!(imports[6].module_name(), "dummy");
477
478        let result = imports[7].ty();
479        assert!(result.is_ok());
480        matches!(result.unwrap(), ExternalInstanceType::Global(_));
481        assert_eq!(imports[7].name(), "glob-i64");
482        assert_eq!(imports[7].module_name(), "dummy");
483
484        let result = imports[8].ty();
485        assert!(result.is_ok());
486        matches!(result.unwrap(), ExternalInstanceType::Global(_));
487        assert_eq!(imports[8].name(), "glob-f32");
488        assert_eq!(imports[8].module_name(), "dummy");
489
490        let result = imports[9].ty();
491        assert!(result.is_ok());
492        matches!(result.unwrap(), ExternalInstanceType::Global(_));
493        assert_eq!(imports[9].name(), "glob-f64");
494        assert_eq!(imports[9].module_name(), "dummy");
495
496        let result = imports[10].ty();
497        assert!(result.is_ok());
498        matches!(result.unwrap(), ExternalInstanceType::Table(_));
499        assert_eq!(imports[10].name(), "tab-func");
500        assert_eq!(imports[10].module_name(), "dummy");
501
502        let result = imports[11].ty();
503        assert!(result.is_ok());
504        matches!(result.unwrap(), ExternalInstanceType::Table(_));
505        assert_eq!(imports[11].name(), "tab-ext");
506        assert_eq!(imports[11].module_name(), "dummy");
507
508        let result = imports[12].ty();
509        assert!(result.is_ok());
510        matches!(result.unwrap(), ExternalInstanceType::Memory(_));
511        assert_eq!(imports[12].name(), "mem1");
512        assert_eq!(imports[12].module_name(), "dummy");
513
514        let result = imports[13].ty();
515        assert!(result.is_ok());
516        matches!(result.unwrap(), ExternalInstanceType::Memory(_));
517        assert_eq!(imports[13].name(), "mem2");
518        assert_eq!(imports[13].module_name(), "dummy");
519
520        // check the function_type function
521        let result = imports[4].ty();
522        assert!(result.is_ok());
523        let ty = result.unwrap();
524        matches!(ty, ExternalInstanceType::Func(_));
525        if let ExternalInstanceType::Func(func_ty) = ty {
526            assert_eq!(func_ty.returns_len(), 1);
527        }
528
529        // check the table_type function
530        let result = imports[11].ty();
531        assert!(result.is_ok());
532        let ty = result.unwrap();
533        matches!(ty, ExternalInstanceType::Table(_));
534        if let ExternalInstanceType::Table(table_ty) = ty {
535            assert_eq!(table_ty.elem_ty(), RefType::ExternRef);
536            assert_eq!(table_ty.minimum(), 10);
537            assert_eq!(table_ty.maximum(), Some(30));
538        }
539
540        // check the memory_type function
541        let result = imports[13].ty();
542        assert!(result.is_ok());
543        let ty = result.unwrap();
544        matches!(ty, ExternalInstanceType::Memory(_));
545        if let ExternalInstanceType::Memory(mem_ty) = ty {
546            assert_eq!(mem_ty.minimum(), 2);
547            assert_eq!(mem_ty.maximum(), None);
548        }
549
550        // check the global_type function
551        let result = imports[7].ty();
552        assert!(result.is_ok());
553        let ty = result.unwrap();
554        matches!(ty, ExternalInstanceType::Global(_));
555        if let ExternalInstanceType::Global(global_ty) = ty {
556            assert_eq!(global_ty.value_ty(), ValType::I64);
557            assert_eq!(global_ty.mutability(), Mutability::Const);
558        }
559    }
560
561    #[ignore = "need to update `import.wat`"]
562    #[test]
563    fn test_module_export() {
564        let path = std::env::current_dir()
565            .unwrap()
566            .ancestors()
567            .nth(2)
568            .unwrap()
569            .join("examples/wasmedge-sys/data/import.wat");
570
571        let result = Config::create();
572        assert!(result.is_ok());
573        let mut config = result.unwrap();
574        config.bulk_memory_operations(true);
575        assert!(config.bulk_memory_operations_enabled());
576
577        // load module from file
578        let result = Loader::create(Some(&config));
579        assert!(result.is_ok());
580        let loader = result.unwrap();
581        let result = loader.from_file(path);
582        assert!(result.is_ok());
583        let module = result.unwrap();
584        assert!(!module.inner.0.is_null());
585
586        // check exports
587
588        assert_eq!(module.count_of_exports(), 16);
589        let exports = module.export();
590
591        // check the ty and name functions
592        let result = exports[0].ty();
593        assert!(result.is_ok());
594        matches!(result.unwrap(), ExternalInstanceType::Func(_));
595        assert_eq!(exports[0].name(), "func-1");
596
597        let result = exports[1].ty();
598        assert!(result.is_ok());
599        matches!(result.unwrap(), ExternalInstanceType::Func(_));
600        assert_eq!(exports[1].name(), "func-2");
601
602        let result = exports[2].ty();
603        assert!(result.is_ok());
604        matches!(result.unwrap(), ExternalInstanceType::Func(_));
605        assert_eq!(exports[2].name(), "func-3");
606
607        let result = exports[3].ty();
608        assert!(result.is_ok());
609        matches!(result.unwrap(), ExternalInstanceType::Func(_));
610        assert_eq!(exports[3].name(), "func-4");
611
612        assert_eq!(module.count_of_exports(), 16);
613
614        let result = exports[4].ty();
615        assert!(result.is_ok());
616        matches!(result.unwrap(), ExternalInstanceType::Func(_));
617        assert_eq!(exports[4].name(), "func-add");
618
619        let result = exports[5].ty();
620        assert!(result.is_ok());
621        matches!(result.unwrap(), ExternalInstanceType::Func(_));
622        assert_eq!(exports[5].name(), "func-mul-2");
623
624        let result = exports[6].ty();
625        assert!(result.is_ok());
626        matches!(result.unwrap(), ExternalInstanceType::Func(_));
627        assert_eq!(exports[6].name(), "func-call-indirect");
628
629        let result = exports[7].ty();
630        assert!(result.is_ok());
631        matches!(result.unwrap(), ExternalInstanceType::Func(_));
632        assert_eq!(exports[7].name(), "func-host-add");
633
634        let result = exports[8].ty();
635        assert!(result.is_ok());
636        matches!(result.unwrap(), ExternalInstanceType::Func(_));
637        assert_eq!(exports[8].name(), "func-host-sub");
638
639        let result = exports[9].ty();
640        assert!(result.is_ok());
641        matches!(result.unwrap(), ExternalInstanceType::Func(_));
642        assert_eq!(exports[9].name(), "func-host-mul");
643
644        let result = exports[10].ty();
645        assert!(result.is_ok());
646        matches!(result.unwrap(), ExternalInstanceType::Func(_));
647        assert_eq!(exports[10].name(), "func-host-div");
648
649        let result = exports[11].ty();
650        assert!(result.is_ok());
651        matches!(result.unwrap(), ExternalInstanceType::Table(_));
652        assert_eq!(exports[11].name(), "tab-func");
653
654        let result = exports[12].ty();
655        assert!(result.is_ok());
656        matches!(result.unwrap(), ExternalInstanceType::Table(_));
657        assert_eq!(exports[12].name(), "tab-ext");
658
659        let result = exports[13].ty();
660        assert!(result.is_ok());
661        matches!(result.unwrap(), ExternalInstanceType::Memory(_));
662        assert_eq!(exports[13].name(), "mem");
663
664        let result = exports[14].ty();
665        assert!(result.is_ok());
666        matches!(result.unwrap(), ExternalInstanceType::Global(_));
667        assert_eq!(exports[14].name(), "glob-mut-i32");
668
669        let result = exports[15].ty();
670        assert!(result.is_ok());
671        matches!(result.unwrap(), ExternalInstanceType::Global(_));
672        assert_eq!(exports[15].name(), "glob-const-f32");
673
674        // check the function_type function
675        let result = exports[4].ty();
676        assert!(result.is_ok());
677        let ty = result.unwrap();
678        matches!(ty, ExternalInstanceType::Func(_));
679        if let ExternalInstanceType::Func(func_ty) = ty {
680            assert_eq!(func_ty.args_len(), 2);
681            assert_eq!(func_ty.returns_len(), 1);
682        }
683
684        // check the table_type function
685        let result = exports[12].ty();
686        assert!(result.is_ok());
687        let ty = result.unwrap();
688        matches!(ty, ExternalInstanceType::Table(_));
689        if let ExternalInstanceType::Table(table_ty) = ty {
690            assert_eq!(table_ty.elem_ty(), RefType::ExternRef);
691            assert_eq!(table_ty.minimum(), 10);
692            assert_eq!(table_ty.maximum(), None);
693        }
694
695        // check the memory_type function
696        let result = exports[13].ty();
697        assert!(result.is_ok());
698        let ty = result.unwrap();
699        matches!(ty, ExternalInstanceType::Memory(_));
700        if let ExternalInstanceType::Memory(mem_ty) = ty {
701            assert_eq!(mem_ty.minimum(), 1);
702            assert_eq!(mem_ty.maximum(), Some(3));
703        }
704
705        // check the global_type function
706        let result = exports[15].ty();
707        assert!(result.is_ok());
708        let ty = result.unwrap();
709        matches!(ty, ExternalInstanceType::Global(_));
710        if let ExternalInstanceType::Global(global_ty) = ty {
711            assert_eq!(global_ty.value_ty(), ValType::F32);
712            assert_eq!(global_ty.mutability(), Mutability::Const);
713        }
714    }
715
716    #[ignore = "need to update `import.wat`"]
717    #[test]
718    fn test_module_send() {
719        let path = std::env::current_dir()
720            .unwrap()
721            .ancestors()
722            .nth(2)
723            .unwrap()
724            .join("examples/wasmedge-sys/data/import.wat");
725
726        let result = Config::create();
727        assert!(result.is_ok());
728        let mut config = result.unwrap();
729        config.bulk_memory_operations(true);
730        assert!(config.bulk_memory_operations_enabled());
731
732        // load module from file
733        let result = Loader::create(Some(&config));
734        assert!(result.is_ok());
735        let loader = result.unwrap();
736        let result = loader.from_file(path);
737        assert!(result.is_ok());
738        let module = result.unwrap();
739        assert!(!module.inner.0.is_null());
740
741        let handle = thread::spawn(move || {
742            // check exports
743
744            assert_eq!(module.count_of_exports(), 16);
745            let exports = module.export();
746
747            // check the ty and name functions
748            let result = exports[0].ty();
749            assert!(result.is_ok());
750            matches!(result.unwrap(), ExternalInstanceType::Func(_));
751            assert_eq!(exports[0].name(), "func-1");
752
753            let result = exports[1].ty();
754            assert!(result.is_ok());
755            matches!(result.unwrap(), ExternalInstanceType::Func(_));
756            assert_eq!(exports[1].name(), "func-2");
757
758            let result = exports[2].ty();
759            assert!(result.is_ok());
760            matches!(result.unwrap(), ExternalInstanceType::Func(_));
761            assert_eq!(exports[2].name(), "func-3");
762
763            let result = exports[3].ty();
764            assert!(result.is_ok());
765            matches!(result.unwrap(), ExternalInstanceType::Func(_));
766            assert_eq!(exports[3].name(), "func-4");
767
768            assert_eq!(module.count_of_exports(), 16);
769
770            let result = exports[4].ty();
771            assert!(result.is_ok());
772            matches!(result.unwrap(), ExternalInstanceType::Func(_));
773            assert_eq!(exports[4].name(), "func-add");
774
775            let result = exports[5].ty();
776            assert!(result.is_ok());
777            matches!(result.unwrap(), ExternalInstanceType::Func(_));
778            assert_eq!(exports[5].name(), "func-mul-2");
779
780            let result = exports[6].ty();
781            assert!(result.is_ok());
782            matches!(result.unwrap(), ExternalInstanceType::Func(_));
783            assert_eq!(exports[6].name(), "func-call-indirect");
784
785            let result = exports[7].ty();
786            assert!(result.is_ok());
787            matches!(result.unwrap(), ExternalInstanceType::Func(_));
788            assert_eq!(exports[7].name(), "func-host-add");
789
790            let result = exports[8].ty();
791            assert!(result.is_ok());
792            matches!(result.unwrap(), ExternalInstanceType::Func(_));
793            assert_eq!(exports[8].name(), "func-host-sub");
794
795            let result = exports[9].ty();
796            assert!(result.is_ok());
797            matches!(result.unwrap(), ExternalInstanceType::Func(_));
798            assert_eq!(exports[9].name(), "func-host-mul");
799
800            let result = exports[10].ty();
801            assert!(result.is_ok());
802            matches!(result.unwrap(), ExternalInstanceType::Func(_));
803            assert_eq!(exports[10].name(), "func-host-div");
804
805            let result = exports[11].ty();
806            assert!(result.is_ok());
807            matches!(result.unwrap(), ExternalInstanceType::Table(_));
808            assert_eq!(exports[11].name(), "tab-func");
809
810            let result = exports[12].ty();
811            assert!(result.is_ok());
812            matches!(result.unwrap(), ExternalInstanceType::Table(_));
813            assert_eq!(exports[12].name(), "tab-ext");
814
815            let result = exports[13].ty();
816            assert!(result.is_ok());
817            matches!(result.unwrap(), ExternalInstanceType::Memory(_));
818            assert_eq!(exports[13].name(), "mem");
819
820            let result = exports[14].ty();
821            assert!(result.is_ok());
822            matches!(result.unwrap(), ExternalInstanceType::Global(_));
823            assert_eq!(exports[14].name(), "glob-mut-i32");
824
825            let result = exports[15].ty();
826            assert!(result.is_ok());
827            matches!(result.unwrap(), ExternalInstanceType::Global(_));
828            assert_eq!(exports[15].name(), "glob-const-f32");
829
830            // check the function_type function
831            let result = exports[4].ty();
832            assert!(result.is_ok());
833            let ty = result.unwrap();
834            matches!(ty, ExternalInstanceType::Func(_));
835            if let ExternalInstanceType::Func(func_ty) = ty {
836                assert_eq!(func_ty.args_len(), 2);
837                assert_eq!(func_ty.returns_len(), 1);
838            }
839
840            // check the table_type function
841            let result = exports[12].ty();
842            assert!(result.is_ok());
843            let ty = result.unwrap();
844            matches!(ty, ExternalInstanceType::Table(_));
845            if let ExternalInstanceType::Table(table_ty) = ty {
846                assert_eq!(table_ty.elem_ty(), RefType::ExternRef);
847                assert_eq!(table_ty.minimum(), 10);
848                assert_eq!(table_ty.maximum(), None);
849            }
850
851            // check the memory_type function
852            let result = exports[13].ty();
853            assert!(result.is_ok());
854            let ty = result.unwrap();
855            matches!(ty, ExternalInstanceType::Memory(_));
856            if let ExternalInstanceType::Memory(mem_ty) = ty {
857                assert_eq!(mem_ty.minimum(), 1);
858                assert_eq!(mem_ty.maximum(), Some(3));
859            }
860
861            // check the global_type function
862            let result = exports[15].ty();
863            assert!(result.is_ok());
864            let ty = result.unwrap();
865            matches!(ty, ExternalInstanceType::Global(_));
866            if let ExternalInstanceType::Global(global_ty) = ty {
867                assert_eq!(global_ty.value_ty(), ValType::F32);
868                assert_eq!(global_ty.mutability(), Mutability::Const);
869            }
870        });
871
872        handle.join().unwrap();
873    }
874
875    #[ignore = "need to update `import.wat`"]
876    #[test]
877    fn test_module_sync() {
878        let path = std::env::current_dir()
879            .unwrap()
880            .ancestors()
881            .nth(2)
882            .unwrap()
883            .join("examples/wasmedge-sys/data/import.wat");
884
885        let result = Config::create();
886        assert!(result.is_ok());
887        let mut config = result.unwrap();
888        config.bulk_memory_operations(true);
889        assert!(config.bulk_memory_operations_enabled());
890
891        // load module from file
892        let result = Loader::create(Some(&config));
893        assert!(result.is_ok());
894        let loader = result.unwrap();
895        let result = loader.from_file(path);
896        assert!(result.is_ok());
897        let module = Arc::new(Mutex::new(result.unwrap()));
898
899        let module_cloned = Arc::clone(&module);
900        let handle = thread::spawn(move || {
901            let result = module_cloned.lock();
902            assert!(result.is_ok());
903            let module = result.unwrap();
904
905            // check exports
906
907            assert_eq!(module.count_of_exports(), 16);
908            let exports = module.export();
909
910            // check the ty and name functions
911            let result = exports[0].ty();
912            assert!(result.is_ok());
913            matches!(result.unwrap(), ExternalInstanceType::Func(_));
914            assert_eq!(exports[0].name(), "func-1");
915
916            let result = exports[1].ty();
917            assert!(result.is_ok());
918            matches!(result.unwrap(), ExternalInstanceType::Func(_));
919            assert_eq!(exports[1].name(), "func-2");
920
921            let result = exports[2].ty();
922            assert!(result.is_ok());
923            matches!(result.unwrap(), ExternalInstanceType::Func(_));
924            assert_eq!(exports[2].name(), "func-3");
925
926            let result = exports[3].ty();
927            assert!(result.is_ok());
928            matches!(result.unwrap(), ExternalInstanceType::Func(_));
929            assert_eq!(exports[3].name(), "func-4");
930
931            assert_eq!(module.count_of_exports(), 16);
932
933            let result = exports[4].ty();
934            assert!(result.is_ok());
935            matches!(result.unwrap(), ExternalInstanceType::Func(_));
936            assert_eq!(exports[4].name(), "func-add");
937
938            let result = exports[5].ty();
939            assert!(result.is_ok());
940            matches!(result.unwrap(), ExternalInstanceType::Func(_));
941            assert_eq!(exports[5].name(), "func-mul-2");
942
943            let result = exports[6].ty();
944            assert!(result.is_ok());
945            matches!(result.unwrap(), ExternalInstanceType::Func(_));
946            assert_eq!(exports[6].name(), "func-call-indirect");
947
948            let result = exports[7].ty();
949            assert!(result.is_ok());
950            matches!(result.unwrap(), ExternalInstanceType::Func(_));
951            assert_eq!(exports[7].name(), "func-host-add");
952
953            let result = exports[8].ty();
954            assert!(result.is_ok());
955            matches!(result.unwrap(), ExternalInstanceType::Func(_));
956            assert_eq!(exports[8].name(), "func-host-sub");
957
958            let result = exports[9].ty();
959            assert!(result.is_ok());
960            matches!(result.unwrap(), ExternalInstanceType::Func(_));
961            assert_eq!(exports[9].name(), "func-host-mul");
962
963            let result = exports[10].ty();
964            assert!(result.is_ok());
965            matches!(result.unwrap(), ExternalInstanceType::Func(_));
966            assert_eq!(exports[10].name(), "func-host-div");
967
968            let result = exports[11].ty();
969            assert!(result.is_ok());
970            matches!(result.unwrap(), ExternalInstanceType::Table(_));
971            assert_eq!(exports[11].name(), "tab-func");
972
973            let result = exports[12].ty();
974            assert!(result.is_ok());
975            matches!(result.unwrap(), ExternalInstanceType::Table(_));
976            assert_eq!(exports[12].name(), "tab-ext");
977
978            let result = exports[13].ty();
979            assert!(result.is_ok());
980            matches!(result.unwrap(), ExternalInstanceType::Memory(_));
981            assert_eq!(exports[13].name(), "mem");
982
983            let result = exports[14].ty();
984            assert!(result.is_ok());
985            matches!(result.unwrap(), ExternalInstanceType::Global(_));
986            assert_eq!(exports[14].name(), "glob-mut-i32");
987
988            let result = exports[15].ty();
989            assert!(result.is_ok());
990            let ty = result.unwrap();
991            matches!(ty, ExternalInstanceType::Global(_));
992            assert_eq!(exports[15].name(), "glob-const-f32");
993
994            // check the function_type function
995            let result = exports[4].ty();
996            assert!(result.is_ok());
997            let ty = result.unwrap();
998            matches!(ty, ExternalInstanceType::Func(_));
999            if let ExternalInstanceType::Func(func_ty) = ty {
1000                assert_eq!(func_ty.args_len(), 2);
1001                assert_eq!(func_ty.returns_len(), 1);
1002            }
1003
1004            // check the table_type function
1005            let result = exports[12].ty();
1006            assert!(result.is_ok());
1007            let ty = result.unwrap();
1008            matches!(ty, ExternalInstanceType::Table(_));
1009            if let ExternalInstanceType::Table(table_ty) = ty {
1010                assert_eq!(table_ty.elem_ty(), RefType::ExternRef);
1011                assert_eq!(table_ty.minimum(), 10);
1012                assert_eq!(table_ty.maximum(), None);
1013            }
1014
1015            // check the memory_type function
1016            let result = exports[13].ty();
1017            assert!(result.is_ok());
1018            let ty = result.unwrap();
1019            matches!(ty, ExternalInstanceType::Memory(_));
1020            if let ExternalInstanceType::Memory(mem_ty) = ty {
1021                assert_eq!(mem_ty.minimum(), 1);
1022                assert_eq!(mem_ty.maximum(), Some(3));
1023            }
1024
1025            // check the global_type function
1026            let result = exports[15].ty();
1027            assert!(result.is_ok());
1028            let ty = result.unwrap();
1029            matches!(ty, ExternalInstanceType::Global(_));
1030            if let ExternalInstanceType::Global(global_ty) = ty {
1031                assert_eq!(global_ty.value_ty(), ValType::F32);
1032                assert_eq!(global_ty.mutability(), Mutability::Const);
1033            }
1034        });
1035
1036        handle.join().unwrap();
1037    }
1038}