mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-06-21 18:51:52 +00:00
types deserialization
This commit is contained in:
@ -2,11 +2,12 @@ use std::io;
|
|||||||
|
|
||||||
mod module;
|
mod module;
|
||||||
mod section;
|
mod section;
|
||||||
|
mod primitives;
|
||||||
|
mod types;
|
||||||
|
|
||||||
pub use self::module::Module;
|
pub use self::module::Module;
|
||||||
pub use self::section::Section;
|
pub use self::section::Section;
|
||||||
|
pub use self::primitives::{VarUint32, VarUint7, VarUint1, VarInt7, Uint32, CountedList};
|
||||||
use byteorder::{LittleEndian, ByteOrder};
|
|
||||||
|
|
||||||
pub trait Deserialize : Sized {
|
pub trait Deserialize : Sized {
|
||||||
type Error;
|
type Error;
|
||||||
@ -19,6 +20,7 @@ pub enum Error {
|
|||||||
InconsistentLength { expected: usize, actual: usize },
|
InconsistentLength { expected: usize, actual: usize },
|
||||||
Other(&'static str),
|
Other(&'static str),
|
||||||
HeapOther(String),
|
HeapOther(String),
|
||||||
|
UnknownValueType(i8),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<io::Error> for Error {
|
impl From<io::Error> for Error {
|
||||||
@ -40,55 +42,22 @@ impl Deserialize for Unparsed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VarUint32(u32);
|
impl From<Unparsed> for Vec<u8> {
|
||||||
|
fn from(u: Unparsed) -> Vec<u8> {
|
||||||
impl From<VarUint32> for usize {
|
u.0
|
||||||
fn from(var: VarUint32) -> usize {
|
|
||||||
var.0 as usize
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deserialize for VarUint32 {
|
fn deserialize_file<P: AsRef<::std::path::Path>>(p: P) -> Result<Module, Error> {
|
||||||
type Error = Error;
|
use std::io::Read;
|
||||||
|
|
||||||
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
|
let mut contents = Vec::new();
|
||||||
let mut res = 0;
|
::std::fs::File::open(p)?.read_to_end(&mut contents)?;
|
||||||
let mut shift = 0;
|
|
||||||
let mut u8buf = [0u8; 1];
|
deserialize_buffer(contents)
|
||||||
loop {
|
|
||||||
reader.read_exact(&mut u8buf)?;
|
|
||||||
let b = u8buf[0] as u32;
|
|
||||||
res |= (b & 0x7f) << shift;
|
|
||||||
shift += 7;
|
|
||||||
if (b >> 7) == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(VarUint32(res))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VarUint7(u8);
|
fn deserialize_buffer<T: Deserialize>(contents: Vec<u8>) -> Result<T, T::Error> {
|
||||||
|
let mut reader = io::Cursor::new(contents);
|
||||||
impl Deserialize for VarUint7 {
|
T::deserialize(&mut reader)
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
|
|
||||||
let mut u8buf = [0u8; 1];
|
|
||||||
reader.read_exact(&mut u8buf)?;
|
|
||||||
Ok(VarUint7(u8buf[0]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Uint32(u32);
|
|
||||||
|
|
||||||
impl Deserialize for Uint32 {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
|
|
||||||
let mut buf = [0u8; 4];
|
|
||||||
reader.read_exact(&mut buf)?;
|
|
||||||
;
|
|
||||||
Ok(Uint32(LittleEndian::read_u32(&buf)))
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -35,8 +35,8 @@ impl Deserialize for Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(Module {
|
Ok(Module {
|
||||||
magic: magic.0,
|
magic: magic.into(),
|
||||||
version: version.0,
|
version: version.into(),
|
||||||
sections: sections,
|
sections: sections,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
166
src/elements/primitives.rs
Normal file
166
src/elements/primitives.rs
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
use std::io;
|
||||||
|
use byteorder::{LittleEndian, ByteOrder};
|
||||||
|
use super::{Error, Deserialize};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct VarUint32(u32);
|
||||||
|
|
||||||
|
impl From<VarUint32> for usize {
|
||||||
|
fn from(var: VarUint32) -> usize {
|
||||||
|
var.0 as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<VarUint32> for u32 {
|
||||||
|
fn from(var: VarUint32) -> u32 {
|
||||||
|
var.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deserialize for VarUint32 {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
|
||||||
|
let mut res = 0;
|
||||||
|
let mut shift = 0;
|
||||||
|
let mut u8buf = [0u8; 1];
|
||||||
|
loop {
|
||||||
|
println!("read 1 byte");
|
||||||
|
reader.read_exact(&mut u8buf)?;
|
||||||
|
let b = u8buf[0] as u32;
|
||||||
|
res |= (b & 0x7f) << shift;
|
||||||
|
shift += 7;
|
||||||
|
if (b >> 7) == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(VarUint32(res))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct VarUint7(u8);
|
||||||
|
|
||||||
|
impl From<VarUint7> for u8 {
|
||||||
|
fn from(v: VarUint7) -> u8 {
|
||||||
|
v.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deserialize for VarUint7 {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
|
||||||
|
let mut u8buf = [0u8; 1];
|
||||||
|
reader.read_exact(&mut u8buf)?;
|
||||||
|
Ok(VarUint7(u8buf[0]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct VarInt7(i8);
|
||||||
|
|
||||||
|
impl From<VarInt7> for i8 {
|
||||||
|
fn from(v: VarInt7) -> i8 {
|
||||||
|
v.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deserialize for VarInt7 {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
|
||||||
|
let mut u8buf = [0u8; 1];
|
||||||
|
reader.read_exact(&mut u8buf)?;
|
||||||
|
// expand sign
|
||||||
|
if u8buf[0] & 0b0100_0000 == 0b0100_0000 { u8buf[0] |= 0b1000_0000 }
|
||||||
|
// todo check range
|
||||||
|
Ok(VarInt7(unsafe { ::std::mem::transmute (u8buf[0]) }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct Uint32(u32);
|
||||||
|
|
||||||
|
impl Deserialize for Uint32 {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
|
||||||
|
let mut buf = [0u8; 4];
|
||||||
|
reader.read_exact(&mut buf)?;
|
||||||
|
// todo check range
|
||||||
|
Ok(Uint32(LittleEndian::read_u32(&buf)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Uint32> for u32 {
|
||||||
|
fn from(var: Uint32) -> u32 {
|
||||||
|
var.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct VarUint1(bool);
|
||||||
|
|
||||||
|
impl From<VarUint1> for bool {
|
||||||
|
fn from(v: VarUint1) -> bool {
|
||||||
|
v.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deserialize for VarUint1 {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
|
||||||
|
let mut u8buf = [0u8; 1];
|
||||||
|
reader.read_exact(&mut u8buf)?;
|
||||||
|
// todo check range
|
||||||
|
Ok(VarUint1(u8buf[0] == 1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CountedList<T: Deserialize>(Vec<T>);
|
||||||
|
|
||||||
|
impl<T: Deserialize> CountedList<T> {
|
||||||
|
pub fn into_inner(self) -> Vec<T> { self.0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Deserialize> Deserialize for CountedList<T> where T::Error : From<Error> {
|
||||||
|
type Error = T::Error;
|
||||||
|
|
||||||
|
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
|
||||||
|
let count: usize = VarUint32::deserialize(reader)?.into();
|
||||||
|
println!("count={}", count);
|
||||||
|
let mut result = Vec::new();
|
||||||
|
for _ in 0..count { result.push(T::deserialize(reader)?); }
|
||||||
|
Ok(CountedList(result))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use super::super::deserialize_buffer;
|
||||||
|
use super::{CountedList, VarInt7};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn counted_list() {
|
||||||
|
let payload = vec![
|
||||||
|
133u8, //(128+5), length is 5
|
||||||
|
0x80, 0x80, 0x80, 0x0, // padding
|
||||||
|
0x01,
|
||||||
|
0x7d,
|
||||||
|
0x05,
|
||||||
|
0x07,
|
||||||
|
0x09,
|
||||||
|
];
|
||||||
|
|
||||||
|
let list: CountedList<VarInt7> =
|
||||||
|
deserialize_buffer(payload).expect("type_section be deserialized");
|
||||||
|
|
||||||
|
let vars = list.into_inner();
|
||||||
|
assert_eq!(5, vars.len());
|
||||||
|
let v3: i8 = (*vars.get(1).unwrap()).into();
|
||||||
|
assert_eq!(-0x03i8, v3);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,9 +1,14 @@
|
|||||||
use std::io;
|
use std::io;
|
||||||
use super::{Deserialize, Unparsed, Error, VarUint7};
|
use super::{Deserialize, Unparsed, Error, VarUint7, VarUint32, CountedList};
|
||||||
|
use super::types::Type;
|
||||||
|
|
||||||
pub struct Section {
|
pub enum Section {
|
||||||
|
Unparsed {
|
||||||
id: u8,
|
id: u8,
|
||||||
unparsed: Unparsed,
|
payload: Vec<u8>,
|
||||||
|
},
|
||||||
|
Custom(Vec<u8>),
|
||||||
|
Type(TypeSection),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deserialize for Section {
|
impl Deserialize for Section {
|
||||||
@ -15,10 +20,73 @@ impl Deserialize for Section {
|
|||||||
Err(_) => { return Err(Error::UnexpectedEof); },
|
Err(_) => { return Err(Error::UnexpectedEof); },
|
||||||
Ok(id) => id,
|
Ok(id) => id,
|
||||||
};
|
};
|
||||||
let unparsed = Unparsed::deserialize(reader)?;
|
|
||||||
Ok(Section {
|
Ok(
|
||||||
id: id.0,
|
match id.into() {
|
||||||
unparsed: unparsed,
|
0 => {
|
||||||
})
|
Section::Custom(Unparsed::deserialize(reader)?.into())
|
||||||
|
},
|
||||||
|
1 => {
|
||||||
|
Section::Type(TypeSection::deserialize(reader)?)
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
Section::Unparsed { id: id.into(), payload: Unparsed::deserialize(reader)?.into() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct TypeSection {
|
||||||
|
types: Vec<Type>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeSection {
|
||||||
|
fn types(&self) -> &[Type] {
|
||||||
|
&self.types
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deserialize for TypeSection {
|
||||||
|
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 types: Vec<Type> = CountedList::deserialize(reader)?.into_inner();
|
||||||
|
Ok(TypeSection { types: types })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use super::super::{deserialize_buffer};
|
||||||
|
use super::{TypeSection, Type};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn type_section() {
|
||||||
|
let payload = vec![
|
||||||
|
129u8, 0x80, 0x80, 0x80, 0x0,
|
||||||
|
// func 1
|
||||||
|
// form=1
|
||||||
|
0x01,
|
||||||
|
// param_count=1
|
||||||
|
129u8, 0x80, 0x80, 0x80, 0x0,
|
||||||
|
// first param
|
||||||
|
0x7e, // i64
|
||||||
|
// no return params
|
||||||
|
0u8
|
||||||
|
];
|
||||||
|
|
||||||
|
let type_section: TypeSection =
|
||||||
|
deserialize_buffer(payload).expect("type_section be deserialized");
|
||||||
|
|
||||||
|
assert_eq!(type_section.types().len(), 1);
|
||||||
|
match type_section.types()[0] {
|
||||||
|
Type::Function(_) => {},
|
||||||
|
_ => panic!("Type should be a function")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
73
src/elements/types.rs
Normal file
73
src/elements/types.rs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
use std::io;
|
||||||
|
use super::{Deserialize, Unparsed, Error, VarUint7, VarInt7, VarUint32, VarUint1};
|
||||||
|
|
||||||
|
pub enum Type {
|
||||||
|
Function(FunctionType),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deserialize for Type {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
|
||||||
|
Ok(Type::Function(FunctionType::deserialize(reader)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ValueType {
|
||||||
|
I32,
|
||||||
|
I64,
|
||||||
|
F32,
|
||||||
|
F64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deserialize for ValueType {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
|
||||||
|
let val = VarInt7::deserialize(reader)?;
|
||||||
|
|
||||||
|
match val.into() {
|
||||||
|
-0x01 => Ok(ValueType::I32),
|
||||||
|
-0x02 => Ok(ValueType::I64),
|
||||||
|
-0x03 => Ok(ValueType::F32),
|
||||||
|
-0x04 => Ok(ValueType::F64),
|
||||||
|
_ => Err(Error::UnknownValueType(val.into())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FunctionType {
|
||||||
|
form: u8,
|
||||||
|
params: Vec<ValueType>,
|
||||||
|
return_type: Option<ValueType>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deserialize for FunctionType {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
|
||||||
|
let form: u8 = VarUint7::deserialize(reader)?.into();
|
||||||
|
println!("function form {}", form);
|
||||||
|
let param_count: usize = VarUint32::deserialize(reader)?.into();
|
||||||
|
|
||||||
|
println!("type param count {}", param_count);
|
||||||
|
|
||||||
|
let mut params = Vec::new();
|
||||||
|
for _ in 0..param_count {
|
||||||
|
params.push(ValueType::deserialize(reader)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
let has_return_type = VarUint1::deserialize(reader)?;
|
||||||
|
let return_type = if has_return_type.into() {
|
||||||
|
Some(ValueType::deserialize(reader)?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(FunctionType {
|
||||||
|
form: form,
|
||||||
|
params: params,
|
||||||
|
return_type: return_type,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user