builders intial

This commit is contained in:
NikVolf
2017-04-06 11:34:31 +03:00
parent 1f09d620e8
commit 74b310113e
9 changed files with 276 additions and 2 deletions

141
src/builder/code.rs Normal file
View File

@ -0,0 +1,141 @@
use super::invoke::{Invoke, Identity};
use elements;
pub enum Signature {
TypeReference(u32),
Inline(elements::FunctionType),
}
pub struct SignatureBuilder<F=Identity> {
callback: F,
signature: Signature,
}
impl<F> SignatureBuilder<F> where F: Invoke<Signature> {
pub fn with_callback(callback: F) -> Self {
SignatureBuilder {
callback: callback,
signature: Signature::TypeReference(0)
}
}
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
}
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
}
pub fn build(self) -> F::Result {
self.callback.invoke(self.signature)
}
}
pub struct FunctionsBuilder<F=Identity> {
callback: F,
section: Vec<Signature>,
}
impl FunctionsBuilder {
/// New empty functions section builder
pub fn new() -> Self {
FunctionsBuilder::with_callback(Identity)
}
}
impl<F> FunctionsBuilder<F> {
pub fn with_callback(callback: F) -> Self {
FunctionsBuilder {
callback: callback,
section: Vec::new(),
}
}
pub fn with_signature(mut self, signature: Signature) -> Self {
self.section.push(signature);
self
}
pub fn signature(self) -> SignatureBuilder<Self> {
SignatureBuilder::with_callback(self)
}
}
impl<F> Invoke<Signature> for FunctionsBuilder<F> {
type Result = Self;
fn invoke(self, signature: Signature) -> Self {
self.with_signature(signature)
}
}
impl<F> FunctionsBuilder<F> where F: Invoke<elements::FunctionsSection> {
pub fn build(self) -> F::Result {
let mut result = elements::FunctionsSection::new();
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)
}
}
pub type SignatureBindings = Vec<Signature>;
impl<F> FunctionsBuilder<F> where F: Invoke<SignatureBindings> {
pub fn bind(self) -> F::Result {
self.callback.invoke(self.section)
}
}
#[cfg(test)]
mod tests {
use super::FunctionsBuilder;
#[test]
fn example() {
let result = FunctionsBuilder::new()
.signature().type_ref(1).build()
.build();
assert_eq!(result.entries().len(), 1);
let result = FunctionsBuilder::new()
.signature().type_ref(1).build()
.bind();
assert_eq!(result.len(), 1);
}
}

15
src/builder/invoke.rs Normal file
View File

@ -0,0 +1,15 @@
//! invoke helper
pub trait Invoke<A> {
type Result;
fn invoke(self, arg: A) -> Self::Result;
}
pub struct Identity;
impl<A> Invoke<A> for Identity {
type Result = A;
fn invoke(self, arg: A) -> A { arg }
}

7
src/builder/mod.rs Normal file
View File

@ -0,0 +1,7 @@
//! Various builders to generate/alter wasm components
mod invoke;
mod module;
mod code;
pub use self::module::{module, ModuleBuilder};

76
src/builder/module.rs Normal file
View File

@ -0,0 +1,76 @@
use super::invoke::{Invoke, Identity};
use super::code::FunctionsBuilder;
use elements;
/// Module builder
pub struct ModuleBuilder<F=Identity> {
callback: F,
sections: Vec<elements::Section>,
}
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,
sections: Vec::new(),
}
}
/// Fill module with sections from iterator
pub fn with_sections<I>(mut self, sections: I) -> Self
where I: IntoIterator<Item=elements::Section>
{
self.sections.extend(sections);
self
}
pub fn with_section(mut self, section: elements::Section) -> Self {
self.sections.push(section);
self
}
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))
}
}
impl<F> Invoke<elements::FunctionsSection> for ModuleBuilder<F>
where F: Invoke<elements::Module>
{
type Result = Self;
fn invoke(self, section: elements::FunctionsSection) -> Self {
self.with_section(elements::Section::Function(section))
}
}
/// Start new module builder
pub fn module() -> ModuleBuilder {
ModuleBuilder::new()
}
#[cfg(test)]
mod tests {
use super::module;
#[test]
fn smoky() {
let module = module().build();
assert_eq!(module.sections().len(), 0);
}
}

View File

@ -14,7 +14,10 @@ mod func;
mod segment; mod segment;
pub use self::module::Module; pub use self::module::Module;
pub use self::section::Section; pub use self::section::{
Section, FunctionsSection, CodeSection, MemorySection, DataSection,
ImportSection, ExportSection, GlobalSection,
};
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};
pub use self::global_entry::GlobalEntry; pub use self::global_entry::GlobalEntry;
@ -22,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}; pub use self::types::{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};

View File

@ -10,6 +10,15 @@ pub struct Module {
} }
impl Module { impl Module {
/// New module with sections
pub fn new(sections: Vec<Section>) -> Self {
Module {
magic: 0x6d736100,
version: 1,
sections: sections,
}
}
/// Version of module. /// Version of module.
pub fn version(&self) -> u32 { self.version } pub fn version(&self) -> u32 { self.version }

View File

@ -251,6 +251,14 @@ impl Serialize for ImportSection {
pub struct FunctionsSection(Vec<Func>); pub struct FunctionsSection(Vec<Func>);
impl FunctionsSection { impl FunctionsSection {
pub fn new() -> FunctionsSection {
FunctionsSection(Vec::new())
}
pub fn entries_mut(&mut self) -> &mut Vec<Func> {
&mut self.0
}
pub fn entries(&self) -> &[Func] { pub fn entries(&self) -> &[Func] {
&self.0 &self.0
} }

View File

@ -121,13 +121,27 @@ pub struct FunctionType {
return_type: Option<ValueType>, return_type: Option<ValueType>,
} }
impl Default for FunctionType {
fn default() -> Self {
FunctionType {
form: 0x60,
params: Vec::new(),
return_type: None,
}
}
}
impl FunctionType { impl FunctionType {
/// 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.
pub fn params(&self) -> &[ValueType] { &self.params } pub fn params(&self) -> &[ValueType] { &self.params }
/// Mutable parameters in the function signature.
pub fn params_mut(&mut self) -> &mut Vec<ValueType> { &mut self.params }
/// Return type in the function signature, if any. /// Return type in the function signature, if any.
pub fn return_type(&self) -> Option<ValueType> { self.return_type } pub fn return_type(&self) -> Option<ValueType> { self.return_type }
/// Mutable type in the function signature, if any.
pub fn return_type_mut(&mut self) -> &mut Option<ValueType> { &mut self.return_type }
} }
impl Deserialize for FunctionType { impl Deserialize for FunctionType {

View File

@ -5,6 +5,7 @@
extern crate byteorder; extern crate byteorder;
pub mod elements; pub mod elements;
pub mod builder;
pub use elements::{ pub use elements::{
Error as SerializationError, Error as SerializationError,