diff --git a/src/builder/export.rs b/src/builder/export.rs new file mode 100644 index 0000000..379aacb --- /dev/null +++ b/src/builder/export.rs @@ -0,0 +1,102 @@ +use super::invoke::{Invoke, Identity}; +use elements; + +pub struct ExportBuilder { + callback: F, + field: String, + binding: elements::Internal, +} + +impl ExportBuilder { + pub fn new() -> Self { + ExportBuilder::with_callback(Identity) + } +} + +impl ExportBuilder { + + pub fn with_callback(callback: F) -> Self { + ExportBuilder { + callback: callback, + field: String::new(), + binding: elements::Internal::Function(0), + } + } + + pub fn field(mut self, field: &str) -> Self { + self.field = field.to_owned(); + self + } + + pub fn with_internal(mut self, external: elements::Internal) -> Self { + self.binding = external; + self + } + + pub fn internal(self) -> ExportInternalBuilder { + ExportInternalBuilder::with_callback(self) + } +} + +impl ExportBuilder where F: Invoke { + pub fn build(self) -> F::Result { + self.callback.invoke(elements::ExportEntry::new(self.field, self.binding)) + } +} + +impl Invoke for ExportBuilder { + type Result = Self; + fn invoke(self, val: elements::Internal) -> Self { + self.with_internal(val) + } +} + +pub struct ExportInternalBuilder { + callback: F, + binding: elements::Internal, +} + +impl ExportInternalBuilder where F: Invoke { + pub fn with_callback(callback: F) -> Self { + ExportInternalBuilder{ + callback: callback, + binding: elements::Internal::Function(0), + } + } + + pub fn func(mut self, index: u32) -> F::Result { + self.binding = elements::Internal::Function(index); + self.callback.invoke(self.binding) + } + + pub fn memory(mut self, index: u32) -> F::Result { + self.binding = elements::Internal::Memory(index); + self.callback.invoke(self.binding) + } + + pub fn table(mut self, index: u32) -> F::Result { + self.binding = elements::Internal::Table(index); + self.callback.invoke(self.binding) + } + + pub fn global(mut self, index: u32) -> F::Result { + self.binding = elements::Internal::Global(index); + self.callback.invoke(self.binding) + } +} + +/// New builder for export entry +pub fn export() -> ExportBuilder { + ExportBuilder::new() +} + +#[cfg(test)] +mod tests { + use super::export; + + #[test] + fn example() { + let entry = export().field("memory").internal().memory(0).build(); + assert_eq!(entry.field(), "memory"); + } +} \ No newline at end of file diff --git a/src/builder/mod.rs b/src/builder/mod.rs index 06766b8..f77ed5c 100644 --- a/src/builder/mod.rs +++ b/src/builder/mod.rs @@ -5,7 +5,9 @@ mod module; mod code; mod misc; mod import; +mod export; pub use self::module::{module, from_module, ModuleBuilder}; pub use self::code::{signatures, signature, function}; -pub use self::import::import; \ No newline at end of file +pub use self::import::import; +pub use self::export::export; \ No newline at end of file diff --git a/src/builder/module.rs b/src/builder/module.rs index 9902d46..cccb521 100644 --- a/src/builder/module.rs +++ b/src/builder/module.rs @@ -1,6 +1,6 @@ use super::invoke::{Invoke, Identity}; use super::code::{self, SignaturesBuilder, FunctionBuilder}; -use super::import; +use super::{import, export}; use elements; /// Module builder @@ -248,11 +248,22 @@ impl ModuleBuilder where F: Invoke { self } + /// With inserted import entry + pub fn with_export(mut self, entry: elements::ExportEntry) -> Self { + self.module.export.entries_mut().push(entry); + self + } + /// Import entry builder pub fn import(self) -> import::ImportBuilder { import::ImportBuilder::with_callback(self) } + /// Export entry builder + pub fn export(self) -> export::ExportBuilder { + export::ExportBuilder::with_callback(self) + } + /// Build module (final step) pub fn build(self) -> F::Result { self.callback.invoke(self.module.into()) @@ -302,6 +313,16 @@ impl Invoke for ModuleBuilder } } +impl Invoke for ModuleBuilder + where F: Invoke +{ + type Result = Self; + + fn invoke(self, entry: elements::ExportEntry) -> Self::Result { + self.with_export(entry) + } +} + /// Start new module builder pub fn module() -> ModuleBuilder { ModuleBuilder::new() @@ -337,4 +358,12 @@ mod tests { assert_eq!(module.code_section().expect("code section to exist").bodies().len(), 1); } + #[test] + fn export() { + let module = module() + .export().field("call").internal().func(0).build() + .build(); + + assert_eq!(module.export_section().expect("export section to exist").entries().len(), 1); + } } diff --git a/src/elements/export_entry.rs b/src/elements/export_entry.rs index b119ac4..7ff78f2 100644 --- a/src/elements/export_entry.rs +++ b/src/elements/export_entry.rs @@ -53,12 +53,23 @@ pub struct ExportEntry { } impl ExportEntry { + /// New export entry + pub fn new(field: String, internal: Internal) -> Self { + ExportEntry { + field_str: field, + internal: internal + } + } + /// Public name pub fn field(&self) -> &str { &self.field_str } + /// Public name (mutable) pub fn field_mut(&mut self) -> &mut str { &mut self.field_str } + /// Internal reference of the export entry. pub fn internal(&self) -> &Internal { &self.internal } + /// Internal reference of the export entry (mutable). pub fn internal_mut(&mut self) -> &mut Internal { &mut self.internal } }