diff --git a/examples/inject.rs b/examples/inject.rs index c03d8d4..03d027a 100644 --- a/examples/inject.rs +++ b/examples/inject.rs @@ -3,6 +3,7 @@ extern crate parity_wasm; use std::env; use parity_wasm::elements; +use parity_wasm::builder; pub fn inject_nop(opcodes: &mut elements::Opcodes) { use parity_wasm::elements::Opcode::*; @@ -38,5 +39,19 @@ fn main() { } } - parity_wasm::serialize_to_file(&args[2], module).unwrap(); + let mut build = builder::from_module(module); + let import_sig = build.push_signature( + builder::signature() + .param().i32() + .param().i32() + .return_type().i32() + .build_sig() + ); + let build = build.import() + .module("env") + .field("log") + .external().func(import_sig) + .build(); + + parity_wasm::serialize_to_file(&args[2], build.build()).unwrap(); } \ No newline at end of file diff --git a/src/builder/code.rs b/src/builder/code.rs index d919f97..710a377 100644 --- a/src/builder/code.rs +++ b/src/builder/code.rs @@ -12,6 +12,12 @@ pub struct SignatureBuilder { signature: elements::FunctionType, } +impl SignatureBuilder { + pub fn new() -> Self { + SignatureBuilder::with_callback(Identity) + } +} + impl SignatureBuilder where F: Invoke { pub fn with_callback(callback: F) -> Self { SignatureBuilder { @@ -50,6 +56,10 @@ impl SignatureBuilder where F: Invoke { pub fn build(self) -> F::Result { self.callback.invoke(self.signature) } + + pub fn build_sig(self) -> Signature { + Signature::Inline(self.signature) + } } impl Invoke> for SignatureBuilder @@ -298,6 +308,11 @@ 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() diff --git a/src/builder/mod.rs b/src/builder/mod.rs index 6a2436e..06766b8 100644 --- a/src/builder/mod.rs +++ b/src/builder/mod.rs @@ -7,5 +7,5 @@ mod misc; mod import; pub use self::module::{module, from_module, ModuleBuilder}; -pub use self::code::{signatures, function}; +pub use self::code::{signatures, signature, function}; pub use self::import::import; \ No newline at end of file diff --git a/src/builder/module.rs b/src/builder/module.rs index 0eacbd7..8a7701b 100644 --- a/src/builder/module.rs +++ b/src/builder/module.rs @@ -123,22 +123,13 @@ impl ModuleBuilder where F: Invoke { pub fn push_function(&mut self, func: code::FunctionDefinition) -> CodeLocation { let signature = func.signature; let body = func.code; - let module = &mut self.module; - let type_ref = match signature { - code::Signature::Inline(func_type) => { - module.types.types_mut().push(elements::Type::Function(func_type)); - module.types.types().len() as u32 - 1 - } - code::Signature::TypeReference(type_ref) => { - type_ref - } - }; + let type_ref = self.resolve_type_ref(signature); - module.functions.entries_mut().push(elements::Func::new(type_ref)); - let signature_index = module.functions.entries_mut().len() as u32 - 1; - module.code.bodies_mut().push(body); - let body_index = module.code.bodies_mut().len() as u32 - 1; + 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; CodeLocation { signature: signature_index, @@ -146,17 +137,36 @@ impl ModuleBuilder where F: Invoke { } } + fn resolve_type_ref(&mut self, signature: code::Signature) -> u32 { + match signature { + code::Signature::Inline(func_type) => { + 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 { + let type_ref = self.resolve_type_ref(signature); + self.module.functions.entries_mut().push(elements::Func::new(type_ref)); + self.module.functions.entries_mut().len() as u32 - 1 + } + /// Push signatures in the module, returning corresponding indices of pushed signatures pub fn push_signatures(&mut self, signatures: code::SignatureBindings) -> Vec { - let module = &mut self.module; let mut result = Vec::new(); // todo: maybe reuse existing types with the equal signatures let raw_functions: Vec = signatures.into_iter().map(|binding| match binding { code::Signature::Inline(func_type) => { - module.types.types_mut().push(elements::Type::Function(func_type)); - module.types.types().len() as u32 - 1 + 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 @@ -165,8 +175,8 @@ impl ModuleBuilder where F: Invoke { ).collect(); for function in raw_functions { - module.functions.entries_mut().push(elements::Func::new(function)); - result.push(module.functions.entries_mut().len() as u32 - 1); + self.module.functions.entries_mut().push(elements::Func::new(function)); + result.push(self.module.functions.entries_mut().len() as u32 - 1); } result