2017-04-03 13:18:50 +03:00
|
|
|
use std::io;
|
2017-04-03 19:51:18 +03:00
|
|
|
use super::{
|
|
|
|
Deserialize, Error, ValueType, VarUint32, CountedList, Opcodes,
|
|
|
|
Serialize, CountedWriter, CountedListWriter,
|
|
|
|
};
|
2017-04-03 13:18:50 +03:00
|
|
|
|
2017-04-03 13:58:49 +03:00
|
|
|
/// Function signature (type reference)
|
|
|
|
pub struct Func(u32);
|
|
|
|
|
|
|
|
impl Func {
|
2017-04-04 03:03:57 +03:00
|
|
|
/// New function signature
|
2017-04-03 13:58:49 +03:00
|
|
|
pub fn new(type_ref: u32) -> Self { Func(type_ref) }
|
|
|
|
|
2017-04-04 03:03:57 +03:00
|
|
|
/// Function signature type reference.
|
2017-04-03 13:58:49 +03:00
|
|
|
pub fn type_ref(&self) -> u32 {
|
|
|
|
self.0
|
|
|
|
}
|
|
|
|
}
|
2017-04-03 13:18:50 +03:00
|
|
|
|
2017-04-04 03:03:57 +03:00
|
|
|
/// Local definition inside the function body.
|
2017-04-03 13:18:50 +03:00
|
|
|
pub struct Local {
|
|
|
|
count: u32,
|
|
|
|
value_type: ValueType,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Local {
|
2017-04-04 03:03:57 +03:00
|
|
|
/// New local with `count` and `value_type`.
|
2017-04-03 20:19:20 +03:00
|
|
|
pub fn new(count: u32, value_type: ValueType) -> Self {
|
|
|
|
Local { count: count, value_type: value_type }
|
|
|
|
}
|
|
|
|
|
2017-04-04 03:03:57 +03:00
|
|
|
/// Number of locals with the shared type.
|
2017-04-03 13:18:50 +03:00
|
|
|
pub fn count(&self) -> u32 { self.count }
|
2017-04-03 20:19:20 +03:00
|
|
|
|
2017-04-04 03:03:57 +03:00
|
|
|
/// Type of the locals.
|
2017-04-03 13:18:50 +03:00
|
|
|
pub fn value_type(&self) -> ValueType { self.value_type }
|
|
|
|
}
|
|
|
|
|
|
|
|
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 })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-03 19:51:18 +03:00
|
|
|
impl Serialize for Local {
|
|
|
|
type Error = Error;
|
|
|
|
|
|
|
|
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
|
|
|
|
VarUint32::from(self.count).serialize(writer)?;
|
|
|
|
self.value_type.serialize(writer)?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-04 03:03:57 +03:00
|
|
|
/// Function body definition.
|
2017-04-03 13:18:50 +03:00
|
|
|
pub struct FuncBody {
|
|
|
|
locals: Vec<Local>,
|
|
|
|
opcodes: Opcodes,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FuncBody {
|
2017-04-04 03:03:57 +03:00
|
|
|
/// New function body with given `locals` and `opcodes`
|
2017-04-03 20:19:20 +03:00
|
|
|
pub fn new(locals: Vec<Local>, opcodes: Opcodes) -> Self {
|
|
|
|
FuncBody { locals: locals, opcodes: opcodes }
|
|
|
|
}
|
|
|
|
|
2017-04-04 03:03:57 +03:00
|
|
|
/// Locals declared in function body.
|
2017-04-03 13:18:50 +03:00
|
|
|
pub fn locals(&self) -> &[Local] { &self.locals }
|
2017-04-03 23:56:21 +03:00
|
|
|
|
2017-04-04 03:03:57 +03:00
|
|
|
/// Opcode sequence of the function body. Minimal opcode sequence
|
|
|
|
/// is just `&[Opcode::End]`
|
2017-04-03 13:18:50 +03:00
|
|
|
pub fn code(&self) -> &Opcodes { &self.opcodes }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Deserialize for FuncBody {
|
|
|
|
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(FuncBody { locals: locals, opcodes: opcodes })
|
|
|
|
}
|
2017-04-03 19:51:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Serialize for FuncBody {
|
|
|
|
type Error = Error;
|
|
|
|
|
|
|
|
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
|
|
|
|
let mut counted_writer = CountedWriter::new(writer);
|
|
|
|
|
|
|
|
let data = self.locals;
|
|
|
|
let counted_list = CountedListWriter::<Local, _>(
|
|
|
|
data.len(),
|
|
|
|
data.into_iter().map(Into::into),
|
|
|
|
);
|
|
|
|
counted_list.serialize(&mut counted_writer)?;
|
2017-04-03 23:56:21 +03:00
|
|
|
|
2017-04-03 19:51:18 +03:00
|
|
|
let code = self.opcodes;
|
|
|
|
code.serialize(&mut counted_writer)?;
|
|
|
|
|
|
|
|
counted_writer.done()?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2017-04-03 13:18:50 +03:00
|
|
|
}
|