1use alloc::vec::Vec;
2use crate::elements;
3use super::{
4 import,
5 export,
6 global,
7 data,
8 invoke::{Invoke, Identity},
9 code::{self, SignaturesBuilder, FunctionBuilder},
10 memory::{self, MemoryBuilder},
11 table::{self, TableBuilder},
12};
13
14pub struct ModuleBuilder<F=Identity> {
16 callback: F,
17 module: ModuleScaffold,
18}
19
20pub struct CodeLocation {
22 pub signature: u32,
24 pub body: u32,
26}
27
28#[derive(Default, PartialEq)]
29struct ModuleScaffold {
30 pub types: elements::TypeSection,
31 pub import: elements::ImportSection,
32 pub functions: elements::FunctionSection,
33 pub table: elements::TableSection,
34 pub memory: elements::MemorySection,
35 pub global: elements::GlobalSection,
36 pub export: elements::ExportSection,
37 pub start: Option<u32>,
38 pub element: elements::ElementSection,
39 pub code: elements::CodeSection,
40 pub data: elements::DataSection,
41 pub other: Vec<elements::Section>,
42}
43
44impl From<elements::Module> for ModuleScaffold {
45 fn from(module: elements::Module) -> Self {
46 let mut types: Option<elements::TypeSection> = None;
47 let mut import: Option<elements::ImportSection> = None;
48 let mut funcs: Option<elements::FunctionSection> = None;
49 let mut table: Option<elements::TableSection> = None;
50 let mut memory: Option<elements::MemorySection> = None;
51 let mut global: Option<elements::GlobalSection> = None;
52 let mut export: Option<elements::ExportSection> = None;
53 let mut start: Option<u32> = None;
54 let mut element: Option<elements::ElementSection> = None;
55 let mut code: Option<elements::CodeSection> = None;
56 let mut data: Option<elements::DataSection> = None;
57
58 let mut other = Vec::new();
59 let mut sections = module.into_sections();
60 while let Some(section) = sections.pop() {
61 match section {
62 elements::Section::Type(sect) => { types = Some(sect); }
63 elements::Section::Import(sect) => { import = Some(sect); }
64 elements::Section::Function(sect) => { funcs = Some(sect); }
65 elements::Section::Table(sect) => { table = Some(sect); }
66 elements::Section::Memory(sect) => { memory = Some(sect); }
67 elements::Section::Global(sect) => { global = Some(sect); }
68 elements::Section::Export(sect) => { export = Some(sect); }
69 elements::Section::Start(index) => { start = Some(index); }
70 elements::Section::Element(sect) => { element = Some(sect); }
71 elements::Section::Code(sect) => { code = Some(sect); }
72 elements::Section::Data(sect) => { data = Some(sect); }
73 section => other.push(section)
74 }
75 }
76
77 ModuleScaffold {
78 types: types.unwrap_or_default(),
79 import: import.unwrap_or_default(),
80 functions: funcs.unwrap_or_default(),
81 table: table.unwrap_or_default(),
82 memory: memory.unwrap_or_default(),
83 global: global.unwrap_or_default(),
84 export: export.unwrap_or_default(),
85 start: start,
86 element: element.unwrap_or_default(),
87 code: code.unwrap_or_default(),
88 data: data.unwrap_or_default(),
89 other,
90 }
91 }
92}
93
94impl From<ModuleScaffold> for elements::Module {
95 fn from(module: ModuleScaffold) -> Self {
96 let mut sections = Vec::new();
97
98 let types = module.types;
99 if types.types().len() > 0 {
100 sections.push(elements::Section::Type(types));
101 }
102 let import = module.import;
103 if import.entries().len() > 0 {
104 sections.push(elements::Section::Import(import));
105 }
106 let functions = module.functions;
107 if functions.entries().len() > 0 {
108 sections.push(elements::Section::Function(functions));
109 }
110 let table = module.table;
111 if table.entries().len() > 0 {
112 sections.push(elements::Section::Table(table));
113 }
114 let memory = module.memory;
115 if memory.entries().len() > 0 {
116 sections.push(elements::Section::Memory(memory));
117 }
118 let global = module.global;
119 if global.entries().len() > 0 {
120 sections.push(elements::Section::Global(global));
121 }
122 let export = module.export;
123 if export.entries().len() > 0 {
124 sections.push(elements::Section::Export(export));
125 }
126 if let Some(start) = module.start {
127 sections.push(elements::Section::Start(start));
128 }
129 let element = module.element;
130 if element.entries().len() > 0 {
131 sections.push(elements::Section::Element(element));
132 }
133 let code = module.code;
134 if code.bodies().len() > 0 {
135 sections.push(elements::Section::Code(code));
136 }
137 let data = module.data;
138 if data.entries().len() > 0 {
139 sections.push(elements::Section::Data(data));
140 }
141 sections.extend(module.other);
142 elements::Module::new(sections)
143 }
144}
145
146impl ModuleBuilder {
147 pub fn new() -> Self {
149 ModuleBuilder::with_callback(Identity)
150 }
151}
152
153impl<F> ModuleBuilder<F> where F: Invoke<elements::Module> {
154 pub fn with_callback(callback: F) -> Self {
156 ModuleBuilder {
157 callback: callback,
158 module: Default::default(),
159 }
160 }
161
162 pub fn with_module(mut self, module: elements::Module) -> Self {
164 self.module = module.into();
165 self
166 }
167
168 pub fn with_sections<I>(mut self, sections: I) -> Self
170 where I: IntoIterator<Item=elements::Section>
171 {
172 self.module.other.extend(sections);
173 self
174 }
175
176 pub fn with_section(mut self, section: elements::Section) -> Self {
178 self.module.other.push(section);
179 self
180 }
181
182 pub fn with_signatures(mut self, bindings: code::SignatureBindings) -> Self {
184 self.push_signatures(bindings);
185 self
186 }
187
188 pub fn push_function(&mut self, func: code::FunctionDefinition) -> CodeLocation {
192 let signature = func.signature;
193 let body = func.code;
194
195 let type_ref = self.resolve_type_ref(signature);
196
197 self.module.functions.entries_mut().push(elements::Func::new(type_ref));
198 let signature_index = self.module.functions.entries_mut().len() as u32 - 1;
199 self.module.code.bodies_mut().push(body);
200 let body_index = self.module.code.bodies_mut().len() as u32 - 1;
201
202 if func.is_main {
203 self.module.start = Some(body_index);
204 }
205
206 CodeLocation {
207 signature: signature_index,
208 body: body_index,
209 }
210 }
211
212 pub fn push_memory(&mut self, mut memory: memory::MemoryDefinition) -> u32 {
214 let entries = self.module.memory.entries_mut();
215 entries.push(elements::MemoryType::new(memory.min, memory.max));
216 let memory_index = (entries.len() - 1) as u32;
217 for data in memory.data.drain(..) {
218 self.module.data.entries_mut()
219 .push(elements::DataSegment::new(memory_index, Some(data.offset), data.values))
220 }
221 memory_index
222 }
223
224 pub fn push_table(&mut self, mut table: table::TableDefinition) -> u32 {
226 let entries = self.module.table.entries_mut();
227 entries.push(elements::TableType::new(table.min, table.max));
228 let table_index = (entries.len() - 1) as u32;
229 for entry in table.elements.drain(..) {
230 self.module.element.entries_mut()
231 .push(elements::ElementSegment::new(table_index, Some(entry.offset), entry.values))
232 }
233 table_index
234 }
235
236 pub fn push_global(&mut self, global: elements::GlobalEntry) -> u32 {
238 let entries = self.module.global.entries_mut();
239 entries.push(global);
240 entries.len() as u32 - 1
241 }
242
243 fn resolve_type_ref(&mut self, signature: code::Signature) -> u32 {
244 match signature {
245 code::Signature::Inline(func_type) => {
246 if let Some(existing_entry) = self.module.types.types().iter().enumerate().find(|(_idx, t)| {
247 let elements::Type::Function(ref existing) = t;
248 *existing == func_type
249 }) {
250 return existing_entry.0 as u32
251 }
252 self.module.types.types_mut().push(elements::Type::Function(func_type));
253 self.module.types.types().len() as u32 - 1
254 }
255 code::Signature::TypeReference(type_ref) => {
256 type_ref
257 }
258 }
259 }
260
261 pub fn push_signature(&mut self, signature: code::Signature) -> u32 {
264 self.resolve_type_ref(signature)
265 }
266
267 pub fn push_signatures(&mut self, signatures: code::SignatureBindings) -> Vec<u32> {
269 signatures.into_iter().map(|binding|
270 self.resolve_type_ref(binding)
271 ).collect()
272 }
273
274 pub fn push_import(&mut self, import: elements::ImportEntry) -> u32 {
277 self.module.import.entries_mut().push(import);
278 self.module.import.entries_mut().len() as u32 - 1
282 }
283
284 pub fn push_export(&mut self, export: elements::ExportEntry) -> u32 {
286 self.module.export.entries_mut().push(export);
287 self.module.export.entries_mut().len() as u32 - 1
288 }
289
290 pub fn function(self) -> FunctionBuilder<Self> {
292 FunctionBuilder::with_callback(self)
293 }
294
295 pub fn memory(self) -> MemoryBuilder<Self> {
297 MemoryBuilder::with_callback(self)
298 }
299
300 pub fn table(self) -> TableBuilder<Self> {
302 TableBuilder::with_callback(self)
303 }
304
305 pub fn functions(self) -> SignaturesBuilder<Self> {
307 SignaturesBuilder::with_callback(self)
308 }
309
310 pub fn with_export(mut self, entry: elements::ExportEntry) -> Self {
312 self.module.export.entries_mut().push(entry);
313 self
314 }
315
316 pub fn with_import(mut self, entry: elements::ImportEntry) -> Self {
318 self.module.import.entries_mut().push(entry);
319 self
320 }
321
322 pub fn import(self) -> import::ImportBuilder<Self> {
338 import::ImportBuilder::with_callback(self)
339 }
340
341 pub fn with_global(mut self, global: elements::GlobalEntry) -> Self {
343 self.module.global.entries_mut().push(global);
344 self
345 }
346
347 pub fn with_table(mut self, table: elements::TableType) -> Self {
349 self.module.table.entries_mut().push(table);
350 self
351 }
352
353 pub fn export(self) -> export::ExportBuilder<Self> {
373 export::ExportBuilder::with_callback(self)
374 }
375
376 pub fn global(self) -> global::GlobalBuilder<Self> {
392 global::GlobalBuilder::with_callback(self)
393 }
394
395 pub fn with_data_segment(mut self, segment: elements::DataSegment) -> Self {
397 self.module.data.entries_mut().push(segment);
398 self
399 }
400
401 pub fn data(self) -> data::DataSegmentBuilder<Self> {
403 data::DataSegmentBuilder::with_callback(self)
404 }
405
406 pub fn build(self) -> F::Result {
408 self.callback.invoke(self.module.into())
409 }
410}
411
412impl<F> Invoke<elements::FunctionSection> for ModuleBuilder<F>
413 where F: Invoke<elements::Module>
414{
415 type Result = Self;
416
417 fn invoke(self, section: elements::FunctionSection) -> Self {
418 self.with_section(elements::Section::Function(section))
419 }
420}
421
422impl<F> Invoke<code::SignatureBindings> for ModuleBuilder<F>
423 where F: Invoke<elements::Module>
424{
425 type Result = Self;
426
427 fn invoke(self, bindings: code::SignatureBindings) -> Self {
428 self.with_signatures(bindings)
429 }
430}
431
432
433impl<F> Invoke<code::FunctionDefinition> for ModuleBuilder<F>
434 where F: Invoke<elements::Module>
435{
436 type Result = Self;
437
438 fn invoke(self, def: code::FunctionDefinition) -> Self {
439 let mut b = self;
440 b.push_function(def);
441 b
442 }
443}
444
445impl<F> Invoke<memory::MemoryDefinition> for ModuleBuilder<F>
446 where F: Invoke<elements::Module>
447{
448 type Result = Self;
449
450 fn invoke(self, def: memory::MemoryDefinition) -> Self {
451 let mut b = self;
452 b.push_memory(def);
453 b
454 }
455}
456
457impl<F> Invoke<table::TableDefinition> for ModuleBuilder<F>
458 where F: Invoke<elements::Module>
459{
460 type Result = Self;
461
462 fn invoke(self, def: table::TableDefinition) -> Self {
463 let mut b = self;
464 b.push_table(def);
465 b
466 }
467}
468
469impl<F> Invoke<elements::ImportEntry> for ModuleBuilder<F>
470 where F: Invoke<elements::Module>
471{
472 type Result = Self;
473
474 fn invoke(self, entry: elements::ImportEntry) -> Self::Result {
475 self.with_import(entry)
476 }
477}
478
479impl<F> Invoke<elements::ExportEntry> for ModuleBuilder<F>
480 where F: Invoke<elements::Module>
481{
482 type Result = Self;
483
484 fn invoke(self, entry: elements::ExportEntry) -> Self::Result {
485 self.with_export(entry)
486 }
487}
488
489impl<F> Invoke<elements::GlobalEntry> for ModuleBuilder<F>
490 where F: Invoke<elements::Module>
491{
492 type Result = Self;
493
494 fn invoke(self, entry: elements::GlobalEntry) -> Self::Result {
495 self.with_global(entry)
496 }
497}
498
499impl<F> Invoke<elements::DataSegment> for ModuleBuilder<F>
500 where F: Invoke<elements::Module>
501{
502 type Result = Self;
503
504 fn invoke(self, segment: elements::DataSegment) -> Self {
505 self.with_data_segment(segment)
506 }
507}
508
509pub fn module() -> ModuleBuilder {
527 ModuleBuilder::new()
528}
529
530pub fn from_module(module: elements::Module) -> ModuleBuilder {
532 ModuleBuilder::new().with_module(module)
533}
534
535#[cfg(test)]
536mod tests {
537
538 use crate::elements;
539 use super::module;
540
541 #[test]
542 fn smoky() {
543 let module = module().build();
544 assert_eq!(module.sections().len(), 0);
545 }
546
547 #[test]
548 fn functions() {
549 let module = module()
550 .function()
551 .signature().param().i32().build()
552 .body().build()
553 .build()
554 .build();
555
556 assert_eq!(module.type_section().expect("type section to exist").types().len(), 1);
557 assert_eq!(module.function_section().expect("function section to exist").entries().len(), 1);
558 assert_eq!(module.code_section().expect("code section to exist").bodies().len(), 1);
559 }
560
561 #[test]
562 fn export() {
563 let module = module()
564 .export().field("call").internal().func(0).build()
565 .build();
566
567 assert_eq!(module.export_section().expect("export section to exist").entries().len(), 1);
568 }
569
570 #[test]
571 fn global() {
572 let module = module()
573 .global().value_type().i64().mutable().init_expr(elements::Instruction::I64Const(5)).build()
574 .build();
575
576 assert_eq!(module.global_section().expect("global section to exist").entries().len(), 1);
577 }
578
579 #[test]
580 fn data() {
581 let module = module()
582 .data()
583 .offset(elements::Instruction::I32Const(16))
584 .value(vec![0u8, 15, 10, 5, 25])
585 .build()
586 .build();
587
588 assert_eq!(module.data_section().expect("data section to exist").entries().len(), 1);
589 }
590
591 #[test]
592 fn reuse_types() {
593 let module = module()
594 .function()
595 .signature().param().i32().build()
596 .body().build()
597 .build()
598 .function()
599 .signature().param().i32().build()
600 .body().build()
601 .build()
602 .build();
603
604 assert_eq!(module.type_section().expect("type section failed").types().len(), 1);
605 }
606 }