mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-13 06:15:33 +00:00
Merge #1056
1056: Integrate Ivan's arg parsing code into --invoke r=syrusakbary a=MarkMcCaskey Co-authored-by: Ivan Enderlin <ivan.enderlin@hoa-project.net> Because #281 is on a branch on a fork, I made a new branch. Does arg parsing when using `--invoke` Co-authored-by: Mark McCaskey <mark@wasmer.io> Co-authored-by: Syrus Akbary <me@syrusakbary.com>
This commit is contained in:
commit
b9f8aace79
@ -2,6 +2,7 @@
|
||||
|
||||
## **[Unreleased]**
|
||||
|
||||
- [#1056](https://github.com/wasmerio/wasmer/pull/1056) Improved `--invoke` args parsing (supporting `i32`, `i64`, `f32` and `f32`) in Wasmer CLI
|
||||
- [#1054](https://github.com/wasmerio/wasmer/pull/1054) Improve `--invoke` output in Wasmer CLI
|
||||
- [#1053](https://github.com/wasmerio/wasmer/pull/1053) For RuntimeError and breakpoints, use Box<Any + Send> instead of Box<Any>.
|
||||
- [#1052](https://github.com/wasmerio/wasmer/pull/1052) Fix minor panic and improve Error handling in singlepass backend.
|
||||
|
@ -38,6 +38,7 @@ use wasmer_runtime_core::{
|
||||
backend::{Backend, Compiler, CompilerConfig, Features, MemoryBoundCheckMode},
|
||||
debug,
|
||||
loader::{Instance as LoadedInstance, LocalLoader},
|
||||
Module,
|
||||
};
|
||||
#[cfg(feature = "wasi")]
|
||||
use wasmer_wasi;
|
||||
@ -246,18 +247,9 @@ struct Run {
|
||||
|
||||
impl Run {
|
||||
/// Used with the `invoke` argument
|
||||
fn parse_args(&self) -> Result<Vec<Value>, String> {
|
||||
let mut args: Vec<Value> = Vec::new();
|
||||
for arg in self.args.iter() {
|
||||
let x = arg.as_str().parse().map_err(|_| {
|
||||
format!(
|
||||
"Can't parse the provided argument {:?} as a integer",
|
||||
arg.as_str()
|
||||
)
|
||||
})?;
|
||||
args.push(Value::I32(x));
|
||||
}
|
||||
Ok(args)
|
||||
fn parse_args(&self, module: &Module, fn_name: &str) -> Result<Vec<Value>, String> {
|
||||
utils::parse_args(module, fn_name, &self.args)
|
||||
.map_err(|e| format!("Invoke failed: {:?}", e))
|
||||
}
|
||||
}
|
||||
|
||||
@ -493,7 +485,7 @@ fn execute_wasi(
|
||||
|
||||
if let Some(invoke_fn) = options.invoke.as_ref() {
|
||||
eprintln!("WARNING: Invoking aribtrary functions with WASI is not officially supported in the WASI standard yet. Use this feature at your own risk!");
|
||||
let args = options.parse_args()?;
|
||||
let args = options.parse_args(&module, invoke_fn)?;
|
||||
let invoke_result = instance
|
||||
.dyn_func(invoke_fn)
|
||||
.map_err(|e| format!("Invoke failed: {:?}", e))?
|
||||
@ -825,12 +817,12 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
||||
.instantiate(&import_object)
|
||||
.map_err(|e| format!("Can't instantiate module: {:?}", e))?;
|
||||
|
||||
let args = options.parse_args()?;
|
||||
|
||||
let invoke_fn = match options.invoke.as_ref() {
|
||||
Some(fun) => fun,
|
||||
_ => "main",
|
||||
};
|
||||
let args = options.parse_args(&module, invoke_fn)?;
|
||||
|
||||
let result = instance
|
||||
.dyn_func(&invoke_fn)
|
||||
.map_err(|e| format!("{:?}", e))?
|
||||
|
115
src/utils.rs
115
src/utils.rs
@ -1,6 +1,121 @@
|
||||
//! Utility functions for the WebAssembly module
|
||||
|
||||
use wasmer_runtime::{types::Type, Module, Value};
|
||||
use wasmer_runtime_core::{backend::SigRegistry, module::ExportIndex};
|
||||
|
||||
/// Detect if a provided binary is a Wasm file
|
||||
pub fn is_wasm_binary(binary: &[u8]) -> bool {
|
||||
binary.starts_with(&[b'\0', b'a', b's', b'm'])
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum InvokeError {
|
||||
CouldNotFindFunction,
|
||||
ExportNotFunction,
|
||||
WrongNumArgs { expected: u16, found: u16 },
|
||||
CouldNotParseArg(String),
|
||||
}
|
||||
|
||||
/// Parses arguments for the `--invoke` flag on the run command
|
||||
pub fn parse_args(
|
||||
module: &Module,
|
||||
fn_name: &str,
|
||||
args: &[String],
|
||||
) -> Result<Vec<Value>, InvokeError> {
|
||||
let export_index = module
|
||||
.info()
|
||||
.exports
|
||||
.get(fn_name)
|
||||
.ok_or(InvokeError::CouldNotFindFunction)?;
|
||||
|
||||
let signature = if let ExportIndex::Func(func_index) = export_index {
|
||||
let sig_index = module
|
||||
.info()
|
||||
.func_assoc
|
||||
.get(*func_index)
|
||||
.expect("broken invariant, incorrect func index");
|
||||
SigRegistry.lookup_signature_ref(&module.info().signatures[*sig_index])
|
||||
} else {
|
||||
return Err(InvokeError::ExportNotFunction);
|
||||
};
|
||||
|
||||
let parameter_types = signature.params();
|
||||
let mut arg_error = None;
|
||||
|
||||
if args.len() != parameter_types.len() {
|
||||
return Err(InvokeError::WrongNumArgs {
|
||||
expected: parameter_types.len() as _,
|
||||
found: args.len() as _,
|
||||
});
|
||||
} else {
|
||||
args.iter()
|
||||
.enumerate()
|
||||
.try_fold(
|
||||
Vec::with_capacity(args.len()),
|
||||
|mut accumulator, (nth, argument)| {
|
||||
if let Some(value) = match parameter_types[nth] {
|
||||
Type::I32 => argument
|
||||
.parse::<i32>()
|
||||
.map(|v| Some(Value::I32(v)))
|
||||
.unwrap_or_else(|_| {
|
||||
arg_error = Some(InvokeError::CouldNotParseArg(format!(
|
||||
"Failed to parse `{:?}` as an `i32`",
|
||||
argument
|
||||
)));
|
||||
None
|
||||
}),
|
||||
Type::I64 => argument
|
||||
.parse::<i64>()
|
||||
.map(|v| Some(Value::I64(v)))
|
||||
.unwrap_or_else(|_| {
|
||||
arg_error = Some(InvokeError::CouldNotParseArg(format!(
|
||||
"Failed to parse `{:?}` as an `i64`",
|
||||
argument
|
||||
)));
|
||||
None
|
||||
}),
|
||||
Type::V128 => argument
|
||||
.parse::<u128>()
|
||||
.map(|v| Some(Value::V128(v)))
|
||||
.unwrap_or_else(|_| {
|
||||
arg_error = Some(InvokeError::CouldNotParseArg(format!(
|
||||
"Failed to parse `{:?}` as an `i128`",
|
||||
argument
|
||||
)));
|
||||
None
|
||||
}),
|
||||
Type::F32 => argument
|
||||
.parse::<f32>()
|
||||
.map(|v| Some(Value::F32(v)))
|
||||
.unwrap_or_else(|_| {
|
||||
arg_error = Some(InvokeError::CouldNotParseArg(format!(
|
||||
"Failed to parse `{:?}` as an `f32`",
|
||||
argument
|
||||
)));
|
||||
None
|
||||
}),
|
||||
Type::F64 => argument
|
||||
.parse::<f64>()
|
||||
.map(|v| Some(Value::F64(v)))
|
||||
.unwrap_or_else(|_| {
|
||||
arg_error = Some(InvokeError::CouldNotParseArg(format!(
|
||||
"Failed to parse `{:?}` as an `f64`",
|
||||
argument
|
||||
)));
|
||||
None
|
||||
}),
|
||||
} {
|
||||
accumulator.push(value);
|
||||
|
||||
Some(accumulator)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
)
|
||||
.map_or_else(
|
||||
|| Err(arg_error.unwrap()),
|
||||
|arguments: Vec<Value>| Ok(arguments),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user