mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-06-21 10:41:54 +00:00
module scaffolding and such
This commit is contained in:
22
examples/build.rs
Normal file
22
examples/build.rs
Normal file
@ -0,0 +1,22 @@
|
||||
extern crate parity_wasm;
|
||||
|
||||
use std::env;
|
||||
|
||||
use parity_wasm::builder;
|
||||
use parity_wasm::elements;
|
||||
|
||||
fn main() {
|
||||
let args = env::args().collect::<Vec<_>>();
|
||||
if args.len() != 2 {
|
||||
println!("Usage: {} output_file.wasm", args[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
let module = builder::module()
|
||||
.functions()
|
||||
.signature().param(elements::ValueType::I32).build()
|
||||
.bind()
|
||||
.build();
|
||||
|
||||
parity_wasm::serialize_to_file(&args[1], module).unwrap();
|
||||
}
|
@ -8,49 +8,25 @@ pub enum Signature {
|
||||
|
||||
pub struct SignatureBuilder<F=Identity> {
|
||||
callback: F,
|
||||
signature: Signature,
|
||||
signature: elements::FunctionType,
|
||||
}
|
||||
|
||||
impl<F> SignatureBuilder<F> where F: Invoke<Signature> {
|
||||
impl<F> SignatureBuilder<F> where F: Invoke<elements::FunctionType> {
|
||||
pub fn with_callback(callback: F) -> Self {
|
||||
SignatureBuilder {
|
||||
callback: callback,
|
||||
signature: Signature::TypeReference(0)
|
||||
signature: elements::FunctionType::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_ref(mut self, val: u32) -> Self {
|
||||
self.signature = Signature::TypeReference(val);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn param(mut self, value_type: elements::ValueType) -> Self {
|
||||
{
|
||||
let signature = &mut self.signature;
|
||||
if let Signature::TypeReference(_) = *signature {
|
||||
*signature = Signature::Inline(elements::FunctionType::default())
|
||||
}
|
||||
|
||||
if let Signature::Inline(ref mut func_type) = *signature {
|
||||
func_type.params_mut().push(value_type);
|
||||
}
|
||||
}
|
||||
self.signature.params_mut().push(value_type);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn return_type(mut self, value_type: elements::ValueType) -> Self {
|
||||
{
|
||||
let signature = &mut self.signature;
|
||||
if let Signature::TypeReference(_) = *signature {
|
||||
*signature = Signature::Inline(elements::FunctionType::default())
|
||||
}
|
||||
|
||||
if let Signature::Inline(ref mut func_type) = *signature {
|
||||
*func_type.return_type_mut() = Some(value_type);
|
||||
}
|
||||
}
|
||||
|
||||
*self.signature.return_type_mut() = Some(value_type);
|
||||
self
|
||||
}
|
||||
|
||||
@ -59,6 +35,27 @@ impl<F> SignatureBuilder<F> where F: Invoke<Signature> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TypeRefBuilder<F=Identity> {
|
||||
callback: F,
|
||||
type_ref: u32,
|
||||
}
|
||||
|
||||
impl<F> TypeRefBuilder<F> where F: Invoke<u32> {
|
||||
pub fn with_callback(callback: F) -> Self {
|
||||
TypeRefBuilder {
|
||||
callback: callback,
|
||||
type_ref: 0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn val(mut self, val: u32) -> Self {
|
||||
self.type_ref = val;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> F::Result { self.callback.invoke(self.type_ref) }
|
||||
}
|
||||
|
||||
pub struct FunctionsBuilder<F=Identity> {
|
||||
callback: F,
|
||||
section: Vec<Signature>,
|
||||
@ -84,16 +81,30 @@ impl<F> FunctionsBuilder<F> {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn type_ref(self) -> TypeRefBuilder<Self> {
|
||||
TypeRefBuilder::with_callback(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> FunctionsBuilder<F> where F: Invoke<SignatureBindings> {
|
||||
pub fn signature(self) -> SignatureBuilder<Self> {
|
||||
SignatureBuilder::with_callback(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> Invoke<Signature> for FunctionsBuilder<F> {
|
||||
impl<F> Invoke<elements::FunctionType> for FunctionsBuilder<F> {
|
||||
type Result = Self;
|
||||
|
||||
fn invoke(self, signature: Signature) -> Self {
|
||||
self.with_signature(signature)
|
||||
fn invoke(self, signature: elements::FunctionType) -> Self {
|
||||
self.with_signature(Signature::Inline(signature))
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> Invoke<u32> for FunctionsBuilder<F> {
|
||||
type Result = Self;
|
||||
|
||||
fn invoke(self, type_ref: u32) -> Self {
|
||||
self.with_signature(Signature::TypeReference(type_ref))
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,21 +130,30 @@ impl<F> FunctionsBuilder<F> where F: Invoke<SignatureBindings> {
|
||||
}
|
||||
}
|
||||
|
||||
/// New function builder.
|
||||
pub fn function() -> FunctionsBuilder {
|
||||
FunctionsBuilder::new()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use super::FunctionsBuilder;
|
||||
use super::function;
|
||||
|
||||
#[test]
|
||||
fn example() {
|
||||
let result = FunctionsBuilder::new()
|
||||
.signature().type_ref(1).build()
|
||||
let result = function()
|
||||
.type_ref().val(1).build()
|
||||
.build();
|
||||
|
||||
assert_eq!(result.entries().len(), 1);
|
||||
|
||||
let result = FunctionsBuilder::new()
|
||||
.signature().type_ref(1).build()
|
||||
let result = function()
|
||||
.signature()
|
||||
.param(::elements::ValueType::I32)
|
||||
.param(::elements::ValueType::I32)
|
||||
.return_type(::elements::ValueType::I64)
|
||||
.build()
|
||||
.bind();
|
||||
|
||||
assert_eq!(result.len(), 1);
|
||||
|
@ -5,3 +5,4 @@ mod module;
|
||||
mod code;
|
||||
|
||||
pub use self::module::{module, ModuleBuilder};
|
||||
pub use self::code::function;
|
@ -1,11 +1,57 @@
|
||||
use super::invoke::{Invoke, Identity};
|
||||
use super::code::FunctionsBuilder;
|
||||
use super::code::{self, FunctionsBuilder};
|
||||
use elements;
|
||||
|
||||
/// Module builder
|
||||
pub struct ModuleBuilder<F=Identity> {
|
||||
callback: F,
|
||||
sections: Vec<elements::Section>,
|
||||
module: ModuleScaffold,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct ModuleScaffold {
|
||||
pub functions: elements::FunctionsSection,
|
||||
pub types: elements::TypeSection,
|
||||
pub other: Vec<elements::Section>,
|
||||
}
|
||||
|
||||
impl From<elements::Module> for ModuleScaffold {
|
||||
fn from(module: elements::Module) -> Self {
|
||||
let mut funcs: Option<elements::FunctionsSection> = None;
|
||||
let mut types: Option<elements::TypeSection> = None;
|
||||
|
||||
let mut sections = module.into_sections();
|
||||
while let Some(section) = sections.pop() {
|
||||
match section {
|
||||
elements::Section::Type(sect) => { types = Some(sect); }
|
||||
elements::Section::Function(sect) => { funcs = Some(sect); }
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
ModuleScaffold {
|
||||
functions: funcs.unwrap_or_default(),
|
||||
types: types.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 functions = module.functions;
|
||||
if functions.entries().len() > 0 {
|
||||
sections.push(elements::Section::Function(functions));
|
||||
}
|
||||
sections.extend(module.other);
|
||||
elements::Module::new(sections)
|
||||
}
|
||||
}
|
||||
|
||||
impl ModuleBuilder {
|
||||
@ -20,7 +66,7 @@ impl<F> ModuleBuilder<F> where F: Invoke<elements::Module> {
|
||||
pub fn with_callback(callback: F) -> Self {
|
||||
ModuleBuilder {
|
||||
callback: callback,
|
||||
sections: Vec::new(),
|
||||
module: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,22 +74,51 @@ impl<F> ModuleBuilder<F> where F: Invoke<elements::Module> {
|
||||
pub fn with_sections<I>(mut self, sections: I) -> Self
|
||||
where I: IntoIterator<Item=elements::Section>
|
||||
{
|
||||
self.sections.extend(sections);
|
||||
self.module.other.extend(sections);
|
||||
self
|
||||
}
|
||||
|
||||
/// Add additional section
|
||||
pub fn with_section(mut self, section: elements::Section) -> Self {
|
||||
self.sections.push(section);
|
||||
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 {
|
||||
// todo bind to type section
|
||||
|
||||
{
|
||||
let module = &mut self.module;
|
||||
|
||||
let raw_functions: Vec<u32> = bindings.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
|
||||
}
|
||||
code::Signature::TypeReference(type_ref) => {
|
||||
type_ref
|
||||
}
|
||||
}
|
||||
).collect();
|
||||
|
||||
for function in raw_functions {
|
||||
module.functions.entries_mut().push(elements::Func::new(function));
|
||||
}
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Define functions section
|
||||
pub fn functions(self) -> FunctionsBuilder<Self> {
|
||||
FunctionsBuilder::with_callback(self)
|
||||
}
|
||||
|
||||
/// Build module (final step)
|
||||
pub fn build(self) -> F::Result {
|
||||
self.callback.invoke(elements::Module::new(self.sections))
|
||||
self.callback.invoke(self.module.into())
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,6 +132,16 @@ impl<F> Invoke<elements::FunctionsSection> for ModuleBuilder<F>
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
/// Start new module builder
|
||||
pub fn module() -> ModuleBuilder {
|
||||
ModuleBuilder::new()
|
||||
@ -73,4 +158,16 @@ mod tests {
|
||||
assert_eq!(module.sections().len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn functions() {
|
||||
let module = module()
|
||||
.functions()
|
||||
.signature().param(::elements::ValueType::I32).build()
|
||||
.bind()
|
||||
.build();
|
||||
|
||||
assert_eq!(module.type_section().expect("type section to exist").types().len(), 1);
|
||||
assert_eq!(module.functions_section().expect("function section to exist").entries().len(), 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ mod segment;
|
||||
pub use self::module::Module;
|
||||
pub use self::section::{
|
||||
Section, FunctionsSection, CodeSection, MemorySection, DataSection,
|
||||
ImportSection, ExportSection, GlobalSection,
|
||||
ImportSection, ExportSection, GlobalSection, TypeSection,
|
||||
};
|
||||
pub use self::import_entry::{ImportEntry, MemoryType, TableType, GlobalType, External};
|
||||
pub use self::export_entry::{ExportEntry, Internal};
|
||||
@ -25,7 +25,7 @@ pub use self::primitives::{
|
||||
VarUint32, VarUint7, VarUint1, VarInt7, Uint32,
|
||||
Uint64, VarUint64, CountedList, CountedWriter, CountedListWriter,
|
||||
};
|
||||
pub use self::types::{ValueType, BlockType, FunctionType};
|
||||
pub use self::types::{Type, ValueType, BlockType, FunctionType};
|
||||
pub use self::ops::{Opcode, Opcodes, InitExpr};
|
||||
pub use self::func::{Func, FuncBody, Local};
|
||||
pub use self::segment::{ElementSegment, DataSegment};
|
||||
@ -122,3 +122,10 @@ pub fn serialize<T: Serialize>(val: T) -> Result<Vec<u8>, T::Error> {
|
||||
val.serialize(&mut buf)?;
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
/// Serialize module to the file
|
||||
pub fn serialize_to_file<P: AsRef<::std::path::Path>>(p: P, module: Module) -> Result<(), Error>
|
||||
{
|
||||
let mut io = ::std::fs::File::create(p)?;
|
||||
module.serialize(&mut io)
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
use std::io;
|
||||
use super::{Deserialize, Serialize, Error, Uint32};
|
||||
use super::section::{Section, CodeSection, TypeSection, ImportSection};
|
||||
use super::section::{Section, CodeSection, TypeSection, ImportSection, FunctionsSection};
|
||||
|
||||
/// WebAssembly module
|
||||
pub struct Module {
|
||||
@ -9,16 +9,29 @@ pub struct Module {
|
||||
sections: Vec<Section>,
|
||||
}
|
||||
|
||||
impl Default for Module {
|
||||
fn default() -> Self {
|
||||
Module {
|
||||
magic: 0x6d736100,
|
||||
version: 1,
|
||||
sections: Vec::with_capacity(16),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Module {
|
||||
/// New module with sections
|
||||
pub fn new(sections: Vec<Section>) -> Self {
|
||||
Module {
|
||||
magic: 0x6d736100,
|
||||
version: 1,
|
||||
sections: sections,
|
||||
sections: sections, ..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Destructure the module, yielding sections
|
||||
pub fn into_sections(self) -> Vec<Section> {
|
||||
self.sections
|
||||
}
|
||||
|
||||
/// Version of module.
|
||||
pub fn version(&self) -> u32 { self.version }
|
||||
|
||||
@ -57,6 +70,14 @@ impl Module {
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Functions signatures section, if any.
|
||||
pub fn functions_section(&self) -> Option<&FunctionsSection> {
|
||||
for section in self.sections() {
|
||||
if let &Section::Function(ref sect) = section { return Some(sect); }
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for Module {
|
||||
|
@ -176,12 +176,20 @@ impl Serialize for Section {
|
||||
}
|
||||
}
|
||||
|
||||
/// Section with type declarations
|
||||
#[derive(Default)]
|
||||
pub struct TypeSection(Vec<Type>);
|
||||
|
||||
impl TypeSection {
|
||||
/// List of type declarations
|
||||
pub fn types(&self) -> &[Type] {
|
||||
&self.0
|
||||
}
|
||||
|
||||
/// List of type declarations (mutable)
|
||||
pub fn types_mut(&mut self) -> &mut Vec<Type> {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for TypeSection {
|
||||
@ -215,6 +223,7 @@ impl Serialize for TypeSection {
|
||||
pub struct ImportSection(Vec<ImportEntry>);
|
||||
|
||||
impl ImportSection {
|
||||
/// List of import entries.
|
||||
pub fn entries(&self) -> &[ImportEntry] {
|
||||
&self.0
|
||||
}
|
||||
@ -248,17 +257,21 @@ impl Serialize for ImportSection {
|
||||
}
|
||||
|
||||
/// Section with function signatures definition.
|
||||
#[derive(Default)]
|
||||
pub struct FunctionsSection(Vec<Func>);
|
||||
|
||||
impl FunctionsSection {
|
||||
/// New functions section
|
||||
pub fn new() -> FunctionsSection {
|
||||
FunctionsSection(Vec::new())
|
||||
}
|
||||
|
||||
/// List of all functions in the section, mutable
|
||||
pub fn entries_mut(&mut self) -> &mut Vec<Func> {
|
||||
&mut self.0
|
||||
}
|
||||
|
||||
/// List of all functions in the section
|
||||
pub fn entries(&self) -> &[Func] {
|
||||
&self.0
|
||||
}
|
||||
@ -335,6 +348,7 @@ impl Serialize for TableSection {
|
||||
pub struct MemorySection(Vec<MemoryType>);
|
||||
|
||||
impl MemorySection {
|
||||
/// List of all memory entries in the section
|
||||
pub fn entries(&self) -> &[MemoryType] {
|
||||
&self.0
|
||||
}
|
||||
@ -371,6 +385,7 @@ impl Serialize for MemorySection {
|
||||
pub struct GlobalSection(Vec<GlobalEntry>);
|
||||
|
||||
impl GlobalSection {
|
||||
/// List of all global entries in the section
|
||||
pub fn entries(&self) -> &[GlobalEntry] {
|
||||
&self.0
|
||||
}
|
||||
@ -407,6 +422,7 @@ impl Serialize for GlobalSection {
|
||||
pub struct ExportSection(Vec<ExportEntry>);
|
||||
|
||||
impl ExportSection {
|
||||
/// List of all export entries in the section
|
||||
pub fn entries(&self) -> &[ExportEntry] {
|
||||
&self.0
|
||||
}
|
||||
@ -443,10 +459,12 @@ impl Serialize for ExportSection {
|
||||
pub struct CodeSection(Vec<FuncBody>);
|
||||
|
||||
impl CodeSection {
|
||||
/// New code section
|
||||
pub fn new(bodies: Vec<FuncBody>) -> Self {
|
||||
CodeSection(bodies)
|
||||
}
|
||||
|
||||
/// All function bodies in the section
|
||||
pub fn bodies(&self) -> &[FuncBody] {
|
||||
&self.0
|
||||
}
|
||||
@ -483,10 +501,12 @@ impl Serialize for CodeSection {
|
||||
pub struct ElementSection(Vec<ElementSegment>);
|
||||
|
||||
impl ElementSection {
|
||||
/// New elements section
|
||||
pub fn new(entries: Vec<ElementSegment>) -> Self {
|
||||
ElementSection(entries)
|
||||
}
|
||||
|
||||
/// New elements entries in the section
|
||||
pub fn entries(&self) -> &[ElementSegment] {
|
||||
&self.0
|
||||
}
|
||||
@ -523,10 +543,12 @@ impl Serialize for ElementSection {
|
||||
pub struct DataSection(Vec<DataSegment>);
|
||||
|
||||
impl DataSection {
|
||||
/// New data section
|
||||
pub fn new(segments: Vec<DataSegment>) -> Self {
|
||||
DataSection(segments)
|
||||
}
|
||||
|
||||
/// List of all data entries in the section
|
||||
pub fn entries(&self) -> &[DataSegment] {
|
||||
&self.0
|
||||
}
|
||||
|
@ -132,6 +132,14 @@ impl Default for FunctionType {
|
||||
}
|
||||
|
||||
impl FunctionType {
|
||||
/// New function type given the signature in-params(`params`) and return type (`return_type`)
|
||||
pub fn new(params: Vec<ValueType>, return_type: Option<ValueType>) -> Self {
|
||||
FunctionType {
|
||||
params: params,
|
||||
return_type: return_type,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
/// Function form (currently only valid value is `0x60`)
|
||||
pub fn form(&self) -> u8 { self.form }
|
||||
/// Parameters in the function signature.
|
||||
|
@ -10,5 +10,7 @@ pub mod builder;
|
||||
pub use elements::{
|
||||
Error as SerializationError,
|
||||
deserialize_buffer,
|
||||
deserialize_file
|
||||
deserialize_file,
|
||||
serialize,
|
||||
serialize_to_file,
|
||||
};
|
||||
|
Reference in New Issue
Block a user