flow args passing

This commit is contained in:
NikVolf
2017-03-31 04:04:51 +03:00
parent f202703106
commit e9534999a4
3 changed files with 163 additions and 1 deletions

View File

@ -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 {

View File

@ -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))
}
}

View File

@ -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")
}
}
}
}