diff --git a/src/graph.rs b/src/graph.rs index 66cf0de..5a3db0d 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -7,8 +7,15 @@ use std::borrow::ToOwned; use std::string::String; use std::collections::BTreeMap; +/// Imported or declared variant of the same thing. +/// +/// In WebAssembly, function/global/memory/table instances can either be +/// imported or declared internally, forming united index space. +#[derive(Debug)] pub enum ImportedOrDeclared { + /// Variant for imported instances. Imported(String, String), + /// Variant for instances declared internally in the module. Declared(T), } @@ -18,74 +25,148 @@ impl From<&elements::ImportEntry> for ImportedOrDeclared { } } +/// Function origin (imported or internal). pub type FuncOrigin = ImportedOrDeclared; +/// Global origin (imported or internal). pub type GlobalOrigin = ImportedOrDeclared>; +/// Memory origin (imported or internal). pub type MemoryOrigin = ImportedOrDeclared; +/// Table origin (imported or internal). pub type TableOrigin = ImportedOrDeclared; +/// Function body. +/// +/// Function consist of declaration (signature, i.e. type reference) +/// and the actual code. This part is the actual code. +#[derive(Debug)] pub struct FuncBody { pub locals: Vec, pub code: Vec, } +/// Function declaration. +/// +/// As with other instances, functions can be either imported or declared +/// within the module - `origin` field is handling this. +#[derive(Debug)] pub struct Func { + /// Function signature/type reference. pub type_ref: EntryRef, + /// Where this function comes from (imported or declared). pub origin: FuncOrigin, } +/// Global declaration. +/// +/// As with other instances, globals can be either imported or declared +/// within the module - `origin` field is handling this. +#[derive(Debug)] pub struct Global { pub content: elements::ValueType, pub is_mut: bool, pub origin: GlobalOrigin, } +/// Instruction. +/// +/// Some instructions don't reference any entities within the WebAssembly module, +/// while others do. This enum is for tracking references when required. +#[derive(Debug)] pub enum Instruction { + /// WebAssembly instruction that does not reference any module entities. Plain(elements::Instruction), + /// Call instruction which references the function. Call(EntryRef), + /// Indirect call instruction which references function type (function signature). CallIndirect(EntryRef, u8), + /// get_global instruction which references the global. GetGlobal(EntryRef), + /// set_global instruction which references the global. SetGlobal(EntryRef), } +/// Memory instance decriptor. +/// +/// As with other similar instances, memory instances can be either imported +/// or declared within the module - `origin` field is handling this. +#[derive(Debug)] pub struct Memory { + /// Declared limits of the table instance. pub limits: elements::ResizableLimits, + /// Origin of the memory instance (internal or imported). pub origin: MemoryOrigin, } +/// Memory instance decriptor. +/// +/// As with other similar instances, memory instances can be either imported +/// or declared within the module - `origin` field is handling this. +#[derive(Debug)] pub struct Table { - pub origin: TableOrigin, + /// Declared limits of the table instance. pub limits: elements::ResizableLimits, + /// Origin of the table instance (internal or imported). + pub origin: TableOrigin, } +/// Segment location. +/// +/// Reserved for future use. Currenty only `Default` variant is supported. +#[derive(Debug)] pub enum SegmentLocation { + /// Not used currently. Passive, + /// Default segment location with index `0`. Default(Vec), + /// Not used currently. WithIndex(u32, Vec), } +/// Data segment of data section. +#[derive(Debug)] pub struct DataSegment { + /// Location of the segment in the linear memory. pub location: SegmentLocation, + /// Raw value of the data segment. pub value: Vec, } +/// Element segment of element section. +#[derive(Debug)] pub struct ElementSegment { + /// Location of the segment in the table space. pub location: SegmentLocation, + /// Raw value (function indices) of the element segment. pub value: Vec, } +/// Export entry reference. +/// +/// Module can export function, global, table or memory instance +/// under specific name (field). +#[derive(Debug)] pub enum ExportLocal { + /// Function reference. Func(EntryRef), + /// Global reference. Global(EntryRef), + /// Table reference. Table(EntryRef), + /// Memory reference. Memory(EntryRef), } +/// Export entry description. +#[derive(Debug)] pub struct Export { + /// Name (field) of the export entry. pub name: String, + /// What entity is exported. pub local: ExportLocal, } -#[derive(Default)] +/// Module +#[derive(Debug, Default)] pub struct Module { pub types: RefList, pub funcs: RefList, diff --git a/src/ref_list.rs b/src/ref_list.rs index a15f644..6c5026e 100644 --- a/src/ref_list.rs +++ b/src/ref_list.rs @@ -84,6 +84,8 @@ impl EntryRef { } } +/// List that tracks references and indices. +#[derive(Debug)] pub struct RefList { items: Vec>, } @@ -96,8 +98,12 @@ impl Default for RefList { impl RefList { + /// New empty list. pub fn new() -> Self { Self::default() } + /// Push new element in the list. + /// + /// Returns refernce tracking entry. pub fn push(&mut self, t: T) -> EntryRef { let idx = self.items.len(); let val: EntryRef<_> = Entry::new(t, idx).into(); @@ -105,6 +111,12 @@ impl RefList { val } + /// Start deleting. + /// + /// Start deleting some entries in the list. Returns transaction + /// that can be populated with number of removed entries. + /// When transaction is finailized, all entries are deleted and + /// internal indices of other entries are updated. pub fn begin_delete(&mut self) -> DeleteTransaction { DeleteTransaction { list: self, @@ -112,6 +124,9 @@ impl RefList { } } + /// Get entry with index (checked). + /// + /// Can return None when index out of bounts. pub fn get(&self, idx: usize) -> Option> { self.items.get(idx).cloned() } @@ -134,14 +149,19 @@ impl RefList { } } + /// Delete several items. pub fn delete(&mut self, indices: &[usize]) { self.done_delete(indices) } + /// Delete one item. pub fn delete_one(&mut self, index: usize) { self.done_delete(&[index]) } + /// Initialize from slice. + /// + /// Slice members are cloned. pub fn from_slice(list: &[T]) -> Self where T: Clone { @@ -154,23 +174,32 @@ impl RefList { res } + /// Length of the list. pub fn len(&self) -> usize { self.items.len() } + /// Clone entry (reference counting object to item) by index. + /// + /// Will panic if index out of bounds. pub fn clone_ref(&self, idx: usize) -> EntryRef { self.items[idx].clone() } + /// Get reference to entry by index. + /// + /// Will panic if index out of bounds. pub fn get_ref(&self, idx: usize) -> &EntryRef { &self.items[idx] } + /// Iterate through entries. pub fn iter(&self) -> slice::Iter> { self.items.iter() } } +/// Delete transaction. #[must_use] pub struct DeleteTransaction<'a, T> { list: &'a mut RefList, @@ -178,12 +207,14 @@ pub struct DeleteTransaction<'a, T> { } impl<'a, T> DeleteTransaction<'a, T> { + /// Add new element to the delete list. pub fn push(self, idx: usize) -> Self { let mut tx = self; tx.deleted.push(idx); tx } + /// Commit transaction. pub fn done(self) { let indices = self.deleted; let list = self.list;