forked from wasmerio/wasmer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.rs
129 lines (120 loc) · 4.8 KB
/
utils.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//! 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),
)
}
}
/// Whether or not Wasmer should print with color
pub fn wasmer_should_print_color() -> bool {
std::env::var("WASMER_COLOR")
.ok()
.and_then(|inner| inner.parse::<bool>().ok())
.unwrap_or(atty::is(atty::Stream::Stdout))
}