310 lines
10 KiB
Rust
Raw Normal View History

2017-03-29 18:16:58 +03:00
use std::io;
2017-06-06 14:19:36 +03:00
use byteorder::{LittleEndian, ByteOrder};
2017-04-03 23:08:13 +03:00
use super::{Deserialize, Serialize, Error, Uint32};
use super::section::{
Section, CodeSection, TypeSection, ImportSection, ExportSection, FunctionSection,
2017-05-10 13:09:37 +03:00
GlobalSection, TableSection, ElementSection, DataSection, MemorySection
};
2017-03-29 18:16:58 +03:00
2017-06-06 14:19:36 +03:00
const WASM_MAGIC_NUMBER: [u8; 4] = [0x00, 0x61, 0x73, 0x6d];
2017-04-04 03:03:57 +03:00
/// WebAssembly module
2017-03-29 18:16:58 +03:00
pub struct Module {
2017-04-03 23:08:13 +03:00
magic: u32,
2017-03-29 18:16:58 +03:00
version: u32,
sections: Vec<Section>,
}
2017-04-06 16:00:12 +03:00
impl Default for Module {
fn default() -> Self {
Module {
magic: 0x6d736100,
version: 1,
sections: Vec::with_capacity(16),
2017-09-06 19:06:14 +02:00
}
2017-04-06 16:00:12 +03:00
}
}
2017-03-29 18:16:58 +03:00
impl Module {
2017-04-06 11:34:31 +03:00
/// New module with sections
pub fn new(sections: Vec<Section>) -> Self {
Module {
2017-04-06 16:00:12 +03:00
sections: sections, ..Default::default()
2017-04-06 11:34:31 +03:00
}
}
2017-04-06 16:00:12 +03:00
/// Destructure the module, yielding sections
pub fn into_sections(self) -> Vec<Section> {
self.sections
}
2017-04-04 00:27:31 +03:00
/// Version of module.
2017-03-29 18:16:58 +03:00
pub fn version(&self) -> u32 { self.version }
2017-03-29 19:40:51 +03:00
2017-04-04 00:27:31 +03:00
/// Sections list.
/// Each known section is optional and may appear at most once.
2017-03-29 19:40:51 +03:00
pub fn sections(&self) -> &[Section] {
&self.sections
}
2017-04-03 22:58:00 +03:00
2017-04-04 00:27:31 +03:00
/// Sections list (mutable)
/// Each known section is optional and may appear at most once.
2017-04-03 22:58:00 +03:00
pub fn sections_mut(&mut self) -> &mut Vec<Section> {
&mut self.sections
}
2017-04-03 23:56:21 +03:00
2017-04-04 00:27:31 +03:00
/// Code section, if any.
2017-04-03 23:56:21 +03:00
pub fn code_section(&self) -> Option<&CodeSection> {
for section in self.sections() {
if let &Section::Code(ref code_section) = section { return Some(code_section); }
}
None
}
2017-04-04 00:22:08 +03:00
2017-04-04 00:27:31 +03:00
/// Types section, if any.
2017-04-04 00:22:08 +03:00
pub fn type_section(&self) -> Option<&TypeSection> {
for section in self.sections() {
if let &Section::Type(ref type_section) = section { return Some(type_section); }
}
None
}
2017-04-04 00:27:31 +03:00
/// Imports section, if any.
2017-04-04 00:22:08 +03:00
pub fn import_section(&self) -> Option<&ImportSection> {
for section in self.sections() {
if let &Section::Import(ref import_section) = section { return Some(import_section); }
}
None
}
2017-04-06 16:00:12 +03:00
/// Globals section, if any.
pub fn global_section(&self) -> Option<&GlobalSection> {
for section in self.sections() {
if let &Section::Global(ref section) = section { return Some(section); }
}
2017-09-06 19:06:14 +02:00
None
}
2017-04-21 14:35:12 +03:00
/// Exports section, if any.
pub fn export_section(&self) -> Option<&ExportSection> {
for section in self.sections() {
if let &Section::Export(ref export_section) = section { return Some(export_section); }
}
None
}
/// Table section, if any.
pub fn table_section(&self) -> Option<&TableSection> {
for section in self.sections() {
if let &Section::Table(ref section) = section { return Some(section); }
}
None
}
/// Data section, if any.
pub fn data_section(&self) -> Option<&DataSection> {
for section in self.sections() {
if let &Section::Data(ref section) = section { return Some(section); }
}
None
}
/// Element section, if any.
pub fn elements_section(&self) -> Option<&ElementSection> {
for section in self.sections() {
if let &Section::Element(ref section) = section { return Some(section); }
}
None
}
/// Memory section, if any.
pub fn memory_section(&self) -> Option<&MemorySection> {
for section in self.sections() {
if let &Section::Memory(ref section) = section { return Some(section); }
}
None
}
2017-04-06 16:00:12 +03:00
/// Functions signatures section, if any.
pub fn function_section(&self) -> Option<&FunctionSection> {
2017-04-06 16:00:12 +03:00
for section in self.sections() {
if let &Section::Function(ref sect) = section { return Some(sect); }
}
2017-09-06 19:06:14 +02:00
None
2017-04-06 16:00:12 +03:00
}
2017-04-28 13:34:58 +03:00
/// Start section, if any.
pub fn start_section(&self) -> Option<u32> {
for section in self.sections() {
if let &Section::Start(sect) = section { return Some(sect); }
}
None
}
2017-03-29 18:16:58 +03:00
}
impl Deserialize for Module {
type Error = super::Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let mut sections = Vec::new();
2017-06-06 14:19:36 +03:00
let mut magic = [0u8; 4];
reader.read(&mut magic)?;
if magic != WASM_MAGIC_NUMBER {
return Err(Error::InvalidMagic);
}
let version: u32 = Uint32::deserialize(reader)?.into();
if version != 1 {
return Err(Error::UnsupportedVersion(version));
}
2017-03-29 18:16:58 +03:00
loop {
match Section::deserialize(reader) {
Err(Error::UnexpectedEof) => { break; },
Err(e) => { return Err(e) },
Ok(section) => { sections.push(section); }
}
}
2017-09-06 19:06:14 +02:00
Ok(Module {
2017-06-06 14:19:36 +03:00
magic: LittleEndian::read_u32(&magic),
version: version,
2017-03-29 18:16:58 +03:00
sections: sections,
})
2017-09-06 19:06:14 +02:00
}
2017-03-29 18:16:58 +03:00
}
2017-04-03 23:08:13 +03:00
impl Serialize for Module {
type Error = Error;
fn serialize<W: io::Write>(self, w: &mut W) -> Result<(), Self::Error> {
Uint32::from(self.magic).serialize(w)?;
Uint32::from(self.version).serialize(w)?;
for section in self.sections.into_iter() {
section.serialize(w)?;
}
Ok(())
}
}
2017-03-29 18:16:58 +03:00
#[cfg(test)]
mod integration_tests {
2017-04-03 23:56:21 +03:00
use super::super::{deserialize_file, serialize, deserialize_buffer, Section};
2017-04-03 23:08:13 +03:00
use super::Module;
2017-03-29 18:16:58 +03:00
#[test]
fn hello() {
2017-03-30 20:55:25 +03:00
let module = deserialize_file("./res/cases/v1/hello.wasm").expect("Should be deserialized");
2017-03-29 18:16:58 +03:00
assert_eq!(module.version(), 1);
2017-03-29 19:40:51 +03:00
assert_eq!(module.sections().len(), 8);
2017-03-29 18:16:58 +03:00
}
2017-04-03 23:08:13 +03:00
#[test]
fn serde() {
2017-04-03 23:56:21 +03:00
let module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
2017-04-03 23:08:13 +03:00
let buf = serialize(module).expect("serialization to succeed");
let module_new: Module = deserialize_buffer(buf).expect("deserialization to succeed");
2017-04-03 23:56:21 +03:00
let module_old = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
2017-04-03 23:08:13 +03:00
assert_eq!(module_old.sections().len(), module_new.sections().len());
}
2017-04-03 23:56:21 +03:00
2017-04-04 00:22:08 +03:00
#[test]
fn serde_type() {
let mut module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
module.sections_mut().retain(|x| {
if let &Section::Type(_) = x { true } else { false }
});
let buf = serialize(module).expect("serialization to succeed");
let module_new: Module = deserialize_buffer(buf).expect("deserialization to succeed");
let module_old = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
assert_eq!(
module_old.type_section().expect("type section exists").types().len(),
module_new.type_section().expect("type section exists").types().len(),
"There should be equal amount of types before and after serialization"
);
}
#[test]
fn serde_import() {
let mut module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
module.sections_mut().retain(|x| {
if let &Section::Import(_) = x { true } else { false }
});
let buf = serialize(module).expect("serialization to succeed");
let module_new: Module = deserialize_buffer(buf).expect("deserialization to succeed");
let module_old = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
assert_eq!(
module_old.import_section().expect("import section exists").entries().len(),
module_new.import_section().expect("import section exists").entries().len(),
"There should be equal amount of import entries before and after serialization"
);
2017-09-06 19:06:14 +02:00
}
2017-04-04 00:22:08 +03:00
2017-04-03 23:56:21 +03:00
#[test]
fn serde_code() {
let mut module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
module.sections_mut().retain(|x| {
if let &Section::Code(_) = x { true } else { false }
});
let buf = serialize(module).expect("serialization to succeed");
let module_new: Module = deserialize_buffer(buf).expect("deserialization to succeed");
let module_old = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
assert_eq!(
module_old.code_section().expect("code section exists").bodies().len(),
module_new.code_section().expect("code section exists").bodies().len(),
"There should be equal amount of function bodies before and after serialization"
);
}
2017-04-20 17:56:15 +03:00
#[test]
fn const_() {
use super::super::Opcode::*;
let module = deserialize_file("./res/cases/v1/const.wasm").expect("Should be deserialized");
let func = &module.code_section().expect("Code section to exist").bodies()[0];
2017-09-07 17:47:43 +02:00
assert_eq!(func.code().elements().len(), 20);
2017-09-06 19:06:14 +02:00
assert_eq!(I64Const(9223372036854775807), func.code().elements()[0]);
assert_eq!(I64Const(-9223372036854775808), func.code().elements()[1]);
2017-09-07 12:56:26 +02:00
assert_eq!(I64Const(-1152894205662152753), func.code().elements()[2]);
2017-09-07 16:16:20 +02:00
assert_eq!(I64Const(-8192), func.code().elements()[3]);
assert_eq!(I32Const(1024), func.code().elements()[4]);
assert_eq!(I32Const(2048), func.code().elements()[5]);
assert_eq!(I32Const(4096), func.code().elements()[6]);
assert_eq!(I32Const(8192), func.code().elements()[7]);
assert_eq!(I32Const(16384), func.code().elements()[8]);
assert_eq!(I32Const(32767), func.code().elements()[9]);
assert_eq!(I32Const(-1024), func.code().elements()[10]);
assert_eq!(I32Const(-2048), func.code().elements()[11]);
assert_eq!(I32Const(-4096), func.code().elements()[12]);
assert_eq!(I32Const(-8192), func.code().elements()[13]);
assert_eq!(I32Const(-16384), func.code().elements()[14]);
assert_eq!(I32Const(-32768), func.code().elements()[15]);
2017-09-07 17:47:43 +02:00
assert_eq!(I32Const(-2147483648), func.code().elements()[16]);
assert_eq!(I32Const(2147483647), func.code().elements()[17]);
2017-04-20 17:56:15 +03:00
}
#[test]
fn store() {
use super::super::Opcode::*;
let module = deserialize_file("./res/cases/v1/offset.wasm").expect("Should be deserialized");
let func = &module.code_section().expect("Code section to exist").bodies()[0];
assert_eq!(func.code().elements().len(), 5);
assert_eq!(I64Store(0, 32), func.code().elements()[2]);
}
2017-03-29 18:16:58 +03:00
}