parity-wasm/src/elements/section.rs

1086 lines
32 KiB
Rust
Raw Normal View History

2017-03-29 18:16:58 +03:00
use std::io;
2017-03-30 23:57:36 +03:00
use super::{
2017-04-03 15:03:18 +03:00
Serialize,
2017-03-30 23:57:36 +03:00
Deserialize,
Unparsed,
Error,
VarUint7,
VarUint32,
CountedList,
ImportEntry,
MemoryType,
TableType,
2017-03-31 01:54:04 +03:00
ExportEntry,
2017-03-31 17:31:33 +03:00
GlobalEntry,
2017-04-03 13:58:49 +03:00
Func,
2017-04-03 13:18:50 +03:00
FuncBody,
2017-04-03 13:42:04 +03:00
ElementSegment,
DataSegment,
2017-04-03 15:03:18 +03:00
CountedWriter,
2017-04-03 15:56:37 +03:00
CountedListWriter,
2017-11-21 20:03:06 +03:00
External,
2018-01-18 19:26:30 +03:00
serialize,
2017-03-30 23:57:36 +03:00
};
2017-03-29 23:13:54 +03:00
use super::types::Type;
2018-01-18 19:26:30 +03:00
use super::name_section::NameSection;
2017-03-29 18:16:58 +03:00
2017-04-04 03:03:57 +03:00
/// Section in the WebAssembly module.
#[derive(Debug, Clone)]
2017-03-29 23:13:54 +03:00
pub enum Section {
2017-04-04 03:03:57 +03:00
/// Section is unparsed.
2017-03-29 23:13:54 +03:00
Unparsed {
2017-04-04 03:03:57 +03:00
/// id of the unparsed section
2017-03-29 23:13:54 +03:00
id: u8,
2017-04-04 03:03:57 +03:00
/// raw bytes of the unparsed section
2017-03-29 23:13:54 +03:00
payload: Vec<u8>,
},
2017-04-04 03:03:57 +03:00
/// Custom section (`id=0`)
2017-06-19 21:14:41 +03:00
Custom(CustomSection),
2017-04-04 03:03:57 +03:00
/// Types section
2017-03-29 23:13:54 +03:00
Type(TypeSection),
2017-04-04 03:03:57 +03:00
/// Import section
2017-03-30 20:55:25 +03:00
Import(ImportSection),
2017-04-04 03:03:57 +03:00
/// Function signatures section
Function(FunctionSection),
2017-04-04 03:03:57 +03:00
/// Table definition section
2017-03-30 23:57:36 +03:00
Table(TableSection),
2017-04-04 03:03:57 +03:00
/// Memory definition section
2017-03-30 23:57:36 +03:00
Memory(MemorySection),
2017-04-04 03:03:57 +03:00
/// Global entries section
2017-03-31 17:31:33 +03:00
Global(GlobalSection),
2017-04-04 03:03:57 +03:00
/// Export definitions
2017-03-31 01:54:04 +03:00
Export(ExportSection),
2017-04-04 03:03:57 +03:00
/// Entry reference of the module
2017-03-31 03:28:03 +03:00
Start(u32),
2017-04-04 03:03:57 +03:00
/// Elements section
2017-04-03 13:42:04 +03:00
Element(ElementSection),
2017-04-04 03:03:57 +03:00
/// Function bodies section
2017-03-31 04:04:51 +03:00
Code(CodeSection),
2017-04-04 03:03:57 +03:00
/// Data definition section
2017-04-03 13:42:04 +03:00
Data(DataSection),
2018-01-18 19:26:30 +03:00
/// Name section
Name(NameSection),
2017-03-29 18:16:58 +03:00
}
impl Deserialize for Section {
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
2017-03-29 19:40:51 +03:00
let id = match VarUint7::deserialize(reader) {
// todo: be more selective detecting no more section
Err(_) => { return Err(Error::UnexpectedEof); },
Ok(id) => id,
};
2017-03-29 23:13:54 +03:00
Ok(
match id.into() {
0 => {
2017-06-19 21:14:41 +03:00
Section::Custom(CustomSection::deserialize(reader)?.into())
2017-03-29 23:13:54 +03:00
},
1 => {
Section::Type(TypeSection::deserialize(reader)?)
},
2017-03-30 20:55:25 +03:00
2 => {
Section::Import(ImportSection::deserialize(reader)?)
},
2017-03-30 23:23:54 +03:00
3 => {
Section::Function(FunctionSection::deserialize(reader)?)
2017-03-30 23:23:54 +03:00
},
2017-03-30 23:57:36 +03:00
4 => {
Section::Table(TableSection::deserialize(reader)?)
},
5 => {
Section::Memory(MemorySection::deserialize(reader)?)
2017-03-31 01:54:04 +03:00
},
2017-03-31 17:31:33 +03:00
6 => {
Section::Global(GlobalSection::deserialize(reader)?)
},
2017-03-31 01:54:04 +03:00
7 => {
Section::Export(ExportSection::deserialize(reader)?)
},
2017-03-31 03:28:03 +03:00
8 => {
let _section_length = VarUint32::deserialize(reader)?;
Section::Start(VarUint32::deserialize(reader)?.into())
},
2017-04-03 13:42:04 +03:00
9 => {
Section::Element(ElementSection::deserialize(reader)?)
},
2017-03-31 04:04:51 +03:00
10 => {
Section::Code(CodeSection::deserialize(reader)?)
},
2017-04-03 13:42:04 +03:00
11 => {
Section::Data(DataSection::deserialize(reader)?)
},
2017-03-29 23:13:54 +03:00
_ => {
Section::Unparsed { id: id.into(), payload: Unparsed::deserialize(reader)?.into() }
}
}
)
2017-10-24 16:11:03 +03:00
}
2017-03-29 23:13:54 +03:00
}
2017-04-03 22:58:00 +03:00
impl Serialize for Section {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
match self {
Section::Custom(custom_section) => {
VarUint7::from(0x00).serialize(writer)?;
2017-06-19 21:14:41 +03:00
custom_section.serialize(writer)?;
2017-04-03 22:58:00 +03:00
},
Section::Unparsed { id, payload } => {
VarUint7::from(id).serialize(writer)?;
writer.write_all(&payload[..])?;
},
Section::Type(type_section) => {
VarUint7::from(0x01).serialize(writer)?;
type_section.serialize(writer)?;
},
2017-04-03 23:08:13 +03:00
Section::Import(import_section) => {
VarUint7::from(0x02).serialize(writer)?;
import_section.serialize(writer)?;
},
Section::Function(function_section) => {
VarUint7::from(0x03).serialize(writer)?;
function_section.serialize(writer)?;
},
Section::Table(table_section) => {
VarUint7::from(0x04).serialize(writer)?;
table_section.serialize(writer)?;
},
Section::Memory(memory_section) => {
VarUint7::from(0x05).serialize(writer)?;
memory_section.serialize(writer)?;
},
Section::Global(global_section) => {
VarUint7::from(0x06).serialize(writer)?;
global_section.serialize(writer)?;
},
Section::Export(export_section) => {
VarUint7::from(0x07).serialize(writer)?;
export_section.serialize(writer)?;
},
Section::Start(index) => {
VarUint7::from(0x08).serialize(writer)?;
let mut counted_writer = CountedWriter::new(writer);
VarUint32::from(index).serialize(&mut counted_writer)?;
counted_writer.done()?;
2017-04-03 23:08:13 +03:00
},
Section::Element(element_section) => {
VarUint7::from(0x09).serialize(writer)?;
element_section.serialize(writer)?;
},
Section::Code(code_section) => {
VarUint7::from(0x0a).serialize(writer)?;
code_section.serialize(writer)?;
},
Section::Data(data_section) => {
VarUint7::from(0x0b).serialize(writer)?;
data_section.serialize(writer)?;
},
2018-01-18 19:26:30 +03:00
Section::Name(name_section) => {
VarUint7::from(0x00).serialize(writer)?;
let custom = CustomSection {
name: "name".to_owned(),
payload: serialize(name_section)?,
};
custom.serialize(writer)?;
}
2017-04-03 22:58:00 +03:00
}
Ok(())
}
}
2017-06-19 21:18:16 +03:00
/// Custom section
#[derive(Debug, Clone)]
2017-06-19 21:14:41 +03:00
pub struct CustomSection {
name: String,
payload: Vec<u8>,
}
2017-06-19 21:18:16 +03:00
impl CustomSection {
/// Name of the custom section
pub fn name(&self) -> &str {
&self.name
}
/// Payload of the custom secion
pub fn payload(&self) -> &[u8] {
&self.payload
}
/// Name of the custom section (mutable)
pub fn name_mut(&mut self) -> &mut String {
&mut self.name
}
/// Payload of the custom section (mutable)
pub fn payload_mut(&mut self) -> &mut Vec<u8> {
&mut self.payload
}
}
2017-06-19 21:14:41 +03:00
impl Deserialize for CustomSection {
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: u32 = VarUint32::deserialize(reader)?.into();
let name = String::deserialize(reader)?;
let payload_left = section_length - (name.len() as u32 + name.len() as u32 / 128 + 1);
let mut payload = vec![0u8; payload_left as usize];
reader.read_exact(&mut payload[..])?;
2017-10-24 16:11:03 +03:00
2017-06-19 21:14:41 +03:00
Ok(CustomSection { name: name, payload: payload })
2017-10-24 16:11:03 +03:00
}
2017-06-19 21:14:41 +03:00
}
impl Serialize for CustomSection {
type Error = Error;
2017-10-24 16:11:03 +03:00
2017-06-19 21:14:41 +03:00
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
use std::io::Write;
let mut counted_writer = CountedWriter::new(writer);
self.name.serialize(&mut counted_writer)?;
counted_writer.write_all(&self.payload[..])?;
counted_writer.done()?;
Ok(())
2017-10-24 16:11:03 +03:00
}
2017-06-19 21:14:41 +03:00
}
2017-04-06 16:00:12 +03:00
/// Section with type declarations
#[derive(Debug, Default, Clone)]
2017-03-30 20:55:25 +03:00
pub struct TypeSection(Vec<Type>);
2017-03-29 23:13:54 +03:00
impl TypeSection {
2017-06-03 18:20:20 +03:00
/// New type section with provided types
pub fn with_types(types: Vec<Type>) -> Self {
TypeSection(types)
}
2017-04-06 16:00:12 +03:00
/// List of type declarations
2017-03-30 20:55:25 +03:00
pub fn types(&self) -> &[Type] {
&self.0
2017-03-29 23:13:54 +03:00
}
2017-04-06 16:00:12 +03:00
/// List of type declarations (mutable)
2017-10-24 16:11:03 +03:00
pub fn types_mut(&mut self) -> &mut Vec<Type> {
2017-04-06 16:00:12 +03:00
&mut self.0
}
2017-03-29 23:13:54 +03:00
}
impl Deserialize for TypeSection {
2017-03-30 20:55:25 +03:00
type Error = Error;
2017-03-29 23:13:54 +03:00
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();
2017-03-30 20:55:25 +03:00
Ok(TypeSection(types))
2017-10-24 16:11:03 +03:00
}
2017-03-30 20:55:25 +03:00
}
2017-04-03 22:58:00 +03:00
impl Serialize for TypeSection {
type Error = Error;
2017-10-24 16:11:03 +03:00
2017-04-03 22:58:00 +03:00
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut counted_writer = CountedWriter::new(writer);
let data = self.0;
let counted_list = CountedListWriter::<Type, _>(
data.len(),
data.into_iter().map(Into::into),
);
counted_list.serialize(&mut counted_writer)?;
counted_writer.done()?;
Ok(())
2017-10-24 16:11:03 +03:00
}
2017-04-03 22:58:00 +03:00
}
2017-04-04 03:03:57 +03:00
/// Section of the imports definition.
2017-10-24 16:11:03 +03:00
#[derive(Debug, Default, Clone)]
2017-03-30 20:55:25 +03:00
pub struct ImportSection(Vec<ImportEntry>);
impl ImportSection {
2017-06-03 18:20:20 +03:00
/// New import section with provided types
pub fn with_entries(entries: Vec<ImportEntry>) -> Self {
ImportSection(entries)
}
2017-04-06 16:00:12 +03:00
/// List of import entries.
2017-03-30 20:55:25 +03:00
pub fn entries(&self) -> &[ImportEntry] {
&self.0
}
2017-04-10 13:11:34 +03:00
/// List of import entries (mutable).
pub fn entries_mut(&mut self) -> &mut Vec<ImportEntry> {
&mut self.0
2017-10-24 16:11:03 +03:00
}
2017-11-21 20:03:06 +03:00
/// Returns number of functions
pub fn functions(&self) -> usize {
self.0.iter()
.filter(|entry| match entry.external() { &External::Function(_) => true, _ => false })
.count()
}
/// Returns number of globals
pub fn globals(&self) -> usize {
self.0.iter()
.filter(|entry| match entry.external() { &External::Global(_) => true, _ => false })
.count()
}
2017-03-30 20:55:25 +03:00
}
impl Deserialize for ImportSection {
2017-04-03 18:23:10 +03:00
type Error = Error;
2017-03-30 20:55:25 +03:00
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<ImportEntry> = CountedList::deserialize(reader)?.into_inner();
Ok(ImportSection(entries))
2017-10-24 16:11:03 +03:00
}
2017-03-29 23:13:54 +03:00
}
2017-04-03 22:58:00 +03:00
impl Serialize for ImportSection {
type Error = Error;
2017-10-24 16:11:03 +03:00
2017-04-03 22:58:00 +03:00
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut counted_writer = CountedWriter::new(writer);
let data = self.0;
let counted_list = CountedListWriter::<ImportEntry, _>(
data.len(),
data.into_iter().map(Into::into),
);
counted_list.serialize(&mut counted_writer)?;
counted_writer.done()?;
Ok(())
2017-10-24 16:11:03 +03:00
}
2017-04-03 22:58:00 +03:00
}
2017-04-04 03:03:57 +03:00
/// Section with function signatures definition.
#[derive(Default, Debug, Clone)]
pub struct FunctionSection(Vec<Func>);
2017-03-30 23:23:54 +03:00
impl FunctionSection {
2017-06-03 18:20:20 +03:00
/// New function signatures section with provided entries
pub fn with_entries(entries: Vec<Func>) -> Self {
FunctionSection(entries)
2017-04-06 11:34:31 +03:00
}
2017-04-06 16:00:12 +03:00
/// List of all functions in the section, mutable
2017-10-24 16:11:03 +03:00
pub fn entries_mut(&mut self) -> &mut Vec<Func> {
2017-04-06 11:34:31 +03:00
&mut self.0
}
2017-04-06 16:00:12 +03:00
/// List of all functions in the section
2017-04-03 13:58:49 +03:00
pub fn entries(&self) -> &[Func] {
2017-03-30 23:23:54 +03:00
&self.0
}
}
impl Deserialize for FunctionSection {
2017-04-03 18:23:10 +03:00
type Error = Error;
2017-03-30 23:23:54 +03:00
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)?;
2017-04-03 13:58:49 +03:00
let funcs: Vec<Func> = CountedList::<VarUint32>::deserialize(reader)?
2017-03-30 23:23:54 +03:00
.into_inner()
.into_iter()
2017-04-03 13:58:49 +03:00
.map(|f| Func::new(f.into()))
2017-03-30 23:23:54 +03:00
.collect();
Ok(FunctionSection(funcs))
2017-04-03 13:58:49 +03:00
}
2017-03-30 23:23:54 +03:00
}
impl Serialize for FunctionSection {
2017-04-03 22:58:00 +03:00
type Error = Error;
2017-10-24 16:11:03 +03:00
2017-04-03 22:58:00 +03:00
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut counted_writer = CountedWriter::new(writer);
let data = self.0;
let counted_list = CountedListWriter::<VarUint32, _>(
data.len(),
data.into_iter().map(|func| func.type_ref().into())
);
counted_list.serialize(&mut counted_writer)?;
counted_writer.done()?;
Ok(())
2017-10-24 16:11:03 +03:00
}
2017-04-03 22:58:00 +03:00
}
2017-04-04 03:03:57 +03:00
/// Section with table definition (currently only one is allowed).
#[derive(Default, Debug, Clone)]
2017-03-30 23:57:36 +03:00
pub struct TableSection(Vec<TableType>);
impl TableSection {
2017-04-12 19:07:10 +03:00
/// Table entries.
2017-03-30 23:57:36 +03:00
pub fn entries(&self) -> &[TableType] {
&self.0
}
2017-05-02 08:01:57 +03:00
2017-06-03 18:20:20 +03:00
/// New table section with provided table entries
pub fn with_entries(entries: Vec<TableType>) -> Self {
TableSection(entries)
2017-10-24 16:11:03 +03:00
}
2017-06-03 18:20:20 +03:00
2017-05-02 08:01:57 +03:00
/// Mutable table entries.
pub fn entries_mut(&mut self) -> &mut Vec<TableType> {
&mut self.0
}
2017-03-30 23:57:36 +03:00
}
impl Deserialize for TableSection {
2017-04-03 18:23:10 +03:00
type Error = Error;
2017-03-30 23:57:36 +03:00
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<TableType> = CountedList::deserialize(reader)?.into_inner();
Ok(TableSection(entries))
2017-10-24 16:11:03 +03:00
}
2017-03-30 23:57:36 +03:00
}
2017-04-03 22:34:12 +03:00
impl Serialize for TableSection {
type Error = Error;
2017-10-24 16:11:03 +03:00
2017-04-03 22:34:12 +03:00
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut counted_writer = CountedWriter::new(writer);
let data = self.0;
let counted_list = CountedListWriter::<TableType, _>(
data.len(),
data.into_iter().map(Into::into),
);
counted_list.serialize(&mut counted_writer)?;
counted_writer.done()?;
Ok(())
2017-10-24 16:11:03 +03:00
}
2017-04-03 22:34:12 +03:00
}
2017-04-04 03:03:57 +03:00
/// Section with table definition (currently only one entry is allowed).
#[derive(Default, Debug, Clone)]
2017-03-30 23:57:36 +03:00
pub struct MemorySection(Vec<MemoryType>);
impl MemorySection {
2017-04-06 16:00:12 +03:00
/// List of all memory entries in the section
2017-03-30 23:57:36 +03:00
pub fn entries(&self) -> &[MemoryType] {
&self.0
}
2017-04-28 13:34:58 +03:00
2017-06-03 18:20:20 +03:00
/// New memory section with memory types
pub fn with_entries(entries: Vec<MemoryType>) -> Self {
MemorySection(entries)
2017-10-24 16:11:03 +03:00
}
2017-06-03 18:20:20 +03:00
2017-04-28 13:34:58 +03:00
/// Mutable list of all memory entries in the section
pub fn entries_mut(&mut self) -> &mut Vec<MemoryType> {
&mut self.0
}
2017-03-30 23:57:36 +03:00
}
impl Deserialize for MemorySection {
2017-04-03 18:23:10 +03:00
type Error = Error;
2017-03-30 23:57:36 +03:00
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<MemoryType> = CountedList::deserialize(reader)?.into_inner();
Ok(MemorySection(entries))
2017-10-24 16:11:03 +03:00
}
2017-03-30 23:57:36 +03:00
}
2017-03-30 23:23:54 +03:00
2017-04-03 22:34:12 +03:00
impl Serialize for MemorySection {
type Error = Error;
2017-10-24 16:11:03 +03:00
2017-04-03 22:34:12 +03:00
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut counted_writer = CountedWriter::new(writer);
let data = self.0;
let counted_list = CountedListWriter::<MemoryType, _>(
data.len(),
data.into_iter().map(Into::into),
);
counted_list.serialize(&mut counted_writer)?;
counted_writer.done()?;
Ok(())
2017-10-24 16:11:03 +03:00
}
2017-04-03 22:34:12 +03:00
}
2017-04-04 03:03:57 +03:00
/// Globals definition section.
#[derive(Default, Debug, Clone)]
2017-03-31 17:31:33 +03:00
pub struct GlobalSection(Vec<GlobalEntry>);
impl GlobalSection {
2017-04-06 16:00:12 +03:00
/// List of all global entries in the section
2017-03-31 17:31:33 +03:00
pub fn entries(&self) -> &[GlobalEntry] {
&self.0
}
2017-05-03 11:06:26 +03:00
2017-06-03 18:20:20 +03:00
/// New global section from list of global entries
pub fn with_entries(entries: Vec<GlobalEntry>) -> Self {
GlobalSection(entries)
}
2017-04-26 15:46:30 +03:00
/// List of all global entries in the section (mutable)
2017-05-03 11:06:26 +03:00
pub fn entries_mut(&mut self) -> &mut Vec<GlobalEntry> {
&mut self.0
}
2017-03-31 17:31:33 +03:00
}
impl Deserialize for GlobalSection {
2017-04-03 18:23:10 +03:00
type Error = Error;
2017-03-31 17:31:33 +03:00
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<GlobalEntry> = CountedList::deserialize(reader)?.into_inner();
Ok(GlobalSection(entries))
2017-10-24 16:11:03 +03:00
}
2017-03-31 17:31:33 +03:00
}
2017-04-03 22:29:44 +03:00
impl Serialize for GlobalSection {
type Error = Error;
2017-10-24 16:11:03 +03:00
2017-04-03 22:29:44 +03:00
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut counted_writer = CountedWriter::new(writer);
let data = self.0;
let counted_list = CountedListWriter::<GlobalEntry, _>(
data.len(),
data.into_iter().map(Into::into),
);
counted_list.serialize(&mut counted_writer)?;
counted_writer.done()?;
Ok(())
2017-10-24 16:11:03 +03:00
}
2017-04-03 22:29:44 +03:00
}
2017-04-04 03:03:57 +03:00
/// List of exports definition.
2017-10-24 16:11:03 +03:00
#[derive(Debug, Default, Clone)]
2017-03-31 01:54:04 +03:00
pub struct ExportSection(Vec<ExportEntry>);
impl ExportSection {
2017-04-06 16:00:12 +03:00
/// List of all export entries in the section
2017-03-31 01:54:04 +03:00
pub fn entries(&self) -> &[ExportEntry] {
&self.0
}
2017-04-20 17:35:53 +03:00
2017-06-03 18:20:20 +03:00
/// New export section from list of export entries
pub fn with_entries(entries: Vec<ExportEntry>) -> Self {
ExportSection(entries)
}
2017-04-20 17:35:53 +03:00
/// List of all export entries in the section (mutable)
pub fn entries_mut(&mut self) -> &mut Vec<ExportEntry> {
&mut self.0
2017-10-24 16:11:03 +03:00
}
2017-03-31 01:54:04 +03:00
}
impl Deserialize for ExportSection {
2017-04-03 18:23:10 +03:00
type Error = Error;
2017-03-31 01:54:04 +03:00
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<ExportEntry> = CountedList::deserialize(reader)?.into_inner();
Ok(ExportSection(entries))
2017-10-24 16:11:03 +03:00
}
2017-03-31 01:54:04 +03:00
}
2017-04-03 22:29:44 +03:00
impl Serialize for ExportSection {
type Error = Error;
2017-10-24 16:11:03 +03:00
2017-04-03 22:29:44 +03:00
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut counted_writer = CountedWriter::new(writer);
let data = self.0;
let counted_list = CountedListWriter::<ExportEntry, _>(
data.len(),
data.into_iter().map(Into::into),
);
counted_list.serialize(&mut counted_writer)?;
counted_writer.done()?;
Ok(())
2017-10-24 16:11:03 +03:00
}
2017-04-03 22:29:44 +03:00
}
2017-04-04 03:03:57 +03:00
/// Section with function bodies of the module.
#[derive(Default, Debug, Clone)]
2017-04-03 13:18:50 +03:00
pub struct CodeSection(Vec<FuncBody>);
2017-03-31 04:04:51 +03:00
impl CodeSection {
2017-06-03 18:20:20 +03:00
/// New code section with specified function bodies
pub fn with_bodies(bodies: Vec<FuncBody>) -> Self {
2017-04-03 20:19:20 +03:00
CodeSection(bodies)
}
2017-04-07 20:00:30 +03:00
/// All function bodies in the section.
2017-04-03 13:18:50 +03:00
pub fn bodies(&self) -> &[FuncBody] {
2017-03-31 04:04:51 +03:00
&self.0
}
2017-04-07 20:00:30 +03:00
/// All function bodies in the section, mutable.
pub fn bodies_mut(&mut self) -> &mut Vec<FuncBody> {
&mut self.0
}
2017-03-31 04:04:51 +03:00
}
impl Deserialize for CodeSection {
2017-04-03 18:23:10 +03:00
type Error = Error;
2017-03-31 04:04:51 +03:00
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)?;
2017-04-03 13:18:50 +03:00
let entries: Vec<FuncBody> = CountedList::deserialize(reader)?.into_inner();
2017-03-31 04:04:51 +03:00
Ok(CodeSection(entries))
2017-10-24 16:11:03 +03:00
}
2017-03-31 04:04:51 +03:00
}
2017-04-03 19:51:18 +03:00
impl Serialize for CodeSection {
type Error = Error;
2017-10-24 16:11:03 +03:00
2017-04-03 19:51:18 +03:00
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut counted_writer = CountedWriter::new(writer);
let data = self.0;
let counted_list = CountedListWriter::<FuncBody, _>(
data.len(),
data.into_iter().map(Into::into),
);
counted_list.serialize(&mut counted_writer)?;
counted_writer.done()?;
Ok(())
}
}
2017-04-04 03:03:57 +03:00
/// Element entries section.
#[derive(Default, Debug, Clone)]
2017-04-03 13:42:04 +03:00
pub struct ElementSection(Vec<ElementSegment>);
impl ElementSection {
2017-04-06 16:00:12 +03:00
/// New elements section
2017-06-03 18:20:20 +03:00
pub fn with_entries(entries: Vec<ElementSegment>) -> Self {
2017-04-03 18:40:49 +03:00
ElementSection(entries)
}
2017-04-06 16:00:12 +03:00
/// New elements entries in the section
2017-04-03 13:42:04 +03:00
pub fn entries(&self) -> &[ElementSegment] {
&self.0
}
2017-05-02 08:01:57 +03:00
/// List of all data entries in the section (mutable)
2017-05-02 08:01:57 +03:00
pub fn entries_mut(&mut self) -> &mut Vec<ElementSegment> {
&mut self.0
2017-10-24 16:11:03 +03:00
}
2017-04-03 13:42:04 +03:00
}
impl Deserialize for ElementSection {
2017-04-03 18:23:10 +03:00
type Error = Error;
2017-04-03 13:42:04 +03:00
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<ElementSegment> = CountedList::deserialize(reader)?.into_inner();
Ok(ElementSection(entries))
2017-10-24 16:11:03 +03:00
}
2017-04-03 13:42:04 +03:00
}
2017-04-03 18:40:49 +03:00
impl Serialize for ElementSection {
type Error = Error;
2017-10-24 16:11:03 +03:00
2017-04-03 18:40:49 +03:00
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut counted_writer = CountedWriter::new(writer);
let data = self.0;
let counted_list = CountedListWriter::<ElementSegment, _>(
data.len(),
data.into_iter().map(Into::into),
);
counted_list.serialize(&mut counted_writer)?;
counted_writer.done()?;
Ok(())
}
}
2017-04-04 03:03:57 +03:00
/// Data entries definitions.
#[derive(Default, Debug, Clone)]
2017-04-03 13:42:04 +03:00
pub struct DataSection(Vec<DataSegment>);
impl DataSection {
2017-04-06 16:00:12 +03:00
/// New data section
2017-06-03 18:20:20 +03:00
pub fn with_entries(entries: Vec<DataSegment>) -> Self {
DataSection(entries)
2017-04-03 18:15:13 +03:00
}
2017-04-06 16:00:12 +03:00
/// List of all data entries in the section
2017-04-03 13:42:04 +03:00
pub fn entries(&self) -> &[DataSegment] {
&self.0
}
2017-05-02 19:10:23 +03:00
/// List of all data entries in the section (mutable)
2017-05-02 19:10:23 +03:00
pub fn entries_mut(&mut self) -> &mut Vec<DataSegment> {
&mut self.0
}
2017-04-03 13:42:04 +03:00
}
impl Deserialize for DataSection {
2017-04-03 15:03:18 +03:00
type Error = Error;
2017-04-03 13:42:04 +03:00
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<DataSegment> = CountedList::deserialize(reader)?.into_inner();
Ok(DataSection(entries))
2017-10-24 16:11:03 +03:00
}
2017-04-03 13:42:04 +03:00
}
2017-04-03 15:03:18 +03:00
impl Serialize for DataSection {
type Error = Error;
2017-10-24 16:11:03 +03:00
2017-04-03 15:03:18 +03:00
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
2017-04-03 18:15:13 +03:00
let mut counted_writer = CountedWriter::new(writer);
2017-04-03 15:56:37 +03:00
let data = self.0;
let counted_list = CountedListWriter::<DataSegment, _>(
data.len(),
data.into_iter().map(Into::into),
);
2017-04-03 18:15:13 +03:00
counted_list.serialize(&mut counted_writer)?;
counted_writer.done()?;
2017-04-03 15:03:18 +03:00
Ok(())
}
}
2017-03-29 23:13:54 +03:00
#[cfg(test)]
mod tests {
2017-04-03 18:15:13 +03:00
use super::super::{
deserialize_buffer, deserialize_file, ValueType, InitExpr, DataSegment,
2017-04-03 20:19:20 +03:00
serialize, ElementSegment, Opcodes, BlockType, Local, FuncBody,
2017-04-03 18:15:13 +03:00
};
2017-04-03 20:19:20 +03:00
use super::{Section, TypeSection, Type, DataSection, ElementSection, CodeSection};
2017-03-30 20:55:25 +03:00
#[test]
fn import_section() {
let module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
let mut found = false;
for section in module.sections() {
match section {
2017-10-24 16:11:03 +03:00
&Section::Import(ref import_section) => {
2017-03-30 20:55:25 +03:00
assert_eq!(25, import_section.entries().len());
found = true
},
_ => { }
}
}
assert!(found, "There should be import section in test5.wasm");
}
2017-03-29 23:13:54 +03:00
2017-12-27 12:28:42 +03:00
fn functions_test_payload() -> &'static [u8] {
&[
2017-03-30 23:49:26 +03:00
// functions section id
2017-10-24 16:11:03 +03:00
0x03u8,
2017-03-30 23:49:26 +03:00
// functions section length
0x87, 0x80, 0x80, 0x80, 0x0,
// number of functions
2017-10-24 16:11:03 +03:00
0x04,
2017-03-30 23:49:26 +03:00
// type reference 1
0x01,
// type reference 2
0x86, 0x80, 0x00,
// type reference 3
2017-10-24 16:11:03 +03:00
0x09,
2017-03-30 23:49:26 +03:00
// type reference 4
0x33
]
}
2017-03-29 23:13:54 +03:00
#[test]
2017-03-30 23:49:26 +03:00
fn fn_section_detect() {
2017-10-24 16:11:03 +03:00
let section: Section =
2017-03-30 23:49:26 +03:00
deserialize_buffer(functions_test_payload()).expect("section to be deserialized");
match section {
Section::Function(_) => {},
_ => {
panic!("Payload should be recognized as functions section")
}
}
}
#[test]
fn fn_section_number() {
2017-10-24 16:11:03 +03:00
let section: Section =
2017-03-30 23:49:26 +03:00
deserialize_buffer(functions_test_payload()).expect("section to be deserialized");
match section {
Section::Function(fn_section) => {
assert_eq!(4, fn_section.entries().len(), "There should be 4 functions total");
},
_ => {
// will be catched by dedicated test
}
2017-10-24 16:11:03 +03:00
}
2017-03-30 23:49:26 +03:00
}
#[test]
fn fn_section_ref() {
2017-10-24 16:11:03 +03:00
let section: Section =
2017-03-30 23:49:26 +03:00
deserialize_buffer(functions_test_payload()).expect("section to be deserialized");
match section {
Section::Function(fn_section) => {
assert_eq!(6, fn_section.entries()[1].type_ref());
},
_ => {
// will be catched by dedicated test
}
2017-10-24 16:11:03 +03:00
}
2017-03-30 23:49:26 +03:00
}
2017-12-27 12:28:42 +03:00
fn types_test_payload() -> &'static [u8] {
&[
2017-03-30 23:49:26 +03:00
// section length
148u8, 0x80, 0x80, 0x80, 0x0,
2017-10-24 16:11:03 +03:00
2017-03-30 23:49:26 +03:00
// 2 functions
130u8, 0x80, 0x80, 0x80, 0x0,
// func 1, form =1
2017-10-24 16:11:03 +03:00
0x01,
2017-03-29 23:13:54 +03:00
// param_count=1
129u8, 0x80, 0x80, 0x80, 0x0,
// first param
0x7e, // i64
// no return params
2017-03-30 23:49:26 +03:00
0x00,
// func 2, form=1
2017-10-24 16:11:03 +03:00
0x01,
2017-03-30 23:49:26 +03:00
// param_count=1
130u8, 0x80, 0x80, 0x80, 0x0,
// first param
2017-10-24 16:11:03 +03:00
0x7e,
2017-03-30 23:49:26 +03:00
// second param
2017-10-24 16:11:03 +03:00
0x7d,
2017-03-30 23:49:26 +03:00
// return param (is_present, param_type)
0x01, 0x7e
]
2017-10-24 16:11:03 +03:00
}
2017-03-30 23:49:26 +03:00
#[test]
fn type_section_len() {
2017-10-24 16:11:03 +03:00
let type_section: TypeSection =
2017-03-30 23:49:26 +03:00
deserialize_buffer(types_test_payload()).expect("type_section be deserialized");
assert_eq!(type_section.types().len(), 2);
}
2017-03-29 23:13:54 +03:00
2017-03-30 23:49:26 +03:00
#[test]
fn type_section_infer() {
2017-10-24 16:11:03 +03:00
let type_section: TypeSection =
2017-03-30 23:49:26 +03:00
deserialize_buffer(types_test_payload()).expect("type_section be deserialized");
2017-03-29 23:13:54 +03:00
2017-03-30 23:49:26 +03:00
let t1 = match &type_section.types()[1] {
2017-03-30 23:57:36 +03:00
&Type::Function(ref func_type) => func_type
2017-03-30 23:49:26 +03:00
};
assert_eq!(Some(ValueType::I64), t1.return_type());
assert_eq!(2, t1.params().len());
2017-03-29 23:13:54 +03:00
}
2017-12-27 12:28:42 +03:00
fn export_payload() -> &'static [u8] {
&[
2017-03-31 01:54:04 +03:00
// section id
0x07,
// section length
148u8, 0x80, 0x80, 0x80, 0x0,
// 6 entries
134u8, 0x80, 0x80, 0x80, 0x0,
2017-10-24 16:11:03 +03:00
// func "A", index 6
2017-03-31 01:54:04 +03:00
// [name_len(1-5 bytes), name_bytes(name_len, internal_kind(1byte), internal_index(1-5 bytes)])
2017-03-31 04:39:31 +03:00
0x01, 0x41, 0x01, 0x86, 0x80, 0x00,
2017-03-31 01:54:04 +03:00
// func "B", index 8
2017-03-31 04:39:31 +03:00
0x01, 0x42, 0x01, 0x86, 0x00,
2017-03-31 01:54:04 +03:00
// func "C", index 7
2017-03-31 04:39:31 +03:00
0x01, 0x43, 0x01, 0x07,
2017-03-31 01:54:04 +03:00
// memory "D", index 0
2017-03-31 04:39:31 +03:00
0x01, 0x44, 0x02, 0x00,
2017-03-31 01:54:04 +03:00
// func "E", index 1
2017-03-31 04:39:31 +03:00
0x01, 0x45, 0x01, 0x01,
2017-03-31 01:54:04 +03:00
// func "F", index 2
2017-03-31 04:39:31 +03:00
0x01, 0x46, 0x01, 0x02
2017-03-31 01:54:04 +03:00
]
}
2017-10-24 16:11:03 +03:00
2017-03-31 01:54:04 +03:00
#[test]
fn export_detect() {
2017-10-24 16:11:03 +03:00
let section: Section =
2017-03-31 01:54:04 +03:00
deserialize_buffer(export_payload()).expect("section to be deserialized");
match section {
Section::Export(_) => {},
_ => {
panic!("Payload should be recognized as export section")
}
}
}
2017-03-31 04:04:51 +03:00
2017-12-27 12:28:42 +03:00
fn code_payload() -> &'static [u8] {
&[
2017-03-31 04:04:51 +03:00
// sectionid
0x0Au8,
// section length, 32
0x20,
// body count
2017-10-24 16:11:03 +03:00
0x01,
2017-03-31 04:04:51 +03:00
// body 1, length 30
2017-10-24 16:11:03 +03:00
0x1E,
2017-03-31 04:04:51 +03:00
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() {
2017-10-24 16:11:03 +03:00
let section: Section =
2017-03-31 04:04:51 +03:00
deserialize_buffer(code_payload()).expect("section to be deserialized");
match section {
Section::Code(_) => {},
_ => {
panic!("Payload should be recognized as a code section")
}
}
}
2017-04-03 18:15:13 +03:00
2017-12-27 12:28:42 +03:00
fn data_payload() -> &'static [u8] {
&[
2017-10-24 16:11:03 +03:00
0x0bu8, // section id
2017-04-03 18:15:13 +03:00
19, // 19 bytes overall
0x01, // number of segments
0x00, // index
0x0b, // just `end` op
// 16x 0x00
2017-10-24 16:11:03 +03:00
0x00, 0x00, 0x00, 0x00,
2017-04-03 18:15:13 +03:00
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
]
}
#[test]
fn data_section_ser() {
2017-06-03 18:20:20 +03:00
let data_section = DataSection::with_entries(
2017-04-03 18:15:13 +03:00
vec![DataSegment::new(0u32, InitExpr::empty(), vec![0u8; 16])]
);
let buf = serialize(data_section).expect("Data section to be serialized");
assert_eq!(buf, vec![
2017-04-03 18:40:49 +03:00
20u8, // 19 bytes overall
2017-04-03 18:15:13 +03:00
0x01, // number of segments
0x00, // index
0x0b, // just `end` op
2017-04-03 18:40:49 +03:00
16, // value of length 16
2017-04-03 18:15:13 +03:00
0x00, 0x00, 0x00, 0x00, // 16x 0x00 as in initialization
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
]);
}
#[test]
fn data_section_detect() {
2017-10-24 16:11:03 +03:00
let section: Section =
2017-04-03 18:15:13 +03:00
deserialize_buffer(data_payload()).expect("section to be deserialized");
match section {
Section::Data(_) => {},
_ => {
panic!("Payload should be recognized as a data section")
}
}
}
2017-04-03 18:40:49 +03:00
#[test]
fn element_section_ser() {
2017-06-03 18:20:20 +03:00
let element_section = ElementSection::with_entries(
2017-04-03 18:40:49 +03:00
vec![ElementSegment::new(0u32, InitExpr::empty(), vec![0u32; 4])]
);
2017-04-03 20:19:20 +03:00
let buf = serialize(element_section).expect("Element section to be serialized");
2017-04-03 18:40:49 +03:00
assert_eq!(buf, vec![
08u8, // 8 bytes overall
0x01, // number of segments
0x00, // index
0x0b, // just `end` op
0x04, // 4 elements
0x00, 0x00, 0x00, 0x00 // 4x 0x00 as in initialization
]);
2017-10-24 16:11:03 +03:00
}
2017-04-03 20:19:20 +03:00
#[test]
fn code_section_ser() {
use super::super::Opcode::*;
2017-06-03 18:20:20 +03:00
let code_section = CodeSection::with_bodies(
2017-04-03 20:19:20 +03:00
vec![
FuncBody::new(
vec![Local::new(1, ValueType::I32)],
Opcodes::new(vec![
2017-06-22 17:52:05 +03:00
Block(BlockType::Value(ValueType::I32)),
GetGlobal(0),
End,
2017-04-03 20:19:20 +03:00
End,
])
)
]);
let buf = serialize(code_section).expect("Code section to be serialized");
assert_eq!(buf, vec![
11u8, // 11 bytes total section size
0x01, // 1 function
9, // function #1 total code size
1, // 1 local variable declaration
1, // amount of variables
2017-04-10 13:11:34 +03:00
0x7f, // type of variable (7-bit, -0x01), negative
2017-04-03 20:19:20 +03:00
0x02, // block
2017-04-10 13:11:34 +03:00
0x7f, // block return type (7-bit, -0x01), negative
2017-04-03 20:19:20 +03:00
0x23, 0x00, // get_global(0)
0x0b, // block end
0x0b, // function end
]);
}
2017-06-02 19:57:25 +03:00
#[test]
fn start_section() {
2017-12-27 12:28:42 +03:00
let section: Section = deserialize_buffer(&[08u8, 01u8, 00u8]).expect("Start section to deserialize");
2017-06-02 19:57:25 +03:00
if let Section::Start(_) = section {
} else {
panic!("Payload should be a start section");
}
let serialized = serialize(section).expect("Start section to successfully serializen");
assert_eq!(serialized, vec![08u8, 01u8, 00u8]);
}
2017-10-24 16:11:03 +03:00
}