208 lines
5.1 KiB
Rust
Raw Normal View History

2017-04-06 11:34:31 +03:00
use elements;
2017-04-06 18:23:02 +03:00
use super::invoke::{Invoke, Identity};
use super::misc::{ValueTypeBuilder, ValueTypesBuilder, OptionalValueTypeBuilder};
2017-04-06 11:34:31 +03:00
pub enum Signature {
TypeReference(u32),
Inline(elements::FunctionType),
}
pub struct SignatureBuilder<F=Identity> {
callback: F,
2017-04-06 16:00:12 +03:00
signature: elements::FunctionType,
2017-04-06 11:34:31 +03:00
}
2017-04-06 16:00:12 +03:00
impl<F> SignatureBuilder<F> where F: Invoke<elements::FunctionType> {
2017-04-06 11:34:31 +03:00
pub fn with_callback(callback: F) -> Self {
SignatureBuilder {
callback: callback,
2017-04-06 16:00:12 +03:00
signature: elements::FunctionType::default(),
2017-04-06 11:34:31 +03:00
}
}
2017-04-06 18:23:02 +03:00
pub fn with_param(mut self, value_type: elements::ValueType) -> Self {
2017-04-06 16:00:12 +03:00
self.signature.params_mut().push(value_type);
2017-04-06 18:23:02 +03:00
self
}
2017-04-06 11:34:31 +03:00
2017-04-06 18:23:02 +03:00
pub fn with_params(mut self, value_types: Vec<elements::ValueType>) -> Self {
self.signature.params_mut().extend(value_types);
2017-04-06 11:34:31 +03:00
self
}
2017-04-06 18:23:02 +03:00
pub fn with_return_type(mut self, return_type: Option<elements::ValueType>) -> Self {
*self.signature.return_type_mut() = return_type;
2017-04-06 11:34:31 +03:00
self
}
2017-04-06 18:23:02 +03:00
pub fn param(self) -> ValueTypeBuilder<Self> {
ValueTypeBuilder::with_callback(self)
}
pub fn params(self) -> ValueTypesBuilder<Self> {
ValueTypesBuilder::with_callback(self)
}
pub fn return_type(self) -> OptionalValueTypeBuilder<Self> {
OptionalValueTypeBuilder::with_callback(self)
}
2017-04-06 11:34:31 +03:00
pub fn build(self) -> F::Result {
self.callback.invoke(self.signature)
}
}
2017-04-06 18:23:02 +03:00
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)
}
}
2017-04-06 16:00:12 +03:00
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) }
}
2017-04-06 11:34:31 +03:00
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
}
2017-04-06 16:00:12 +03:00
pub fn type_ref(self) -> TypeRefBuilder<Self> {
TypeRefBuilder::with_callback(self)
}
}
impl<F> FunctionsBuilder<F> where F: Invoke<SignatureBindings> {
2017-04-06 11:34:31 +03:00
pub fn signature(self) -> SignatureBuilder<Self> {
SignatureBuilder::with_callback(self)
}
}
2017-04-06 16:00:12 +03:00
impl<F> Invoke<elements::FunctionType> for FunctionsBuilder<F> {
type Result = Self;
fn invoke(self, signature: elements::FunctionType) -> Self {
self.with_signature(Signature::Inline(signature))
}
}
impl<F> Invoke<u32> for FunctionsBuilder<F> {
2017-04-06 11:34:31 +03:00
type Result = Self;
2017-04-06 16:00:12 +03:00
fn invoke(self, type_ref: u32) -> Self {
self.with_signature(Signature::TypeReference(type_ref))
2017-04-06 11:34:31 +03:00
}
}
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)
}
}
2017-04-06 16:00:12 +03:00
/// New function builder.
pub fn function() -> FunctionsBuilder {
FunctionsBuilder::new()
}
2017-04-06 11:34:31 +03:00
#[cfg(test)]
mod tests {
2017-04-06 16:00:12 +03:00
use super::function;
2017-04-06 11:34:31 +03:00
#[test]
fn example() {
2017-04-06 16:00:12 +03:00
let result = function()
.type_ref().val(1).build()
2017-04-06 11:34:31 +03:00
.build();
assert_eq!(result.entries().len(), 1);
2017-04-06 16:00:12 +03:00
let result = function()
.signature()
2017-04-06 18:23:02 +03:00
.param().i32()
.param().i32()
.return_type().i64()
2017-04-06 16:00:12 +03:00
.build()
2017-04-06 11:34:31 +03:00
.bind();
assert_eq!(result.len(), 1);
}
}