2017-04-06 11:34:31 +03:00
|
|
|
use super::invoke::{Invoke, Identity};
|
2017-04-11 13:35:19 +03:00
|
|
|
use super::code::{self, SignaturesBuilder, FunctionBuilder};
|
2017-04-28 13:34:58 +03:00
|
|
|
use super::memory::{self, MemoryBuilder};
|
2017-05-02 08:01:57 +03:00
|
|
|
use super::table::{self, TableBuilder};
|
2017-06-09 15:17:12 +03:00
|
|
|
use super::{import, export, global, data};
|
2017-04-06 11:34:31 +03:00
|
|
|
use elements;
|
|
|
|
|
|
|
|
/// Module builder
|
|
|
|
pub struct ModuleBuilder<F=Identity> {
|
|
|
|
callback: F,
|
2017-04-06 16:00:12 +03:00
|
|
|
module: ModuleScaffold,
|
|
|
|
}
|
|
|
|
|
2017-04-07 20:00:30 +03:00
|
|
|
/// Location of the internal module function
|
|
|
|
pub struct CodeLocation {
|
|
|
|
/// Location (index in 'functions' section) of the signature
|
|
|
|
pub signature: u32,
|
|
|
|
/// Location (index in the 'code' section) of the body
|
|
|
|
pub body: u32,
|
|
|
|
}
|
|
|
|
|
2017-04-06 16:00:12 +03:00
|
|
|
#[derive(Default)]
|
|
|
|
struct ModuleScaffold {
|
|
|
|
pub types: elements::TypeSection,
|
2017-04-07 15:29:02 +03:00
|
|
|
pub import: elements::ImportSection,
|
2017-06-03 23:31:38 +03:00
|
|
|
pub functions: elements::FunctionSection,
|
2017-04-12 19:07:10 +03:00
|
|
|
pub table: elements::TableSection,
|
|
|
|
pub memory: elements::MemorySection,
|
|
|
|
pub global: elements::GlobalSection,
|
|
|
|
pub export: elements::ExportSection,
|
|
|
|
pub start: Option<u32>,
|
|
|
|
pub element: elements::ElementSection,
|
2017-04-07 20:00:30 +03:00
|
|
|
pub code: elements::CodeSection,
|
2017-04-12 19:07:10 +03:00
|
|
|
pub data: elements::DataSection,
|
2017-04-06 16:00:12 +03:00
|
|
|
pub other: Vec<elements::Section>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<elements::Module> for ModuleScaffold {
|
|
|
|
fn from(module: elements::Module) -> Self {
|
|
|
|
let mut types: Option<elements::TypeSection> = None;
|
2017-04-07 15:29:02 +03:00
|
|
|
let mut import: Option<elements::ImportSection> = None;
|
2017-06-03 23:31:38 +03:00
|
|
|
let mut funcs: Option<elements::FunctionSection> = None;
|
2017-04-12 19:07:10 +03:00
|
|
|
let mut table: Option<elements::TableSection> = None;
|
|
|
|
let mut memory: Option<elements::MemorySection> = None;
|
|
|
|
let mut global: Option<elements::GlobalSection> = None;
|
|
|
|
let mut export: Option<elements::ExportSection> = None;
|
|
|
|
let mut start: Option<u32> = None;
|
|
|
|
let mut element: Option<elements::ElementSection> = None;
|
2017-04-07 20:00:30 +03:00
|
|
|
let mut code: Option<elements::CodeSection> = None;
|
2017-04-12 19:07:10 +03:00
|
|
|
let mut data: Option<elements::DataSection> = None;
|
2017-04-06 16:00:12 +03:00
|
|
|
|
|
|
|
let mut sections = module.into_sections();
|
|
|
|
while let Some(section) = sections.pop() {
|
|
|
|
match section {
|
|
|
|
elements::Section::Type(sect) => { types = Some(sect); }
|
2017-04-07 15:29:02 +03:00
|
|
|
elements::Section::Import(sect) => { import = Some(sect); }
|
2017-04-12 19:07:10 +03:00
|
|
|
elements::Section::Function(sect) => { funcs = Some(sect); }
|
|
|
|
elements::Section::Table(sect) => { table = Some(sect); }
|
|
|
|
elements::Section::Memory(sect) => { memory = Some(sect); }
|
|
|
|
elements::Section::Global(sect) => { global = Some(sect); }
|
|
|
|
elements::Section::Export(sect) => { export = Some(sect); }
|
|
|
|
elements::Section::Start(index) => { start = Some(index); }
|
|
|
|
elements::Section::Element(sect) => { element = Some(sect); }
|
2017-04-07 20:00:30 +03:00
|
|
|
elements::Section::Code(sect) => { code = Some(sect); }
|
2017-04-12 19:07:10 +03:00
|
|
|
elements::Section::Data(sect) => { data = Some(sect); }
|
2017-04-06 16:00:12 +03:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ModuleScaffold {
|
|
|
|
types: types.unwrap_or_default(),
|
2017-04-07 15:29:02 +03:00
|
|
|
import: import.unwrap_or_default(),
|
2017-04-12 19:07:10 +03:00
|
|
|
functions: funcs.unwrap_or_default(),
|
|
|
|
table: table.unwrap_or_default(),
|
|
|
|
memory: memory.unwrap_or_default(),
|
|
|
|
global: global.unwrap_or_default(),
|
|
|
|
export: export.unwrap_or_default(),
|
|
|
|
start: start,
|
|
|
|
element: element.unwrap_or_default(),
|
2017-04-07 20:00:30 +03:00
|
|
|
code: code.unwrap_or_default(),
|
2017-04-12 19:07:10 +03:00
|
|
|
data: data.unwrap_or_default(),
|
2017-04-06 16:00:12 +03:00
|
|
|
other: sections,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<ModuleScaffold> for elements::Module {
|
|
|
|
fn from(module: ModuleScaffold) -> Self {
|
|
|
|
let mut sections = Vec::new();
|
|
|
|
|
|
|
|
let types = module.types;
|
|
|
|
if types.types().len() > 0 {
|
|
|
|
sections.push(elements::Section::Type(types));
|
|
|
|
}
|
2017-04-07 15:29:02 +03:00
|
|
|
let import = module.import;
|
|
|
|
if import.entries().len() > 0 {
|
|
|
|
sections.push(elements::Section::Import(import));
|
|
|
|
}
|
2017-04-11 13:06:24 +03:00
|
|
|
let functions = module.functions;
|
|
|
|
if functions.entries().len() > 0 {
|
|
|
|
sections.push(elements::Section::Function(functions));
|
2017-04-12 19:07:10 +03:00
|
|
|
}
|
|
|
|
let table = module.table;
|
|
|
|
if table.entries().len() > 0 {
|
|
|
|
sections.push(elements::Section::Table(table));
|
|
|
|
}
|
|
|
|
let memory = module.memory;
|
|
|
|
if memory.entries().len() > 0 {
|
|
|
|
sections.push(elements::Section::Memory(memory));
|
|
|
|
}
|
|
|
|
let global = module.global;
|
|
|
|
if global.entries().len() > 0 {
|
|
|
|
sections.push(elements::Section::Global(global));
|
|
|
|
}
|
|
|
|
let export = module.export;
|
|
|
|
if export.entries().len() > 0 {
|
|
|
|
sections.push(elements::Section::Export(export));
|
|
|
|
}
|
|
|
|
if let Some(start) = module.start {
|
|
|
|
sections.push(elements::Section::Start(start));
|
|
|
|
}
|
|
|
|
let element = module.element;
|
|
|
|
if element.entries().len() > 0 {
|
|
|
|
sections.push(elements::Section::Element(element));
|
|
|
|
}
|
2017-04-11 13:35:19 +03:00
|
|
|
let code = module.code;
|
|
|
|
if code.bodies().len() > 0 {
|
|
|
|
sections.push(elements::Section::Code(code));
|
|
|
|
}
|
2017-04-12 19:07:10 +03:00
|
|
|
let data = module.data;
|
|
|
|
if data.entries().len() > 0 {
|
|
|
|
sections.push(elements::Section::Data(data));
|
|
|
|
}
|
2017-04-06 16:00:12 +03:00
|
|
|
sections.extend(module.other);
|
|
|
|
elements::Module::new(sections)
|
|
|
|
}
|
2017-04-06 11:34:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ModuleBuilder {
|
|
|
|
/// New empty module builder
|
|
|
|
pub fn new() -> Self {
|
|
|
|
ModuleBuilder::with_callback(Identity)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F> ModuleBuilder<F> where F: Invoke<elements::Module> {
|
|
|
|
/// New module builder with bound callback
|
|
|
|
pub fn with_callback(callback: F) -> Self {
|
|
|
|
ModuleBuilder {
|
|
|
|
callback: callback,
|
2017-04-06 16:00:12 +03:00
|
|
|
module: Default::default(),
|
2017-04-06 11:34:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-10 13:11:34 +03:00
|
|
|
/// Builder from raw module
|
|
|
|
pub fn with_module(mut self, module: elements::Module) -> Self {
|
|
|
|
self.module = module.into();
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2017-04-06 11:34:31 +03:00
|
|
|
/// Fill module with sections from iterator
|
|
|
|
pub fn with_sections<I>(mut self, sections: I) -> Self
|
|
|
|
where I: IntoIterator<Item=elements::Section>
|
|
|
|
{
|
2017-04-06 16:00:12 +03:00
|
|
|
self.module.other.extend(sections);
|
2017-04-06 11:34:31 +03:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2017-04-06 16:00:12 +03:00
|
|
|
/// Add additional section
|
2017-04-06 11:34:31 +03:00
|
|
|
pub fn with_section(mut self, section: elements::Section) -> Self {
|
2017-04-06 16:00:12 +03:00
|
|
|
self.module.other.push(section);
|
2017-04-06 11:34:31 +03:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2017-04-06 16:00:12 +03:00
|
|
|
/// Binds to the type section, creates additional types when required
|
|
|
|
pub fn with_signatures(mut self, bindings: code::SignatureBindings) -> Self {
|
2017-04-07 14:04:27 +03:00
|
|
|
self.push_signatures(bindings);
|
|
|
|
self
|
|
|
|
}
|
2017-04-06 16:00:12 +03:00
|
|
|
|
2017-04-07 20:00:30 +03:00
|
|
|
/// Push stand-alone function definition, creating sections, signature and code blocks
|
|
|
|
/// in corresponding sections.
|
|
|
|
/// `FunctionDefinition` can be build using `builder::function` builder
|
|
|
|
pub fn push_function(&mut self, func: code::FunctionDefinition) -> CodeLocation {
|
|
|
|
let signature = func.signature;
|
|
|
|
let body = func.code;
|
|
|
|
|
2017-04-10 13:58:14 +03:00
|
|
|
let type_ref = self.resolve_type_ref(signature);
|
2017-04-07 20:00:30 +03:00
|
|
|
|
2017-04-10 13:58:14 +03:00
|
|
|
self.module.functions.entries_mut().push(elements::Func::new(type_ref));
|
|
|
|
let signature_index = self.module.functions.entries_mut().len() as u32 - 1;
|
|
|
|
self.module.code.bodies_mut().push(body);
|
|
|
|
let body_index = self.module.code.bodies_mut().len() as u32 - 1;
|
2017-04-07 20:00:30 +03:00
|
|
|
|
2017-04-28 13:34:58 +03:00
|
|
|
if func.is_main {
|
|
|
|
self.module.start = Some(body_index);
|
|
|
|
}
|
|
|
|
|
2017-04-07 20:00:30 +03:00
|
|
|
CodeLocation {
|
|
|
|
signature: signature_index,
|
|
|
|
body: body_index,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-28 13:34:58 +03:00
|
|
|
/// Push linear memory region
|
2017-05-02 19:10:23 +03:00
|
|
|
pub fn push_memory(&mut self, mut memory: memory::MemoryDefinition) -> u32 {
|
2017-04-28 13:34:58 +03:00
|
|
|
let entries = self.module.memory.entries_mut();
|
|
|
|
entries.push(elements::MemoryType::new(memory.min, memory.max));
|
2017-05-02 19:10:23 +03:00
|
|
|
let memory_index = (entries.len() - 1) as u32;
|
|
|
|
for data in memory.data.drain(..) {
|
|
|
|
self.module.data.entries_mut()
|
|
|
|
.push(elements::DataSegment::new(memory_index, data.offset, data.values))
|
|
|
|
}
|
|
|
|
memory_index
|
2017-04-28 13:34:58 +03:00
|
|
|
}
|
|
|
|
|
2017-05-02 08:01:57 +03:00
|
|
|
/// Push table
|
|
|
|
pub fn push_table(&mut self, mut table: table::TableDefinition) -> u32 {
|
|
|
|
let entries = self.module.table.entries_mut();
|
2017-09-04 12:00:01 +03:00
|
|
|
entries.push(elements::TableType::new(table.min, table.max));
|
2017-05-02 08:01:57 +03:00
|
|
|
let table_index = (entries.len() - 1) as u32;
|
|
|
|
for entry in table.elements.drain(..) {
|
|
|
|
self.module.element.entries_mut()
|
|
|
|
.push(elements::ElementSegment::new(table_index, entry.offset, entry.values))
|
|
|
|
}
|
|
|
|
table_index
|
|
|
|
}
|
|
|
|
|
2017-04-10 13:58:14 +03:00
|
|
|
fn resolve_type_ref(&mut self, signature: code::Signature) -> u32 {
|
|
|
|
match signature {
|
|
|
|
code::Signature::Inline(func_type) => {
|
2017-04-11 14:06:59 +03:00
|
|
|
// todo: maybe search for existing type
|
2017-04-10 13:58:14 +03:00
|
|
|
self.module.types.types_mut().push(elements::Type::Function(func_type));
|
|
|
|
self.module.types.types().len() as u32 - 1
|
|
|
|
}
|
|
|
|
code::Signature::TypeReference(type_ref) => {
|
|
|
|
type_ref
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Push one function signature, returning it's calling index.
|
|
|
|
/// Can create corresponding type in type section.
|
|
|
|
pub fn push_signature(&mut self, signature: code::Signature) -> u32 {
|
2017-04-11 14:04:40 +03:00
|
|
|
self.resolve_type_ref(signature)
|
2017-04-10 13:58:14 +03:00
|
|
|
}
|
|
|
|
|
2017-04-07 14:04:27 +03:00
|
|
|
/// Push signatures in the module, returning corresponding indices of pushed signatures
|
|
|
|
pub fn push_signatures(&mut self, signatures: code::SignatureBindings) -> Vec<u32> {
|
2017-04-11 14:06:59 +03:00
|
|
|
signatures.into_iter().map(|binding|
|
|
|
|
self.resolve_type_ref(binding)
|
|
|
|
).collect()
|
2017-04-06 16:00:12 +03:00
|
|
|
}
|
|
|
|
|
2017-04-12 17:48:24 +03:00
|
|
|
/// Push import entry to module. Not that it does not update calling indices in
|
|
|
|
/// function bodies.
|
|
|
|
pub fn push_import(&mut self, import: elements::ImportEntry) -> u32 {
|
|
|
|
self.module.import.entries_mut().push(import);
|
|
|
|
// todo: actually update calling addresses in function bodies
|
|
|
|
// todo: also batch push
|
|
|
|
|
|
|
|
self.module.import.entries_mut().len() as u32 - 1
|
|
|
|
}
|
|
|
|
|
2017-05-15 15:40:08 +03:00
|
|
|
/// Push export entry to module.
|
|
|
|
pub fn push_export(&mut self, export: elements::ExportEntry) -> u32 {
|
|
|
|
self.module.export.entries_mut().push(export);
|
|
|
|
self.module.export.entries_mut().len() as u32 - 1
|
|
|
|
}
|
|
|
|
|
2017-04-11 14:07:45 +03:00
|
|
|
/// Add new function using dedicated builder
|
2017-04-11 13:35:19 +03:00
|
|
|
pub fn function(self) -> FunctionBuilder<Self> {
|
|
|
|
FunctionBuilder::with_callback(self)
|
|
|
|
}
|
|
|
|
|
2017-04-28 13:34:58 +03:00
|
|
|
/// Add new linear memory using dedicated builder
|
|
|
|
pub fn memory(self) -> MemoryBuilder<Self> {
|
|
|
|
MemoryBuilder::with_callback(self)
|
|
|
|
}
|
|
|
|
|
2017-05-02 08:01:57 +03:00
|
|
|
/// Add new table using dedicated builder
|
|
|
|
pub fn table(self) -> TableBuilder<Self> {
|
|
|
|
TableBuilder::with_callback(self)
|
|
|
|
}
|
|
|
|
|
2017-04-06 16:00:12 +03:00
|
|
|
/// Define functions section
|
2017-04-07 14:04:27 +03:00
|
|
|
pub fn functions(self) -> SignaturesBuilder<Self> {
|
|
|
|
SignaturesBuilder::with_callback(self)
|
2017-04-06 11:34:31 +03:00
|
|
|
}
|
|
|
|
|
2017-05-03 09:09:41 +03:00
|
|
|
/// With inserted export entry
|
|
|
|
pub fn with_export(mut self, entry: elements::ExportEntry) -> Self {
|
|
|
|
self.module.export.entries_mut().push(entry);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2017-04-10 13:11:34 +03:00
|
|
|
/// With inserted import entry
|
|
|
|
pub fn with_import(mut self, entry: elements::ImportEntry) -> Self {
|
|
|
|
self.module.import.entries_mut().push(entry);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Import entry builder
|
2017-06-27 13:54:51 +03:00
|
|
|
/// # Examples
|
|
|
|
/// ```
|
|
|
|
/// use parity_wasm::builder::module;
|
|
|
|
///
|
|
|
|
/// let module = module()
|
|
|
|
/// .import()
|
|
|
|
/// .module("env")
|
|
|
|
/// .field("memory")
|
|
|
|
/// .external().memory(256, Some(256))
|
|
|
|
/// .build()
|
|
|
|
/// .build();
|
|
|
|
///
|
|
|
|
/// assert_eq!(module.import_section().expect("import section to exist").entries().len(), 1);
|
|
|
|
/// ```
|
2017-04-10 13:11:34 +03:00
|
|
|
pub fn import(self) -> import::ImportBuilder<Self> {
|
|
|
|
import::ImportBuilder::with_callback(self)
|
|
|
|
}
|
|
|
|
|
2017-05-03 11:06:26 +03:00
|
|
|
/// With global variable
|
|
|
|
pub fn with_global(mut self, global: elements::GlobalEntry) -> Self {
|
|
|
|
self.module.global.entries_mut().push(global);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2017-06-13 12:01:59 +03:00
|
|
|
/// With table
|
|
|
|
pub fn with_table(mut self, table: elements::TableType) -> Self {
|
|
|
|
self.module.table.entries_mut().push(table);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2017-05-09 15:23:05 +03:00
|
|
|
/// Export entry builder
|
2017-06-27 14:12:57 +03:00
|
|
|
/// # Examples
|
|
|
|
/// ```
|
|
|
|
/// use parity_wasm::builder::module;
|
|
|
|
/// use parity_wasm::elements::Opcode::*;
|
|
|
|
///
|
|
|
|
/// let module = module()
|
|
|
|
/// .global()
|
|
|
|
/// .value_type().i32()
|
|
|
|
/// .init_expr(I32Const(0))
|
|
|
|
/// .build()
|
|
|
|
/// .export()
|
|
|
|
/// .field("_zero")
|
|
|
|
/// .internal().global(0)
|
|
|
|
/// .build()
|
|
|
|
/// .build();
|
|
|
|
///
|
2017-06-27 18:36:27 +03:00
|
|
|
/// assert_eq!(module.export_section().expect("export section to exist").entries().len(), 1);
|
2017-06-27 14:12:57 +03:00
|
|
|
/// ```
|
2017-05-09 15:23:05 +03:00
|
|
|
pub fn export(self) -> export::ExportBuilder<Self> {
|
|
|
|
export::ExportBuilder::with_callback(self)
|
|
|
|
}
|
|
|
|
|
2017-05-09 17:38:51 +03:00
|
|
|
/// Glboal entry builder
|
2017-06-27 18:36:27 +03:00
|
|
|
/// # Examples
|
|
|
|
/// ```
|
|
|
|
/// use parity_wasm::builder::module;
|
|
|
|
/// use parity_wasm::elements::Opcode::*;
|
|
|
|
///
|
|
|
|
/// let module = module()
|
|
|
|
/// .global()
|
|
|
|
/// .value_type().i32()
|
|
|
|
/// .init_expr(I32Const(0))
|
|
|
|
/// .build()
|
|
|
|
/// .build();
|
|
|
|
///
|
|
|
|
/// assert_eq!(module.global_section().expect("global section to exist").entries().len(), 1);
|
|
|
|
/// ```
|
2017-05-09 17:38:51 +03:00
|
|
|
pub fn global(self) -> global::GlobalBuilder<Self> {
|
|
|
|
global::GlobalBuilder::with_callback(self)
|
|
|
|
}
|
|
|
|
|
2017-06-09 15:17:12 +03:00
|
|
|
/// Add data segment to the builder
|
|
|
|
pub fn with_data_segment(mut self, segment: elements::DataSegment) -> Self {
|
|
|
|
self.module.data.entries_mut().push(segment);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Data entry builder
|
|
|
|
pub fn data(self) -> data::DataSegmentBuilder<Self> {
|
|
|
|
data::DataSegmentBuilder::with_callback(self)
|
|
|
|
}
|
|
|
|
|
2017-04-06 11:34:31 +03:00
|
|
|
/// Build module (final step)
|
|
|
|
pub fn build(self) -> F::Result {
|
2017-04-06 16:00:12 +03:00
|
|
|
self.callback.invoke(self.module.into())
|
2017-04-06 11:34:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-03 23:31:38 +03:00
|
|
|
impl<F> Invoke<elements::FunctionSection> for ModuleBuilder<F>
|
2017-04-06 11:34:31 +03:00
|
|
|
where F: Invoke<elements::Module>
|
|
|
|
{
|
|
|
|
type Result = Self;
|
|
|
|
|
2017-06-03 23:31:38 +03:00
|
|
|
fn invoke(self, section: elements::FunctionSection) -> Self {
|
2017-04-06 11:34:31 +03:00
|
|
|
self.with_section(elements::Section::Function(section))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-06 16:00:12 +03:00
|
|
|
impl<F> Invoke<code::SignatureBindings> for ModuleBuilder<F>
|
|
|
|
where F: Invoke<elements::Module>
|
|
|
|
{
|
|
|
|
type Result = Self;
|
|
|
|
|
|
|
|
fn invoke(self, bindings: code::SignatureBindings) -> Self {
|
|
|
|
self.with_signatures(bindings)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-11 13:35:19 +03:00
|
|
|
|
|
|
|
impl<F> Invoke<code::FunctionDefinition> for ModuleBuilder<F>
|
|
|
|
where F: Invoke<elements::Module>
|
|
|
|
{
|
|
|
|
type Result = Self;
|
|
|
|
|
|
|
|
fn invoke(self, def: code::FunctionDefinition) -> Self {
|
|
|
|
let mut b = self;
|
|
|
|
b.push_function(def);
|
|
|
|
b
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-28 13:34:58 +03:00
|
|
|
impl<F> Invoke<memory::MemoryDefinition> for ModuleBuilder<F>
|
|
|
|
where F: Invoke<elements::Module>
|
|
|
|
{
|
|
|
|
type Result = Self;
|
|
|
|
|
|
|
|
fn invoke(self, def: memory::MemoryDefinition) -> Self {
|
|
|
|
let mut b = self;
|
|
|
|
b.push_memory(def);
|
|
|
|
b
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-02 08:01:57 +03:00
|
|
|
impl<F> Invoke<table::TableDefinition> for ModuleBuilder<F>
|
|
|
|
where F: Invoke<elements::Module>
|
|
|
|
{
|
|
|
|
type Result = Self;
|
|
|
|
|
|
|
|
fn invoke(self, def: table::TableDefinition) -> Self {
|
|
|
|
let mut b = self;
|
|
|
|
b.push_table(def);
|
|
|
|
b
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-10 13:11:34 +03:00
|
|
|
impl<F> Invoke<elements::ImportEntry> for ModuleBuilder<F>
|
|
|
|
where F: Invoke<elements::Module>
|
|
|
|
{
|
|
|
|
type Result = Self;
|
|
|
|
|
|
|
|
fn invoke(self, entry: elements::ImportEntry) -> Self::Result {
|
|
|
|
self.with_import(entry)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-09 15:23:05 +03:00
|
|
|
impl<F> Invoke<elements::ExportEntry> for ModuleBuilder<F>
|
|
|
|
where F: Invoke<elements::Module>
|
|
|
|
{
|
|
|
|
type Result = Self;
|
|
|
|
|
|
|
|
fn invoke(self, entry: elements::ExportEntry) -> Self::Result {
|
|
|
|
self.with_export(entry)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-09 17:38:51 +03:00
|
|
|
impl<F> Invoke<elements::GlobalEntry> for ModuleBuilder<F>
|
|
|
|
where F: Invoke<elements::Module>
|
|
|
|
{
|
|
|
|
type Result = Self;
|
|
|
|
|
|
|
|
fn invoke(self, entry: elements::GlobalEntry) -> Self::Result {
|
|
|
|
self.with_global(entry)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-09 15:17:12 +03:00
|
|
|
impl<F> Invoke<elements::DataSegment> for ModuleBuilder<F>
|
|
|
|
where F: Invoke<elements::Module>
|
|
|
|
{
|
|
|
|
type Result = Self;
|
|
|
|
|
|
|
|
fn invoke(self, segment: elements::DataSegment) -> Self {
|
|
|
|
self.with_data_segment(segment)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-06 11:34:31 +03:00
|
|
|
/// Start new module builder
|
2017-06-27 13:45:33 +03:00
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use parity_wasm::builder;
|
|
|
|
///
|
|
|
|
/// let module = builder::module()
|
|
|
|
/// .function()
|
|
|
|
/// .signature().param().i32().build()
|
|
|
|
/// .body().build()
|
|
|
|
/// .build()
|
|
|
|
/// .build();
|
|
|
|
///
|
|
|
|
/// assert_eq!(module.type_section().expect("type section to exist").types().len(), 1);
|
|
|
|
/// assert_eq!(module.function_section().expect("function section to exist").entries().len(), 1);
|
|
|
|
/// assert_eq!(module.code_section().expect("code section to exist").bodies().len(), 1);
|
|
|
|
/// ```
|
2017-04-06 11:34:31 +03:00
|
|
|
pub fn module() -> ModuleBuilder {
|
|
|
|
ModuleBuilder::new()
|
|
|
|
}
|
|
|
|
|
2017-04-10 13:11:34 +03:00
|
|
|
/// Start builder to extend existing module
|
|
|
|
pub fn from_module(module: elements::Module) -> ModuleBuilder {
|
|
|
|
ModuleBuilder::new().with_module(module)
|
|
|
|
}
|
|
|
|
|
2017-04-06 11:34:31 +03:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
|
|
|
|
use super::module;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn smoky() {
|
|
|
|
let module = module().build();
|
|
|
|
assert_eq!(module.sections().len(), 0);
|
|
|
|
}
|
|
|
|
|
2017-04-06 16:00:12 +03:00
|
|
|
#[test]
|
|
|
|
fn functions() {
|
|
|
|
let module = module()
|
2017-04-11 13:35:19 +03:00
|
|
|
.function()
|
|
|
|
.signature().param().i32().build()
|
|
|
|
.body().build()
|
|
|
|
.build()
|
2017-04-06 16:00:12 +03:00
|
|
|
.build();
|
|
|
|
|
|
|
|
assert_eq!(module.type_section().expect("type section to exist").types().len(), 1);
|
2017-06-03 23:37:36 +03:00
|
|
|
assert_eq!(module.function_section().expect("function section to exist").entries().len(), 1);
|
2017-04-11 13:35:19 +03:00
|
|
|
assert_eq!(module.code_section().expect("code section to exist").bodies().len(), 1);
|
2017-04-06 16:00:12 +03:00
|
|
|
}
|
|
|
|
|
2017-05-09 15:23:05 +03:00
|
|
|
#[test]
|
|
|
|
fn export() {
|
|
|
|
let module = module()
|
|
|
|
.export().field("call").internal().func(0).build()
|
|
|
|
.build();
|
|
|
|
|
|
|
|
assert_eq!(module.export_section().expect("export section to exist").entries().len(), 1);
|
|
|
|
}
|
2017-05-09 17:38:51 +03:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn global() {
|
|
|
|
let module = module()
|
|
|
|
.global().value_type().i64().mutable().init_expr(::elements::Opcode::I64Const(5)).build()
|
|
|
|
.build();
|
|
|
|
|
|
|
|
assert_eq!(module.global_section().expect("global section to exist").entries().len(), 1);
|
|
|
|
}
|
2017-06-09 15:19:21 +03:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn data() {
|
|
|
|
let module = module()
|
|
|
|
.data()
|
|
|
|
.offset(::elements::Opcode::I32Const(16))
|
|
|
|
.value(vec![0u8, 15, 10, 5, 25])
|
|
|
|
.build()
|
|
|
|
.build();
|
|
|
|
|
|
|
|
assert_eq!(module.data_section().expect("data section to exist").entries().len(), 1);
|
|
|
|
}
|
2017-05-09 17:38:51 +03:00
|
|
|
}
|