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