wasm_interface_cli/commands/
check.rs

1use std::path::PathBuf;
2use structopt::StructOpt;
3
4#[derive(Debug, StructOpt)]
5pub struct CheckOpt {
6    #[structopt(long = "interface", short = "i", raw(multiple = "true"))]
7    pub interface_files: Vec<PathBuf>,
8    pub wasm_module_file: PathBuf,
9}
10
11fn load_interfaces(interface_paths: &[PathBuf]) -> Result<Vec<wasm_interface::Interface>, String> {
12    let mut ret = vec![];
13    for ip in interface_paths {
14        let interface_contents = std::fs::read_to_string(&ip).map_err(|e| {
15            format!(
16                "Could not read interface file {}: {}",
17                ip.to_string_lossy(),
18                e
19            )
20        })?;
21        let interface =
22            wasm_interface::parser::parse_interface(&interface_contents).map_err(|e| {
23                format!(
24                    "Failed to parse interface in file {}: {}",
25                    ip.to_string_lossy(),
26                    e
27                )
28            })?;
29        ret.push(interface);
30    }
31
32    Ok(ret)
33}
34
35pub fn check(check_opt: CheckOpt) -> Result<(), String> {
36    if check_opt.interface_files.len() == 0 {
37        println!("WARN: no interfaces given, checking against the empty interface");
38    }
39    let interfaces = load_interfaces(&check_opt.interface_files)?;
40
41    let mut interface = wasm_interface::Interface::default();
42    for int in interfaces {
43        interface = interface.merge(int)?;
44    }
45
46    let wasm = std::fs::read(&check_opt.wasm_module_file)
47        .map_err(|e| format!("Could not read in wasm module data: {}", e))?;
48    match wasm_interface::validate::validate_wasm_and_report_errors(&wasm, &interface) {
49        Ok(_) => {
50            println!(
51                "āœ… Module satisfies interface{}",
52                if check_opt.interface_files.len() > 1 {
53                    "s"
54                } else {
55                    ""
56                }
57            );
58            Ok(())
59        }
60        Err(wasm_interface::validate::WasmValidationError::InvalidWasm { error }) => {
61            Err(format!("Wasm module is invalid: {}", error))
62        }
63        Err(wasm_interface::validate::WasmValidationError::InterfaceViolated { mut errors }) => {
64            // lazy hack to make output stable
65            errors.sort();
66            Err(format!(
67                "Wasm interface violated, {} errors detected: {}",
68                errors.len(),
69                errors
70                    .into_iter()
71                    .fold(String::new(), |a, b| a + "\nāŒ " + &b)
72            ))
73        }
74        Err(wasm_interface::validate::WasmValidationError::UnsupportedType { error }) => {
75            Err(format!("Unsupported type found in Wasm module: {}", error))
76        }
77    }
78}