module scaffolding and such

This commit is contained in:
NikVolf
2017-04-06 16:00:12 +03:00
parent 74b310113e
commit 29f64f3fec
9 changed files with 251 additions and 51 deletions

22
examples/build.rs Normal file
View 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();
}

View File

@ -8,49 +8,25 @@ pub enum Signature {
pub struct SignatureBuilder<F=Identity> { pub struct SignatureBuilder<F=Identity> {
callback: F, 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 { pub fn with_callback(callback: F) -> Self {
SignatureBuilder { SignatureBuilder {
callback: callback, 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 { pub fn param(mut self, value_type: elements::ValueType) -> Self {
{ self.signature.params_mut().push(value_type);
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 self
} }
pub fn return_type(mut self, value_type: elements::ValueType) -> Self { pub fn return_type(mut self, value_type: elements::ValueType) -> Self {
{ *self.signature.return_type_mut() = Some(value_type);
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 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> { pub struct FunctionsBuilder<F=Identity> {
callback: F, callback: F,
section: Vec<Signature>, section: Vec<Signature>,
@ -84,16 +81,30 @@ impl<F> FunctionsBuilder<F> {
self 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> { pub fn signature(self) -> SignatureBuilder<Self> {
SignatureBuilder::with_callback(self) SignatureBuilder::with_callback(self)
} }
} }
impl<F> Invoke<Signature> for FunctionsBuilder<F> { impl<F> Invoke<elements::FunctionType> for FunctionsBuilder<F> {
type Result = Self; type Result = Self;
fn invoke(self, signature: Signature) -> Self { fn invoke(self, signature: elements::FunctionType) -> Self {
self.with_signature(signature) 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)] #[cfg(test)]
mod tests { mod tests {
use super::FunctionsBuilder; use super::function;
#[test] #[test]
fn example() { fn example() {
let result = FunctionsBuilder::new() let result = function()
.signature().type_ref(1).build() .type_ref().val(1).build()
.build(); .build();
assert_eq!(result.entries().len(), 1); assert_eq!(result.entries().len(), 1);
let result = FunctionsBuilder::new() let result = function()
.signature().type_ref(1).build() .signature()
.param(::elements::ValueType::I32)
.param(::elements::ValueType::I32)
.return_type(::elements::ValueType::I64)
.build()
.bind(); .bind();
assert_eq!(result.len(), 1); assert_eq!(result.len(), 1);

View File

@ -5,3 +5,4 @@ mod module;
mod code; mod code;
pub use self::module::{module, ModuleBuilder}; pub use self::module::{module, ModuleBuilder};
pub use self::code::function;

View File

@ -1,11 +1,57 @@
use super::invoke::{Invoke, Identity}; use super::invoke::{Invoke, Identity};
use super::code::FunctionsBuilder; use super::code::{self, FunctionsBuilder};
use elements; use elements;
/// Module builder /// Module builder
pub struct ModuleBuilder<F=Identity> { pub struct ModuleBuilder<F=Identity> {
callback: F, 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 { impl ModuleBuilder {
@ -20,7 +66,7 @@ impl<F> ModuleBuilder<F> where F: Invoke<elements::Module> {
pub fn with_callback(callback: F) -> Self { pub fn with_callback(callback: F) -> Self {
ModuleBuilder { ModuleBuilder {
callback: callback, 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 pub fn with_sections<I>(mut self, sections: I) -> Self
where I: IntoIterator<Item=elements::Section> where I: IntoIterator<Item=elements::Section>
{ {
self.sections.extend(sections); self.module.other.extend(sections);
self self
} }
/// Add additional section
pub fn with_section(mut self, section: elements::Section) -> Self { pub fn with_section(mut self, section: elements::Section) -> Self {
self.sections.push(section); self.module.other.push(section);
self 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> { pub fn functions(self) -> FunctionsBuilder<Self> {
FunctionsBuilder::with_callback(self) FunctionsBuilder::with_callback(self)
} }
/// Build module (final step) /// Build module (final step)
pub fn build(self) -> F::Result { 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 /// Start new module builder
pub fn module() -> ModuleBuilder { pub fn module() -> ModuleBuilder {
ModuleBuilder::new() ModuleBuilder::new()
@ -73,4 +158,16 @@ mod tests {
assert_eq!(module.sections().len(), 0); 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);
}
} }

View File

@ -16,7 +16,7 @@ mod segment;
pub use self::module::Module; pub use self::module::Module;
pub use self::section::{ pub use self::section::{
Section, FunctionsSection, CodeSection, MemorySection, DataSection, 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::import_entry::{ImportEntry, MemoryType, TableType, GlobalType, External};
pub use self::export_entry::{ExportEntry, Internal}; pub use self::export_entry::{ExportEntry, Internal};
@ -25,7 +25,7 @@ pub use self::primitives::{
VarUint32, VarUint7, VarUint1, VarInt7, Uint32, VarUint32, VarUint7, VarUint1, VarInt7, Uint32,
Uint64, VarUint64, CountedList, CountedWriter, CountedListWriter, 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::ops::{Opcode, Opcodes, InitExpr};
pub use self::func::{Func, FuncBody, Local}; pub use self::func::{Func, FuncBody, Local};
pub use self::segment::{ElementSegment, DataSegment}; 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)?; val.serialize(&mut buf)?;
Ok(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)
}

View File

@ -1,6 +1,6 @@
use std::io; use std::io;
use super::{Deserialize, Serialize, Error, Uint32}; use super::{Deserialize, Serialize, Error, Uint32};
use super::section::{Section, CodeSection, TypeSection, ImportSection}; use super::section::{Section, CodeSection, TypeSection, ImportSection, FunctionsSection};
/// WebAssembly module /// WebAssembly module
pub struct Module { pub struct Module {
@ -9,16 +9,29 @@ pub struct Module {
sections: Vec<Section>, sections: Vec<Section>,
} }
impl Default for Module {
fn default() -> Self {
Module {
magic: 0x6d736100,
version: 1,
sections: Vec::with_capacity(16),
}
}
}
impl Module { impl Module {
/// New module with sections /// New module with sections
pub fn new(sections: Vec<Section>) -> Self { pub fn new(sections: Vec<Section>) -> Self {
Module { Module {
magic: 0x6d736100, sections: sections, ..Default::default()
version: 1,
sections: sections,
} }
} }
/// Destructure the module, yielding sections
pub fn into_sections(self) -> Vec<Section> {
self.sections
}
/// Version of module. /// Version of module.
pub fn version(&self) -> u32 { self.version } pub fn version(&self) -> u32 { self.version }
@ -57,6 +70,14 @@ impl Module {
} }
None 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 { impl Deserialize for Module {

View File

@ -176,12 +176,20 @@ impl Serialize for Section {
} }
} }
/// Section with type declarations
#[derive(Default)]
pub struct TypeSection(Vec<Type>); pub struct TypeSection(Vec<Type>);
impl TypeSection { impl TypeSection {
/// List of type declarations
pub fn types(&self) -> &[Type] { pub fn types(&self) -> &[Type] {
&self.0 &self.0
} }
/// List of type declarations (mutable)
pub fn types_mut(&mut self) -> &mut Vec<Type> {
&mut self.0
}
} }
impl Deserialize for TypeSection { impl Deserialize for TypeSection {
@ -215,6 +223,7 @@ impl Serialize for TypeSection {
pub struct ImportSection(Vec<ImportEntry>); pub struct ImportSection(Vec<ImportEntry>);
impl ImportSection { impl ImportSection {
/// List of import entries.
pub fn entries(&self) -> &[ImportEntry] { pub fn entries(&self) -> &[ImportEntry] {
&self.0 &self.0
} }
@ -248,17 +257,21 @@ impl Serialize for ImportSection {
} }
/// Section with function signatures definition. /// Section with function signatures definition.
#[derive(Default)]
pub struct FunctionsSection(Vec<Func>); pub struct FunctionsSection(Vec<Func>);
impl FunctionsSection { impl FunctionsSection {
/// New functions section
pub fn new() -> FunctionsSection { pub fn new() -> FunctionsSection {
FunctionsSection(Vec::new()) FunctionsSection(Vec::new())
} }
/// List of all functions in the section, mutable
pub fn entries_mut(&mut self) -> &mut Vec<Func> { pub fn entries_mut(&mut self) -> &mut Vec<Func> {
&mut self.0 &mut self.0
} }
/// List of all functions in the section
pub fn entries(&self) -> &[Func] { pub fn entries(&self) -> &[Func] {
&self.0 &self.0
} }
@ -335,6 +348,7 @@ impl Serialize for TableSection {
pub struct MemorySection(Vec<MemoryType>); pub struct MemorySection(Vec<MemoryType>);
impl MemorySection { impl MemorySection {
/// List of all memory entries in the section
pub fn entries(&self) -> &[MemoryType] { pub fn entries(&self) -> &[MemoryType] {
&self.0 &self.0
} }
@ -371,6 +385,7 @@ impl Serialize for MemorySection {
pub struct GlobalSection(Vec<GlobalEntry>); pub struct GlobalSection(Vec<GlobalEntry>);
impl GlobalSection { impl GlobalSection {
/// List of all global entries in the section
pub fn entries(&self) -> &[GlobalEntry] { pub fn entries(&self) -> &[GlobalEntry] {
&self.0 &self.0
} }
@ -407,6 +422,7 @@ impl Serialize for GlobalSection {
pub struct ExportSection(Vec<ExportEntry>); pub struct ExportSection(Vec<ExportEntry>);
impl ExportSection { impl ExportSection {
/// List of all export entries in the section
pub fn entries(&self) -> &[ExportEntry] { pub fn entries(&self) -> &[ExportEntry] {
&self.0 &self.0
} }
@ -443,10 +459,12 @@ impl Serialize for ExportSection {
pub struct CodeSection(Vec<FuncBody>); pub struct CodeSection(Vec<FuncBody>);
impl CodeSection { impl CodeSection {
/// New code section
pub fn new(bodies: Vec<FuncBody>) -> Self { pub fn new(bodies: Vec<FuncBody>) -> Self {
CodeSection(bodies) CodeSection(bodies)
} }
/// All function bodies in the section
pub fn bodies(&self) -> &[FuncBody] { pub fn bodies(&self) -> &[FuncBody] {
&self.0 &self.0
} }
@ -483,10 +501,12 @@ impl Serialize for CodeSection {
pub struct ElementSection(Vec<ElementSegment>); pub struct ElementSection(Vec<ElementSegment>);
impl ElementSection { impl ElementSection {
/// New elements section
pub fn new(entries: Vec<ElementSegment>) -> Self { pub fn new(entries: Vec<ElementSegment>) -> Self {
ElementSection(entries) ElementSection(entries)
} }
/// New elements entries in the section
pub fn entries(&self) -> &[ElementSegment] { pub fn entries(&self) -> &[ElementSegment] {
&self.0 &self.0
} }
@ -523,10 +543,12 @@ impl Serialize for ElementSection {
pub struct DataSection(Vec<DataSegment>); pub struct DataSection(Vec<DataSegment>);
impl DataSection { impl DataSection {
/// New data section
pub fn new(segments: Vec<DataSegment>) -> Self { pub fn new(segments: Vec<DataSegment>) -> Self {
DataSection(segments) DataSection(segments)
} }
/// List of all data entries in the section
pub fn entries(&self) -> &[DataSegment] { pub fn entries(&self) -> &[DataSegment] {
&self.0 &self.0
} }

View File

@ -132,6 +132,14 @@ impl Default for FunctionType {
} }
impl 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`) /// Function form (currently only valid value is `0x60`)
pub fn form(&self) -> u8 { self.form } pub fn form(&self) -> u8 { self.form }
/// Parameters in the function signature. /// Parameters in the function signature.

View File

@ -10,5 +10,7 @@ pub mod builder;
pub use elements::{ pub use elements::{
Error as SerializationError, Error as SerializationError,
deserialize_buffer, deserialize_buffer,
deserialize_file deserialize_file,
serialize,
serialize_to_file,
}; };