2020-02-21 12:23:58 +01:00
|
|
|
//! Parse the WIT binary representation into an [AST](crate::ast).
|
2020-02-10 16:39:06 +01:00
|
|
|
|
2019-09-26 14:14:46 +02:00
|
|
|
use crate::{ast::*, interpreter::Instruction};
|
2019-09-12 22:44:20 +02:00
|
|
|
use nom::{
|
|
|
|
error::{make_error, ErrorKind, ParseError},
|
|
|
|
Err, IResult,
|
|
|
|
};
|
|
|
|
use std::{convert::TryFrom, str};
|
|
|
|
|
2020-03-24 16:29:29 +01:00
|
|
|
/// Parse a type kind.
|
|
|
|
impl TryFrom<u8> for TypeKind {
|
|
|
|
type Error = &'static str;
|
|
|
|
|
|
|
|
fn try_from(code: u8) -> Result<Self, Self::Error> {
|
|
|
|
Ok(match code {
|
|
|
|
0x00 => Self::Function,
|
|
|
|
0x01 => Self::Record,
|
|
|
|
_ => return Err("Unknown type kind code."),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-24 18:12:01 +01:00
|
|
|
/// Parse an interface kind.
|
|
|
|
impl TryFrom<u8> for InterfaceKind {
|
2019-09-13 14:50:17 +02:00
|
|
|
type Error = &'static str;
|
|
|
|
|
|
|
|
fn try_from(code: u8) -> Result<Self, Self::Error> {
|
|
|
|
Ok(match code {
|
2020-02-24 18:12:01 +01:00
|
|
|
0x00 => Self::Type,
|
|
|
|
0x01 => Self::Import,
|
|
|
|
0x02 => Self::Adapter,
|
|
|
|
0x03 => Self::Export,
|
|
|
|
0x04 => Self::Implementation,
|
|
|
|
_ => return Err("Unknown interface kind code."),
|
2019-09-13 14:50:17 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-10 16:39:06 +01:00
|
|
|
/// Parse a byte.
|
2019-09-12 22:44:20 +02:00
|
|
|
fn byte<'input, E: ParseError<&'input [u8]>>(input: &'input [u8]) -> IResult<&'input [u8], u8, E> {
|
|
|
|
if input.is_empty() {
|
|
|
|
return Err(Err::Error(make_error(input, ErrorKind::Eof)));
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok((&input[1..], input[0]))
|
|
|
|
}
|
|
|
|
|
2020-02-13 11:41:02 +01:00
|
|
|
/// Parse an unsigned Little Endian Based (LEB) with value no larger
|
|
|
|
/// than a 64-bits number. Read
|
2020-02-13 13:36:18 +01:00
|
|
|
/// [LEB128](https://en.wikipedia.org/wiki/LEB128) to learn more, or
|
|
|
|
/// the Variable Length Data Section from the [DWARF 4
|
|
|
|
/// standard](http://dwarfstd.org/doc/DWARF4.pdf).
|
|
|
|
fn uleb<'input, E: ParseError<&'input [u8]>>(input: &'input [u8]) -> IResult<&'input [u8], u64, E> {
|
2019-09-12 22:44:20 +02:00
|
|
|
if input.is_empty() {
|
|
|
|
return Err(Err::Error(make_error(input, ErrorKind::Eof)));
|
|
|
|
}
|
|
|
|
|
2020-02-14 12:19:29 +01:00
|
|
|
let (output, bytes) = match input.iter().position(|&byte| byte & 0x80 == 0) {
|
2020-02-13 13:36:18 +01:00
|
|
|
Some(length) if length <= 8 => (&input[length + 1..], &input[..=length]),
|
|
|
|
Some(_) => return Err(Err::Error(make_error(input, ErrorKind::TooLarge))),
|
|
|
|
None => return Err(Err::Error(make_error(input, ErrorKind::Eof))),
|
2019-09-12 22:44:20 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
Ok((
|
|
|
|
output,
|
|
|
|
bytes
|
|
|
|
.iter()
|
|
|
|
.rev()
|
2019-09-20 12:02:11 +02:00
|
|
|
.fold(0, |acc, byte| (acc << 7) | u64::from(byte & 0x7f)),
|
2019-09-12 22:44:20 +02:00
|
|
|
))
|
|
|
|
}
|
|
|
|
|
2020-03-26 13:17:36 +01:00
|
|
|
/// Parse an interface type.
|
|
|
|
fn ty<'input, E: ParseError<&'input [u8]>>(
|
|
|
|
mut input: &'input [u8],
|
|
|
|
) -> IResult<&'input [u8], InterfaceType, E> {
|
|
|
|
if input.is_empty() {
|
|
|
|
return Err(Err::Error(make_error(input, ErrorKind::Eof)));
|
|
|
|
}
|
|
|
|
|
|
|
|
consume!((input, opcode) = byte(input)?);
|
|
|
|
|
|
|
|
let ty = match opcode {
|
|
|
|
0x00 => InterfaceType::S8,
|
|
|
|
0x01 => InterfaceType::S16,
|
|
|
|
0x02 => InterfaceType::S32,
|
|
|
|
0x03 => InterfaceType::S64,
|
|
|
|
0x04 => InterfaceType::U8,
|
|
|
|
0x05 => InterfaceType::U16,
|
|
|
|
0x06 => InterfaceType::U32,
|
|
|
|
0x07 => InterfaceType::U64,
|
|
|
|
0x08 => InterfaceType::F32,
|
|
|
|
0x09 => InterfaceType::F64,
|
|
|
|
0x0a => InterfaceType::String,
|
|
|
|
0x0b => InterfaceType::Anyref,
|
|
|
|
0x0c => InterfaceType::I32,
|
|
|
|
0x0d => InterfaceType::I64,
|
|
|
|
0x0e => {
|
|
|
|
consume!((input, record_type) = record_type(input)?);
|
|
|
|
|
|
|
|
InterfaceType::Record(record_type)
|
|
|
|
}
|
|
|
|
_ => return Err(Err::Error(make_error(input, ErrorKind::ParseTo))),
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok((input, ty))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Parse an record type.
|
|
|
|
fn record_type<'input, E: ParseError<&'input [u8]>>(
|
|
|
|
input: &'input [u8],
|
|
|
|
) -> IResult<&'input [u8], RecordType, E> {
|
|
|
|
let (output, fields) = list(input, ty)?;
|
|
|
|
|
|
|
|
Ok((output, RecordType { fields }))
|
|
|
|
}
|
|
|
|
|
2020-02-10 16:39:06 +01:00
|
|
|
/// Parse a UTF-8 string.
|
2019-09-12 22:44:20 +02:00
|
|
|
fn string<'input, E: ParseError<&'input [u8]>>(
|
|
|
|
input: &'input [u8],
|
|
|
|
) -> IResult<&'input [u8], &'input str, 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)));
|
|
|
|
}
|
|
|
|
|
2020-02-13 13:52:23 +01:00
|
|
|
Ok((
|
|
|
|
&input[length..],
|
|
|
|
str::from_utf8(&input[..length])
|
|
|
|
.map_err(|_| Err::Error(make_error(input, ErrorKind::ParseTo)))?,
|
|
|
|
))
|
2019-09-12 22:44:20 +02:00
|
|
|
}
|
|
|
|
|
2020-02-26 15:38:59 +01:00
|
|
|
/// Parse a list, with an item parser.
|
2019-09-20 12:02:11 +02:00
|
|
|
#[allow(clippy::type_complexity)]
|
2019-09-12 22:44:20 +02:00
|
|
|
fn list<'input, I, E: ParseError<&'input [u8]>>(
|
|
|
|
input: &'input [u8],
|
|
|
|
item_parser: fn(&'input [u8]) -> IResult<&'input [u8], I, E>,
|
|
|
|
) -> IResult<&'input [u8], Vec<I>, E> {
|
|
|
|
if input.is_empty() {
|
|
|
|
return Err(Err::Error(make_error(input, ErrorKind::Eof)));
|
|
|
|
}
|
|
|
|
|
|
|
|
let length = input[0] as usize;
|
|
|
|
let mut input = &input[1..];
|
|
|
|
|
|
|
|
if input.len() < length {
|
|
|
|
return Err(Err::Error(make_error(input, ErrorKind::Eof)));
|
|
|
|
}
|
|
|
|
|
2019-09-26 01:00:17 +02:00
|
|
|
let mut items = Vec::with_capacity(length as usize);
|
2019-09-12 22:44:20 +02:00
|
|
|
|
|
|
|
for _ in 0..length {
|
|
|
|
consume!((input, item) = item_parser(input)?);
|
|
|
|
items.push(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok((input, items))
|
|
|
|
}
|
|
|
|
|
2020-02-10 16:39:06 +01:00
|
|
|
/// Parse an instruction with its arguments.
|
|
|
|
fn instruction<'input, E: ParseError<&'input [u8]>>(
|
2019-09-12 22:44:20 +02:00
|
|
|
input: &'input [u8],
|
|
|
|
) -> IResult<&'input [u8], Instruction, E> {
|
|
|
|
let (mut input, opcode) = byte(input)?;
|
|
|
|
|
|
|
|
Ok(match opcode {
|
|
|
|
0x00 => {
|
2020-02-13 13:36:18 +01:00
|
|
|
consume!((input, argument_0) = uleb(input)?);
|
2020-03-31 08:17:52 +02:00
|
|
|
|
2020-02-26 15:42:29 +01:00
|
|
|
(
|
|
|
|
input,
|
|
|
|
Instruction::ArgumentGet {
|
|
|
|
index: argument_0 as u32,
|
|
|
|
},
|
|
|
|
)
|
2019-09-12 22:44:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
0x01 => {
|
2020-02-13 13:36:18 +01:00
|
|
|
consume!((input, argument_0) = uleb(input)?);
|
2020-03-31 08:17:52 +02:00
|
|
|
|
2019-09-25 23:29:08 +02:00
|
|
|
(
|
|
|
|
input,
|
2020-03-09 14:33:17 +01:00
|
|
|
Instruction::CallCore {
|
2019-09-25 23:29:08 +02:00
|
|
|
function_index: argument_0 as usize,
|
|
|
|
},
|
|
|
|
)
|
2019-09-12 22:44:20 +02:00
|
|
|
}
|
|
|
|
|
2020-03-24 12:43:57 +01:00
|
|
|
0x02 => (input, Instruction::S8FromI32),
|
|
|
|
0x03 => (input, Instruction::S8FromI64),
|
|
|
|
0x04 => (input, Instruction::S16FromI32),
|
|
|
|
0x05 => (input, Instruction::S16FromI64),
|
|
|
|
0x06 => (input, Instruction::S32FromI32),
|
|
|
|
0x07 => (input, Instruction::S32FromI64),
|
|
|
|
0x08 => (input, Instruction::S64FromI32),
|
|
|
|
0x09 => (input, Instruction::S64FromI64),
|
|
|
|
0x0a => (input, Instruction::I32FromS8),
|
|
|
|
0x0b => (input, Instruction::I32FromS16),
|
|
|
|
0x0c => (input, Instruction::I32FromS32),
|
|
|
|
0x0d => (input, Instruction::I32FromS64),
|
|
|
|
0x0e => (input, Instruction::I64FromS8),
|
|
|
|
0x0f => (input, Instruction::I64FromS16),
|
|
|
|
0x10 => (input, Instruction::I64FromS32),
|
|
|
|
0x11 => (input, Instruction::I64FromS64),
|
|
|
|
0x12 => (input, Instruction::U8FromI32),
|
|
|
|
0x13 => (input, Instruction::U8FromI64),
|
|
|
|
0x14 => (input, Instruction::U16FromI32),
|
|
|
|
0x15 => (input, Instruction::U16FromI64),
|
|
|
|
0x16 => (input, Instruction::U32FromI32),
|
|
|
|
0x17 => (input, Instruction::U32FromI64),
|
|
|
|
0x18 => (input, Instruction::U64FromI32),
|
|
|
|
0x19 => (input, Instruction::U64FromI64),
|
|
|
|
0x1a => (input, Instruction::I32FromU8),
|
|
|
|
0x1b => (input, Instruction::I32FromU16),
|
|
|
|
0x1c => (input, Instruction::I32FromU32),
|
|
|
|
0x1d => (input, Instruction::I32FromU64),
|
|
|
|
0x1e => (input, Instruction::I64FromU8),
|
|
|
|
0x1f => (input, Instruction::I64FromU16),
|
|
|
|
0x20 => (input, Instruction::I64FromU32),
|
|
|
|
0x21 => (input, Instruction::I64FromU64),
|
|
|
|
|
2020-03-24 13:25:06 +01:00
|
|
|
0x22 => (input, Instruction::StringLiftMemory),
|
2020-03-24 12:43:57 +01:00
|
|
|
0x23 => {
|
2020-03-10 10:25:58 +01:00
|
|
|
consume!((input, argument_0) = uleb(input)?);
|
2020-03-31 08:17:52 +02:00
|
|
|
|
2019-09-25 23:29:08 +02:00
|
|
|
(
|
|
|
|
input,
|
2020-03-24 13:25:06 +01:00
|
|
|
Instruction::StringLowerMemory {
|
2020-03-10 10:25:58 +01:00
|
|
|
allocator_index: argument_0 as u32,
|
2019-09-25 23:29:08 +02:00
|
|
|
},
|
|
|
|
)
|
2019-09-12 22:44:20 +02:00
|
|
|
}
|
2020-03-24 15:33:42 +01:00
|
|
|
0x24 => (input, Instruction::StringSize),
|
|
|
|
|
2020-03-31 08:17:52 +02:00
|
|
|
0x25 => {
|
|
|
|
consume!((input, argument_0) = uleb(input)?);
|
|
|
|
|
|
|
|
(
|
|
|
|
input,
|
|
|
|
Instruction::RecordLift {
|
|
|
|
type_index: argument_0 as u32,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2020-04-02 12:05:22 +02:00
|
|
|
0x26 => {
|
|
|
|
consume!((input, argument_0) = uleb(input)?);
|
|
|
|
|
|
|
|
(
|
|
|
|
input,
|
|
|
|
Instruction::RecordLower {
|
|
|
|
type_index: argument_0 as u32,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2020-03-31 08:17:52 +02:00
|
|
|
|
2019-09-12 22:44:20 +02:00
|
|
|
_ => return Err(Err::Error(make_error(input, ErrorKind::ParseTo))),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-02-10 16:39:06 +01:00
|
|
|
/// Parse a list of types.
|
2019-09-13 14:26:49 +02:00
|
|
|
fn types<'input, E: ParseError<&'input [u8]>>(
|
2020-02-13 13:56:30 +01:00
|
|
|
mut input: &'input [u8],
|
2019-09-12 22:44:20 +02:00
|
|
|
) -> IResult<&'input [u8], Vec<Type>, E> {
|
2020-02-13 13:36:18 +01:00
|
|
|
consume!((input, number_of_types) = uleb(input)?);
|
2019-09-12 22:44:20 +02:00
|
|
|
|
2019-09-26 01:00:17 +02:00
|
|
|
let mut types = Vec::with_capacity(number_of_types as usize);
|
|
|
|
|
2019-09-12 22:44:20 +02:00
|
|
|
for _ in 0..number_of_types {
|
2020-03-24 16:29:29 +01:00
|
|
|
consume!((input, type_kind) = byte(input)?);
|
|
|
|
|
|
|
|
let type_kind = TypeKind::try_from(type_kind)
|
|
|
|
.map_err(|_| Err::Error(make_error(input, ErrorKind::ParseTo)))?;
|
|
|
|
|
|
|
|
match type_kind {
|
|
|
|
TypeKind::Function => {
|
|
|
|
consume!((input, inputs) = list(input, ty)?);
|
|
|
|
consume!((input, outputs) = list(input, ty)?);
|
2019-09-12 22:44:20 +02:00
|
|
|
|
2020-03-24 16:29:29 +01:00
|
|
|
types.push(Type::Function { inputs, outputs });
|
|
|
|
}
|
|
|
|
|
|
|
|
TypeKind::Record => {
|
2020-03-26 13:17:36 +01:00
|
|
|
consume!((input, record_type) = record_type(input)?);
|
2020-03-24 16:29:29 +01:00
|
|
|
|
2020-03-26 13:17:36 +01:00
|
|
|
types.push(Type::Record(record_type));
|
2020-03-24 16:29:29 +01:00
|
|
|
}
|
|
|
|
}
|
2019-09-12 22:44:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok((input, types))
|
|
|
|
}
|
|
|
|
|
2020-02-10 16:39:06 +01:00
|
|
|
/// Parse a list of imports.
|
2020-02-10 15:41:10 +01:00
|
|
|
fn imports<'input, E: ParseError<&'input [u8]>>(
|
2020-02-13 13:56:30 +01:00
|
|
|
mut input: &'input [u8],
|
2020-02-10 15:41:10 +01:00
|
|
|
) -> IResult<&'input [u8], Vec<Import>, E> {
|
2020-02-13 13:36:18 +01:00
|
|
|
consume!((input, number_of_imports) = uleb(input)?);
|
2019-09-12 22:44:20 +02:00
|
|
|
|
2020-02-10 15:41:10 +01:00
|
|
|
let mut imports = Vec::with_capacity(number_of_imports as usize);
|
2019-09-26 01:00:17 +02:00
|
|
|
|
2020-02-10 15:41:10 +01:00
|
|
|
for _ in 0..number_of_imports {
|
2020-02-24 18:12:01 +01:00
|
|
|
consume!((input, namespace) = string(input)?);
|
|
|
|
consume!((input, name) = string(input)?);
|
|
|
|
consume!((input, signature_type) = uleb(input)?);
|
2019-09-12 22:44:20 +02:00
|
|
|
|
2020-02-10 15:41:10 +01:00
|
|
|
imports.push(Import {
|
2020-02-24 18:12:01 +01:00
|
|
|
namespace,
|
|
|
|
name,
|
|
|
|
signature_type: signature_type as u32,
|
2019-09-12 22:44:20 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-02-10 15:41:10 +01:00
|
|
|
Ok((input, imports))
|
2019-09-12 22:44:20 +02:00
|
|
|
}
|
|
|
|
|
2020-02-10 16:39:06 +01:00
|
|
|
/// Parse a list of adapters.
|
2019-09-13 14:26:49 +02:00
|
|
|
fn adapters<'input, E: ParseError<&'input [u8]>>(
|
2020-02-13 13:56:30 +01:00
|
|
|
mut input: &'input [u8],
|
2019-09-12 22:44:20 +02:00
|
|
|
) -> IResult<&'input [u8], Vec<Adapter>, E> {
|
2020-02-13 13:36:18 +01:00
|
|
|
consume!((input, number_of_adapters) = uleb(input)?);
|
2019-09-12 22:44:20 +02:00
|
|
|
|
2019-09-26 01:00:17 +02:00
|
|
|
let mut adapters = Vec::with_capacity(number_of_adapters as usize);
|
|
|
|
|
2019-09-12 22:44:20 +02:00
|
|
|
for _ in 0..number_of_adapters {
|
2020-02-24 18:12:01 +01:00
|
|
|
consume!((input, function_type) = uleb(input)?);
|
|
|
|
consume!((input, instructions) = list(input, instruction)?);
|
|
|
|
|
|
|
|
adapters.push(Adapter {
|
|
|
|
function_type: function_type as u32,
|
|
|
|
instructions,
|
|
|
|
});
|
2019-09-12 22:44:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok((input, adapters))
|
|
|
|
}
|
|
|
|
|
2020-02-24 18:12:01 +01:00
|
|
|
/// Parse a list of exports.
|
|
|
|
fn exports<'input, E: ParseError<&'input [u8]>>(
|
|
|
|
mut input: &'input [u8],
|
|
|
|
) -> IResult<&'input [u8], Vec<Export>, E> {
|
|
|
|
consume!((input, number_of_exports) = uleb(input)?);
|
|
|
|
|
|
|
|
let mut exports = Vec::with_capacity(number_of_exports as usize);
|
|
|
|
|
|
|
|
for _ in 0..number_of_exports {
|
|
|
|
consume!((input, name) = string(input)?);
|
|
|
|
consume!((input, function_type) = uleb(input)?);
|
|
|
|
|
|
|
|
exports.push(Export {
|
|
|
|
name,
|
|
|
|
function_type: function_type as u32,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok((input, exports))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Parse a list of implementations.
|
|
|
|
fn implementations<'input, E: ParseError<&'input [u8]>>(
|
|
|
|
mut input: &'input [u8],
|
|
|
|
) -> IResult<&'input [u8], Vec<Implementation>, E> {
|
|
|
|
consume!((input, number_of_implementations) = uleb(input)?);
|
|
|
|
|
|
|
|
let mut implementations = Vec::with_capacity(number_of_implementations as usize);
|
|
|
|
|
|
|
|
for _ in 0..number_of_implementations {
|
|
|
|
consume!((input, core_function_type) = uleb(input)?);
|
|
|
|
consume!((input, adapter_function_type) = uleb(input)?);
|
|
|
|
|
|
|
|
implementations.push(Implementation {
|
|
|
|
core_function_type: core_function_type as u32,
|
|
|
|
adapter_function_type: adapter_function_type as u32,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok((input, implementations))
|
|
|
|
}
|
|
|
|
|
2020-02-17 13:52:00 +01:00
|
|
|
/// Parse complete interfaces.
|
|
|
|
fn interfaces<'input, E: ParseError<&'input [u8]>>(
|
|
|
|
bytes: &'input [u8],
|
|
|
|
) -> IResult<&'input [u8], Interfaces, E> {
|
|
|
|
let mut input = bytes;
|
|
|
|
|
2020-02-24 18:12:01 +01:00
|
|
|
let mut all_types = vec![];
|
|
|
|
let mut all_imports = vec![];
|
|
|
|
let mut all_adapters = vec![];
|
|
|
|
let mut all_exports = vec![];
|
|
|
|
let mut all_implementations = vec![];
|
|
|
|
|
2020-02-26 15:32:14 +01:00
|
|
|
while !input.is_empty() {
|
|
|
|
consume!((input, interface_kind) = byte(input)?);
|
|
|
|
|
|
|
|
let interface_kind = InterfaceKind::try_from(interface_kind)
|
|
|
|
.map_err(|_| Err::Error(make_error(input, ErrorKind::ParseTo)))?;
|
|
|
|
|
|
|
|
match interface_kind {
|
|
|
|
InterfaceKind::Type => {
|
|
|
|
consume!((input, mut new_types) = types(input)?);
|
|
|
|
all_types.append(&mut new_types);
|
|
|
|
}
|
|
|
|
|
|
|
|
InterfaceKind::Import => {
|
|
|
|
consume!((input, mut new_imports) = imports(input)?);
|
|
|
|
all_imports.append(&mut new_imports);
|
|
|
|
}
|
|
|
|
|
|
|
|
InterfaceKind::Adapter => {
|
|
|
|
consume!((input, mut new_adapters) = adapters(input)?);
|
|
|
|
all_adapters.append(&mut new_adapters);
|
|
|
|
}
|
|
|
|
|
|
|
|
InterfaceKind::Export => {
|
|
|
|
consume!((input, mut new_exports) = exports(input)?);
|
|
|
|
all_exports.append(&mut new_exports);
|
|
|
|
}
|
|
|
|
|
|
|
|
InterfaceKind::Implementation => {
|
|
|
|
consume!((input, mut new_implementations) = implementations(input)?);
|
|
|
|
all_implementations.append(&mut new_implementations)
|
|
|
|
}
|
2020-02-24 18:12:01 +01:00
|
|
|
}
|
|
|
|
}
|
2020-02-17 13:52:00 +01:00
|
|
|
|
|
|
|
Ok((
|
|
|
|
input,
|
|
|
|
Interfaces {
|
2020-02-24 18:12:01 +01:00
|
|
|
types: all_types,
|
|
|
|
imports: all_imports,
|
|
|
|
adapters: all_adapters,
|
|
|
|
exports: all_exports,
|
|
|
|
implementations: all_implementations,
|
2020-02-17 13:52:00 +01:00
|
|
|
},
|
|
|
|
))
|
|
|
|
}
|
|
|
|
|
2020-02-10 16:39:06 +01:00
|
|
|
/// Parse a sequence of bytes, expecting it to be a valid WIT binary
|
2020-02-21 12:23:58 +01:00
|
|
|
/// representation, into an [`Interfaces`](crate::ast::Interfaces)
|
|
|
|
/// structure.
|
2020-02-10 16:48:25 +01:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use wasmer_interface_types::{
|
|
|
|
/// ast::*,
|
|
|
|
/// decoders::binary::parse,
|
|
|
|
/// interpreter::Instruction,
|
|
|
|
/// };
|
|
|
|
///
|
|
|
|
/// let input = &[
|
2020-02-26 15:32:14 +01:00
|
|
|
/// 0x00, // type section
|
2020-02-10 16:48:25 +01:00
|
|
|
/// 0x01, // 1 type
|
2020-03-26 11:18:24 +01:00
|
|
|
/// 0x00, // function type
|
2020-02-24 16:23:31 +01:00
|
|
|
/// 0x01, // list of 1 item
|
2020-02-26 15:32:14 +01:00
|
|
|
/// 0x00, // S8
|
|
|
|
/// 0x01, // list of 1 item
|
|
|
|
/// 0x01, // S16
|
|
|
|
/// //
|
|
|
|
/// 0x01, // import section
|
2020-02-10 16:48:25 +01:00
|
|
|
/// 0x01, // 1 import
|
2020-02-26 15:32:14 +01:00
|
|
|
/// 0x02, // string of 2 bytes
|
|
|
|
/// 0x61, 0x62, // "a", "b"
|
2020-02-10 16:48:25 +01:00
|
|
|
/// 0x01, // string of 1 byte
|
2020-02-26 15:32:14 +01:00
|
|
|
/// 0x63, // "c"
|
|
|
|
/// 0x00, // signature type
|
|
|
|
/// //
|
|
|
|
/// 0x02, // adapter section
|
2020-02-10 16:48:25 +01:00
|
|
|
/// 0x01, // 1 adapter
|
2020-02-26 15:32:14 +01:00
|
|
|
/// 0x00, // function type
|
2020-02-10 16:48:25 +01:00
|
|
|
/// 0x01, // list of 1 item
|
|
|
|
/// 0x00, 0x01, // ArgumentGet { index: 1 }
|
2020-02-26 15:32:14 +01:00
|
|
|
/// //
|
|
|
|
/// 0x03, // export section
|
|
|
|
/// 0x01, // 1 export
|
|
|
|
/// 0x02, // string of 2 bytes
|
|
|
|
/// 0x61, 0x62, // "a", "b"
|
|
|
|
/// 0x01, // function type
|
|
|
|
/// //
|
|
|
|
/// 0x04, // implementation section
|
|
|
|
/// 0x01, // 1 implementation
|
|
|
|
/// 0x02, // core function type
|
|
|
|
/// 0x03, // adapter function type
|
2020-02-10 16:48:25 +01:00
|
|
|
/// ];
|
|
|
|
/// let output = Ok((
|
|
|
|
/// &[] as &[u8],
|
|
|
|
/// Interfaces {
|
2020-03-26 11:18:24 +01:00
|
|
|
/// types: vec![Type::Function {
|
2020-02-26 15:32:14 +01:00
|
|
|
/// inputs: vec![InterfaceType::S8],
|
|
|
|
/// outputs: vec![InterfaceType::S16],
|
2020-02-24 16:23:31 +01:00
|
|
|
/// }],
|
2020-02-10 16:48:25 +01:00
|
|
|
/// imports: vec![Import {
|
2020-02-26 15:32:14 +01:00
|
|
|
/// namespace: "ab",
|
|
|
|
/// name: "c",
|
|
|
|
/// signature_type: 0,
|
2020-02-10 16:48:25 +01:00
|
|
|
/// }],
|
2020-02-26 15:32:14 +01:00
|
|
|
/// adapters: vec![Adapter {
|
|
|
|
/// function_type: 0,
|
2020-02-10 16:48:25 +01:00
|
|
|
/// instructions: vec![Instruction::ArgumentGet { index: 1 }],
|
|
|
|
/// }],
|
2020-02-26 15:32:14 +01:00
|
|
|
/// exports: vec![Export {
|
|
|
|
/// name: "ab",
|
|
|
|
/// function_type: 1,
|
|
|
|
/// }],
|
|
|
|
/// implementations: vec![Implementation {
|
|
|
|
/// core_function_type: 2,
|
|
|
|
/// adapter_function_type: 3,
|
|
|
|
/// }],
|
2020-02-10 16:48:25 +01:00
|
|
|
/// },
|
|
|
|
/// ));
|
|
|
|
///
|
|
|
|
/// assert_eq!(parse::<()>(input), output);
|
|
|
|
/// ```
|
2019-09-12 22:44:20 +02:00
|
|
|
pub fn parse<'input, E: ParseError<&'input [u8]>>(
|
|
|
|
bytes: &'input [u8],
|
|
|
|
) -> IResult<&'input [u8], Interfaces, E> {
|
2020-02-17 13:52:00 +01:00
|
|
|
interfaces(bytes)
|
2019-09-12 22:44:20 +02:00
|
|
|
}
|
2019-09-13 12:00:05 +02:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
2020-02-13 13:36:18 +01:00
|
|
|
use nom::{error, Err};
|
2019-09-13 12:00:05 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_byte() {
|
|
|
|
let input = &[0x01, 0x02, 0x03];
|
|
|
|
let output = Ok((&[0x02, 0x03][..], 0x01u8));
|
|
|
|
|
|
|
|
assert_eq!(byte::<()>(input), output);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2020-02-13 13:36:18 +01:00
|
|
|
fn test_uleb_1_byte() {
|
2019-09-13 12:00:05 +02:00
|
|
|
let input = &[0x01, 0x02, 0x03];
|
|
|
|
let output = Ok((&[0x02, 0x03][..], 0x01u64));
|
|
|
|
|
2020-02-13 13:36:18 +01:00
|
|
|
assert_eq!(uleb::<()>(input), output);
|
2019-09-13 12:00:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2020-02-13 13:36:18 +01:00
|
|
|
fn test_uleb_3_bytes() {
|
2019-09-13 12:00:05 +02:00
|
|
|
let input = &[0xfc, 0xff, 0x01, 0x02];
|
|
|
|
let output = Ok((&[0x02][..], 0x7ffcu64));
|
|
|
|
|
2020-02-13 13:36:18 +01:00
|
|
|
assert_eq!(uleb::<()>(input), output);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Examples from Figure 22 of [DWARF 4
|
|
|
|
// standard](http://dwarfstd.org/doc/DWARF4.pdf).
|
|
|
|
#[test]
|
|
|
|
fn test_uleb_from_dwarf_standard() {
|
|
|
|
macro_rules! assert_uleb {
|
|
|
|
($to_parse:expr => $expected_result:expr) => {
|
|
|
|
assert_eq!(uleb::<()>($to_parse), Ok((&[][..], $expected_result)));
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
assert_uleb!(&[2u8] => 2u64);
|
|
|
|
assert_uleb!(&[127u8] => 127u64);
|
|
|
|
assert_uleb!(&[0x80, 1u8] => 128u64);
|
|
|
|
assert_uleb!(&[1u8 | 0x80, 1] => 129u64);
|
|
|
|
assert_uleb!(&[2u8 | 0x80, 1] => 130u64);
|
|
|
|
assert_uleb!(&[57u8 | 0x80, 100] => 12857u64);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_uleb_eof() {
|
|
|
|
let input = &[0x80];
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
uleb::<(&[u8], error::ErrorKind)>(input),
|
|
|
|
Err(Err::Error((&input[..], error::ErrorKind::Eof))),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_uleb_overflow() {
|
|
|
|
let input = &[
|
|
|
|
0x01 | 0x80,
|
|
|
|
0x02 | 0x80,
|
|
|
|
0x03 | 0x80,
|
|
|
|
0x04 | 0x80,
|
|
|
|
0x05 | 0x80,
|
|
|
|
0x06 | 0x80,
|
|
|
|
0x07 | 0x80,
|
|
|
|
0x08 | 0x80,
|
|
|
|
0x09 | 0x80,
|
|
|
|
0x0a,
|
|
|
|
];
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
uleb::<(&[u8], error::ErrorKind)>(input),
|
|
|
|
Err(Err::Error((&input[..], error::ErrorKind::TooLarge))),
|
|
|
|
);
|
2019-09-13 12:00:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_ty() {
|
|
|
|
let input = &[
|
2020-03-26 13:17:36 +01:00
|
|
|
0x0f, // list of 15 items
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
0x00, // S8
|
|
|
|
0x01, // S16
|
|
|
|
0x02, // S32
|
|
|
|
0x03, // S64
|
|
|
|
0x04, // U8
|
|
|
|
0x05, // U16
|
|
|
|
0x06, // U32
|
|
|
|
0x07, // U64
|
|
|
|
0x08, // F32
|
|
|
|
0x09, // F64
|
|
|
|
0x0a, // String
|
|
|
|
0x0b, // Anyref
|
|
|
|
0x0c, // I32
|
|
|
|
0x0d, // I64
|
2020-03-26 13:17:36 +01:00
|
|
|
0x0e, 0x01, 0x02, // Record
|
2019-09-13 12:00:05 +02:00
|
|
|
0x01,
|
|
|
|
];
|
|
|
|
let output = Ok((
|
|
|
|
&[0x01][..],
|
|
|
|
vec![
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
InterfaceType::S8,
|
|
|
|
InterfaceType::S16,
|
|
|
|
InterfaceType::S32,
|
|
|
|
InterfaceType::S64,
|
|
|
|
InterfaceType::U8,
|
|
|
|
InterfaceType::U16,
|
|
|
|
InterfaceType::U32,
|
|
|
|
InterfaceType::U64,
|
|
|
|
InterfaceType::F32,
|
|
|
|
InterfaceType::F64,
|
2019-09-13 12:00:05 +02:00
|
|
|
InterfaceType::String,
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
InterfaceType::Anyref,
|
2019-09-13 12:00:05 +02:00
|
|
|
InterfaceType::I32,
|
|
|
|
InterfaceType::I64,
|
2020-03-26 13:17:36 +01:00
|
|
|
InterfaceType::Record(RecordType {
|
|
|
|
fields: vec![InterfaceType::S32],
|
|
|
|
}),
|
2019-09-13 12:00:05 +02:00
|
|
|
],
|
|
|
|
));
|
|
|
|
|
2020-03-26 13:17:36 +01:00
|
|
|
assert_eq!(list::<_, ()>(input, ty), output);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_record_type() {
|
|
|
|
let input = &[
|
|
|
|
0x03, // list of 3 items
|
|
|
|
0x01, // 1 field
|
|
|
|
0x0a, // String
|
|
|
|
0x02, // 2 fields
|
|
|
|
0x0a, // String
|
|
|
|
0x0c, // I32
|
|
|
|
0x03, // 3 fields
|
|
|
|
0x0a, // String
|
|
|
|
0x0e, // Record
|
|
|
|
0x02, // 2 fields
|
|
|
|
0x0c, // I32
|
|
|
|
0x0c, // I32
|
|
|
|
0x09, // F64
|
|
|
|
0x01,
|
|
|
|
];
|
|
|
|
let output = Ok((
|
|
|
|
&[0x01][..],
|
|
|
|
vec![
|
|
|
|
RecordType {
|
|
|
|
fields: vec![InterfaceType::String],
|
|
|
|
},
|
|
|
|
RecordType {
|
|
|
|
fields: vec![InterfaceType::String, InterfaceType::I32],
|
|
|
|
},
|
|
|
|
RecordType {
|
|
|
|
fields: vec![
|
|
|
|
InterfaceType::String,
|
|
|
|
InterfaceType::Record(RecordType {
|
|
|
|
fields: vec![InterfaceType::I32, InterfaceType::I32],
|
|
|
|
}),
|
|
|
|
InterfaceType::F64,
|
|
|
|
],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
));
|
|
|
|
|
|
|
|
assert_eq!(list::<_, ()>(input, record_type), output);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_string() {
|
|
|
|
let input = &[
|
|
|
|
0x03, // string of 3 bytes
|
|
|
|
0x61, // "a"
|
|
|
|
0x62, // "b"
|
|
|
|
0x63, // "c"
|
|
|
|
0x64, 0x65,
|
|
|
|
];
|
|
|
|
let output = Ok((&[0x64, 0x65][..], "abc"));
|
|
|
|
|
|
|
|
assert_eq!(string::<()>(input), output);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_list() {
|
|
|
|
let input = &[
|
|
|
|
0x02, // list of 2 items
|
|
|
|
0x01, // string of 1 byte
|
|
|
|
0x61, // "a"
|
|
|
|
0x02, // string of 2 bytes
|
|
|
|
0x62, // "b"
|
|
|
|
0x63, // "c"
|
|
|
|
0x07,
|
|
|
|
];
|
|
|
|
let output = Ok((&[0x07][..], vec!["a", "bc"]));
|
|
|
|
|
|
|
|
assert_eq!(list::<_, ()>(input, string), output);
|
2019-09-13 12:00:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_instructions() {
|
|
|
|
let input = &[
|
2020-04-02 12:05:22 +02:00
|
|
|
0x27, // list of 39 items
|
2019-09-25 23:29:08 +02:00
|
|
|
0x00, 0x01, // ArgumentGet { index: 1 }
|
2020-03-09 14:33:17 +01:00
|
|
|
0x01, 0x01, // CallCore { function_index: 1 }
|
2020-03-24 12:43:57 +01:00
|
|
|
0x02, // S8FromI32
|
|
|
|
0x03, // S8FromI64
|
|
|
|
0x04, // S16FromI32
|
|
|
|
0x05, // S16FromI64
|
|
|
|
0x06, // S32FromI32
|
|
|
|
0x07, // S32FromI64
|
|
|
|
0x08, // S64FromI32
|
|
|
|
0x09, // S64FromI64
|
|
|
|
0x0a, // I32FromS8
|
|
|
|
0x0b, // I32FromS16
|
|
|
|
0x0c, // I32FromS32
|
|
|
|
0x0d, // I32FromS64
|
|
|
|
0x0e, // I64FromS8
|
|
|
|
0x0f, // I64FromS16
|
|
|
|
0x10, // I64FromS32
|
|
|
|
0x11, // I64FromS64
|
|
|
|
0x12, // U8FromI32
|
|
|
|
0x13, // U8FromI64
|
|
|
|
0x14, // U16FromI32
|
|
|
|
0x15, // U16FromI64
|
|
|
|
0x16, // U32FromI32
|
|
|
|
0x17, // U32FromI64
|
|
|
|
0x18, // U64FromI32
|
|
|
|
0x19, // U64FromI64
|
|
|
|
0x1a, // I32FromU8
|
|
|
|
0x1b, // I32FromU16
|
|
|
|
0x1c, // I32FromU32
|
|
|
|
0x1d, // I32FromU64
|
|
|
|
0x1e, // I64FromU8
|
|
|
|
0x1f, // I64FromU16
|
|
|
|
0x20, // I64FromU32
|
|
|
|
0x21, // I64FromU64
|
2020-03-24 13:25:06 +01:00
|
|
|
0x22, // StringLiftMemory
|
|
|
|
0x23, 0x01, // StringLowerMemory { allocator_index: 1 }
|
2020-03-24 15:33:42 +01:00
|
|
|
0x24, // StringSize
|
2020-03-31 08:17:52 +02:00
|
|
|
0x25, 0x01, // RecordLift { type_index: 1 },
|
2020-04-02 12:05:22 +02:00
|
|
|
0x26, 0x01, // RecordLower { type_index: 1 },
|
2019-09-13 12:00:05 +02:00
|
|
|
0x0a,
|
|
|
|
];
|
|
|
|
let output = Ok((
|
|
|
|
&[0x0a][..],
|
|
|
|
vec![
|
2019-09-25 23:29:08 +02:00
|
|
|
Instruction::ArgumentGet { index: 1 },
|
2020-03-09 14:33:17 +01:00
|
|
|
Instruction::CallCore { function_index: 1 },
|
2020-03-24 12:43:57 +01:00
|
|
|
Instruction::S8FromI32,
|
|
|
|
Instruction::S8FromI64,
|
|
|
|
Instruction::S16FromI32,
|
|
|
|
Instruction::S16FromI64,
|
|
|
|
Instruction::S32FromI32,
|
|
|
|
Instruction::S32FromI64,
|
|
|
|
Instruction::S64FromI32,
|
|
|
|
Instruction::S64FromI64,
|
|
|
|
Instruction::I32FromS8,
|
|
|
|
Instruction::I32FromS16,
|
|
|
|
Instruction::I32FromS32,
|
|
|
|
Instruction::I32FromS64,
|
|
|
|
Instruction::I64FromS8,
|
|
|
|
Instruction::I64FromS16,
|
|
|
|
Instruction::I64FromS32,
|
|
|
|
Instruction::I64FromS64,
|
|
|
|
Instruction::U8FromI32,
|
|
|
|
Instruction::U8FromI64,
|
|
|
|
Instruction::U16FromI32,
|
|
|
|
Instruction::U16FromI64,
|
|
|
|
Instruction::U32FromI32,
|
|
|
|
Instruction::U32FromI64,
|
|
|
|
Instruction::U64FromI32,
|
|
|
|
Instruction::U64FromI64,
|
|
|
|
Instruction::I32FromU8,
|
|
|
|
Instruction::I32FromU16,
|
|
|
|
Instruction::I32FromU32,
|
|
|
|
Instruction::I32FromU64,
|
|
|
|
Instruction::I64FromU8,
|
|
|
|
Instruction::I64FromU16,
|
|
|
|
Instruction::I64FromU32,
|
|
|
|
Instruction::I64FromU64,
|
2020-03-24 13:25:06 +01:00
|
|
|
Instruction::StringLiftMemory,
|
|
|
|
Instruction::StringLowerMemory { allocator_index: 1 },
|
2020-03-24 15:33:42 +01:00
|
|
|
Instruction::StringSize,
|
2020-03-31 08:17:52 +02:00
|
|
|
Instruction::RecordLift { type_index: 1 },
|
2020-04-02 12:05:22 +02:00
|
|
|
Instruction::RecordLower { type_index: 1 },
|
2019-09-13 12:00:05 +02:00
|
|
|
],
|
|
|
|
));
|
|
|
|
|
2020-03-26 13:17:36 +01:00
|
|
|
assert_eq!(list::<_, ()>(input, instruction), output);
|
2019-09-13 12:00:05 +02:00
|
|
|
}
|
2019-09-13 14:24:03 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_exports() {
|
|
|
|
let input = &[
|
|
|
|
0x02, // 2 exports
|
|
|
|
0x02, // string of 2 bytes
|
|
|
|
0x61, 0x62, // "a", "b"
|
2020-02-26 15:32:14 +01:00
|
|
|
0x01, // function type
|
2019-09-13 14:24:03 +02:00
|
|
|
0x02, // string of 2 bytes
|
|
|
|
0x63, 0x64, // "c", "d"
|
2020-02-26 15:32:14 +01:00
|
|
|
0x02, // function type
|
2019-09-13 14:24:03 +02:00
|
|
|
];
|
|
|
|
let output = Ok((
|
|
|
|
&[] as &[u8],
|
|
|
|
vec![
|
|
|
|
Export {
|
|
|
|
name: "ab",
|
2020-02-26 15:32:14 +01:00
|
|
|
function_type: 1,
|
2019-09-13 14:24:03 +02:00
|
|
|
},
|
|
|
|
Export {
|
|
|
|
name: "cd",
|
2020-02-26 15:32:14 +01:00
|
|
|
function_type: 2,
|
2019-09-13 14:24:03 +02:00
|
|
|
},
|
|
|
|
],
|
|
|
|
));
|
|
|
|
|
|
|
|
assert_eq!(exports::<()>(input), output);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_types() {
|
|
|
|
let input = &[
|
2020-03-26 11:18:24 +01:00
|
|
|
0x02, // 2 type
|
|
|
|
0x00, // function type
|
2019-09-13 14:24:03 +02:00
|
|
|
0x02, // list of 2 items
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
0x02, // S32
|
|
|
|
0x02, // S32
|
2020-02-24 16:23:31 +01:00
|
|
|
0x01, // list of 2 items
|
|
|
|
0x02, // S32
|
2020-03-26 11:18:24 +01:00
|
|
|
0x01, // record type
|
|
|
|
0x02, // list of 2 items
|
|
|
|
0x02, // S32
|
|
|
|
0x02, // S32
|
2019-09-13 14:24:03 +02:00
|
|
|
];
|
|
|
|
let output = Ok((
|
|
|
|
&[] as &[u8],
|
2020-03-26 11:18:24 +01:00
|
|
|
vec![
|
|
|
|
Type::Function {
|
|
|
|
inputs: vec![InterfaceType::S32, InterfaceType::S32],
|
|
|
|
outputs: vec![InterfaceType::S32],
|
|
|
|
},
|
2020-03-26 13:17:36 +01:00
|
|
|
Type::Record(RecordType {
|
2020-03-26 11:18:24 +01:00
|
|
|
fields: vec![InterfaceType::S32, InterfaceType::S32],
|
2020-03-26 13:17:36 +01:00
|
|
|
}),
|
2020-03-26 11:18:24 +01:00
|
|
|
],
|
2019-09-13 14:24:03 +02:00
|
|
|
));
|
|
|
|
|
|
|
|
assert_eq!(types::<()>(input), output);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2020-02-10 15:41:10 +01:00
|
|
|
fn test_imports() {
|
2019-09-13 14:24:03 +02:00
|
|
|
let input = &[
|
2020-02-10 15:41:10 +01:00
|
|
|
0x02, // 2 imports
|
2019-09-13 14:24:03 +02:00
|
|
|
0x01, // string of 1 byte
|
|
|
|
0x61, // "a"
|
|
|
|
0x01, // string of 1 byte
|
|
|
|
0x62, // "b"
|
2020-02-26 15:32:14 +01:00
|
|
|
0x01, // signature type
|
2019-09-13 14:24:03 +02:00
|
|
|
0x01, // string of 1 byte
|
|
|
|
0x63, // "c"
|
|
|
|
0x01, // string of 1 byte
|
|
|
|
0x64, // "d"
|
2020-02-26 15:32:14 +01:00
|
|
|
0x02, // signature type
|
2019-09-13 14:24:03 +02:00
|
|
|
];
|
|
|
|
let output = Ok((
|
|
|
|
&[] as &[u8],
|
|
|
|
vec![
|
2020-02-10 15:41:10 +01:00
|
|
|
Import {
|
2019-09-13 14:24:03 +02:00
|
|
|
namespace: "a",
|
|
|
|
name: "b",
|
2020-02-26 15:32:14 +01:00
|
|
|
signature_type: 1,
|
2019-09-13 14:24:03 +02:00
|
|
|
},
|
2020-02-10 15:41:10 +01:00
|
|
|
Import {
|
2019-09-13 14:24:03 +02:00
|
|
|
namespace: "c",
|
|
|
|
name: "d",
|
2020-02-26 15:32:14 +01:00
|
|
|
signature_type: 2,
|
2019-09-13 14:24:03 +02:00
|
|
|
},
|
|
|
|
],
|
|
|
|
));
|
|
|
|
|
2020-02-10 15:41:10 +01:00
|
|
|
assert_eq!(imports::<()>(input), output);
|
2019-09-13 14:24:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_adapters() {
|
|
|
|
let input = &[
|
2020-02-26 15:38:59 +01:00
|
|
|
0x01, // 1 adapters
|
|
|
|
0x00, // function type
|
2019-09-13 14:24:03 +02:00
|
|
|
0x01, // list of 1 item
|
2019-09-25 23:29:08 +02:00
|
|
|
0x00, 0x01, // ArgumentGet { index: 1 }
|
2019-09-13 14:24:03 +02:00
|
|
|
];
|
|
|
|
let output = Ok((
|
|
|
|
&[] as &[u8],
|
2020-02-26 15:38:59 +01:00
|
|
|
vec![Adapter {
|
|
|
|
function_type: 0,
|
|
|
|
instructions: vec![Instruction::ArgumentGet { index: 1 }],
|
|
|
|
}],
|
2019-09-13 14:24:03 +02:00
|
|
|
));
|
|
|
|
|
|
|
|
assert_eq!(adapters::<()>(input), output);
|
|
|
|
}
|
|
|
|
|
2020-02-10 16:39:34 +01:00
|
|
|
#[test]
|
|
|
|
fn test_parse() {
|
|
|
|
let input = &[
|
2020-02-26 15:32:14 +01:00
|
|
|
0x00, // type section
|
|
|
|
0x01, // 1 type
|
2020-03-26 11:18:24 +01:00
|
|
|
0x00, // function type
|
2020-02-10 16:39:34 +01:00
|
|
|
0x01, // list of 1 item
|
2020-02-26 15:32:14 +01:00
|
|
|
0x00, // S8
|
2020-02-10 16:39:34 +01:00
|
|
|
0x01, // list of 1 item
|
2020-02-26 15:32:14 +01:00
|
|
|
0x01, // S16
|
|
|
|
//
|
|
|
|
0x01, // import section
|
2020-02-10 16:39:34 +01:00
|
|
|
0x01, // 1 import
|
2020-02-26 15:32:14 +01:00
|
|
|
0x02, // string of 2 bytes
|
|
|
|
0x61, 0x62, // "a", "b"
|
2020-02-10 16:39:34 +01:00
|
|
|
0x01, // string of 1 byte
|
2020-02-26 15:32:14 +01:00
|
|
|
0x63, // "c"
|
|
|
|
0x00, // signature type
|
|
|
|
//
|
|
|
|
0x02, // adapter section
|
|
|
|
0x01, // 1 adapter
|
|
|
|
0x00, // function type
|
2020-02-10 16:39:34 +01:00
|
|
|
0x01, // list of 1 item
|
2020-02-26 15:32:14 +01:00
|
|
|
0x00, 0x01, // ArgumentGet { index: 1 }
|
|
|
|
//
|
|
|
|
0x03, // export section
|
|
|
|
0x01, // 1 export
|
|
|
|
0x02, // string of 2 bytes
|
|
|
|
0x61, 0x62, // "a", "b"
|
|
|
|
0x01, // function type
|
|
|
|
//
|
|
|
|
0x04, // implementation section
|
|
|
|
0x01, // 1 implementation
|
|
|
|
0x02, // core function type
|
|
|
|
0x03, // adapter function type
|
2020-02-10 16:39:34 +01:00
|
|
|
];
|
|
|
|
let output = Ok((
|
|
|
|
&[] as &[u8],
|
|
|
|
Interfaces {
|
2020-03-26 11:18:24 +01:00
|
|
|
types: vec![Type::Function {
|
2020-02-26 15:32:14 +01:00
|
|
|
inputs: vec![InterfaceType::S8],
|
|
|
|
outputs: vec![InterfaceType::S16],
|
2020-02-24 16:23:31 +01:00
|
|
|
}],
|
2020-02-10 16:39:34 +01:00
|
|
|
imports: vec![Import {
|
2020-02-26 15:32:14 +01:00
|
|
|
namespace: "ab",
|
|
|
|
name: "c",
|
|
|
|
signature_type: 0,
|
2020-02-10 16:39:34 +01:00
|
|
|
}],
|
2020-02-26 15:32:14 +01:00
|
|
|
adapters: vec![Adapter {
|
|
|
|
function_type: 0,
|
2020-02-10 16:39:34 +01:00
|
|
|
instructions: vec![Instruction::ArgumentGet { index: 1 }],
|
2020-02-26 15:32:14 +01:00
|
|
|
}],
|
|
|
|
exports: vec![Export {
|
|
|
|
name: "ab",
|
|
|
|
function_type: 1,
|
|
|
|
}],
|
|
|
|
implementations: vec![Implementation {
|
|
|
|
core_function_type: 2,
|
|
|
|
adapter_function_type: 3,
|
|
|
|
}],
|
2020-02-10 16:39:34 +01:00
|
|
|
},
|
|
|
|
));
|
|
|
|
|
2020-02-17 13:52:00 +01:00
|
|
|
assert_eq!(interfaces::<()>(input), output);
|
2020-02-10 16:39:34 +01:00
|
|
|
}
|
2019-09-13 12:00:05 +02:00
|
|
|
}
|