1 // This examples allow to query all function exports of the
2 // provided wasm module
3 
4 extern crate parity_wasm;
5 
6 use std::env::args;
7 
8 use parity_wasm::elements::{Internal, External, Type, FunctionType, Module};
9 
10 // Auxillary function to resolve function type (signature) given it's callable index
type_by_index(module: &Module, index: usize) -> FunctionType11 fn type_by_index(module: &Module, index: usize) -> FunctionType {
12 
13 	// Demand that function and type section exist. Otherwise, fail with a
14 	// corresponding error.
15 	let function_section = module.function_section().expect("No function section found");
16 	let type_section = module.type_section().expect("No type section found");
17 
18 	// This counts the number of _function_ imports listed by the module, excluding
19 	// the globals, since indexing for actual functions for `call` and `export` purposes
20 	// includes both imported and own functions. So we actualy need the imported function count
21 	// to resolve actual index of the given function in own functions list.
22 	let import_section_len: usize = match module.import_section() {
23 			Some(import) =>
24 				import.entries().iter().filter(|entry| match entry.external() {
25 					&External::Function(_) => true,
26 					_ => false,
27 					}).count(),
28 			None => 0,
29 		};
30 
31 	// Substract the value queried in the previous step from the provided index
32 	// to get own function index from which we can query type next.
33 	let function_index_in_section = index - import_section_len;
34 
35 	// Query the own function given we have it's index
36 	let func_type_ref: usize = function_section.entries()[function_index_in_section].type_ref() as usize;
37 
38 	// Finally, return function type (signature)
39 	match type_section.types()[func_type_ref] {
40 		Type::Function(ref func_type) => func_type.clone(),
41 	}
42 }
43 
main()44 fn main() {
45 
46 	// Example executable takes one argument which must
47 	// refernce the existing file with a valid wasm module
48 	let args: Vec<_> = args().collect();
49 	if args.len() < 2 {
50 		println!("Prints export function names with and their types");
51 		println!("Usage: {} <wasm file>", args[0]);
52 		return;
53 	}
54 
55 	// Here we load module using dedicated for this purpose
56 	// `deserialize_file` function (which works only with modules)
57 	let module = parity_wasm::deserialize_file(&args[1]).expect("File to be deserialized");
58 
59 	// Query the export section from the loaded module. Note that not every
60 	// wasm module obliged to contain export section. So in case there is no
61 	// any export section, we panic with the corresponding error.
62 	let export_section = module.export_section().expect("No export section found");
63 
64 	// Process all exports, leaving only those which reference the internal function
65 	// of the wasm module
66 	let exports: Vec<String> = export_section.entries().iter()
67 		.filter_map(|entry|
68 			// This is match on export variant, which can be function, global,table or memory
69 			// We are interested only in functions for an example
70 			match *entry.internal() {
71 				// Return function export name (return by field() function and it's index)
72 				Internal::Function(index) => Some((entry.field(), index as usize)),
73 				_ => None
74 			})
75 		// Another map to resolve function signature index given it's internal index and return
76 		// the printable string of the export
77 		.map(|(field, index)| format!("{:}: {:?}", field, type_by_index(&module, index).params())).collect();
78 
79 	// Print the result
80 	for export in exports {
81 		println!("{:}", export);
82 	}
83 }
84