mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-07-03 08:32:06 +00:00
flow args passing
This commit is contained in:
@ -14,6 +14,7 @@ pub use self::import_entry::{ImportEntry, MemoryType, TableType, External};
|
||||
pub use self::export_entry::{ExportEntry, Internal};
|
||||
pub use self::primitives::{VarUint32, VarUint7, VarUint1, VarInt7, Uint32, CountedList};
|
||||
pub use self::types::{ValueType, BlockType};
|
||||
pub use self::ops::{Opcode, Opcodes};
|
||||
|
||||
pub trait Deserialize : Sized {
|
||||
type Error;
|
||||
@ -30,6 +31,7 @@ pub enum Error {
|
||||
NonUtf8String,
|
||||
UnknownExternalKind(u8),
|
||||
UnknownInternalKind(u8),
|
||||
UnknownOpcode(u8),
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
|
@ -1,5 +1,5 @@
|
||||
use std::io;
|
||||
use super::{Deserialize, Error, VarUint7, VarInt7, VarUint1, CountedList, BlockType};
|
||||
use super::{Deserialize, Error, VarUint7, VarInt7, VarUint1, VarUint32, CountedList, BlockType};
|
||||
|
||||
pub struct Opcodes(Vec<Opcode>);
|
||||
|
||||
@ -190,3 +190,62 @@ pub enum Opcode {
|
||||
F32ReinterpretI32,
|
||||
F64ReinterpretI64,
|
||||
}
|
||||
|
||||
impl Opcode {
|
||||
pub fn is_terminal(&self) -> bool {
|
||||
match self {
|
||||
&Opcode::End => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for Opcode {
|
||||
type Error = Error;
|
||||
|
||||
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
|
||||
use self::Opcode::*;
|
||||
|
||||
let val: u8 = VarUint7::deserialize(reader)?.into();
|
||||
|
||||
Ok(
|
||||
match val {
|
||||
0x00 => Unreachable,
|
||||
0x01 => Nop,
|
||||
0x02 => Block(BlockType::deserialize(reader)?, Opcodes::deserialize(reader)?),
|
||||
0x0b => End,
|
||||
|
||||
0x20 => SetLocal(VarUint32::deserialize(reader)?.into()),
|
||||
0x21 => SetLocal(VarUint32::deserialize(reader)?.into()),
|
||||
0x23 => GetGlobal(VarUint32::deserialize(reader)?.into()),
|
||||
0x24 => SetGlobal(VarUint32::deserialize(reader)?.into()),
|
||||
|
||||
0x41 => I32Const(VarUint32::deserialize(reader)?.into()),
|
||||
|
||||
0x6a => I32Add,
|
||||
0x71 => I32And,
|
||||
|
||||
_ => { return Err(Error::UnknownOpcode(val)); }
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for Opcodes {
|
||||
type Error = Error;
|
||||
|
||||
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
|
||||
let mut opcodes = Vec::new();
|
||||
|
||||
loop {
|
||||
let opcode = Opcode::deserialize(reader)?;
|
||||
let is_terminal = opcode.is_terminal();
|
||||
opcodes.push(opcode);
|
||||
if is_terminal {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Opcodes(opcodes))
|
||||
}
|
||||
}
|
@ -10,6 +10,8 @@ use super::{
|
||||
MemoryType,
|
||||
TableType,
|
||||
ExportEntry,
|
||||
Opcodes,
|
||||
ValueType,
|
||||
};
|
||||
|
||||
use super::types::Type;
|
||||
@ -27,6 +29,7 @@ pub enum Section {
|
||||
Memory(MemorySection),
|
||||
Export(ExportSection),
|
||||
Start(u32),
|
||||
Code(CodeSection),
|
||||
}
|
||||
|
||||
impl Deserialize for Section {
|
||||
@ -66,6 +69,9 @@ impl Deserialize for Section {
|
||||
let _section_length = VarUint32::deserialize(reader)?;
|
||||
Section::Start(VarUint32::deserialize(reader)?.into())
|
||||
},
|
||||
10 => {
|
||||
Section::Code(CodeSection::deserialize(reader)?)
|
||||
},
|
||||
_ => {
|
||||
Section::Unparsed { id: id.into(), payload: Unparsed::deserialize(reader)?.into() }
|
||||
}
|
||||
@ -201,6 +207,57 @@ impl Deserialize for ExportSection {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CodeSection(Vec<FunctionBody>);
|
||||
|
||||
impl CodeSection {
|
||||
pub fn bodies(&self) -> &[FunctionBody] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for CodeSection {
|
||||
type Error = Error;
|
||||
|
||||
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
|
||||
// todo: maybe use reader.take(section_length)
|
||||
let _section_length = VarUint32::deserialize(reader)?;
|
||||
let entries: Vec<FunctionBody> = CountedList::deserialize(reader)?.into_inner();
|
||||
Ok(CodeSection(entries))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Local {
|
||||
count: u32,
|
||||
value_type: ValueType,
|
||||
}
|
||||
|
||||
impl Deserialize for Local {
|
||||
type Error = Error;
|
||||
|
||||
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
|
||||
let count = VarUint32::deserialize(reader)?;
|
||||
let value_type = ValueType::deserialize(reader)?;
|
||||
Ok(Local { count: count.into(), value_type: value_type })
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FunctionBody {
|
||||
locals: Vec<Local>,
|
||||
opcodes: Opcodes,
|
||||
}
|
||||
|
||||
impl Deserialize for FunctionBody {
|
||||
type Error = Error;
|
||||
|
||||
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
|
||||
// todo: maybe use reader.take(section_length)
|
||||
let _body_size = VarUint32::deserialize(reader)?;
|
||||
let locals: Vec<Local> = CountedList::deserialize(reader)?.into_inner();
|
||||
let opcodes = Opcodes::deserialize(reader)?;
|
||||
Ok(FunctionBody { locals: locals, opcodes: opcodes })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
@ -372,4 +429,48 @@ mod tests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn code_payload() -> Vec<u8> {
|
||||
vec![
|
||||
// sectionid
|
||||
0x0Au8,
|
||||
// section length, 32
|
||||
0x20,
|
||||
// body count
|
||||
0x01,
|
||||
// body 1, length 30
|
||||
0x1E,
|
||||
0x01, 0x01, 0x7F, // local i32 (one collection of length one of type i32)
|
||||
0x02, 0x7F, // block i32
|
||||
0x23, 0x00, // get_global 0
|
||||
0x21, 0x01, // set_local 1
|
||||
0x23, 0x00, // get_global 0
|
||||
0x20, 0x00, // get_local 0
|
||||
0x6A, // i32.add
|
||||
0x24, 0x00, // set_global 0
|
||||
0x23, 0x00, // get_global 0
|
||||
0x41, 0x0F, // i32.const 15
|
||||
0x6A, // i32.add
|
||||
0x41, 0x70, // i32.const -16
|
||||
0x71, // i32.and
|
||||
0x24, 0x00, // set_global 0
|
||||
0x20, 0x01, // get_local 1
|
||||
0x0B,
|
||||
0x0B,
|
||||
]
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn code_detect() {
|
||||
|
||||
let section: Section =
|
||||
deserialize_buffer(code_payload()).expect("section to be deserialized");
|
||||
|
||||
match section {
|
||||
Section::Code(_) => {},
|
||||
_ => {
|
||||
panic!("Payload should be recognized as a code section")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user