types deserialization

This commit is contained in:
NikVolf
2017-03-29 23:13:54 +03:00
parent 3fa3a96d3a
commit b504dbc61c
5 changed files with 335 additions and 59 deletions

View File

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

View File

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

View File

@ -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 {
pub enum Section {
Unparsed {
id: u8,
unparsed: Unparsed,
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
View 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,
})
}
}