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