sophon_wasm/builder/
module.rs1use super::invoke::{Invoke, Identity};
2use super::code::{self, SignaturesBuilder, FunctionBuilder};
3use super::memory::{self, MemoryBuilder};
4use super::table::{self, TableBuilder};
5use super::{import, export, global, data};
6use elements;
7
8pub struct ModuleBuilder<F=Identity> {
10 callback: F,
11 module: ModuleScaffold,
12}
13
14pub struct CodeLocation {
16 pub signature: u32,
18 pub body: u32,
20}
21
22#[derive(Default)]
23struct ModuleScaffold {
24 pub types: elements::TypeSection,
25 pub import: elements::ImportSection,
26 pub functions: elements::FunctionSection,
27 pub table: elements::TableSection,
28 pub memory: elements::MemorySection,
29 pub global: elements::GlobalSection,
30 pub export: elements::ExportSection,
31 pub start: Option<u32>,
32 pub element: elements::ElementSection,
33 pub code: elements::CodeSection,
34 pub data: elements::DataSection,
35 pub other: Vec<elements::Section>,
36}
37
38impl From<elements::Module> for ModuleScaffold {
39 fn from(module: elements::Module) -> Self {
40 let mut types: Option<elements::TypeSection> = None;
41 let mut import: Option<elements::ImportSection> = None;
42 let mut funcs: Option<elements::FunctionSection> = None;
43 let mut table: Option<elements::TableSection> = None;
44 let mut memory: Option<elements::MemorySection> = None;
45 let mut global: Option<elements::GlobalSection> = None;
46 let mut export: Option<elements::ExportSection> = None;
47 let mut start: Option<u32> = None;
48 let mut element: Option<elements::ElementSection> = None;
49 let mut code: Option<elements::CodeSection> = None;
50 let mut data: Option<elements::DataSection> = None;
51
52 let mut sections = module.into_sections();
53 while let Some(section) = sections.pop() {
54 match section {
55 elements::Section::Type(sect) => { types = Some(sect); }
56 elements::Section::Import(sect) => { import = Some(sect); }
57 elements::Section::Function(sect) => { funcs = Some(sect); }
58 elements::Section::Table(sect) => { table = Some(sect); }
59 elements::Section::Memory(sect) => { memory = Some(sect); }
60 elements::Section::Global(sect) => { global = Some(sect); }
61 elements::Section::Export(sect) => { export = Some(sect); }
62 elements::Section::Start(index) => { start = Some(index); }
63 elements::Section::Element(sect) => { element = Some(sect); }
64 elements::Section::Code(sect) => { code = Some(sect); }
65 elements::Section::Data(sect) => { data = Some(sect); }
66 _ => {}
67 }
68 }
69
70 ModuleScaffold {
71 types: types.unwrap_or_default(),
72 import: import.unwrap_or_default(),
73 functions: funcs.unwrap_or_default(),
74 table: table.unwrap_or_default(),
75 memory: memory.unwrap_or_default(),
76 global: global.unwrap_or_default(),
77 export: export.unwrap_or_default(),
78 start: start,
79 element: element.unwrap_or_default(),
80 code: code.unwrap_or_default(),
81 data: data.unwrap_or_default(),
82 other: sections,
83 }
84 }
85}
86
87impl From<ModuleScaffold> for elements::Module {
88 fn from(module: ModuleScaffold) -> Self {
89 let mut sections = Vec::new();
90
91 let types = module.types;
92 if types.types().len() > 0 {
93 sections.push(elements::Section::Type(types));
94 }
95 let import = module.import;
96 if import.entries().len() > 0 {
97 sections.push(elements::Section::Import(import));
98 }
99 let functions = module.functions;
100 if functions.entries().len() > 0 {
101 sections.push(elements::Section::Function(functions));
102 }
103 let table = module.table;
104 if table.entries().len() > 0 {
105 sections.push(elements::Section::Table(table));
106 }
107 let memory = module.memory;
108 if memory.entries().len() > 0 {
109 sections.push(elements::Section::Memory(memory));
110 }
111 let global = module.global;
112 if global.entries().len() > 0 {
113 sections.push(elements::Section::Global(global));
114 }
115 let export = module.export;
116 if export.entries().len() > 0 {
117 sections.push(elements::Section::Export(export));
118 }
119 if let Some(start) = module.start {
120 sections.push(elements::Section::Start(start));
121 }
122 let element = module.element;
123 if element.entries().len() > 0 {
124 sections.push(elements::Section::Element(element));
125 }
126 let code = module.code;
127 if code.bodies().len() > 0 {
128 sections.push(elements::Section::Code(code));
129 }
130 let data = module.data;
131 if data.entries().len() > 0 {
132 sections.push(elements::Section::Data(data));
133 }
134 sections.extend(module.other);
135 elements::Module::new(sections)
136 }
137}
138
139impl ModuleBuilder {
140 pub fn new() -> Self {
142 ModuleBuilder::with_callback(Identity)
143 }
144}
145
146impl<F> ModuleBuilder<F> where F: Invoke<elements::Module> {
147 pub fn with_callback(callback: F) -> Self {
149 ModuleBuilder {
150 callback: callback,
151 module: Default::default(),
152 }
153 }
154
155 pub fn with_module(mut self, module: elements::Module) -> Self {
157 self.module = module.into();
158 self
159 }
160
161 pub fn with_sections<I>(mut self, sections: I) -> Self
163 where I: IntoIterator<Item=elements::Section>
164 {
165 self.module.other.extend(sections);
166 self
167 }
168
169 pub fn with_section(mut self, section: elements::Section) -> Self {
171 self.module.other.push(section);
172 self
173 }
174
175 pub fn with_signatures(mut self, bindings: code::SignatureBindings) -> Self {
177 self.push_signatures(bindings);
178 self
179 }
180
181 pub fn push_function(&mut self, func: code::FunctionDefinition) -> CodeLocation {
185 let signature = func.signature;
186 let body = func.code;
187
188 let type_ref = self.resolve_type_ref(signature);
189
190 self.module.functions.entries_mut().push(elements::Func::new(type_ref));
191 let signature_index = self.module.functions.entries_mut().len() as u32 - 1;
192 self.module.code.bodies_mut().push(body);
193 let body_index = self.module.code.bodies_mut().len() as u32 - 1;
194
195 if func.is_main {
196 self.module.start = Some(body_index);
197 }
198
199 CodeLocation {
200 signature: signature_index,
201 body: body_index,
202 }
203 }
204
205 pub fn push_memory(&mut self, mut memory: memory::MemoryDefinition) -> u32 {
207 let entries = self.module.memory.entries_mut();
208 entries.push(elements::MemoryType::new(memory.min, memory.max));
209 let memory_index = (entries.len() - 1) as u32;
210 for data in memory.data.drain(..) {
211 self.module.data.entries_mut()
212 .push(elements::DataSegment::new(memory_index, data.offset, data.values))
213 }
214 memory_index
215 }
216
217 pub fn push_table(&mut self, mut table: table::TableDefinition) -> u32 {
219 let entries = self.module.table.entries_mut();
220 entries.push(elements::TableType::new(table.min, table.max));
221 let table_index = (entries.len() - 1) as u32;
222 for entry in table.elements.drain(..) {
223 self.module.element.entries_mut()
224 .push(elements::ElementSegment::new(table_index, entry.offset, entry.values))
225 }
226 table_index
227 }
228
229 fn resolve_type_ref(&mut self, signature: code::Signature) -> u32 {
230 match signature {
231 code::Signature::Inline(func_type) => {
232 self.module.types.types_mut().push(elements::Type::Function(func_type));
234 self.module.types.types().len() as u32 - 1
235 }
236 code::Signature::TypeReference(type_ref) => {
237 type_ref
238 }
239 }
240 }
241
242 pub fn push_signature(&mut self, signature: code::Signature) -> u32 {
245 self.resolve_type_ref(signature)
246 }
247
248 pub fn push_signatures(&mut self, signatures: code::SignatureBindings) -> Vec<u32> {
250 signatures.into_iter().map(|binding|
251 self.resolve_type_ref(binding)
252 ).collect()
253 }
254
255 pub fn push_import(&mut self, import: elements::ImportEntry) -> u32 {
258 self.module.import.entries_mut().push(import);
259 self.module.import.entries_mut().len() as u32 - 1
263 }
264
265 pub fn push_export(&mut self, export: elements::ExportEntry) -> u32 {
267 self.module.export.entries_mut().push(export);
268 self.module.export.entries_mut().len() as u32 - 1
269 }
270
271 pub fn function(self) -> FunctionBuilder<Self> {
273 FunctionBuilder::with_callback(self)
274 }
275
276 pub fn memory(self) -> MemoryBuilder<Self> {
278 MemoryBuilder::with_callback(self)
279 }
280
281 pub fn table(self) -> TableBuilder<Self> {
283 TableBuilder::with_callback(self)
284 }
285
286 pub fn functions(self) -> SignaturesBuilder<Self> {
288 SignaturesBuilder::with_callback(self)
289 }
290
291 pub fn with_export(mut self, entry: elements::ExportEntry) -> Self {
293 self.module.export.entries_mut().push(entry);
294 self
295 }
296
297 pub fn with_import(mut self, entry: elements::ImportEntry) -> Self {
299 self.module.import.entries_mut().push(entry);
300 self
301 }
302
303 pub fn import(self) -> import::ImportBuilder<Self> {
319 import::ImportBuilder::with_callback(self)
320 }
321
322 pub fn with_global(mut self, global: elements::GlobalEntry) -> Self {
324 self.module.global.entries_mut().push(global);
325 self
326 }
327
328 pub fn with_table(mut self, table: elements::TableType) -> Self {
330 self.module.table.entries_mut().push(table);
331 self
332 }
333
334 pub fn export(self) -> export::ExportBuilder<Self> {
354 export::ExportBuilder::with_callback(self)
355 }
356
357 pub fn global(self) -> global::GlobalBuilder<Self> {
373 global::GlobalBuilder::with_callback(self)
374 }
375
376 pub fn with_data_segment(mut self, segment: elements::DataSegment) -> Self {
378 self.module.data.entries_mut().push(segment);
379 self
380 }
381
382 pub fn data(self) -> data::DataSegmentBuilder<Self> {
384 data::DataSegmentBuilder::with_callback(self)
385 }
386
387 pub fn build(self) -> F::Result {
389 self.callback.invoke(self.module.into())
390 }
391}
392
393impl<F> Invoke<elements::FunctionSection> for ModuleBuilder<F>
394 where F: Invoke<elements::Module>
395{
396 type Result = Self;
397
398 fn invoke(self, section: elements::FunctionSection) -> Self {
399 self.with_section(elements::Section::Function(section))
400 }
401}
402
403impl<F> Invoke<code::SignatureBindings> for ModuleBuilder<F>
404 where F: Invoke<elements::Module>
405{
406 type Result = Self;
407
408 fn invoke(self, bindings: code::SignatureBindings) -> Self {
409 self.with_signatures(bindings)
410 }
411}
412
413
414impl<F> Invoke<code::FunctionDefinition> for ModuleBuilder<F>
415 where F: Invoke<elements::Module>
416{
417 type Result = Self;
418
419 fn invoke(self, def: code::FunctionDefinition) -> Self {
420 let mut b = self;
421 b.push_function(def);
422 b
423 }
424}
425
426impl<F> Invoke<memory::MemoryDefinition> for ModuleBuilder<F>
427 where F: Invoke<elements::Module>
428{
429 type Result = Self;
430
431 fn invoke(self, def: memory::MemoryDefinition) -> Self {
432 let mut b = self;
433 b.push_memory(def);
434 b
435 }
436}
437
438impl<F> Invoke<table::TableDefinition> for ModuleBuilder<F>
439 where F: Invoke<elements::Module>
440{
441 type Result = Self;
442
443 fn invoke(self, def: table::TableDefinition) -> Self {
444 let mut b = self;
445 b.push_table(def);
446 b
447 }
448}
449
450impl<F> Invoke<elements::ImportEntry> for ModuleBuilder<F>
451 where F: Invoke<elements::Module>
452{
453 type Result = Self;
454
455 fn invoke(self, entry: elements::ImportEntry) -> Self::Result {
456 self.with_import(entry)
457 }
458}
459
460impl<F> Invoke<elements::ExportEntry> for ModuleBuilder<F>
461 where F: Invoke<elements::Module>
462{
463 type Result = Self;
464
465 fn invoke(self, entry: elements::ExportEntry) -> Self::Result {
466 self.with_export(entry)
467 }
468}
469
470impl<F> Invoke<elements::GlobalEntry> for ModuleBuilder<F>
471 where F: Invoke<elements::Module>
472{
473 type Result = Self;
474
475 fn invoke(self, entry: elements::GlobalEntry) -> Self::Result {
476 self.with_global(entry)
477 }
478}
479
480impl<F> Invoke<elements::DataSegment> for ModuleBuilder<F>
481 where F: Invoke<elements::Module>
482{
483 type Result = Self;
484
485 fn invoke(self, segment: elements::DataSegment) -> Self {
486 self.with_data_segment(segment)
487 }
488}
489
490pub fn module() -> ModuleBuilder {
508 ModuleBuilder::new()
509}
510
511pub fn from_module(module: elements::Module) -> ModuleBuilder {
513 ModuleBuilder::new().with_module(module)
514}
515
516#[cfg(test)]
517mod tests {
518
519 use super::module;
520
521 #[test]
522 fn smoky() {
523 let module = module().build();
524 assert_eq!(module.sections().len(), 0);
525 }
526
527 #[test]
528 fn functions() {
529 let module = module()
530 .function()
531 .signature().param().i32().build()
532 .body().build()
533 .build()
534 .build();
535
536 assert_eq!(module.type_section().expect("type section to exist").types().len(), 1);
537 assert_eq!(module.function_section().expect("function section to exist").entries().len(), 1);
538 assert_eq!(module.code_section().expect("code section to exist").bodies().len(), 1);
539 }
540
541 #[test]
542 fn export() {
543 let module = module()
544 .export().field("call").internal().func(0).build()
545 .build();
546
547 assert_eq!(module.export_section().expect("export section to exist").entries().len(), 1);
548 }
549
550 #[test]
551 fn global() {
552 let module = module()
553 .global().value_type().i64().mutable().init_expr(::elements::Opcode::I64Const(5)).build()
554 .build();
555
556 assert_eq!(module.global_section().expect("global section to exist").entries().len(), 1);
557 }
558
559 #[test]
560 fn data() {
561 let module = module()
562 .data()
563 .offset(::elements::Opcode::I32Const(16))
564 .value(vec![0u8, 15, 10, 5, 25])
565 .build()
566 .build();
567
568 assert_eq!(module.data_section().expect("data section to exist").entries().len(), 1);
569 }
570 }