add some docs

This commit is contained in:
NikVolf 2019-01-23 13:47:44 +03:00
parent c3833efca7
commit 62ea903c3a
2 changed files with 114 additions and 2 deletions

View File

@ -7,8 +7,15 @@ use std::borrow::ToOwned;
use std::string::String; use std::string::String;
use std::collections::BTreeMap; 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<T=()> { pub enum ImportedOrDeclared<T=()> {
/// Variant for imported instances.
Imported(String, String), Imported(String, String),
/// Variant for instances declared internally in the module.
Declared(T), Declared(T),
} }
@ -18,74 +25,148 @@ impl<T> From<&elements::ImportEntry> for ImportedOrDeclared<T> {
} }
} }
/// Function origin (imported or internal).
pub type FuncOrigin = ImportedOrDeclared<FuncBody>; pub type FuncOrigin = ImportedOrDeclared<FuncBody>;
/// Global origin (imported or internal).
pub type GlobalOrigin = ImportedOrDeclared<Vec<Instruction>>; pub type GlobalOrigin = ImportedOrDeclared<Vec<Instruction>>;
/// Memory origin (imported or internal).
pub type MemoryOrigin = ImportedOrDeclared; pub type MemoryOrigin = ImportedOrDeclared;
/// Table origin (imported or internal).
pub type TableOrigin = ImportedOrDeclared; 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 struct FuncBody {
pub locals: Vec<elements::Local>, pub locals: Vec<elements::Local>,
pub code: Vec<Instruction>, pub code: Vec<Instruction>,
} }
/// 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 { pub struct Func {
/// Function signature/type reference.
pub type_ref: EntryRef<elements::Type>, pub type_ref: EntryRef<elements::Type>,
/// Where this function comes from (imported or declared).
pub origin: FuncOrigin, 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 struct Global {
pub content: elements::ValueType, pub content: elements::ValueType,
pub is_mut: bool, pub is_mut: bool,
pub origin: GlobalOrigin, 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 { pub enum Instruction {
/// WebAssembly instruction that does not reference any module entities.
Plain(elements::Instruction), Plain(elements::Instruction),
/// Call instruction which references the function.
Call(EntryRef<Func>), Call(EntryRef<Func>),
/// Indirect call instruction which references function type (function signature).
CallIndirect(EntryRef<elements::Type>, u8), CallIndirect(EntryRef<elements::Type>, u8),
/// get_global instruction which references the global.
GetGlobal(EntryRef<Global>), GetGlobal(EntryRef<Global>),
/// set_global instruction which references the global.
SetGlobal(EntryRef<Global>), SetGlobal(EntryRef<Global>),
} }
/// 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 { pub struct Memory {
/// Declared limits of the table instance.
pub limits: elements::ResizableLimits, pub limits: elements::ResizableLimits,
/// Origin of the memory instance (internal or imported).
pub origin: MemoryOrigin, 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 struct Table {
pub origin: TableOrigin, /// Declared limits of the table instance.
pub limits: elements::ResizableLimits, 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 { pub enum SegmentLocation {
/// Not used currently.
Passive, Passive,
/// Default segment location with index `0`.
Default(Vec<Instruction>), Default(Vec<Instruction>),
/// Not used currently.
WithIndex(u32, Vec<Instruction>), WithIndex(u32, Vec<Instruction>),
} }
/// Data segment of data section.
#[derive(Debug)]
pub struct DataSegment { pub struct DataSegment {
/// Location of the segment in the linear memory.
pub location: SegmentLocation, pub location: SegmentLocation,
/// Raw value of the data segment.
pub value: Vec<u8>, pub value: Vec<u8>,
} }
/// Element segment of element section.
#[derive(Debug)]
pub struct ElementSegment { pub struct ElementSegment {
/// Location of the segment in the table space.
pub location: SegmentLocation, pub location: SegmentLocation,
/// Raw value (function indices) of the element segment.
pub value: Vec<u32>, pub value: Vec<u32>,
} }
/// Export entry reference.
///
/// Module can export function, global, table or memory instance
/// under specific name (field).
#[derive(Debug)]
pub enum ExportLocal { pub enum ExportLocal {
/// Function reference.
Func(EntryRef<Func>), Func(EntryRef<Func>),
/// Global reference.
Global(EntryRef<Global>), Global(EntryRef<Global>),
/// Table reference.
Table(EntryRef<Table>), Table(EntryRef<Table>),
/// Memory reference.
Memory(EntryRef<Memory>), Memory(EntryRef<Memory>),
} }
/// Export entry description.
#[derive(Debug)]
pub struct Export { pub struct Export {
/// Name (field) of the export entry.
pub name: String, pub name: String,
/// What entity is exported.
pub local: ExportLocal, pub local: ExportLocal,
} }
#[derive(Default)] /// Module
#[derive(Debug, Default)]
pub struct Module { pub struct Module {
pub types: RefList<elements::Type>, pub types: RefList<elements::Type>,
pub funcs: RefList<Func>, pub funcs: RefList<Func>,

View File

@ -84,6 +84,8 @@ impl<T> EntryRef<T> {
} }
} }
/// List that tracks references and indices.
#[derive(Debug)]
pub struct RefList<T> { pub struct RefList<T> {
items: Vec<EntryRef<T>>, items: Vec<EntryRef<T>>,
} }
@ -96,8 +98,12 @@ impl<T> Default for RefList<T> {
impl<T> RefList<T> { impl<T> RefList<T> {
/// New empty list.
pub fn new() -> Self { Self::default() } pub fn new() -> Self { Self::default() }
/// Push new element in the list.
///
/// Returns refernce tracking entry.
pub fn push(&mut self, t: T) -> EntryRef<T> { pub fn push(&mut self, t: T) -> EntryRef<T> {
let idx = self.items.len(); let idx = self.items.len();
let val: EntryRef<_> = Entry::new(t, idx).into(); let val: EntryRef<_> = Entry::new(t, idx).into();
@ -105,6 +111,12 @@ impl<T> RefList<T> {
val 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<T> { pub fn begin_delete(&mut self) -> DeleteTransaction<T> {
DeleteTransaction { DeleteTransaction {
list: self, list: self,
@ -112,6 +124,9 @@ impl<T> RefList<T> {
} }
} }
/// Get entry with index (checked).
///
/// Can return None when index out of bounts.
pub fn get(&self, idx: usize) -> Option<EntryRef<T>> { pub fn get(&self, idx: usize) -> Option<EntryRef<T>> {
self.items.get(idx).cloned() self.items.get(idx).cloned()
} }
@ -134,14 +149,19 @@ impl<T> RefList<T> {
} }
} }
/// Delete several items.
pub fn delete(&mut self, indices: &[usize]) { pub fn delete(&mut self, indices: &[usize]) {
self.done_delete(indices) self.done_delete(indices)
} }
/// Delete one item.
pub fn delete_one(&mut self, index: usize) { pub fn delete_one(&mut self, index: usize) {
self.done_delete(&[index]) self.done_delete(&[index])
} }
/// Initialize from slice.
///
/// Slice members are cloned.
pub fn from_slice(list: &[T]) -> Self pub fn from_slice(list: &[T]) -> Self
where T: Clone where T: Clone
{ {
@ -154,23 +174,32 @@ impl<T> RefList<T> {
res res
} }
/// Length of the list.
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.items.len() 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<T> { pub fn clone_ref(&self, idx: usize) -> EntryRef<T> {
self.items[idx].clone() 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<T> { pub fn get_ref(&self, idx: usize) -> &EntryRef<T> {
&self.items[idx] &self.items[idx]
} }
/// Iterate through entries.
pub fn iter(&self) -> slice::Iter<EntryRef<T>> { pub fn iter(&self) -> slice::Iter<EntryRef<T>> {
self.items.iter() self.items.iter()
} }
} }
/// Delete transaction.
#[must_use] #[must_use]
pub struct DeleteTransaction<'a, T> { pub struct DeleteTransaction<'a, T> {
list: &'a mut RefList<T>, list: &'a mut RefList<T>,
@ -178,12 +207,14 @@ pub struct DeleteTransaction<'a, T> {
} }
impl<'a, T> DeleteTransaction<'a, T> { impl<'a, T> DeleteTransaction<'a, T> {
/// Add new element to the delete list.
pub fn push(self, idx: usize) -> Self { pub fn push(self, idx: usize) -> Self {
let mut tx = self; let mut tx = self;
tx.deleted.push(idx); tx.deleted.push(idx);
tx tx
} }
/// Commit transaction.
pub fn done(self) { pub fn done(self) {
let indices = self.deleted; let indices = self.deleted;
let list = self.list; let list = self.list;