summaryrefslogtreecommitdiffstats
path: root/third_party/rust/parity-wasm/src/builder
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/parity-wasm/src/builder
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--third_party/rust/parity-wasm/src/builder/code.rs414
-rw-r--r--third_party/rust/parity-wasm/src/builder/data.rs56
-rw-r--r--third_party/rust/parity-wasm/src/builder/export.rs116
-rw-r--r--third_party/rust/parity-wasm/src/builder/global.rs93
-rw-r--r--third_party/rust/parity-wasm/src/builder/import.rs130
-rw-r--r--third_party/rust/parity-wasm/src/builder/invoke.rs17
-rw-r--r--third_party/rust/parity-wasm/src/builder/memory.rs85
-rw-r--r--third_party/rust/parity-wasm/src/builder/misc.rs93
-rw-r--r--third_party/rust/parity-wasm/src/builder/mod.rs25
-rw-r--r--third_party/rust/parity-wasm/src/builder/module.rs598
-rw-r--r--third_party/rust/parity-wasm/src/builder/table.rs85
11 files changed, 1712 insertions, 0 deletions
diff --git a/third_party/rust/parity-wasm/src/builder/code.rs b/third_party/rust/parity-wasm/src/builder/code.rs
new file mode 100644
index 0000000000..305a7e7fad
--- /dev/null
+++ b/third_party/rust/parity-wasm/src/builder/code.rs
@@ -0,0 +1,414 @@
+use alloc::vec::Vec;
+use crate::elements;
+use super::{
+ invoke::{Invoke, Identity},
+ misc::{ValueTypeBuilder, ValueTypesBuilder, OptionalValueTypeBuilder},
+};
+
+/// Signature template description
+pub enum Signature {
+ TypeReference(u32),
+ Inline(elements::FunctionType),
+}
+
+/// Signature builder
+pub struct SignatureBuilder<F=Identity> {
+ callback: F,
+ signature: elements::FunctionType,
+}
+
+impl SignatureBuilder {
+ /// New signature builder
+ pub fn new() -> Self {
+ SignatureBuilder::with_callback(Identity)
+ }
+}
+
+impl<F> SignatureBuilder<F> where F: Invoke<elements::FunctionType> {
+ /// New builder with callback function specified
+ pub fn with_callback(callback: F) -> Self {
+ SignatureBuilder {
+ callback: callback,
+ signature: elements::FunctionType::default(),
+ }
+ }
+
+ /// Add argument to signature builder
+ pub fn with_param(mut self, value_type: elements::ValueType) -> Self {
+ self.signature.params_mut().push(value_type);
+ self
+ }
+
+ /// Add multiple arguments to signature builder
+ pub fn with_params(mut self, value_types: Vec<elements::ValueType>) -> Self {
+ self.signature.params_mut().extend(value_types);
+ self
+ }
+
+ /// Override signature return type
+ pub fn with_return_type(mut self, return_type: Option<elements::ValueType>) -> Self {
+ *self.signature.return_type_mut() = return_type;
+ self
+ }
+
+ /// Start build new argument
+ pub fn param(self) -> ValueTypeBuilder<Self> {
+ ValueTypeBuilder::with_callback(self)
+ }
+
+ /// Start build multiple arguments
+ pub fn params(self) -> ValueTypesBuilder<Self> {
+ ValueTypesBuilder::with_callback(self)
+ }
+
+ /// Start building return type
+ pub fn return_type(self) -> OptionalValueTypeBuilder<Self> {
+ OptionalValueTypeBuilder::with_callback(self)
+ }
+
+ /// Finish current builder
+ pub fn build(self) -> F::Result {
+ self.callback.invoke(self.signature)
+ }
+
+ /// Finish current builder returning intermediate `Signature` struct
+ pub fn build_sig(self) -> Signature {
+ Signature::Inline(self.signature)
+ }
+}
+
+impl<F> Invoke<Vec<elements::ValueType>> for SignatureBuilder<F>
+ where F: Invoke<elements::FunctionType>
+{
+ type Result = Self;
+
+ fn invoke(self, args: Vec<elements::ValueType>) -> Self {
+ self.with_params(args)
+ }
+}
+
+impl<F> Invoke<Option<elements::ValueType>> for SignatureBuilder<F>
+ where F: Invoke<elements::FunctionType>
+{
+ type Result = Self;
+
+ fn invoke(self, arg: Option<elements::ValueType>) -> Self {
+ self.with_return_type(arg)
+ }
+}
+
+impl<F> Invoke<elements::ValueType> for SignatureBuilder<F>
+ where F: Invoke<elements::FunctionType>
+{
+ type Result = Self;
+
+ fn invoke(self, arg: elements::ValueType) -> Self {
+ self.with_param(arg)
+ }
+}
+
+/// Type (signature) reference builder (for function/import/indirect call)
+pub struct TypeRefBuilder<F=Identity> {
+ callback: F,
+ type_ref: u32,
+}
+
+impl<F> TypeRefBuilder<F> where F: Invoke<u32> {
+ /// New builder chained with specified callback
+ pub fn with_callback(callback: F) -> Self {
+ TypeRefBuilder {
+ callback: callback,
+ type_ref: 0
+ }
+ }
+
+ /// Set/override of type reference
+ pub fn val(mut self, val: u32) -> Self {
+ self.type_ref = val;
+ self
+ }
+
+ /// Finish current builder
+ pub fn build(self) -> F::Result { self.callback.invoke(self.type_ref) }
+}
+
+/// Multiple signatures builder
+pub struct SignaturesBuilder<F=Identity> {
+ callback: F,
+ section: Vec<Signature>,
+}
+
+impl SignaturesBuilder {
+ /// New empty functions section builder
+ pub fn new() -> Self {
+ SignaturesBuilder::with_callback(Identity)
+ }
+}
+
+impl<F> SignaturesBuilder<F> {
+ /// New builder chained with specified callback
+ pub fn with_callback(callback: F) -> Self {
+ SignaturesBuilder {
+ callback: callback,
+ section: Vec::new(),
+ }
+ }
+
+ /// Push new signature into the builder output
+ pub fn with_signature(mut self, signature: Signature) -> Self {
+ self.section.push(signature);
+ self
+ }
+
+ /// Start building new signature with `TypeRefBuilder`
+ pub fn type_ref(self) -> TypeRefBuilder<Self> {
+ TypeRefBuilder::with_callback(self)
+ }
+}
+
+impl<F> SignaturesBuilder<F> where F: Invoke<SignatureBindings> {
+ /// Start building new signature with dedicated builder
+ pub fn signature(self) -> SignatureBuilder<Self> {
+ SignatureBuilder::with_callback(self)
+ }
+}
+
+impl<F> Invoke<elements::FunctionType> for SignaturesBuilder<F> {
+ type Result = Self;
+
+ fn invoke(self, signature: elements::FunctionType) -> Self {
+ self.with_signature(Signature::Inline(signature))
+ }
+}
+
+impl<F> Invoke<u32> for SignaturesBuilder<F> {
+ type Result = Self;
+
+ fn invoke(self, type_ref: u32) -> Self {
+ self.with_signature(Signature::TypeReference(type_ref))
+ }
+}
+
+impl<F> SignaturesBuilder<F> where F: Invoke<elements::FunctionSection> {
+
+ /// Finalize builder spawning element
+ pub fn build(self) -> F::Result {
+ let mut result = elements::FunctionSection::default();
+ for f in self.section.into_iter() {
+ if let Signature::TypeReference(type_ref) = f {
+ result.entries_mut().push(elements::Func::new(type_ref));
+ } else {
+ unreachable!(); // never possible with current generics impl-s
+ }
+ }
+ self.callback.invoke(result)
+ }
+}
+
+/// Signature bindings
+pub type SignatureBindings = Vec<Signature>;
+
+impl<F> SignaturesBuilder<F> where F: Invoke<SignatureBindings> {
+ /// Bind signature list
+ pub fn bind(self) -> F::Result {
+ self.callback.invoke(self.section)
+ }
+}
+
+/// Function body (code) builder
+pub struct FuncBodyBuilder<F=Identity> {
+ callback: F,
+ body: elements::FuncBody,
+}
+
+impl<F> FuncBodyBuilder<F> {
+ /// New body (code) builder given the chain callback
+ pub fn with_callback(callback: F) -> Self {
+ FuncBodyBuilder {
+ callback: callback,
+ body: elements::FuncBody::new(Vec::new(), elements::Instructions::empty()),
+ }
+ }
+}
+
+impl<F> FuncBodyBuilder<F> where F: Invoke<elements::FuncBody> {
+ /// Set/override entirely with FuncBody struct
+ pub fn with_func(mut self, func: elements::FuncBody) -> Self {
+ self.body = func;
+ self
+ }
+
+ /// Extend function local list with new entries
+ pub fn with_locals(mut self, locals: Vec<elements::Local>) -> Self {
+ self.body.locals_mut().extend(locals);
+ self
+ }
+
+ /// Set code of the function
+ pub fn with_instructions(mut self, instructions: elements::Instructions) -> Self {
+ *self.body.code_mut() = instructions;
+ self
+ }
+
+ /// Finish current builder spawning resulting struct
+ pub fn build(self) -> F::Result {
+ self.callback.invoke(self.body)
+ }
+}
+
+/// Function definition (extended structure to specify function entirely, incl. signature, mainness and code)
+pub struct FunctionDefinition {
+ /// Is this function is start function
+ pub is_main: bool,
+ /// Signature description
+ pub signature: Signature,
+ /// Body (code) of the function
+ pub code: elements::FuncBody,
+}
+
+impl Default for FunctionDefinition {
+ fn default() -> Self {
+ FunctionDefinition {
+ is_main: false,
+ signature: Signature::TypeReference(0),
+ code: elements::FuncBody::empty(),
+ }
+ }
+}
+
+/// Function definition builder
+pub struct FunctionBuilder<F=Identity> {
+ callback: F,
+ func: FunctionDefinition,
+}
+
+impl FunctionBuilder {
+ /// New function builder
+ pub fn new() -> Self {
+ FunctionBuilder::with_callback(Identity)
+ }
+}
+
+impl<F> FunctionBuilder<F> where F: Invoke<FunctionDefinition> {
+ /// New function builder with chained callback
+ pub fn with_callback(callback: F) -> Self {
+ FunctionBuilder {
+ callback: callback,
+ func: Default::default(),
+ }
+ }
+
+ /// Set that this function is main entry point
+ pub fn main(mut self) -> Self {
+ self.func.is_main = true;
+ self
+ }
+
+ /// Start signature builder of the function
+ pub fn signature(self) -> SignatureBuilder<Self> {
+ SignatureBuilder::with_callback(self)
+ }
+
+ /// Override current signature entirely with new one from known struct
+ pub fn with_signature(mut self, signature: Signature) -> Self {
+ self.func.signature = signature;
+ self
+ }
+
+ /// Start code (body) builder
+ pub fn body(self) -> FuncBodyBuilder<Self> {
+ FuncBodyBuilder::with_callback(self)
+ }
+
+ /// Set body (code) for this function
+ pub fn with_body(mut self, body: elements::FuncBody) -> Self {
+ self.func.code = body;
+ self
+ }
+
+ /// Finalize current builder spawning resulting struct in the callback
+ pub fn build(self) -> F::Result {
+ self.callback.invoke(self.func)
+ }
+}
+
+impl<F> Invoke<elements::FunctionType> for FunctionBuilder<F> where F: Invoke<FunctionDefinition> {
+ type Result = Self;
+
+ fn invoke(self, signature: elements::FunctionType) -> Self {
+ self.with_signature(Signature::Inline(signature))
+ }
+}
+
+impl<F> Invoke<u32> for FunctionBuilder<F> where F: Invoke<FunctionDefinition> {
+ type Result = Self;
+
+ fn invoke(self, type_ref: u32) -> Self {
+ self.with_signature(Signature::TypeReference(type_ref))
+ }
+}
+
+impl<F> Invoke<elements::FuncBody> for FunctionBuilder<F> where F: Invoke<FunctionDefinition> {
+ type Result = Self;
+
+ fn invoke(self, body: elements::FuncBody) -> Self::Result {
+ self.with_body(body)
+ }
+}
+
+/// New builder of signature list
+pub fn signatures() -> SignaturesBuilder {
+ SignaturesBuilder::new()
+}
+
+/// New signature builder
+pub fn signature() -> SignatureBuilder {
+ SignatureBuilder::new()
+}
+
+/// New builder of function (signature & body)
+pub fn function() -> FunctionBuilder {
+ FunctionBuilder::new()
+}
+
+#[cfg(test)]
+mod tests {
+
+ use super::{signatures, function};
+ use crate::elements;
+
+ #[test]
+ fn example() {
+ let result = signatures()
+ .type_ref().val(1).build()
+ .build();
+
+ assert_eq!(result.entries().len(), 1);
+
+ let result = signatures()
+ .signature()
+ .param().i32()
+ .param().i32()
+ .return_type().i64()
+ .build()
+ .bind();
+
+ assert_eq!(result.len(), 1);
+ }
+
+ #[test]
+ fn func_example() {
+ let func = function()
+ .signature()
+ .param().i32()
+ .return_type().i32()
+ .build()
+ .body()
+ .with_instructions(elements::Instructions::empty())
+ .build()
+ .build();
+
+ assert_eq!(func.code.locals().len(), 0);
+ assert_eq!(func.code.code().elements().len(), 1);
+ }
+}
diff --git a/third_party/rust/parity-wasm/src/builder/data.rs b/third_party/rust/parity-wasm/src/builder/data.rs
new file mode 100644
index 0000000000..bca5e34f1a
--- /dev/null
+++ b/third_party/rust/parity-wasm/src/builder/data.rs
@@ -0,0 +1,56 @@
+use alloc::vec::Vec;
+use super::invoke::{Identity, Invoke};
+use crate::elements;
+
+/// Data segment builder
+pub struct DataSegmentBuilder<F=Identity> {
+ callback: F,
+ // todo: add mapper once multiple memory refs possible
+ mem_index: u32,
+ offset: elements::InitExpr,
+ value: Vec<u8>,
+}
+
+impl DataSegmentBuilder {
+ /// New data segment builder
+ pub fn new() -> Self {
+ DataSegmentBuilder::with_callback(Identity)
+ }
+}
+
+impl<F> DataSegmentBuilder<F> {
+ /// New data segment builder inside the chain context
+ pub fn with_callback(callback: F) -> Self {
+ DataSegmentBuilder {
+ callback: callback,
+ mem_index: 0,
+ offset: elements::InitExpr::empty(),
+ value: Vec::new(),
+ }
+ }
+
+ /// Set offset initialization instruction. `End` instruction will be added automatically.
+ pub fn offset(mut self, instruction: elements::Instruction) -> Self {
+ self.offset = elements::InitExpr::new(vec![instruction, elements::Instruction::End]);
+ self
+ }
+
+ /// Set the bytes value of the segment
+ pub fn value(mut self, value: Vec<u8>) -> Self {
+ self.value = value;
+ self
+ }
+}
+
+impl<F> DataSegmentBuilder<F> where F: Invoke<elements::DataSegment> {
+ /// Finish current builder, spawning resulting struct
+ pub fn build(self) -> F::Result {
+ self.callback.invoke(
+ elements::DataSegment::new(
+ self.mem_index,
+ Some(self.offset),
+ self.value,
+ )
+ )
+ }
+}
diff --git a/third_party/rust/parity-wasm/src/builder/export.rs b/third_party/rust/parity-wasm/src/builder/export.rs
new file mode 100644
index 0000000000..a2de79c24e
--- /dev/null
+++ b/third_party/rust/parity-wasm/src/builder/export.rs
@@ -0,0 +1,116 @@
+use alloc::{borrow::ToOwned, string::String};
+use super::invoke::{Invoke, Identity};
+use crate::elements;
+
+/// Export entry builder
+pub struct ExportBuilder<F=Identity> {
+ callback: F,
+ field: String,
+ binding: elements::Internal,
+}
+
+impl ExportBuilder {
+ /// New export builder
+ pub fn new() -> Self {
+ ExportBuilder::with_callback(Identity)
+ }
+}
+
+impl<F> ExportBuilder<F> {
+
+ /// New export entry builder in the specified chained context
+ pub fn with_callback(callback: F) -> Self {
+ ExportBuilder {
+ callback: callback,
+ field: String::new(),
+ binding: elements::Internal::Function(0),
+ }
+ }
+
+ /// Set the field name of the export entry
+ pub fn field(mut self, field: &str) -> Self {
+ self.field = field.to_owned();
+ self
+ }
+
+ /// Specify the internal module mapping for this entry
+ pub fn with_internal(mut self, external: elements::Internal) -> Self {
+ self.binding = external;
+ self
+ }
+
+ /// Start the internal builder for this export entry
+ pub fn internal(self) -> ExportInternalBuilder<Self> {
+ ExportInternalBuilder::with_callback(self)
+ }
+}
+
+impl<F> ExportBuilder<F> where F: Invoke<elements::ExportEntry> {
+ /// Finalize export entry builder spawning the resulting struct
+ pub fn build(self) -> F::Result {
+ self.callback.invoke(elements::ExportEntry::new(self.field, self.binding))
+ }
+}
+
+impl<F> Invoke<elements::Internal> for ExportBuilder<F> {
+ type Result = Self;
+ fn invoke(self, val: elements::Internal) -> Self {
+ self.with_internal(val)
+ }
+}
+
+/// Internal mapping builder for export entry
+pub struct ExportInternalBuilder<F=Identity> {
+ callback: F,
+ binding: elements::Internal,
+}
+
+impl<F> ExportInternalBuilder<F> where F: Invoke<elements::Internal> {
+ /// New export entry internal mapping for the chained context
+ pub fn with_callback(callback: F) -> Self {
+ ExportInternalBuilder{
+ callback: callback,
+ binding: elements::Internal::Function(0),
+ }
+ }
+
+ /// Map to function by index
+ pub fn func(mut self, index: u32) -> F::Result {
+ self.binding = elements::Internal::Function(index);
+ self.callback.invoke(self.binding)
+ }
+
+ /// Map to memory
+ pub fn memory(mut self, index: u32) -> F::Result {
+ self.binding = elements::Internal::Memory(index);
+ self.callback.invoke(self.binding)
+ }
+
+ /// Map to table
+ pub fn table(mut self, index: u32) -> F::Result {
+ self.binding = elements::Internal::Table(index);
+ self.callback.invoke(self.binding)
+ }
+
+ /// Map to global
+ pub fn global(mut self, index: u32) -> F::Result {
+ self.binding = elements::Internal::Global(index);
+ self.callback.invoke(self.binding)
+ }
+}
+
+/// New builder for export entry
+pub fn export() -> ExportBuilder {
+ ExportBuilder::new()
+}
+
+#[cfg(test)]
+mod tests {
+ use super::export;
+
+ #[test]
+ fn example() {
+ let entry = export().field("memory").internal().memory(0).build();
+ assert_eq!(entry.field(), "memory");
+ }
+}
diff --git a/third_party/rust/parity-wasm/src/builder/global.rs b/third_party/rust/parity-wasm/src/builder/global.rs
new file mode 100644
index 0000000000..0b3acb8560
--- /dev/null
+++ b/third_party/rust/parity-wasm/src/builder/global.rs
@@ -0,0 +1,93 @@
+use super::{
+ invoke::{Invoke, Identity},
+ misc::ValueTypeBuilder,
+};
+
+use crate::elements;
+
+/// Global builder
+pub struct GlobalBuilder<F=Identity> {
+ callback: F,
+ value_type: elements::ValueType,
+ is_mutable: bool,
+ init_expr: elements::InitExpr,
+}
+
+impl GlobalBuilder {
+ /// New global builder
+ pub fn new() -> Self {
+ GlobalBuilder::with_callback(Identity)
+ }
+}
+
+impl<F> GlobalBuilder<F> {
+ /// New global builder with callback (in chained context)
+ pub fn with_callback(callback: F) -> Self {
+ GlobalBuilder {
+ callback: callback,
+ value_type: elements::ValueType::I32,
+ init_expr: elements::InitExpr::empty(),
+ is_mutable: false,
+ }
+ }
+
+ /// Set/override resulting global type
+ pub fn with_type(mut self, value_type: elements::ValueType) -> Self {
+ self.value_type = value_type;
+ self
+ }
+
+ /// Set mutabilty to true
+ pub fn mutable(mut self) -> Self {
+ self.is_mutable = true;
+ self
+ }
+
+ /// Set initialization expression instruction for this global (`end` instruction will be added automatically)
+ pub fn init_expr(mut self, instruction: elements::Instruction) -> Self {
+ self.init_expr = elements::InitExpr::new(vec![instruction, elements::Instruction::End]);
+ self
+ }
+
+ /// Start value type builder
+ pub fn value_type(self) -> ValueTypeBuilder<Self> {
+ ValueTypeBuilder::with_callback(self)
+ }
+}
+
+impl<F> GlobalBuilder<F> where F: Invoke<elements::GlobalEntry> {
+ /// Finalize current builder spawning resulting struct
+ pub fn build(self) -> F::Result {
+ self.callback.invoke(
+ elements::GlobalEntry::new(
+ elements::GlobalType::new(self.value_type, self.is_mutable),
+ self.init_expr,
+ )
+ )
+ }
+}
+
+impl<F> Invoke<elements::ValueType> for GlobalBuilder<F> {
+ type Result = Self;
+ fn invoke(self, the_type: elements::ValueType) -> Self {
+ self.with_type(the_type)
+ }
+}
+
+/// New builder for export entry
+pub fn global() -> GlobalBuilder {
+ GlobalBuilder::new()
+}
+
+#[cfg(test)]
+mod tests {
+ use super::global;
+ use crate::elements;
+
+ #[test]
+ fn example() {
+ let entry = global().value_type().i32().build();
+ assert_eq!(entry.global_type().content_type(), elements::ValueType::I32);
+ assert_eq!(entry.global_type().is_mutable(), false);
+ }
+}
diff --git a/third_party/rust/parity-wasm/src/builder/import.rs b/third_party/rust/parity-wasm/src/builder/import.rs
new file mode 100644
index 0000000000..4d9d7665fe
--- /dev/null
+++ b/third_party/rust/parity-wasm/src/builder/import.rs
@@ -0,0 +1,130 @@
+use alloc::{borrow::ToOwned, string::String};
+use super::invoke::{Identity, Invoke};
+use crate::elements;
+
+/// Import builder
+pub struct ImportBuilder<F=Identity> {
+ callback: F,
+ module: String,
+ field: String,
+ binding: elements::External,
+}
+
+impl ImportBuilder {
+ /// New import builder
+ pub fn new() -> Self {
+ ImportBuilder::with_callback(Identity)
+ }
+}
+
+impl<F> ImportBuilder<F> {
+ /// New import builder with callback (in chained context)
+ pub fn with_callback(callback: F) -> Self {
+ ImportBuilder {
+ callback: callback,
+ module: String::new(),
+ field: String::new(),
+ binding: elements::External::Function(0),
+ }
+ }
+
+ /// Set/override module name
+ pub fn module(mut self, name: &str) -> Self {
+ self.module = name.to_owned();
+ self
+ }
+
+ /// Set/override field name
+ pub fn field(mut self, name: &str) -> Self {
+ self.field = name.to_owned();
+ self
+ }
+
+ /// Set/override both module name and field name
+ pub fn path(self, module: &str, field: &str) -> Self {
+ self.module(module).field(field)
+ }
+
+ /// Set/override external mapping for this import
+ pub fn with_external(mut self, external: elements::External) -> Self {
+ self.binding = external;
+ self
+ }
+
+ /// Start new external mapping builder
+ pub fn external(self) -> ImportExternalBuilder<Self> {
+ ImportExternalBuilder::with_callback(self)
+ }
+}
+
+impl<F> ImportBuilder<F> where F: Invoke<elements::ImportEntry> {
+ /// Finalize current builder spawning the resulting struct
+ pub fn build(self) -> F::Result {
+ self.callback.invoke(elements::ImportEntry::new(self.module, self.field, self.binding))
+ }
+}
+
+impl<F> Invoke<elements::External> for ImportBuilder<F> {
+ type Result = Self;
+ fn invoke(self, val: elements::External) -> Self {
+ self.with_external(val)
+ }
+}
+
+/// Import to external mapping builder
+pub struct ImportExternalBuilder<F=Identity> {
+ callback: F,
+ binding: elements::External,
+}
+
+impl<F> ImportExternalBuilder<F> where F: Invoke<elements::External> {
+ /// New import to external mapping builder with callback (in chained context)
+ pub fn with_callback(callback: F) -> Self {
+ ImportExternalBuilder{
+ callback: callback,
+ binding: elements::External::Function(0),
+ }
+ }
+
+ /// Function mapping with type reference
+ pub fn func(mut self, index: u32) -> F::Result {
+ self.binding = elements::External::Function(index);
+ self.callback.invoke(self.binding)
+ }
+
+ /// Memory mapping with specified limits
+ pub fn memory(mut self, min: u32, max: Option<u32>) -> F::Result {
+ self.binding = elements::External::Memory(elements::MemoryType::new(min, max));
+ self.callback.invoke(self.binding)
+ }
+
+ /// Table mapping with specified limits
+ pub fn table(mut self, min: u32, max: Option<u32>) -> F::Result {
+ self.binding = elements::External::Table(elements::TableType::new(min, max));
+ self.callback.invoke(self.binding)
+ }
+
+ /// Global mapping with speciifed type and mutability
+ pub fn global(mut self, value_type: elements::ValueType, is_mut: bool) -> F::Result {
+ self.binding = elements::External::Global(elements::GlobalType::new(value_type, is_mut));
+ self.callback.invoke(self.binding)
+ }
+}
+
+/// New builder for import entry
+pub fn import() -> ImportBuilder {
+ ImportBuilder::new()
+}
+
+#[cfg(test)]
+mod tests {
+ use super::import;
+
+ #[test]
+ fn example() {
+ let entry = import().module("env").field("memory").external().memory(256, Some(256)).build();
+
+ assert_eq!(entry.module(), "env");
+ assert_eq!(entry.field(), "memory");
+ }
+}
diff --git a/third_party/rust/parity-wasm/src/builder/invoke.rs b/third_party/rust/parity-wasm/src/builder/invoke.rs
new file mode 100644
index 0000000000..1dd6598d0d
--- /dev/null
+++ b/third_party/rust/parity-wasm/src/builder/invoke.rs
@@ -0,0 +1,17 @@
+//! invoke helper
+
+/// Helper trait to allow chaining
+pub trait Invoke<A> {
+ type Result;
+
+ fn invoke(self, arg: A) -> Self::Result;
+}
+
+/// Identity chain element
+pub struct Identity;
+
+impl<A> Invoke<A> for Identity {
+ type Result = A;
+
+ fn invoke(self, arg: A) -> A { arg }
+} \ No newline at end of file
diff --git a/third_party/rust/parity-wasm/src/builder/memory.rs b/third_party/rust/parity-wasm/src/builder/memory.rs
new file mode 100644
index 0000000000..9f7a6887ef
--- /dev/null
+++ b/third_party/rust/parity-wasm/src/builder/memory.rs
@@ -0,0 +1,85 @@
+use alloc::vec::Vec;
+use crate::elements;
+use super::invoke::{Invoke, Identity};
+
+/// Memory definition struct
+#[derive(Debug, PartialEq)]
+pub struct MemoryDefinition {
+ /// Minimum memory size
+ pub min: u32,
+ /// Maximum memory size
+ pub max: Option<u32>,
+ /// Memory data segments (static regions)
+ pub data: Vec<MemoryDataDefinition>,
+}
+
+/// Memory static region entry definition
+#[derive(Debug, PartialEq)]
+pub struct MemoryDataDefinition {
+ /// Segment initialization expression for offset
+ pub offset: elements::InitExpr,
+ /// Raw bytes of static region
+ pub values: Vec<u8>,
+}
+
+/// Memory and static regions builder
+pub struct MemoryBuilder<F=Identity> {
+ callback: F,
+ memory: MemoryDefinition,
+}
+
+impl MemoryBuilder {
+ /// New memory builder
+ pub fn new() -> Self {
+ MemoryBuilder::with_callback(Identity)
+ }
+}
+
+impl<F> MemoryBuilder<F> where F: Invoke<MemoryDefinition> {
+ /// New memory builder with callback (in chained context)
+ pub fn with_callback(callback: F) -> Self {
+ MemoryBuilder {
+ callback: callback,
+ memory: Default::default(),
+ }
+ }
+
+ /// Set/override minimum size
+ pub fn with_min(mut self, min: u32) -> Self {
+ self.memory.min = min;
+ self
+ }
+
+ /// Set/override maximum size
+ pub fn with_max(mut self, max: Option<u32>) -> Self {
+ self.memory.max = max;
+ self
+ }
+
+ /// Push new static region with initialized offset expression and raw bytes
+ pub fn with_data(mut self, index: u32, values: Vec<u8>) -> Self {
+ self.memory.data.push(MemoryDataDefinition {
+ offset: elements::InitExpr::new(vec![
+ elements::Instruction::I32Const(index as i32),
+ elements::Instruction::End,
+ ]),
+ values: values,
+ });
+ self
+ }
+
+ /// Finalize current builder, spawning resulting struct
+ pub fn build(self) -> F::Result {
+ self.callback.invoke(self.memory)
+ }
+}
+
+impl Default for MemoryDefinition {
+ fn default() -> Self {
+ MemoryDefinition {
+ min: 1,
+ max: None,
+ data: Vec::new(),
+ }
+ }
+}
diff --git a/third_party/rust/parity-wasm/src/builder/misc.rs b/third_party/rust/parity-wasm/src/builder/misc.rs
new file mode 100644
index 0000000000..2b6cd2dcc5
--- /dev/null
+++ b/third_party/rust/parity-wasm/src/builder/misc.rs
@@ -0,0 +1,93 @@
+use alloc::vec::Vec;
+use super::invoke::{Invoke, Identity};
+use crate::elements;
+
+pub struct ValueTypeBuilder<F=Identity> {
+ callback: F,
+}
+
+impl<F> ValueTypeBuilder<F> where F: Invoke<elements::ValueType> {
+ pub fn with_callback(callback: F) -> Self {
+ ValueTypeBuilder { callback: callback }
+ }
+
+ pub fn i32(self) -> F::Result {
+ self.callback.invoke(elements::ValueType::I32)
+ }
+
+ pub fn i64(self) -> F::Result {
+ self.callback.invoke(elements::ValueType::I64)
+ }
+
+ pub fn f32(self) -> F::Result {
+ self.callback.invoke(elements::ValueType::F32)
+ }
+
+ pub fn f64(self) -> F::Result {
+ self.callback.invoke(elements::ValueType::F64)
+ }
+}
+
+pub struct OptionalValueTypeBuilder<F=Identity> {
+ callback: F,
+}
+
+impl<F> OptionalValueTypeBuilder<F> where F: Invoke<Option<elements::ValueType>> {
+ pub fn with_callback(callback: F) -> Self {
+ OptionalValueTypeBuilder { callback: callback }
+ }
+
+ pub fn i32(self) -> F::Result {
+ self.callback.invoke(Some(elements::ValueType::I32))
+ }
+
+ pub fn i64(self) -> F::Result {
+ self.callback.invoke(Some(elements::ValueType::I64))
+ }
+
+ pub fn f32(self) -> F::Result {
+ self.callback.invoke(Some(elements::ValueType::F32))
+ }
+
+ pub fn f64(self) -> F::Result {
+ self.callback.invoke(Some(elements::ValueType::F64))
+ }
+}
+
+pub struct ValueTypesBuilder<F=Identity> {
+ callback: F,
+ value_types: Vec<elements::ValueType>,
+}
+
+impl<F> ValueTypesBuilder<F> where F: Invoke<Vec<elements::ValueType>> {
+ pub fn with_callback(callback: F) -> Self {
+ ValueTypesBuilder {
+ callback: callback,
+ value_types: Vec::new(),
+ }
+ }
+
+ pub fn i32(mut self) -> Self {
+ self.value_types.push(elements::ValueType::I32);
+ self
+ }
+
+ pub fn i64(mut self) -> Self {
+ self.value_types.push(elements::ValueType::I64);
+ self
+ }
+
+ pub fn f32(mut self) -> Self {
+ self.value_types.push(elements::ValueType::F32);
+ self
+ }
+
+ pub fn f64(mut self) -> Self {
+ self.value_types.push(elements::ValueType::F64);
+ self
+ }
+
+ pub fn build(self) -> F::Result {
+ self.callback.invoke(self.value_types)
+ }
+}
diff --git a/third_party/rust/parity-wasm/src/builder/mod.rs b/third_party/rust/parity-wasm/src/builder/mod.rs
new file mode 100644
index 0000000000..b40b05efcd
--- /dev/null
+++ b/third_party/rust/parity-wasm/src/builder/mod.rs
@@ -0,0 +1,25 @@
+//! Various builders to generate/alter wasm components
+
+mod invoke;
+mod module;
+mod code;
+mod misc;
+mod import;
+mod memory;
+mod table;
+mod export;
+mod global;
+mod data;
+
+pub use self::code::{
+ signatures, signature, function, SignatureBuilder, SignaturesBuilder,
+ FunctionBuilder, TypeRefBuilder, FuncBodyBuilder, FunctionDefinition,
+};
+pub use self::data::DataSegmentBuilder;
+pub use self::export::{export, ExportBuilder, ExportInternalBuilder};
+pub use self::global::{global, GlobalBuilder};
+pub use self::import::{import, ImportBuilder};
+pub use self::invoke::Identity;
+pub use self::memory::MemoryBuilder;
+pub use self::module::{module, from_module, ModuleBuilder};
+pub use self::table::{TableBuilder, TableDefinition, TableEntryDefinition};
diff --git a/third_party/rust/parity-wasm/src/builder/module.rs b/third_party/rust/parity-wasm/src/builder/module.rs
new file mode 100644
index 0000000000..49806e126c
--- /dev/null
+++ b/third_party/rust/parity-wasm/src/builder/module.rs
@@ -0,0 +1,598 @@
+use alloc::vec::Vec;
+use crate::elements;
+use super::{
+ import,
+ export,
+ global,
+ data,
+ invoke::{Invoke, Identity},
+ code::{self, SignaturesBuilder, FunctionBuilder},
+ memory::{self, MemoryBuilder},
+ table::{self, TableBuilder},
+};
+
+/// Module builder
+pub struct ModuleBuilder<F=Identity> {
+ callback: F,
+ module: ModuleScaffold,
+}
+
+/// 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,
+}
+
+#[derive(Default, PartialEq)]
+struct ModuleScaffold {
+ pub types: elements::TypeSection,
+ pub import: elements::ImportSection,
+ pub functions: elements::FunctionSection,
+ pub table: elements::TableSection,
+ pub memory: elements::MemorySection,
+ pub global: elements::GlobalSection,
+ pub export: elements::ExportSection,
+ pub start: Option<u32>,
+ pub element: elements::ElementSection,
+ pub code: elements::CodeSection,
+ pub data: elements::DataSection,
+ pub other: Vec<elements::Section>,
+}
+
+impl From<elements::Module> for ModuleScaffold {
+ fn from(module: elements::Module) -> Self {
+ let mut types: Option<elements::TypeSection> = None;
+ let mut import: Option<elements::ImportSection> = None;
+ let mut funcs: Option<elements::FunctionSection> = None;
+ 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;
+ let mut code: Option<elements::CodeSection> = None;
+ let mut data: Option<elements::DataSection> = None;
+
+ let mut sections = module.into_sections();
+ while let Some(section) = sections.pop() {
+ match section {
+ elements::Section::Type(sect) => { types = Some(sect); }
+ elements::Section::Import(sect) => { import = Some(sect); }
+ 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); }
+ elements::Section::Code(sect) => { code = Some(sect); }
+ elements::Section::Data(sect) => { data = Some(sect); }
+ _ => {}
+ }
+ }
+
+ ModuleScaffold {
+ types: types.unwrap_or_default(),
+ import: import.unwrap_or_default(),
+ 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(),
+ code: code.unwrap_or_default(),
+ data: data.unwrap_or_default(),
+ 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));
+ }
+ let import = module.import;
+ if import.entries().len() > 0 {
+ sections.push(elements::Section::Import(import));
+ }
+ let functions = module.functions;
+ if functions.entries().len() > 0 {
+ sections.push(elements::Section::Function(functions));
+ }
+ 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));
+ }
+ let code = module.code;
+ if code.bodies().len() > 0 {
+ sections.push(elements::Section::Code(code));
+ }
+ let data = module.data;
+ if data.entries().len() > 0 {
+ sections.push(elements::Section::Data(data));
+ }
+ sections.extend(module.other);
+ elements::Module::new(sections)
+ }
+}
+
+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,
+ module: Default::default(),
+ }
+ }
+
+ /// Builder from raw module
+ pub fn with_module(mut self, module: elements::Module) -> Self {
+ self.module = module.into();
+ self
+ }
+
+ /// Fill module with sections from iterator
+ pub fn with_sections<I>(mut self, sections: I) -> Self
+ where I: IntoIterator<Item=elements::Section>
+ {
+ self.module.other.extend(sections);
+ self
+ }
+
+ /// Add additional section
+ pub fn with_section(mut self, section: elements::Section) -> Self {
+ self.module.other.push(section);
+ self
+ }
+
+ /// Binds to the type section, creates additional types when required
+ pub fn with_signatures(mut self, bindings: code::SignatureBindings) -> Self {
+ self.push_signatures(bindings);
+ self
+ }
+
+ /// 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;
+
+ let type_ref = self.resolve_type_ref(signature);
+
+ 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;
+
+ if func.is_main {
+ self.module.start = Some(body_index);
+ }
+
+ CodeLocation {
+ signature: signature_index,
+ body: body_index,
+ }
+ }
+
+ /// Push linear memory region
+ pub fn push_memory(&mut self, mut memory: memory::MemoryDefinition) -> u32 {
+ let entries = self.module.memory.entries_mut();
+ entries.push(elements::MemoryType::new(memory.min, memory.max));
+ 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, Some(data.offset), data.values))
+ }
+ memory_index
+ }
+
+ /// Push table
+ pub fn push_table(&mut self, mut table: table::TableDefinition) -> u32 {
+ let entries = self.module.table.entries_mut();
+ entries.push(elements::TableType::new(table.min, table.max));
+ 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, Some(entry.offset), entry.values))
+ }
+ table_index
+ }
+
+ fn resolve_type_ref(&mut self, signature: code::Signature) -> u32 {
+ match signature {
+ code::Signature::Inline(func_type) => {
+ if let Some(existing_entry) = self.module.types.types().iter().enumerate().find(|(_idx, t)| {
+ let elements::Type::Function(ref existing) = t;
+ *existing == func_type
+ }) {
+ return existing_entry.0 as u32
+ }
+ 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 {
+ self.resolve_type_ref(signature)
+ }
+
+ /// Push signatures in the module, returning corresponding indices of pushed signatures
+ pub fn push_signatures(&mut self, signatures: code::SignatureBindings) -> Vec<u32> {
+ signatures.into_iter().map(|binding|
+ self.resolve_type_ref(binding)
+ ).collect()
+ }
+
+ /// Push import entry to module. Note that this 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
+ }
+
+ /// 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
+ }
+
+ /// Add new function using dedicated builder
+ pub fn function(self) -> FunctionBuilder<Self> {
+ FunctionBuilder::with_callback(self)
+ }
+
+ /// Add new linear memory using dedicated builder
+ pub fn memory(self) -> MemoryBuilder<Self> {
+ MemoryBuilder::with_callback(self)
+ }
+
+ /// Add new table using dedicated builder
+ pub fn table(self) -> TableBuilder<Self> {
+ TableBuilder::with_callback(self)
+ }
+
+ /// Define functions section
+ pub fn functions(self) -> SignaturesBuilder<Self> {
+ SignaturesBuilder::with_callback(self)
+ }
+
+ /// With inserted export entry
+ pub fn with_export(mut self, entry: elements::ExportEntry) -> Self {
+ self.module.export.entries_mut().push(entry);
+ self
+ }
+
+ /// 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
+ /// # 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);
+ /// ```
+ pub fn import(self) -> import::ImportBuilder<Self> {
+ import::ImportBuilder::with_callback(self)
+ }
+
+ /// With global variable
+ pub fn with_global(mut self, global: elements::GlobalEntry) -> Self {
+ self.module.global.entries_mut().push(global);
+ self
+ }
+
+ /// With table
+ pub fn with_table(mut self, table: elements::TableType) -> Self {
+ self.module.table.entries_mut().push(table);
+ self
+ }
+
+ /// Export entry builder
+ /// # Examples
+ /// ```
+ /// use parity_wasm::builder::module;
+ /// use parity_wasm::elements::Instruction::*;
+ ///
+ /// let module = module()
+ /// .global()
+ /// .value_type().i32()
+ /// .init_expr(I32Const(0))
+ /// .build()
+ /// .export()
+ /// .field("_zero")
+ /// .internal().global(0)
+ /// .build()
+ /// .build();
+ ///
+ /// assert_eq!(module.export_section().expect("export section to exist").entries().len(), 1);
+ /// ```
+ pub fn export(self) -> export::ExportBuilder<Self> {
+ export::ExportBuilder::with_callback(self)
+ }
+
+ /// Glboal entry builder
+ /// # Examples
+ /// ```
+ /// use parity_wasm::builder::module;
+ /// use parity_wasm::elements::Instruction::*;
+ ///
+ /// 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);
+ /// ```
+ pub fn global(self) -> global::GlobalBuilder<Self> {
+ global::GlobalBuilder::with_callback(self)
+ }
+
+ /// 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)
+ }
+
+ /// Build module (final step)
+ pub fn build(self) -> F::Result {
+ self.callback.invoke(self.module.into())
+ }
+}
+
+impl<F> Invoke<elements::FunctionSection> for ModuleBuilder<F>
+ where F: Invoke<elements::Module>
+{
+ type Result = Self;
+
+ fn invoke(self, section: elements::FunctionSection) -> Self {
+ self.with_section(elements::Section::Function(section))
+ }
+}
+
+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)
+ }
+}
+
+
+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
+ }
+}
+
+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
+ }
+}
+
+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
+ }
+}
+
+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)
+ }
+}
+
+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)
+ }
+}
+
+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)
+ }
+}
+
+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)
+ }
+}
+
+/// Start new module builder
+/// # 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);
+/// ```
+pub fn module() -> ModuleBuilder {
+ ModuleBuilder::new()
+}
+
+/// Start builder to extend existing module
+pub fn from_module(module: elements::Module) -> ModuleBuilder {
+ ModuleBuilder::new().with_module(module)
+}
+
+#[cfg(test)]
+mod tests {
+
+ use crate::elements;
+ use super::module;
+
+ #[test]
+ fn smoky() {
+ let module = module().build();
+ assert_eq!(module.sections().len(), 0);
+ }
+
+ #[test]
+ fn functions() {
+ let module = 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);
+ }
+
+ #[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);
+ }
+
+ #[test]
+ fn global() {
+ let module = module()
+ .global().value_type().i64().mutable().init_expr(elements::Instruction::I64Const(5)).build()
+ .build();
+
+ assert_eq!(module.global_section().expect("global section to exist").entries().len(), 1);
+ }
+
+ #[test]
+ fn data() {
+ let module = module()
+ .data()
+ .offset(elements::Instruction::I32Const(16))
+ .value(vec![0u8, 15, 10, 5, 25])
+ .build()
+ .build();
+
+ assert_eq!(module.data_section().expect("data section to exist").entries().len(), 1);
+ }
+
+ #[test]
+ fn reuse_types() {
+ let module = module()
+ .function()
+ .signature().param().i32().build()
+ .body().build()
+ .build()
+ .function()
+ .signature().param().i32().build()
+ .body().build()
+ .build()
+ .build();
+
+ assert_eq!(module.type_section().expect("type section failed").types().len(), 1);
+ }
+ }
diff --git a/third_party/rust/parity-wasm/src/builder/table.rs b/third_party/rust/parity-wasm/src/builder/table.rs
new file mode 100644
index 0000000000..29bbe2d2dc
--- /dev/null
+++ b/third_party/rust/parity-wasm/src/builder/table.rs
@@ -0,0 +1,85 @@
+use alloc::vec::Vec;
+use crate::elements;
+use super::invoke::{Invoke, Identity};
+
+/// Table definition
+#[derive(Debug, PartialEq)]
+pub struct TableDefinition {
+ /// Minimum length
+ pub min: u32,
+ /// Maximum length, if any
+ pub max: Option<u32>,
+ /// Element segments, if any
+ pub elements: Vec<TableEntryDefinition>,
+}
+
+/// Table elements entry definition
+#[derive(Debug, PartialEq)]
+pub struct TableEntryDefinition {
+ /// Offset initialization expression
+ pub offset: elements::InitExpr,
+ /// Values of initialization
+ pub values: Vec<u32>,
+}
+
+/// Table builder
+pub struct TableBuilder<F=Identity> {
+ callback: F,
+ table: TableDefinition,
+}
+
+impl TableBuilder {
+ /// New table builder
+ pub fn new() -> Self {
+ TableBuilder::with_callback(Identity)
+ }
+}
+
+impl<F> TableBuilder<F> where F: Invoke<TableDefinition> {
+ /// New table builder with callback in chained context
+ pub fn with_callback(callback: F) -> Self {
+ TableBuilder {
+ callback: callback,
+ table: Default::default(),
+ }
+ }
+
+ /// Set/override minimum length
+ pub fn with_min(mut self, min: u32) -> Self {
+ self.table.min = min;
+ self
+ }
+
+ /// Set/override maximum length
+ pub fn with_max(mut self, max: Option<u32>) -> Self {
+ self.table.max = max;
+ self
+ }
+
+ /// Generate initialization expression and element values on specified index
+ pub fn with_element(mut self, index: u32, values: Vec<u32>) -> Self {
+ self.table.elements.push(TableEntryDefinition {
+ offset: elements::InitExpr::new(vec![
+ elements::Instruction::I32Const(index as i32),
+ elements::Instruction::End,
+ ]),
+ values: values,
+ });
+ self
+ }
+
+ /// Finalize current builder spawning resulting struct
+ pub fn build(self) -> F::Result {
+ self.callback.invoke(self.table)
+ }
+}
+
+impl Default for TableDefinition {
+ fn default() -> Self {
+ TableDefinition {
+ min: 0,
+ max: None,
+ elements: Vec::new(),
+ }
+ }
+}