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