diff --git a/src/builder/data.rs b/src/builder/data.rs new file mode 100644 index 0000000..46398e5 --- /dev/null +++ b/src/builder/data.rs @@ -0,0 +1,49 @@ +use super::invoke::{Identity, Invoke}; +use elements; + +pub struct DataSegmentBuilder { + callback: F, + // todo: add mapper once multiple memory refs possible + mem_index: u32, + offset: elements::InitExpr, + value: Vec, +} + +impl DataSegmentBuilder { + pub fn new() -> Self { + DataSegmentBuilder::with_callback(Identity) + } +} + +impl DataSegmentBuilder { + pub fn with_callback(callback: F) -> Self { + DataSegmentBuilder { + callback: callback, + mem_index: 0, + offset: elements::InitExpr::empty(), + value: Vec::new(), + } + } + + pub fn offset(mut self, opcode: elements::Opcode) -> Self { + self.offset = elements::InitExpr::new(vec![opcode, elements::Opcode::End]); + self + } + + pub fn value(mut self, value: Vec) -> Self { + self.value = value; + self + } +} + +impl DataSegmentBuilder where F: Invoke { + pub fn build(self) -> F::Result { + self.callback.invoke( + elements::DataSegment::new( + self.mem_index, + self.offset, + self.value, + ) + ) + } +} \ No newline at end of file diff --git a/src/builder/global.rs b/src/builder/global.rs index 2cae4ba..9c666f3 100644 --- a/src/builder/global.rs +++ b/src/builder/global.rs @@ -56,7 +56,6 @@ impl GlobalBuilder where F: Invoke { } } - impl Invoke for GlobalBuilder { type Result = Self; fn invoke(self, the_type: elements::ValueType) -> Self { diff --git a/src/builder/mod.rs b/src/builder/mod.rs index 7d7437e..d590a75 100644 --- a/src/builder/mod.rs +++ b/src/builder/mod.rs @@ -9,6 +9,7 @@ mod memory; mod table; mod export; mod global; +mod data; pub use self::module::{module, from_module, ModuleBuilder}; pub use self::code::{signatures, signature, function}; diff --git a/src/builder/module.rs b/src/builder/module.rs index 8086a96..584b2d9 100644 --- a/src/builder/module.rs +++ b/src/builder/module.rs @@ -2,7 +2,7 @@ use super::invoke::{Invoke, Identity}; use super::code::{self, SignaturesBuilder, FunctionBuilder}; use super::memory::{self, MemoryBuilder}; use super::table::{self, TableBuilder}; -use super::{import, export, global}; +use super::{import, export, global, data}; use elements; /// Module builder @@ -321,6 +321,17 @@ impl ModuleBuilder where F: Invoke { global::GlobalBuilder::with_callback(self) } + /// Add data segment to the builder + pub fn with_data_segment(mut self, segment: elements::DataSegment) -> Self { + self.module.data.entries_mut().push(segment); + self + } + + /// Data entry builder + pub fn data(self) -> data::DataSegmentBuilder { + data::DataSegmentBuilder::with_callback(self) + } + /// Build module (final step) pub fn build(self) -> F::Result { self.callback.invoke(self.module.into()) @@ -414,6 +425,16 @@ impl Invoke for ModuleBuilder } } +impl Invoke for ModuleBuilder + where F: Invoke +{ + type Result = Self; + + fn invoke(self, segment: elements::DataSegment) -> Self { + self.with_data_segment(segment) + } +} + /// Start new module builder pub fn module() -> ModuleBuilder { ModuleBuilder::new() @@ -466,4 +487,16 @@ mod tests { assert_eq!(module.global_section().expect("global section to exist").entries().len(), 1); } + + #[test] + fn data() { + let module = module() + .data() + .offset(::elements::Opcode::I32Const(16)) + .value(vec![0u8, 15, 10, 5, 25]) + .build() + .build(); + + assert_eq!(module.data_section().expect("data section to exist").entries().len(), 1); + } }