1use indexmap::IndexMap;
2use std::mem;
3use wasm_encoder::{Function, MemArg};
4use wit_parser::TypeId;
5
6const VERSION: u32 = 3;
7
8#[derive(Default)]
9pub struct Metadata {
10 pub import_funcs: Vec<ImportFunc>,
11 pub export_funcs: Vec<ExportFunc>,
12 pub resources: Vec<Resource>,
13 pub records: Vec<Record>,
14 pub flags: Vec<Flags>,
15 pub tuples: Vec<Tuple>,
16 pub variants: Vec<Variant>,
17 pub enums: Vec<Enum>,
18 pub options: Vec<WitOption>,
19 pub results: Vec<WitResult>,
20 pub lists: Vec<List>,
21 pub maps: Vec<Map>,
22 pub fixed_length_lists: Vec<FixedLengthList>,
23 pub futures: Vec<Future>,
24 pub streams: Vec<Stream>,
25 pub aliases: Vec<Alias>,
26}
27
28pub struct ImportFunc {
29 pub interface: Option<String>,
30 pub name: String,
31 pub sync_import_elem_index: Option<u32>,
32 pub async_import_elem_index: Option<u32>,
33 pub async_import_lift_results_elem_index: Option<u32>,
34 pub args: Vec<Type>,
35 pub result: Option<Type>,
36 pub async_abi_area: Option<(usize, usize)>,
37}
38
39pub struct ExportFunc {
40 pub interface: Option<String>,
41 pub name: String,
42 pub async_export_task_return_elem_index: Option<u32>,
43 pub args: Vec<Type>,
44 pub result: Option<Type>,
45}
46
47pub struct Resource {
48 pub id: TypeId,
49 pub interface: Option<String>,
50 pub name: String,
51 pub drop_elem_index: u32,
52 pub new_elem_index: Option<u32>,
53 pub rep_elem_index: Option<u32>,
54}
55
56pub struct Record {
57 pub id: TypeId,
58 pub interface: Option<String>,
59 pub name: String,
60 pub fields: Vec<(String, Type)>,
61}
62
63pub struct Flags {
64 pub id: TypeId,
65 pub interface: Option<String>,
66 pub name: String,
67 pub names: Vec<String>,
68}
69
70pub struct Tuple {
71 pub id: TypeId,
72 pub interface: Option<String>,
73 pub name: Option<String>,
74 pub types: Vec<Type>,
75}
76
77pub struct Variant {
78 pub id: TypeId,
79 pub interface: Option<String>,
80 pub name: String,
81 pub cases: Vec<(String, Option<Type>)>,
82}
83
84pub struct Enum {
85 pub id: TypeId,
86 pub interface: Option<String>,
87 pub name: String,
88 pub names: Vec<String>,
89}
90
91pub struct WitOption {
92 pub id: TypeId,
93 pub interface: Option<String>,
94 pub name: Option<String>,
95 pub ty: Type,
96}
97
98pub struct WitResult {
99 pub id: TypeId,
100 pub interface: Option<String>,
101 pub name: Option<String>,
102 pub ok: Option<Type>,
103 pub err: Option<Type>,
104}
105
106pub struct List {
107 pub id: TypeId,
108 pub interface: Option<String>,
109 pub name: Option<String>,
110 pub ty: Type,
111}
112
113pub struct FixedLengthList {
114 pub id: TypeId,
115 pub interface: Option<String>,
116 pub name: Option<String>,
117 pub len: u32,
118 pub ty: Type,
119}
120
121pub struct Map {
122 pub id: TypeId,
123 pub interface: Option<String>,
124 pub name: Option<String>,
125 pub key_type: Type,
126 pub value_type: Type,
127}
128
129pub struct Future {
130 pub id: TypeId,
131 pub interface: Option<String>,
132 pub name: Option<String>,
133 pub ty: Option<Type>,
134 pub new_elem_index: u32,
135 pub read_elem_index: u32,
136 pub write_elem_index: u32,
137 pub cancel_read_elem_index: u32,
138 pub cancel_write_elem_index: u32,
139 pub drop_readable_elem_index: u32,
140 pub drop_writable_elem_index: u32,
141 pub lift_elem_index: Option<u32>,
142 pub lower_elem_index: Option<u32>,
143 pub abi_payload_size: usize,
144 pub abi_payload_align: usize,
145}
146
147pub struct Stream {
148 pub id: TypeId,
149 pub interface: Option<String>,
150 pub name: Option<String>,
151 pub ty: Option<Type>,
152 pub new_elem_index: u32,
153 pub read_elem_index: u32,
154 pub write_elem_index: u32,
155 pub cancel_read_elem_index: u32,
156 pub cancel_write_elem_index: u32,
157 pub drop_readable_elem_index: u32,
158 pub drop_writable_elem_index: u32,
159 pub lift_elem_index: Option<u32>,
160 pub lower_elem_index: Option<u32>,
161 pub abi_payload_size: usize,
162 pub abi_payload_align: usize,
163}
164
165pub struct Alias {
166 pub id: TypeId,
167 pub interface: Option<String>,
168 pub name: String,
169 pub ty: Type,
170}
171
172#[derive(Copy, Clone)]
173pub enum Type {
174 U8,
175 U16,
176 U32,
177 U64,
178 S8,
179 S16,
180 S32,
181 S64,
182 Bool,
183 Char,
184 F32,
185 F64,
186 String,
187 ErrorContext,
188 Record(usize),
189 Own(usize),
190 Borrow(usize),
191 Flags(usize),
192 Tuple(usize),
193 Variant(usize),
194 Enum(usize),
195 Option(usize),
196 Result(usize),
197 List(usize),
198 FixedLengthList(usize),
199 Map(usize),
200 Future(usize),
201 Stream(usize),
202 Alias(usize),
203}
204
205struct Encoder {
206 data: Vec<u8>,
207 table_base: u32,
208 memory_base: u32,
209 relocs: Vec<Reloc>,
210 strings: IndexMap<String, SymbolId>,
211 symbol_offsets: Vec<usize>,
212}
213
214struct Reloc {
215 sym: SymbolId,
216 offset: usize,
217 addend: usize,
218 kind: RelocKind,
219}
220
221enum RelocKind {
222 Data,
223 Table,
224}
225
226#[derive(Debug, PartialEq, Copy, Clone)]
227struct SymbolId(usize);
228
229impl SymbolId {
230 const TABLE: SymbolId = SymbolId(usize::MAX);
231}
232
233impl Metadata {
234 pub fn encode(&self, table_base: u32, memory_base: u32) -> (u32, Vec<u8>, Option<Function>) {
235 let mut encoder = Encoder {
236 data: Vec::new(),
237 table_base,
238 memory_base,
239 relocs: Vec::new(),
240 strings: IndexMap::new(),
241 symbol_offsets: Vec::new(),
242 };
243
244 let import_funcs = encoder.encode_list(&self.import_funcs, Encoder::encode_import_funcs);
245 let export_funcs = encoder.encode_list(&self.export_funcs, Encoder::encode_export_funcs);
246 let resources = encoder.encode_list(&self.resources, Encoder::encode_resources);
247 let records = encoder.encode_list(&self.records, Encoder::encode_records);
248 let flags = encoder.encode_list(&self.flags, Encoder::encode_flags);
249 let tuples = encoder.encode_list(&self.tuples, Encoder::encode_tuples);
250 let variants = encoder.encode_list(&self.variants, Encoder::encode_variants);
251 let enums = encoder.encode_list(&self.enums, Encoder::encode_enums);
252 let options = encoder.encode_list(&self.options, Encoder::encode_options);
253 let results = encoder.encode_list(&self.results, Encoder::encode_results);
254 let lists = encoder.encode_list(&self.lists, Encoder::encode_lists);
255 let maps = encoder.encode_list(&self.maps, Encoder::encode_maps);
256 let fixed_length_lists =
257 encoder.encode_list(&self.fixed_length_lists, Encoder::encode_fixed_length_lists);
258 let futures = encoder.encode_list(&self.futures, Encoder::encode_futures);
259 let streams = encoder.encode_list(&self.streams, Encoder::encode_streams);
260 let aliases = encoder.encode_list(&self.aliases, Encoder::encode_aliases);
261
262 let sym_metadata = encoder.symbol();
263 encoder.bind(sym_metadata);
264 encoder.put_u32(VERSION);
265 for (sym, len) in [
266 import_funcs,
267 export_funcs,
268 resources,
269 records,
270 flags,
271 tuples,
272 variants,
273 enums,
274 options,
275 results,
276 lists,
277 maps,
278 fixed_length_lists,
279 futures,
280 streams,
281 aliases,
282 ] {
283 encoder.put_usize(len);
284 if len > 0 {
285 encoder.memory_ptr(sym);
286 } else {
287 encoder.put_usize(0);
288 }
289 }
290
291 encoder.encode_strings();
292
293 let apply_relocs = encoder.generate_apply_relocs();
294 (
295 u32::try_from(encoder.symbol_offsets[sym_metadata.0]).unwrap(),
296 encoder.finish(),
297 apply_relocs,
298 )
299 }
300}
301
302impl Encoder {
303 fn encode_list<T>(
304 &mut self,
305 list: &[T],
306 encode: impl Fn(&mut Self, &[T]),
307 ) -> (SymbolId, usize) {
308 let ret = self.symbol();
309 self.bind(ret);
310 encode(self, list);
311 (ret, list.len())
312 }
313
314 fn encode_import_funcs(&mut self, funcs: &[ImportFunc]) {
315 let mut deferred_args = Vec::new();
316 for func in funcs {
317 let ImportFunc {
318 interface,
319 name,
320 sync_import_elem_index,
321 async_import_elem_index,
322 async_import_lift_results_elem_index,
323 args,
324 result,
325 async_abi_area,
326 } = func;
327 self.opt_string_ptr(interface.as_deref());
328 self.string_ptr(name);
329 self.opt_elem_index(*sync_import_elem_index);
330 self.opt_elem_index(*async_import_elem_index);
331 self.opt_elem_index(*async_import_lift_results_elem_index);
332 self.list(args, &mut deferred_args);
333 self.opt_ty(result.as_ref());
334 match async_abi_area {
335 Some((size, align)) => {
336 self.put_usize(*size);
337 self.put_usize(*align);
338 }
339 None => {
340 self.put_usize(0);
341 self.put_usize(0);
342 }
343 }
344 }
345
346 for (sym, args) in deferred_args {
347 self.bind(sym);
348 for arg in args {
349 self.ty(arg);
350 }
351 }
352 }
353
354 fn encode_export_funcs(&mut self, funcs: &[ExportFunc]) {
355 let mut deferred_args = Vec::new();
356 for func in funcs {
357 let ExportFunc {
358 interface,
359 name,
360 async_export_task_return_elem_index,
361 args,
362 result,
363 } = func;
364 self.opt_string_ptr(interface.as_deref());
365 self.string_ptr(name);
366 self.opt_elem_index(*async_export_task_return_elem_index);
367 self.list(args, &mut deferred_args);
368 self.opt_ty(result.as_ref());
369 }
370
371 for (sym, args) in deferred_args {
372 self.bind(sym);
373 for arg in args {
374 self.ty(arg);
375 }
376 }
377 }
378
379 fn encode_resources(&mut self, resources: &[Resource]) {
380 for resource in resources {
381 let Resource {
382 id: _,
383 interface,
384 name,
385 drop_elem_index,
386 new_elem_index,
387 rep_elem_index,
388 } = resource;
389 self.opt_string_ptr(interface.as_deref());
390 self.string_ptr(name);
391 self.elem_index(*drop_elem_index);
392 self.opt_elem_index(*new_elem_index);
393 self.opt_elem_index(*rep_elem_index);
394 }
395 }
396
397 fn encode_records(&mut self, records: &[Record]) {
398 let mut deferred_fields = Vec::new();
399 for record in records {
400 let Record {
401 id: _,
402 interface,
403 name,
404 fields,
405 } = record;
406 self.opt_string_ptr(interface.as_deref());
407 self.string_ptr(name);
408 self.list(fields, &mut deferred_fields);
409 }
410
411 for (sym, fields) in deferred_fields {
412 self.bind(sym);
413 for (name, ty) in fields {
414 self.string_ptr(name);
415 self.ty(ty);
416 }
417 }
418 }
419
420 fn encode_flags(&mut self, flags: &[Flags]) {
421 let mut deferred = Vec::new();
422 for flags in flags {
423 let Flags {
424 id: _,
425 interface,
426 name,
427 names,
428 } = flags;
429 self.opt_string_ptr(interface.as_deref());
430 self.string_ptr(name);
431 self.list(names, &mut deferred);
432 }
433
434 for (sym, names) in deferred {
435 self.bind(sym);
436 for name in names {
437 self.string_ptr(name);
438 }
439 }
440 }
441
442 fn encode_tuples(&mut self, tuples: &[Tuple]) {
443 let mut deferred = Vec::new();
444 for tuple in tuples {
445 let Tuple {
446 id: _,
447 interface,
448 name,
449 types,
450 } = tuple;
451 self.opt_string_ptr(interface.as_deref());
452 self.opt_string_ptr(name.as_deref());
453 self.list(types, &mut deferred);
454 }
455
456 for (sym, types) in deferred {
457 self.bind(sym);
458 for ty in types {
459 self.ty(ty);
460 }
461 }
462 }
463
464 fn encode_variants(&mut self, variants: &[Variant]) {
465 let mut deferred = Vec::new();
466 for variant in variants {
467 let Variant {
468 id: _,
469 interface,
470 name,
471 cases,
472 } = variant;
473 self.opt_string_ptr(interface.as_deref());
474 self.string_ptr(name);
475 self.list(cases, &mut deferred);
476 }
477
478 for (sym, cases) in deferred {
479 self.bind(sym);
480 for (name, ty) in cases {
481 self.string_ptr(name);
482 self.opt_ty(ty.as_ref());
483 }
484 }
485 }
486
487 fn encode_enums(&mut self, enums: &[Enum]) {
488 let mut deferred = Vec::new();
489 for e in enums {
490 let Enum {
491 id: _,
492 interface,
493 name,
494 names,
495 } = e;
496 self.opt_string_ptr(interface.as_deref());
497 self.string_ptr(name);
498 self.list(names, &mut deferred);
499 }
500
501 for (sym, names) in deferred {
502 self.bind(sym);
503 for name in names {
504 self.string_ptr(name);
505 }
506 }
507 }
508
509 fn encode_options(&mut self, options: &[WitOption]) {
510 for option in options {
511 let WitOption {
512 id: _,
513 interface,
514 name,
515 ty,
516 } = option;
517 self.opt_string_ptr(interface.as_deref());
518 self.opt_string_ptr(name.as_deref());
519 self.ty(ty);
520 }
521 }
522
523 fn encode_results(&mut self, results: &[WitResult]) {
524 for result in results {
525 let WitResult {
526 id: _,
527 interface,
528 name,
529 ok,
530 err,
531 } = result;
532 self.opt_string_ptr(interface.as_deref());
533 self.opt_string_ptr(name.as_deref());
534 self.opt_ty(ok.as_ref());
535 self.opt_ty(err.as_ref());
536 }
537 }
538
539 fn encode_lists(&mut self, lists: &[List]) {
540 for list in lists {
541 let List {
542 id: _,
543 interface,
544 name,
545 ty,
546 } = list;
547 self.opt_string_ptr(interface.as_deref());
548 self.opt_string_ptr(name.as_deref());
549 self.ty(ty);
550 }
551 }
552
553 fn encode_maps(&mut self, maps: &[Map]) {
554 for map in maps {
555 let Map {
556 id: _,
557 interface,
558 name,
559 key_type,
560 value_type,
561 } = map;
562 self.opt_string_ptr(interface.as_deref());
563 self.opt_string_ptr(name.as_deref());
564 self.ty(key_type);
565 self.ty(value_type);
566 }
567 }
568
569 fn encode_fixed_length_lists(&mut self, lists: &[FixedLengthList]) {
570 for list in lists {
571 let FixedLengthList {
572 id: _,
573 interface,
574 name,
575 len,
576 ty,
577 } = list;
578 self.opt_string_ptr(interface.as_deref());
579 self.opt_string_ptr(name.as_deref());
580 self.put_u32(*len);
581 self.ty(ty);
582 }
583 }
584
585 fn encode_futures(&mut self, futures: &[Future]) {
586 for future in futures {
587 let Future {
588 id: _,
589 interface,
590 name,
591 ty,
592 new_elem_index,
593 read_elem_index,
594 write_elem_index,
595 cancel_read_elem_index,
596 cancel_write_elem_index,
597 drop_readable_elem_index,
598 drop_writable_elem_index,
599 lift_elem_index,
600 lower_elem_index,
601 abi_payload_size,
602 abi_payload_align,
603 } = future;
604 self.opt_string_ptr(interface.as_deref());
605 self.opt_string_ptr(name.as_deref());
606 self.opt_ty(ty.as_ref());
607 self.elem_index(*new_elem_index);
608 self.elem_index(*read_elem_index);
609 self.elem_index(*write_elem_index);
610 self.elem_index(*cancel_read_elem_index);
611 self.elem_index(*cancel_write_elem_index);
612 self.elem_index(*drop_readable_elem_index);
613 self.elem_index(*drop_writable_elem_index);
614 self.opt_elem_index(*lift_elem_index);
615 self.opt_elem_index(*lower_elem_index);
616 self.put_usize(*abi_payload_size);
617 self.put_usize(*abi_payload_align);
618 }
619 }
620
621 fn encode_streams(&mut self, streams: &[Stream]) {
622 for stream in streams {
623 let Stream {
624 id: _,
625 interface,
626 name,
627 ty,
628 new_elem_index,
629 read_elem_index,
630 write_elem_index,
631 cancel_read_elem_index,
632 cancel_write_elem_index,
633 drop_readable_elem_index,
634 drop_writable_elem_index,
635 lift_elem_index,
636 lower_elem_index,
637 abi_payload_size,
638 abi_payload_align,
639 } = stream;
640 self.opt_string_ptr(interface.as_deref());
641 self.opt_string_ptr(name.as_deref());
642 self.opt_ty(ty.as_ref());
643 self.elem_index(*new_elem_index);
644 self.elem_index(*read_elem_index);
645 self.elem_index(*write_elem_index);
646 self.elem_index(*cancel_read_elem_index);
647 self.elem_index(*cancel_write_elem_index);
648 self.elem_index(*drop_readable_elem_index);
649 self.elem_index(*drop_writable_elem_index);
650 self.opt_elem_index(*lift_elem_index);
651 self.opt_elem_index(*lower_elem_index);
652 self.put_usize(*abi_payload_size);
653 self.put_usize(*abi_payload_align);
654 }
655 }
656
657 fn encode_aliases(&mut self, aliases: &[Alias]) {
658 for alias in aliases {
659 let Alias {
660 id: _,
661 interface,
662 name,
663 ty,
664 } = alias;
665 self.opt_string_ptr(interface.as_deref());
666 self.string_ptr(name);
667 self.ty(ty);
668 }
669 }
670
671 fn encode_strings(&mut self) {
672 for (string, sym) in mem::take(&mut self.strings) {
673 self.bind(sym);
674 self.data.extend_from_slice(string.as_bytes());
675 self.data.push(0);
676 }
677 }
678
679 fn symbol(&mut self) -> SymbolId {
684 let ret = SymbolId(self.symbol_offsets.len());
685 self.symbol_offsets.push(usize::MAX);
686 ret
687 }
688
689 fn bind(&mut self, sym: SymbolId) {
693 assert_eq!(self.symbol_offsets[sym.0], usize::MAX);
694 self.symbol_offsets[sym.0] = self.data.len();
695 }
696
697 fn put_u32(&mut self, value: u32) {
698 self.data.extend_from_slice(&value.to_le_bytes());
699 }
700
701 fn put_usize(&mut self, value: usize) {
702 self.put_u32(value.try_into().unwrap());
703 }
704
705 fn list<'a, T>(&mut self, list: &'a [T], deferred: &mut Vec<(SymbolId, &'a [T])>) {
710 self.put_usize(list.len());
711 if list.is_empty() {
712 self.put_usize(0);
713 } else {
714 let sym = self.symbol();
715 deferred.push((sym, list));
716 self.memory_ptr(sym);
717 }
718 }
719
720 fn memory_ptr(&mut self, sym: SymbolId) {
722 self.add_reloc(sym, 0, RelocKind::Data);
723 self.put_u32(0);
724 }
725
726 fn opt_elem_index(&mut self, value: Option<u32>) {
727 match value {
728 Some(name) => self.elem_index(name),
729 None => self.put_u32(0),
730 }
731 }
732
733 fn elem_index(&mut self, value: u32) {
734 self.add_reloc(SymbolId::TABLE, value.try_into().unwrap(), RelocKind::Table);
735 self.put_u32(0);
736 }
737
738 fn opt_string_ptr(&mut self, value: Option<&str>) {
740 match value {
741 Some(name) => self.string_ptr(name),
742 None => self.put_u32(0),
743 }
744 }
745
746 fn string_ptr(&mut self, value: &str) {
748 let string_sym = if self.strings.contains_key(value) {
749 self.strings[value]
750 } else {
751 let sym = self.symbol();
752 self.strings.insert(value.to_string(), sym);
753 sym
754 };
755 self.memory_ptr(string_sym);
756 }
757
758 fn ty(&mut self, ty: &Type) {
759 let index = |discr: u32, index: &usize| {
760 let index = u32::try_from(*index).unwrap();
761 assert_eq!(index << 8 >> 8, index);
762 (index << 8) | discr
763 };
764 let val = match ty {
765 Type::U8 => 0,
766 Type::U16 => 1,
767 Type::U32 => 2,
768 Type::U64 => 3,
769 Type::S8 => 4,
770 Type::S16 => 5,
771 Type::S32 => 6,
772 Type::S64 => 7,
773 Type::Bool => 8,
774 Type::Char => 9,
775 Type::F32 => 10,
776 Type::F64 => 11,
777 Type::String => 12,
778 Type::ErrorContext => 13,
779 Type::Record(i) => index(14, i),
780 Type::Own(i) => index(15, i),
781 Type::Borrow(i) => index(16, i),
782 Type::Flags(i) => index(17, i),
783 Type::Tuple(i) => index(18, i),
784 Type::Variant(i) => index(19, i),
785 Type::Enum(i) => index(20, i),
786 Type::Option(i) => index(21, i),
787 Type::Result(i) => index(22, i),
788 Type::List(i) => index(23, i),
789 Type::Map(i) => index(24, i),
790 Type::FixedLengthList(i) => index(25, i),
791 Type::Future(i) => index(26, i),
792 Type::Stream(i) => index(27, i),
793 Type::Alias(i) => index(28, i),
794 };
795 self.put_u32(val);
796 }
797
798 fn opt_ty(&mut self, ty: Option<&Type>) {
799 match ty {
800 Some(ty) => self.ty(ty),
801 None => self.put_u32(u32::MAX),
802 }
803 }
804
805 fn add_reloc(&mut self, sym: SymbolId, addend: usize, kind: RelocKind) {
806 self.relocs.push(Reloc {
807 sym,
808 offset: self.data.len(),
809 addend,
810 kind,
811 });
812 }
813
814 fn generate_apply_relocs(&mut self) -> Option<Function> {
815 if self.relocs.is_empty() {
816 return None;
817 }
818 let mut func = Function::new([]);
819 let mut ins = func.instructions();
820 for reloc in self.relocs.iter() {
821 let addend_i32 = u32::try_from(reloc.addend).unwrap() as i32;
822
823 ins.global_get(self.memory_base);
824 match reloc.kind {
825 RelocKind::Data => {
826 ins.global_get(self.memory_base);
827 let offset = self.symbol_offsets[reloc.sym.0];
828 assert!(
829 offset != usize::MAX,
830 "failed to bind symbol {}",
831 reloc.sym.0,
832 );
833
834 let sym_i32 = u32::try_from(offset).unwrap() as i32;
835 ins.i32_const(sym_i32);
836 ins.i32_add();
837 }
838 RelocKind::Table => {
839 ins.global_get(self.table_base);
840 assert_eq!(reloc.sym, SymbolId::TABLE);
841 }
842 }
843 if addend_i32 != 0 {
844 ins.i32_const(addend_i32);
845 ins.i32_add();
846 }
847 ins.i32_store(MemArg {
848 align: 2,
849 memory_index: 0,
850 offset: u64::try_from(reloc.offset).unwrap(),
851 });
852 }
853 ins.end();
854 Some(func)
855 }
856
857 fn finish(self) -> Vec<u8> {
858 self.data
859 }
860}