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