mirror of
https://github.com/fluencelabs/interface-types
synced 2024-12-04 15:20:20 +00:00
update
This commit is contained in:
parent
458adc2534
commit
d4bc6326b9
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -185,7 +185,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce"
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-interface-types"
|
||||
name = "wasmer-interface-types-fl"
|
||||
version = "0.17.0"
|
||||
dependencies = [
|
||||
"nom",
|
||||
|
@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "wasmer-interface-types"
|
||||
name = "wasmer-interface-types-fl"
|
||||
version = "0.17.0"
|
||||
description = "WebAssembly Interface Types library for Wasmer"
|
||||
license = "MIT"
|
||||
|
11
src/ast.rs
11
src/ast.rs
@ -26,11 +26,18 @@ pub enum Type {
|
||||
/// (@interface type (func (param i32 i32) (result string)))
|
||||
/// ```
|
||||
Function {
|
||||
/// Name of a function.
|
||||
name: String,
|
||||
|
||||
/// Types for the parameters (`(param …)`).
|
||||
inputs: Vec<InterfaceType>,
|
||||
arg_types: Vec<InterfaceType>,
|
||||
|
||||
/// Name of function argument types.
|
||||
// TODO: introduce a struct combines name and type of a field
|
||||
arg_names: Vec<String>,
|
||||
|
||||
/// Types for the results (`(result …)`).
|
||||
outputs: Vec<InterfaceType>,
|
||||
output_types: Vec<InterfaceType>,
|
||||
},
|
||||
|
||||
/// A record type, like:
|
||||
|
@ -121,7 +121,7 @@ fn record_type<'input, E: ParseError<&'input [u8]>>(
|
||||
))
|
||||
}
|
||||
|
||||
/// Parse a UTF-8 string.
|
||||
/// Parse a UTF-8 string into &str.
|
||||
fn string<'input, E: ParseError<&'input [u8]>>(
|
||||
input: &'input [u8],
|
||||
) -> IResult<&'input [u8], &'input str, E> {
|
||||
@ -143,6 +143,28 @@ fn string<'input, E: ParseError<&'input [u8]>>(
|
||||
))
|
||||
}
|
||||
|
||||
/// Parse a UTF-8 string into String.
|
||||
fn owned_string<'input, E: ParseError<&'input [u8]>>(
|
||||
input: &'input [u8],
|
||||
) -> IResult<&'input [u8], String, E> {
|
||||
if input.is_empty() {
|
||||
return Err(Err::Error(make_error(input, ErrorKind::Eof)));
|
||||
}
|
||||
|
||||
let length = input[0] as usize;
|
||||
let input = &input[1..];
|
||||
|
||||
if input.len() < length {
|
||||
return Err(Err::Error(make_error(input, ErrorKind::Eof)));
|
||||
}
|
||||
|
||||
Ok((
|
||||
&input[length..],
|
||||
String::from_utf8(input[..length].to_vec())
|
||||
.map_err(|_| Err::Error(make_error(input, ErrorKind::ParseTo)))?,
|
||||
))
|
||||
}
|
||||
|
||||
/// Parse a list, with an item parser.
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn list<'input, I, E: ParseError<&'input [u8]>>(
|
||||
@ -306,10 +328,17 @@ fn types<'input, E: ParseError<&'input [u8]>>(
|
||||
|
||||
match type_kind {
|
||||
TypeKind::Function => {
|
||||
consume!((input, inputs) = list(input, ty)?);
|
||||
consume!((input, outputs) = list(input, ty)?);
|
||||
consume!((input, name) = string(input)?);
|
||||
consume!((input, arg_types) = list(input, ty)?);
|
||||
consume!((input, arg_names) = list(input, owned_string)?);
|
||||
consume!((input, output_types) = list(input, ty)?);
|
||||
|
||||
types.push(Type::Function { inputs, outputs });
|
||||
types.push(Type::Function {
|
||||
name: String::from(name),
|
||||
arg_types,
|
||||
arg_names,
|
||||
output_types,
|
||||
});
|
||||
}
|
||||
|
||||
TypeKind::Record => {
|
||||
|
@ -403,7 +403,7 @@ impl Parse<'_> for AtInterface {
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
enum FunctionType {
|
||||
Input(Vec<InterfaceType>),
|
||||
Header(String, Vec<String>, Vec<InterfaceType>),
|
||||
Output(Vec<InterfaceType>),
|
||||
}
|
||||
|
||||
@ -414,14 +414,17 @@ impl Parse<'_> for FunctionType {
|
||||
|
||||
if lookahead.peek::<keyword::param>() {
|
||||
parser.parse::<keyword::param>()?;
|
||||
let func_name = parser.parse()?;
|
||||
|
||||
let mut inputs = vec![];
|
||||
let mut names = vec![];
|
||||
let mut types = vec![];
|
||||
|
||||
while !parser.is_empty() {
|
||||
inputs.push(parser.parse()?);
|
||||
names.push(parser.parse()?);
|
||||
types.push(parser.parse()?);
|
||||
}
|
||||
|
||||
Ok(FunctionType::Input(inputs))
|
||||
Ok(FunctionType::Header(func_name, names, types))
|
||||
} else if lookahead.peek::<keyword::result>() {
|
||||
parser.parse::<keyword::result>()?;
|
||||
|
||||
@ -488,21 +491,39 @@ impl<'a> Parse<'a> for Type {
|
||||
if lookahead.peek::<keyword::func>() {
|
||||
parser.parse::<keyword::func>()?;
|
||||
|
||||
let mut input_types = vec![];
|
||||
let mut arg_types = vec![];
|
||||
let mut arg_names = vec![];
|
||||
let mut output_types = vec![];
|
||||
let mut name: Option<String> = None;
|
||||
|
||||
while !parser.is_empty() {
|
||||
let function_type = parser.parse::<FunctionType>()?;
|
||||
|
||||
match function_type {
|
||||
FunctionType::Input(mut inputs) => input_types.append(&mut inputs),
|
||||
FunctionType::Header(func_name, mut names, mut types) => {
|
||||
name = Some(func_name);
|
||||
arg_names.append(&mut names);
|
||||
arg_types.append(&mut types);
|
||||
},
|
||||
FunctionType::Output(mut outputs) => output_types.append(&mut outputs),
|
||||
}
|
||||
}
|
||||
|
||||
if name.is_none() {
|
||||
return Err(parser.error("Malformed wast: function doesn't contain name"));
|
||||
}
|
||||
|
||||
if arg_types.len() != arg_names.len() {
|
||||
return Err(parser.error("Malformed wast: function argument types count should be equal to argument names count"));
|
||||
}
|
||||
|
||||
// It's has been already checked for None.
|
||||
let name = name.unwrap();
|
||||
Ok(Type::Function {
|
||||
inputs: input_types,
|
||||
outputs: output_types,
|
||||
name,
|
||||
arg_types,
|
||||
arg_names,
|
||||
output_types,
|
||||
})
|
||||
} else if lookahead.peek::<keyword::record>() {
|
||||
Ok(Type::Record(parser.parse()?))
|
||||
@ -874,7 +895,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_param_empty() {
|
||||
let input = buffer("(param)");
|
||||
let output = FunctionType::Input(vec![]);
|
||||
let output = FunctionType::InputTypes(vec![]);
|
||||
|
||||
assert_eq!(parser::parse::<FunctionType>(&input).unwrap(), output);
|
||||
}
|
||||
@ -882,7 +903,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_param() {
|
||||
let input = buffer("(param i32 string)");
|
||||
let output = FunctionType::Input(vec![InterfaceType::I32, InterfaceType::String]);
|
||||
let output = FunctionType::InputTypes(vec![InterfaceType::I32, InterfaceType::String]);
|
||||
|
||||
assert_eq!(parser::parse::<FunctionType>(&input).unwrap(), output);
|
||||
}
|
||||
|
@ -66,6 +66,24 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Encode a String into bytes.
|
||||
///
|
||||
/// Decoder is `decoders::binary::string`.
|
||||
impl<W> ToBytes<W> for String
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
||||
// Size first.
|
||||
writer.write_all(&[self.len() as u8])?;
|
||||
|
||||
// Then the string.
|
||||
writer.write_all(self.as_bytes())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Encode a vector into bytes.
|
||||
///
|
||||
/// Decoder is `decoders::binary::list`.
|
||||
@ -165,10 +183,17 @@ where
|
||||
{
|
||||
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
||||
match self {
|
||||
Type::Function { inputs, outputs } => {
|
||||
Type::Function {
|
||||
name,
|
||||
arg_types,
|
||||
arg_names,
|
||||
output_types,
|
||||
} => {
|
||||
TypeKind::Function.to_bytes(writer)?;
|
||||
inputs.to_bytes(writer)?;
|
||||
outputs.to_bytes(writer)?;
|
||||
name.to_bytes(writer)?;
|
||||
arg_types.to_bytes(writer)?;
|
||||
arg_names.to_bytes(writer)?;
|
||||
output_types.to_bytes(writer)?;
|
||||
}
|
||||
|
||||
Type::Record(record_type) => {
|
||||
|
@ -158,19 +158,23 @@ impl ToString for &Instruction {
|
||||
|
||||
/// Encode a list of `InterfaceType` representing inputs into a
|
||||
/// string.
|
||||
fn input_types_to_param(input_types: &[InterfaceType]) -> String {
|
||||
if input_types.is_empty() {
|
||||
"".into()
|
||||
fn encode_arguments(arg_types: &[InterfaceType], arg_names: &[String]) -> String {
|
||||
// here we know that arg_names and arg_types have the same length
|
||||
if arg_names.is_empty() {
|
||||
String::from("")
|
||||
} else {
|
||||
format!(
|
||||
"\n (param{})",
|
||||
input_types
|
||||
.iter()
|
||||
.fold(String::new(), |mut accumulator, interface_type| {
|
||||
arg_names.iter().zip(arg_types.iter()).fold(
|
||||
String::new(),
|
||||
|mut accumulator, (name, ty)| {
|
||||
accumulator.push(' ');
|
||||
accumulator.push_str(&interface_type.to_string());
|
||||
accumulator.push_str(name);
|
||||
accumulator.push_str(": ");
|
||||
accumulator.push_str(&ty.to_string());
|
||||
accumulator
|
||||
})
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -198,10 +202,16 @@ fn output_types_to_result(output_types: &[InterfaceType]) -> String {
|
||||
impl<'input> ToString for &Type {
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
Type::Function { inputs, outputs } => format!(
|
||||
r#"(@interface type (func{inputs}{outputs}))"#,
|
||||
inputs = input_types_to_param(&inputs),
|
||||
outputs = output_types_to_result(&outputs),
|
||||
Type::Function {
|
||||
name,
|
||||
arg_types,
|
||||
arg_names,
|
||||
output_types,
|
||||
} => format!(
|
||||
r#"(@interface type (func {name} {args}{output_types}))"#,
|
||||
name = name,
|
||||
args = encode_arguments(arg_types, arg_names),
|
||||
output_types = output_types_to_result(&output_types),
|
||||
),
|
||||
|
||||
Type::Record(record_type) => format!(
|
||||
|
Loading…
Reference in New Issue
Block a user