Skip to main content

tinywasm_cli/
value_parse.rs

1use eyre::{Result, bail};
2use tinywasm::types::{FuncType, WasmType, WasmValue};
3
4use crate::output::format_wasm_type;
5
6pub fn parse_invocation_args(ty: &FuncType, args: &[String]) -> Result<Vec<WasmValue>> {
7    if args.len() != ty.params().len() {
8        bail!("wrong number of arguments: expected {}, got {}", ty.params().len(), args.len())
9    }
10
11    ty.params().iter().enumerate().map(|(idx, param_ty)| parse_arg(idx, *param_ty, &args[idx])).collect()
12}
13
14fn parse_arg(index: usize, ty: WasmType, value: &str) -> Result<WasmValue> {
15    let parsed = match ty {
16        WasmType::I32 => value.parse::<i32>().map(WasmValue::from).map_err(|e| format_error(index, ty, value, e))?,
17        WasmType::I64 => value.parse::<i64>().map(WasmValue::from).map_err(|e| format_error(index, ty, value, e))?,
18        WasmType::F32 => value.parse::<f32>().map(WasmValue::from).map_err(|e| format_error(index, ty, value, e))?,
19        WasmType::F64 => value.parse::<f64>().map(WasmValue::from).map_err(|e| format_error(index, ty, value, e))?,
20        WasmType::V128 => value
21            .parse::<i128>()
22            .map(|v| WasmValue::V128(v.to_le_bytes()))
23            .map_err(|e| format_error(index, ty, value, e))?,
24        WasmType::RefFunc | WasmType::RefExtern => {
25            bail!(
26                "unsupported CLI argument type at position {}: {}; use the embedding API for reference values",
27                index + 1,
28                format_wasm_type(ty)
29            )
30        }
31    };
32
33    Ok(parsed)
34}
35
36fn format_error(index: usize, ty: WasmType, value: &str, error: impl core::fmt::Display) -> eyre::Report {
37    eyre::eyre!("failed to parse argument {} as {} from `{value}`: {error}", index + 1, format_wasm_type(ty))
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    #[test]
45    fn parses_numeric_args() {
46        let ty = FuncType::new(&[WasmType::I32, WasmType::F64], &[WasmType::I32]);
47        let args = vec!["1".to_string(), "2.5".to_string()];
48        let parsed = parse_invocation_args(&ty, &args).unwrap();
49        assert_eq!(parsed, vec![WasmValue::I32(1), WasmValue::F64(2.5)]);
50    }
51
52    #[test]
53    fn rejects_wrong_arity() {
54        let ty = FuncType::new(&[WasmType::I32], &[]);
55        let err = parse_invocation_args(&ty, &[]).unwrap_err();
56        assert!(err.to_string().contains("wrong number of arguments"));
57    }
58}