From 9e3823c3f27bf376756fea34e18474de9ea83ba5 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Fri, 31 Mar 2017 01:54:04 +0300 Subject: [PATCH] export section --- examples/info.rs | 3 ++ src/elements/export_entry.rs | 48 +++++++++++++++++++++++++++ src/elements/mod.rs | 5 ++- src/elements/section.rs | 63 +++++++++++++++++++++++++++++++++++- src/lib.rs | 8 ++++- 5 files changed, 124 insertions(+), 3 deletions(-) create mode 100644 src/elements/export_entry.rs diff --git a/examples/info.rs b/examples/info.rs index fc530c0..a1cc050 100644 --- a/examples/info.rs +++ b/examples/info.rs @@ -19,6 +19,9 @@ fn main() { &Section::Import(ref import_section) => { println!("Imports {}", import_section.entries().len()); }, + &Section::Export(ref exports_section) => { + println!("Exports {}", exports_section.entries().len()); + }, &Section::Function(ref functions_section) => { println!("Functions {}", functions_section.entries().len()); }, diff --git a/src/elements/export_entry.rs b/src/elements/export_entry.rs new file mode 100644 index 0000000..aca91d0 --- /dev/null +++ b/src/elements/export_entry.rs @@ -0,0 +1,48 @@ +use std::io; +use super::{Deserialize, Error, VarUint7, VarUint32}; + +pub enum Internal { + Function(u32), + Table(u32), + Memory(u32), + Global(u32), +} + +impl Deserialize for Internal { + type Error = Error; + + fn deserialize(reader: &mut R) -> Result { + let kind = VarUint7::deserialize(reader)?; + match kind.into() { + 0x00 => Ok(Internal::Function(VarUint32::deserialize(reader)?.into())), + 0x01 => Ok(Internal::Table(VarUint32::deserialize(reader)?.into())), + 0x02 => Ok(Internal::Memory(VarUint32::deserialize(reader)?.into())), + 0x03 => Ok(Internal::Global(VarUint32::deserialize(reader)?.into())), + _ => Err(Error::UnknownInternalKind(kind.into())), + } + } +} + +pub struct ExportEntry { + field_str: String, + internal: Internal, +} + +impl ExportEntry { + pub fn field(&self) -> &str { &self.field_str } + pub fn internal(&self) -> &Internal { &self.internal } +} + +impl Deserialize for ExportEntry { + type Error = Error; + + fn deserialize(reader: &mut R) -> Result { + let field_str = String::deserialize(reader)?; + let internal = Internal::deserialize(reader)?; + + Ok(ExportEntry { + field_str: field_str, + internal: internal, + }) + } +} \ No newline at end of file diff --git a/src/elements/mod.rs b/src/elements/mod.rs index d8029f1..417adac 100644 --- a/src/elements/mod.rs +++ b/src/elements/mod.rs @@ -5,10 +5,12 @@ mod section; mod primitives; mod types; mod import_entry; +mod export_entry; pub use self::module::Module; pub use self::section::Section; -pub use self::import_entry::{ImportEntry, MemoryType, TableType}; +pub use self::import_entry::{ImportEntry, MemoryType, TableType, External}; +pub use self::export_entry::{ExportEntry, Internal}; pub use self::primitives::{VarUint32, VarUint7, VarUint1, VarInt7, Uint32, CountedList}; pub use self::types::ValueType; @@ -26,6 +28,7 @@ pub enum Error { UnknownValueType(i8), NonUtf8String, UnknownExternalKind(u8), + UnknownInternalKind(u8), } impl From for Error { diff --git a/src/elements/section.rs b/src/elements/section.rs index 2b93873..e562fc6 100644 --- a/src/elements/section.rs +++ b/src/elements/section.rs @@ -9,6 +9,7 @@ use super::{ ImportEntry, MemoryType, TableType, + ExportEntry, }; use super::types::Type; @@ -24,6 +25,7 @@ pub enum Section { Function(FunctionsSection), Table(TableSection), Memory(MemorySection), + Export(ExportSection), } impl Deserialize for Section { @@ -55,7 +57,10 @@ impl Deserialize for Section { }, 5 => { Section::Memory(MemorySection::deserialize(reader)?) - }, + }, + 7 => { + Section::Export(ExportSection::deserialize(reader)?) + }, _ => { Section::Unparsed { id: id.into(), payload: Unparsed::deserialize(reader)?.into() } } @@ -172,6 +177,25 @@ impl Deserialize for MemorySection { } } +pub struct ExportSection(Vec); + +impl ExportSection { + pub fn entries(&self) -> &[ExportEntry] { + &self.0 + } +} + +impl Deserialize for ExportSection { + type Error = Error; + + fn deserialize(reader: &mut R) -> Result { + // todo: maybe use reader.take(section_length) + let _section_length = VarUint32::deserialize(reader)?; + let entries: Vec = CountedList::deserialize(reader)?.into_inner(); + Ok(ExportSection(entries)) + } +} + #[cfg(test)] mod tests { @@ -306,4 +330,41 @@ mod tests { assert_eq!(2, t1.params().len()); } + fn export_payload() -> Vec { + vec![ + // section id + 0x07, + // section length + 148u8, 0x80, 0x80, 0x80, 0x0, + // 6 entries + 134u8, 0x80, 0x80, 0x80, 0x0, + // func "A", index 6 + // [name_len(1-5 bytes), name_bytes(name_len, internal_kind(1byte), internal_index(1-5 bytes)]) + 0x01, 0x30, 0x01, 0x86, 0x80, 0x00, + // func "B", index 8 + 0x01, 0x31, 0x01, 0x86, 0x00, + // func "C", index 7 + 0x01, 0x32, 0x01, 0x07, + // memory "D", index 0 + 0x01, 0x33, 0x02, 0x00, + // func "E", index 1 + 0x01, 0x34, 0x01, 0x01, + // func "F", index 2 + 0x01, 0x35, 0x01, 0x02 + ] + } + + + #[test] + fn export_detect() { + let section: Section = + deserialize_buffer(export_payload()).expect("section to be deserialized"); + + match section { + Section::Export(_) => {}, + _ => { + panic!("Payload should be recognized as export section") + } + } + } } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index fa65fab..91d1a58 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,4 +2,10 @@ extern crate byteorder; mod elements; -pub use elements::{Section, Module, Error as DeserializeError, deserialize_buffer, deserialize_file}; +pub use elements::{ + Section, + Module, + Error as DeserializeError, + deserialize_buffer, + deserialize_file +};