diff --git a/src/elements/mod.rs b/src/elements/mod.rs index 6a694f2..7e77bfd 100644 --- a/src/elements/mod.rs +++ b/src/elements/mod.rs @@ -9,6 +9,7 @@ mod export_entry; mod global_entry; mod ops; mod func; +mod segment; pub use self::module::Module; pub use self::section::Section; @@ -19,6 +20,7 @@ pub use self::primitives::{VarUint32, VarUint7, VarUint1, VarInt7, Uint32, Uint6 pub use self::types::{ValueType, BlockType}; pub use self::ops::{Opcode, Opcodes, InitExpr}; pub use self::func::{FuncBody, Local}; +pub use self::segment::{ElementSegment, DataSegment}; pub trait Deserialize : Sized { type Error; diff --git a/src/elements/section.rs b/src/elements/section.rs index b7e6417..0ba19c6 100644 --- a/src/elements/section.rs +++ b/src/elements/section.rs @@ -12,6 +12,8 @@ use super::{ ExportEntry, GlobalEntry, FuncBody, + ElementSegment, + DataSegment, }; use super::types::Type; @@ -30,7 +32,9 @@ pub enum Section { Global(GlobalSection), Export(ExportSection), Start(u32), + Element(ElementSection), Code(CodeSection), + Data(DataSection), } impl Deserialize for Section { @@ -73,9 +77,15 @@ impl Deserialize for Section { let _section_length = VarUint32::deserialize(reader)?; Section::Start(VarUint32::deserialize(reader)?.into()) }, + 9 => { + Section::Element(ElementSection::deserialize(reader)?) + }, 10 => { Section::Code(CodeSection::deserialize(reader)?) }, + 11 => { + Section::Data(DataSection::deserialize(reader)?) + }, _ => { Section::Unparsed { id: id.into(), payload: Unparsed::deserialize(reader)?.into() } } @@ -249,6 +259,44 @@ impl Deserialize for CodeSection { } } +pub struct ElementSection(Vec); + +impl ElementSection { + pub fn entries(&self) -> &[ElementSegment] { + &self.0 + } +} + +impl Deserialize for ElementSection { + 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(ElementSection(entries)) + } +} + +pub struct DataSection(Vec); + +impl DataSection { + pub fn entries(&self) -> &[DataSegment] { + &self.0 + } +} + +impl Deserialize for DataSection { + 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(DataSection(entries)) + } +} + #[cfg(test)] mod tests { diff --git a/src/elements/segment.rs b/src/elements/segment.rs new file mode 100644 index 0000000..7756127 --- /dev/null +++ b/src/elements/segment.rs @@ -0,0 +1,65 @@ +use std::io; +use super::{Deserialize, Error, VarUint32, CountedList, InitExpr}; + +pub struct ElementSegment { + index: u32, + offset: InitExpr, + members: Vec, +} + +impl ElementSegment { + pub fn members(&self) -> &[u32] { &self.members } + pub fn index(&self) -> u32 { self.index } + pub fn offset(&self) -> &InitExpr { &self.offset } +} + +impl Deserialize for ElementSegment { + type Error = Error; + + fn deserialize(reader: &mut R) -> Result { + let index = VarUint32::deserialize(reader)?; + let offset = InitExpr::deserialize(reader)?; + let funcs: Vec = CountedList::::deserialize(reader)? + .into_inner() + .into_iter() + .map(Into::into) + .collect(); + + Ok(ElementSegment { + index: index.into(), + offset: offset, + members: funcs, + }) + } +} + +pub struct DataSegment { + index: u32, + offset: InitExpr, + value: Vec, +} + +impl DataSegment { + pub fn index(&self) -> u32 { self.index } + pub fn offset(&self) -> &InitExpr { &self.offset } + pub fn value(&self) -> &[u8] { &self.value } +} + +impl Deserialize for DataSegment { + type Error = Error; + + fn deserialize(reader: &mut R) -> Result { + let index = VarUint32::deserialize(reader)?; + let offset = InitExpr::deserialize(reader)?; + let value_len = VarUint32::deserialize(reader)?; + + let mut value_buf = vec![0u8; value_len.into()]; + reader.read_exact(&mut value_buf[..])?; + + Ok(DataSegment { + index: index.into(), + offset: offset, + value: value_buf, + }) + } +} \ No newline at end of file