1use 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#[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
45pub trait AsInstance {
47 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 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 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 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 fn func_len(&self) -> u32 {
206 unsafe { ffi::WasmEdge_ModuleInstanceListFunctionLength(self.as_ptr()) }
207 }
208
209 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 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 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 fn table_len(&self) -> u32 {
288 unsafe { ffi::WasmEdge_ModuleInstanceListTableLength(self.as_ptr()) }
289 }
290
291 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 fn mem_len(&self) -> u32 {
318 unsafe { ffi::WasmEdge_ModuleInstanceListMemoryLength(self.as_ptr()) }
319 }
320
321 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 fn global_len(&self) -> u32 {
348 unsafe { ffi::WasmEdge_ModuleInstanceListGlobalLength(self.as_ptr()) }
349 }
350
351 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 unsafe fn as_ptr(&self) -> *const ffi::WasmEdge_ModuleInstanceContext;
381}
382
383#[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 pub fn create(name: impl AsRef<str>, data: Box<T>) -> WasmEdgeResult<Self> {
416 let raw_name = WasmEdgeString::from(name.as_ref());
417
418 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 pub unsafe fn as_raw(&self) -> *mut ffi::WasmEdge_ModuleInstanceContext {
442 self.inner.0
443 }
444
445 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#[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 pub fn create(
547 args: Option<Vec<&str>>,
548 envs: Option<Vec<&str>>,
549 preopens: Option<Vec<&str>>,
550 ) -> WasmEdgeResult<Self> {
551 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 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 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 pub fn name(&self) -> &str {
607 "wasi_snapshot_preview1"
608 }
609
610 pub fn init_wasi(
620 &mut self,
621 args: Option<Vec<&str>>,
622 envs: Option<Vec<&str>>,
623 preopens: Option<Vec<&str>>,
624 ) {
625 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 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 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 pub fn exit_code(&self) -> u32 {
678 unsafe { ffi::WasmEdge_ModuleInstanceWASIGetExitCode(self.0.as_ptr()) }
679 }
680
681 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 let result = ImportModule::<()>::create(host_name, Box::new(()));
726 assert!(result.is_ok());
727 let mut import = result.unwrap();
728
729 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 import.add_func("func-add", host_func);
743
744 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 import.add_table("table", host_table);
751
752 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 import.add_memory("memory", host_memory);
761
762 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 import.add_global("global_i32", host_global);
769 }
770
771 #[cfg(target_family = "unix")]
772 #[test]
773 fn test_instance_wasi() {
774 {
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 let result = ImportModule::create(module_name, Box::new(()));
816 assert!(result.is_ok());
817 let mut import = result.unwrap();
818
819 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 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 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 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 let mut executor = Executor::create(None, None)?;
853
854 let mut store = Store::create()?;
856
857 executor.register_import_module(&mut store, &import)?;
858
859 let result = store.module("extern_module");
861 assert!(result.is_ok());
862 let instance = result.unwrap();
863
864 assert!(instance.name().is_some());
866 assert_eq!(instance.name().unwrap(), "extern_module");
867
868 let result = instance.get_func("add");
870 assert!(result.is_ok());
871 let func = result.unwrap();
872
873 let result = func.ty();
875 assert!(result.is_some());
876 let ty = result.unwrap();
877
878 assert_eq!(ty.args(), &[ValType::I32, ValType::I32]);
880
881 assert_eq!(ty.returns(), &[ValType::I32]);
883
884 let result = instance.get_table("table");
886 assert!(result.is_ok());
887 let table = result.unwrap();
888
889 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 let result = instance.get_memory_ref("mem");
899 assert!(result.is_ok());
900 let memory = result.unwrap();
901
902 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 let result = instance.get_global("global");
911 assert!(result.is_ok());
912 let global = result.unwrap();
913
914 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 let result = ImportModule::create(module_name, Box::new(()));
931 assert!(result.is_ok());
932 let mut import = result.unwrap();
933
934 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 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 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 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 let mut executor = Executor::create(None, None)?;
968
969 let mut store = Store::create()?;
971
972 executor.register_import_module(&mut store, &import)?;
973
974 let result = store.module("extern_module");
976 assert!(result.is_ok());
977 let instance = result.unwrap();
978
979 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}