mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-06-21 10:41:54 +00:00
types deserialization
This commit is contained in:
@ -2,11 +2,12 @@ use std::io;
|
||||
|
||||
mod module;
|
||||
mod section;
|
||||
mod primitives;
|
||||
mod types;
|
||||
|
||||
pub use self::module::Module;
|
||||
pub use self::section::Section;
|
||||
|
||||
use byteorder::{LittleEndian, ByteOrder};
|
||||
pub use self::primitives::{VarUint32, VarUint7, VarUint1, VarInt7, Uint32, CountedList};
|
||||
|
||||
pub trait Deserialize : Sized {
|
||||
type Error;
|
||||
@ -19,6 +20,7 @@ pub enum Error {
|
||||
InconsistentLength { expected: usize, actual: usize },
|
||||
Other(&'static str),
|
||||
HeapOther(String),
|
||||
UnknownValueType(i8),
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
@ -40,55 +42,22 @@ impl Deserialize for Unparsed {
|
||||
}
|
||||
}
|
||||
|
||||
struct VarUint32(u32);
|
||||
|
||||
impl From<VarUint32> for usize {
|
||||
fn from(var: VarUint32) -> usize {
|
||||
var.0 as usize
|
||||
impl From<Unparsed> for Vec<u8> {
|
||||
fn from(u: Unparsed) -> Vec<u8> {
|
||||
u.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for VarUint32 {
|
||||
type Error = Error;
|
||||
fn deserialize_file<P: AsRef<::std::path::Path>>(p: P) -> Result<Module, Error> {
|
||||
use std::io::Read;
|
||||
|
||||
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 {
|
||||
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))
|
||||
}
|
||||
let mut contents = Vec::new();
|
||||
::std::fs::File::open(p)?.read_to_end(&mut contents)?;
|
||||
|
||||
deserialize_buffer(contents)
|
||||
}
|
||||
|
||||
struct VarUint7(u8);
|
||||
|
||||
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]))
|
||||
}
|
||||
}
|
||||
|
||||
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)))
|
||||
}
|
||||
}
|
||||
fn deserialize_buffer<T: Deserialize>(contents: Vec<u8>) -> Result<T, T::Error> {
|
||||
let mut reader = io::Cursor::new(contents);
|
||||
T::deserialize(&mut reader)
|
||||
}
|
@ -35,8 +35,8 @@ impl Deserialize for Module {
|
||||
}
|
||||
|
||||
Ok(Module {
|
||||
magic: magic.0,
|
||||
version: version.0,
|
||||
magic: magic.into(),
|
||||
version: version.into(),
|
||||
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 super::{Deserialize, Unparsed, Error, VarUint7};
|
||||
use super::{Deserialize, Unparsed, Error, VarUint7, VarUint32, CountedList};
|
||||
use super::types::Type;
|
||||
|
||||
pub struct Section {
|
||||
id: u8,
|
||||
unparsed: Unparsed,
|
||||
pub enum Section {
|
||||
Unparsed {
|
||||
id: u8,
|
||||
payload: Vec<u8>,
|
||||
},
|
||||
Custom(Vec<u8>),
|
||||
Type(TypeSection),
|
||||
}
|
||||
|
||||
impl Deserialize for Section {
|
||||
@ -15,10 +20,73 @@ impl Deserialize for Section {
|
||||
Err(_) => { return Err(Error::UnexpectedEof); },
|
||||
Ok(id) => id,
|
||||
};
|
||||
let unparsed = Unparsed::deserialize(reader)?;
|
||||
Ok(Section {
|
||||
id: id.0,
|
||||
unparsed: unparsed,
|
||||
})
|
||||
|
||||
Ok(
|
||||
match id.into() {
|
||||
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