1 //! Dummy implementations of things that a Wasm module can import. 2 3 use anyhow::ensure; 4 use wasmtime::*; 5 6 /// Create a set of dummy functions/globals/etc for the given imports. 7 pub fn dummy_linker<T>(store: &mut Store<T>, module: &Module) -> Result<Linker<T>> { 8 let mut linker = Linker::new(store.engine()); 9 linker.allow_shadowing(true); 10 for import in module.imports() { 11 let extern_ = dummy_extern(store, import.ty())?; 12 linker 13 .define(&store, import.module(), import.name(), extern_) 14 .unwrap(); 15 } 16 Ok(linker) 17 } 18 19 /// Construct a dummy `Extern` from its type signature 20 pub fn dummy_extern<T>(store: &mut Store<T>, ty: ExternType) -> Result<Extern> { 21 Ok(match ty { 22 ExternType::Func(func_ty) => Extern::Func(dummy_func(store, func_ty)?), 23 ExternType::Global(global_ty) => Extern::Global(dummy_global(store, global_ty)?), 24 ExternType::Table(table_ty) => Extern::Table(dummy_table(store, table_ty)?), 25 ExternType::Memory(mem_ty) => Extern::Memory(dummy_memory(store, mem_ty)?), 26 }) 27 } 28 29 /// Construct a dummy function for the given function type 30 pub fn dummy_func<T>(store: &mut Store<T>, ty: FuncType) -> Result<Func> { 31 let dummy_results = ty.results().map(dummy_value).collect::<Result<Vec<_>>>()?; 32 Ok(Func::new(store, ty.clone(), move |_, _, results| { 33 for (slot, dummy) in results.iter_mut().zip(&dummy_results) { 34 *slot = dummy.clone(); 35 } 36 Ok(()) 37 })) 38 } 39 40 /// Construct a dummy value for the given value type. 41 pub fn dummy_value(val_ty: ValType) -> Result<Val> { 42 Ok(match val_ty { 43 ValType::I32 => Val::I32(0), 44 ValType::I64 => Val::I64(0), 45 ValType::F32 => Val::F32(0), 46 ValType::F64 => Val::F64(0), 47 ValType::V128 => Val::V128(0.into()), 48 ValType::Ref(r) => { 49 ensure!( 50 r.is_nullable(), 51 "cannot construct a dummy value of type `{r}`" 52 ); 53 Val::null_ref(r.heap_type()) 54 } 55 }) 56 } 57 58 /// Construct a sequence of dummy values for the given types. 59 pub fn dummy_values(val_tys: impl IntoIterator<Item = ValType>) -> Result<Vec<Val>> { 60 val_tys.into_iter().map(dummy_value).collect() 61 } 62 63 /// Construct a dummy global for the given global type. 64 pub fn dummy_global<T>(store: &mut Store<T>, ty: GlobalType) -> Result<Global> { 65 let val = dummy_value(ty.content().clone())?; 66 Global::new(store, ty, val) 67 } 68 69 /// Construct a dummy table for the given table type. 70 pub fn dummy_table<T>(store: &mut Store<T>, ty: TableType) -> Result<Table> { 71 let init_val = dummy_value(ty.element().clone().into())?; 72 Table::new(store, ty, init_val.ref_().unwrap()) 73 } 74 75 /// Construct a dummy memory for the given memory type. 76 pub fn dummy_memory<T>(store: &mut Store<T>, ty: MemoryType) -> Result<Memory> { 77 Memory::new(store, ty) 78 } 79 80 #[cfg(test)] 81 mod tests { 82 use super::*; 83 84 fn store() -> Store<()> { 85 let mut config = Config::default(); 86 config.wasm_multi_memory(true); 87 let engine = wasmtime::Engine::new(&config).unwrap(); 88 Store::new(&engine, ()) 89 } 90 91 #[test] 92 fn dummy_table_import() { 93 let mut store = store(); 94 let table = dummy_table(&mut store, TableType::new(RefType::EXTERNREF, 10, None)).unwrap(); 95 assert_eq!(table.size(&store), 10); 96 for i in 0..10 { 97 assert!(table.get(&mut store, i).unwrap().unwrap_extern().is_none()); 98 } 99 } 100 101 #[test] 102 fn dummy_global_import() { 103 let mut store = store(); 104 let global = 105 dummy_global(&mut store, GlobalType::new(ValType::I32, Mutability::Const)).unwrap(); 106 assert!(global.ty(&store).content().is_i32()); 107 assert_eq!(global.ty(&store).mutability(), Mutability::Const); 108 } 109 110 #[test] 111 fn dummy_memory_import() { 112 let mut store = store(); 113 let memory = dummy_memory(&mut store, MemoryType::new(1, None)).unwrap(); 114 assert_eq!(memory.size(&store), 1); 115 } 116 117 #[test] 118 fn dummy_function_import() { 119 let mut store = store(); 120 let func_ty = FuncType::new(store.engine(), vec![ValType::I32], vec![ValType::I64]); 121 let func = dummy_func(&mut store, func_ty.clone()).unwrap(); 122 let actual_ty = func.ty(&store); 123 assert!(FuncType::eq(&actual_ty, &func_ty)); 124 } 125 } 126