wast/component/
binary.rs

1use crate::component::*;
2use crate::core;
3use crate::core::EncodeOptions;
4use crate::token::{Id, NameAnnotation};
5use wasm_encoder::{
6    CanonicalFunctionSection, ComponentAliasSection, ComponentCoreTypeEncoder,
7    ComponentDefinedTypeEncoder, ComponentExportSection, ComponentImportSection,
8    ComponentInstanceSection, ComponentNameSection, ComponentSection, ComponentSectionId,
9    ComponentStartSection, ComponentTypeEncoder, ComponentTypeSection, CoreTypeSection,
10    InstanceSection, NameMap, NestedComponentSection, RawSection,
11};
12
13pub fn encode(component: &Component<'_>, options: &EncodeOptions) -> Vec<u8> {
14    match &component.kind {
15        ComponentKind::Text(fields) => {
16            encode_fields(&component.id, &component.name, fields, options).finish()
17        }
18        ComponentKind::Binary(bytes) => bytes.iter().flat_map(|b| b.iter().copied()).collect(),
19    }
20}
21
22fn encode_fields(
23    // TODO: use the id and name for a future names section
24    component_id: &Option<Id<'_>>,
25    component_name: &Option<NameAnnotation<'_>>,
26    fields: &[ComponentField<'_>],
27    options: &EncodeOptions,
28) -> wasm_encoder::Component {
29    let mut e = Encoder::default();
30
31    for field in fields {
32        match field {
33            ComponentField::CoreModule(m) => e.encode_core_module(m, options),
34            ComponentField::CoreInstance(i) => e.encode_core_instance(i),
35            ComponentField::CoreType(t) => e.encode_core_type(t),
36            ComponentField::CoreRec(t) => e.encode_core_rec(t),
37            ComponentField::Component(c) => e.encode_component(c, options),
38            ComponentField::Instance(i) => e.encode_instance(i),
39            ComponentField::Alias(a) => e.encode_alias(a),
40            ComponentField::Type(t) => e.encode_type(t),
41            ComponentField::CanonicalFunc(f) => e.encode_canonical_func(f),
42            ComponentField::CoreFunc(_) | ComponentField::Func(_) => {
43                unreachable!("should be expanded already")
44            }
45            ComponentField::Start(s) => e.encode_start(s),
46            ComponentField::Import(i) => e.encode_import(i),
47            ComponentField::Export(ex) => e.encode_export(ex),
48            ComponentField::Custom(c) => e.encode_custom(c),
49            ComponentField::Producers(c) => e.encode_producers(c),
50        }
51    }
52
53    e.flush(None);
54    e.encode_names(component_id, component_name);
55
56    e.component
57}
58
59fn encode_core_type(encoder: ComponentCoreTypeEncoder, ty: &CoreTypeDef) {
60    match ty {
61        CoreTypeDef::Def(def) => {
62            encoder.core().subtype(&def.to_subtype());
63        }
64        CoreTypeDef::Module(t) => {
65            encoder.module(&t.into());
66        }
67    }
68}
69
70fn encode_type(encoder: ComponentTypeEncoder, ty: &TypeDef) {
71    match ty {
72        TypeDef::Defined(t) => {
73            encode_defined_type(encoder.defined_type(), t);
74        }
75        TypeDef::Func(f) => {
76            let mut encoder = encoder.function();
77            encoder.params(f.params.iter().map(|p| (p.name, &p.ty)));
78
79            encoder.result(f.result.as_ref().map(|ty| ty.into()));
80        }
81        TypeDef::Component(c) => {
82            encoder.component(&c.into());
83        }
84        TypeDef::Instance(i) => {
85            encoder.instance(&i.into());
86        }
87        TypeDef::Resource(i) => {
88            let dtor = i.dtor.as_ref().map(|i| i.idx.into());
89            encoder.resource(i.rep.into(), dtor);
90        }
91    }
92}
93
94fn encode_defined_type(encoder: ComponentDefinedTypeEncoder, ty: &ComponentDefinedType) {
95    match ty {
96        ComponentDefinedType::Primitive(p) => encoder.primitive((*p).into()),
97        ComponentDefinedType::Record(r) => {
98            encoder.record(r.fields.iter().map(|f| (f.name, &f.ty)));
99        }
100        ComponentDefinedType::Variant(v) => {
101            encoder.variant(v.cases.iter().map(|c| {
102                (
103                    c.name,
104                    c.ty.as_ref().map(Into::into),
105                    c.refines.as_ref().map(Into::into),
106                )
107            }));
108        }
109        ComponentDefinedType::List(l) => {
110            encoder.list(l.element.as_ref());
111        }
112        ComponentDefinedType::FixedSizeList(l) => {
113            encoder.fixed_size_list(l.element.as_ref(), l.elements);
114        }
115        ComponentDefinedType::Tuple(t) => {
116            encoder.tuple(t.fields.iter());
117        }
118        ComponentDefinedType::Flags(f) => {
119            encoder.flags(f.names.iter().copied());
120        }
121        ComponentDefinedType::Enum(e) => {
122            encoder.enum_type(e.names.iter().copied());
123        }
124        ComponentDefinedType::Option(o) => {
125            encoder.option(o.element.as_ref());
126        }
127        ComponentDefinedType::Result(e) => {
128            encoder.result(
129                e.ok.as_deref().map(Into::into),
130                e.err.as_deref().map(Into::into),
131            );
132        }
133        ComponentDefinedType::Own(i) => encoder.own((*i).into()),
134        ComponentDefinedType::Borrow(i) => encoder.borrow((*i).into()),
135        ComponentDefinedType::Stream(s) => encoder.stream(s.element.as_deref().map(Into::into)),
136        ComponentDefinedType::Future(f) => encoder.future(f.element.as_deref().map(Into::into)),
137    }
138}
139
140#[derive(Default)]
141struct Encoder<'a> {
142    component: wasm_encoder::Component,
143    current_section_id: Option<u8>,
144
145    // Core sections
146    // Note: module sections are written immediately
147    core_instances: InstanceSection,
148    core_types: CoreTypeSection,
149
150    // Component sections
151    // Note: custom, component, start sections are written immediately
152    instances: ComponentInstanceSection,
153    aliases: ComponentAliasSection,
154    types: ComponentTypeSection,
155    funcs: CanonicalFunctionSection,
156    imports: ComponentImportSection,
157    exports: ComponentExportSection,
158
159    core_func_names: Vec<Option<&'a str>>,
160    core_table_names: Vec<Option<&'a str>>,
161    core_memory_names: Vec<Option<&'a str>>,
162    core_global_names: Vec<Option<&'a str>>,
163    core_type_names: Vec<Option<&'a str>>,
164    core_module_names: Vec<Option<&'a str>>,
165    core_instance_names: Vec<Option<&'a str>>,
166    core_tag_names: Vec<Option<&'a str>>,
167    func_names: Vec<Option<&'a str>>,
168    value_names: Vec<Option<&'a str>>,
169    type_names: Vec<Option<&'a str>>,
170    component_names: Vec<Option<&'a str>>,
171    instance_names: Vec<Option<&'a str>>,
172}
173
174impl<'a> Encoder<'a> {
175    fn encode_custom(&mut self, custom: &Custom) {
176        // Flush any in-progress section before encoding the customs section
177        self.flush(None);
178        self.component.section(&custom.to_section());
179    }
180
181    fn encode_producers(&mut self, custom: &core::Producers) {
182        self.flush(None);
183        self.component.section(&custom.to_section());
184    }
185
186    fn encode_core_module(&mut self, module: &CoreModule<'a>, options: &EncodeOptions) {
187        // Flush any in-progress section before encoding the module
188        self.flush(None);
189
190        self.core_module_names
191            .push(get_name(&module.id, &module.name));
192
193        match &module.kind {
194            CoreModuleKind::Import { .. } => unreachable!("should be expanded already"),
195            CoreModuleKind::Inline { fields } => {
196                // TODO: replace this with a wasm-encoder based encoding (should return `wasm_encoder::Module`)
197                let data = crate::core::binary::encode(&module.id, &module.name, fields, options);
198                self.component.section(&RawSection {
199                    id: ComponentSectionId::CoreModule.into(),
200                    data: &data,
201                });
202            }
203        }
204    }
205
206    fn encode_core_instance(&mut self, instance: &CoreInstance<'a>) {
207        self.core_instance_names
208            .push(get_name(&instance.id, &instance.name));
209        match &instance.kind {
210            CoreInstanceKind::Instantiate { module, args } => {
211                self.core_instances.instantiate(
212                    module.into(),
213                    args.iter().map(|arg| (arg.name, (&arg.kind).into())),
214                );
215            }
216            CoreInstanceKind::BundleOfExports(exports) => {
217                self.core_instances.export_items(exports.iter().map(|e| {
218                    let (kind, index) = (&e.item).into();
219                    (e.name, kind, index)
220                }));
221            }
222        }
223
224        self.flush(Some(self.core_instances.id()));
225    }
226
227    fn encode_core_type(&mut self, ty: &CoreType<'a>) {
228        self.core_type_names.push(get_name(&ty.id, &ty.name));
229        encode_core_type(self.core_types.ty(), &ty.def);
230        self.flush(Some(self.core_types.id()));
231    }
232
233    fn encode_core_rec(&mut self, ty: &core::Rec<'a>) {
234        for ty in ty.types.iter() {
235            self.core_type_names.push(get_name(&ty.id, &ty.name));
236        }
237        self.core_types
238            .ty()
239            .core()
240            .rec(ty.types.iter().map(|t| t.to_subtype()));
241        self.flush(Some(self.core_types.id()));
242    }
243
244    fn encode_component(&mut self, component: &NestedComponent<'a>, options: &EncodeOptions) {
245        self.component_names
246            .push(get_name(&component.id, &component.name));
247        // Flush any in-progress section before encoding the component
248        self.flush(None);
249
250        match &component.kind {
251            NestedComponentKind::Import { .. } => unreachable!("should be expanded already"),
252            NestedComponentKind::Inline(fields) => {
253                self.component
254                    .section(&NestedComponentSection(&encode_fields(
255                        &component.id,
256                        &component.name,
257                        fields,
258                        options,
259                    )));
260            }
261        }
262    }
263
264    fn encode_instance(&mut self, instance: &Instance<'a>) {
265        self.instance_names
266            .push(get_name(&instance.id, &instance.name));
267        match &instance.kind {
268            InstanceKind::Import { .. } => unreachable!("should be expanded already"),
269            InstanceKind::Instantiate { component, args } => {
270                self.instances.instantiate(
271                    component.into(),
272                    args.iter().map(|arg| {
273                        let (kind, index) = (&arg.kind).into();
274                        (arg.name, kind, index)
275                    }),
276                );
277            }
278            InstanceKind::BundleOfExports(exports) => {
279                self.instances.export_items(exports.iter().map(|e| {
280                    let (kind, index) = (&e.kind).into();
281                    (e.name.0, kind, index)
282                }));
283            }
284        }
285
286        self.flush(Some(self.instances.id()));
287    }
288
289    fn encode_alias(&mut self, alias: &Alias<'a>) {
290        let name = get_name(&alias.id, &alias.name);
291        self.aliases.alias((&alias.target).into());
292        match &alias.target {
293            AliasTarget::Export { kind, .. } => {
294                self.names_for_component_export_alias(*kind).push(name);
295            }
296            AliasTarget::CoreExport { kind, .. } => {
297                self.names_for_core_export_alias(*kind).push(name);
298            }
299            AliasTarget::Outer { kind, .. } => {
300                self.names_for_component_outer_alias(*kind).push(name);
301            }
302        }
303
304        self.flush(Some(self.aliases.id()));
305    }
306
307    fn encode_start(&mut self, start: &Start) {
308        // Flush any in-progress section before encoding the start section
309        self.flush(None);
310
311        self.component.section(&ComponentStartSection {
312            function_index: start.func.into(),
313            args: start.args.iter().map(|a| a.idx.into()).collect::<Vec<_>>(),
314            results: start.results.len() as u32,
315        });
316    }
317
318    fn encode_type(&mut self, ty: &Type<'a>) {
319        self.type_names.push(get_name(&ty.id, &ty.name));
320        encode_type(self.types.ty(), &ty.def);
321        self.flush(Some(self.types.id()));
322    }
323
324    fn encode_canonical_func(&mut self, func: &CanonicalFunc<'a>) {
325        let name = get_name(&func.id, &func.name);
326        match &func.kind {
327            CanonicalFuncKind::Lift { ty, info } => {
328                self.func_names.push(name);
329                self.funcs.lift(
330                    info.func.idx.into(),
331                    ty.into(),
332                    info.opts.iter().map(Into::into),
333                );
334            }
335            CanonicalFuncKind::Core(core) => match core {
336                CoreFuncKind::Alias(_) => {
337                    panic!("should have been removed during expansion")
338                }
339                CoreFuncKind::Lower(info) => {
340                    self.core_func_names.push(name);
341                    self.funcs
342                        .lower(info.func.idx.into(), info.opts.iter().map(Into::into));
343                }
344                CoreFuncKind::ResourceNew(info) => {
345                    self.core_func_names.push(name);
346                    self.funcs.resource_new(info.ty.into());
347                }
348                CoreFuncKind::ResourceDrop(info) => {
349                    self.core_func_names.push(name);
350                    if info.async_ {
351                        self.funcs.resource_drop_async(info.ty.into());
352                    } else {
353                        self.funcs.resource_drop(info.ty.into());
354                    }
355                }
356                CoreFuncKind::ResourceRep(info) => {
357                    self.core_func_names.push(name);
358                    self.funcs.resource_rep(info.ty.into());
359                }
360                CoreFuncKind::ThreadSpawnRef(info) => {
361                    self.core_func_names.push(name);
362                    self.funcs.thread_spawn_ref(info.ty.into());
363                }
364                CoreFuncKind::ThreadSpawnIndirect(info) => {
365                    self.core_func_names.push(name);
366                    self.funcs
367                        .thread_spawn_indirect(info.ty.into(), info.table.idx.into());
368                }
369                CoreFuncKind::ThreadAvailableParallelism(_info) => {
370                    self.core_func_names.push(name);
371                    self.funcs.thread_available_parallelism();
372                }
373                CoreFuncKind::BackpressureSet => {
374                    self.core_func_names.push(name);
375                    self.funcs.backpressure_set();
376                }
377                CoreFuncKind::BackpressureInc => {
378                    self.core_func_names.push(name);
379                    self.funcs.backpressure_inc();
380                }
381                CoreFuncKind::BackpressureDec => {
382                    self.core_func_names.push(name);
383                    self.funcs.backpressure_dec();
384                }
385                CoreFuncKind::TaskReturn(info) => {
386                    self.core_func_names.push(name);
387                    self.funcs.task_return(
388                        info.result
389                            .as_ref()
390                            .map(|ty| wasm_encoder::ComponentValType::from(ty)),
391                        info.opts.iter().map(Into::into),
392                    );
393                }
394                CoreFuncKind::TaskCancel => {
395                    self.core_func_names.push(name);
396                    self.funcs.task_cancel();
397                }
398                CoreFuncKind::ContextGet(i) => {
399                    self.core_func_names.push(name);
400                    self.funcs.context_get(*i);
401                }
402                CoreFuncKind::ContextSet(i) => {
403                    self.core_func_names.push(name);
404                    self.funcs.context_set(*i);
405                }
406                CoreFuncKind::ThreadYield(info) => {
407                    self.core_func_names.push(name);
408                    self.funcs.thread_yield(info.cancellable);
409                }
410                CoreFuncKind::SubtaskDrop => {
411                    self.core_func_names.push(name);
412                    self.funcs.subtask_drop();
413                }
414                CoreFuncKind::SubtaskCancel(info) => {
415                    self.core_func_names.push(name);
416                    self.funcs.subtask_cancel(info.async_);
417                }
418                CoreFuncKind::StreamNew(info) => {
419                    self.core_func_names.push(name);
420                    self.funcs.stream_new(info.ty.into());
421                }
422                CoreFuncKind::StreamRead(info) => {
423                    self.core_func_names.push(name);
424                    self.funcs
425                        .stream_read(info.ty.into(), info.opts.iter().map(Into::into));
426                }
427                CoreFuncKind::StreamWrite(info) => {
428                    self.core_func_names.push(name);
429                    self.funcs
430                        .stream_write(info.ty.into(), info.opts.iter().map(Into::into));
431                }
432                CoreFuncKind::StreamCancelRead(info) => {
433                    self.core_func_names.push(name);
434                    self.funcs.stream_cancel_read(info.ty.into(), info.async_);
435                }
436                CoreFuncKind::StreamCancelWrite(info) => {
437                    self.core_func_names.push(name);
438                    self.funcs.stream_cancel_write(info.ty.into(), info.async_);
439                }
440                CoreFuncKind::StreamDropReadable(info) => {
441                    self.core_func_names.push(name);
442                    self.funcs.stream_drop_readable(info.ty.into());
443                }
444                CoreFuncKind::StreamDropWritable(info) => {
445                    self.core_func_names.push(name);
446                    self.funcs.stream_drop_writable(info.ty.into());
447                }
448                CoreFuncKind::FutureNew(info) => {
449                    self.core_func_names.push(name);
450                    self.funcs.future_new(info.ty.into());
451                }
452                CoreFuncKind::FutureRead(info) => {
453                    self.core_func_names.push(name);
454                    self.funcs
455                        .future_read(info.ty.into(), info.opts.iter().map(Into::into));
456                }
457                CoreFuncKind::FutureWrite(info) => {
458                    self.core_func_names.push(name);
459                    self.funcs
460                        .future_write(info.ty.into(), info.opts.iter().map(Into::into));
461                }
462                CoreFuncKind::FutureCancelRead(info) => {
463                    self.core_func_names.push(name);
464                    self.funcs.future_cancel_read(info.ty.into(), info.async_);
465                }
466                CoreFuncKind::FutureCancelWrite(info) => {
467                    self.core_func_names.push(name);
468                    self.funcs.future_cancel_write(info.ty.into(), info.async_);
469                }
470                CoreFuncKind::FutureDropReadable(info) => {
471                    self.core_func_names.push(name);
472                    self.funcs.future_drop_readable(info.ty.into());
473                }
474                CoreFuncKind::FutureDropWritable(info) => {
475                    self.core_func_names.push(name);
476                    self.funcs.future_drop_writable(info.ty.into());
477                }
478                CoreFuncKind::ErrorContextNew(info) => {
479                    self.core_func_names.push(name);
480                    self.funcs
481                        .error_context_new(info.opts.iter().map(Into::into));
482                }
483                CoreFuncKind::ErrorContextDebugMessage(info) => {
484                    self.core_func_names.push(name);
485                    self.funcs
486                        .error_context_debug_message(info.opts.iter().map(Into::into));
487                }
488                CoreFuncKind::ErrorContextDrop => {
489                    self.core_func_names.push(name);
490                    self.funcs.error_context_drop();
491                }
492                CoreFuncKind::WaitableSetNew => {
493                    self.core_func_names.push(name);
494                    self.funcs.waitable_set_new();
495                }
496                CoreFuncKind::WaitableSetWait(info) => {
497                    self.core_func_names.push(name);
498                    self.funcs
499                        .waitable_set_wait(info.async_, info.memory.idx.into());
500                }
501                CoreFuncKind::WaitableSetPoll(info) => {
502                    self.core_func_names.push(name);
503                    self.funcs
504                        .waitable_set_poll(info.async_, info.memory.idx.into());
505                }
506                CoreFuncKind::WaitableSetDrop => {
507                    self.core_func_names.push(name);
508                    self.funcs.waitable_set_drop();
509                }
510                CoreFuncKind::WaitableJoin => {
511                    self.core_func_names.push(name);
512                    self.funcs.waitable_join();
513                }
514                CoreFuncKind::ThreadIndex => {
515                    self.core_func_names.push(name);
516                    self.funcs.thread_index();
517                }
518                CoreFuncKind::ThreadNewIndirect(info) => {
519                    self.core_func_names.push(name);
520                    self.funcs
521                        .thread_new_indirect(info.ty.into(), info.table.idx.into());
522                }
523                CoreFuncKind::ThreadSwitchTo(info) => {
524                    self.core_func_names.push(name);
525                    self.funcs.thread_switch_to(info.cancellable);
526                }
527                CoreFuncKind::ThreadSuspend(info) => {
528                    self.core_func_names.push(name);
529                    self.funcs.thread_suspend(info.cancellable);
530                }
531                CoreFuncKind::ThreadResumeLater => {
532                    self.core_func_names.push(name);
533                    self.funcs.thread_resume_later();
534                }
535                CoreFuncKind::ThreadYieldTo(info) => {
536                    self.core_func_names.push(name);
537                    self.funcs.thread_yield_to(info.cancellable);
538                }
539            },
540        }
541
542        self.flush(Some(self.funcs.id()));
543    }
544
545    fn encode_import(&mut self, import: &ComponentImport<'a>) {
546        let name = get_name(&import.item.id, &import.item.name);
547        self.names_for_item_kind(&import.item.kind).push(name);
548        self.imports
549            .import(import.name.0, (&import.item.kind).into());
550        self.flush(Some(self.imports.id()));
551    }
552
553    fn encode_export(&mut self, export: &ComponentExport<'a>) {
554        let name = get_name(&export.id, &export.debug_name);
555        let (kind, index) = (&export.kind).into();
556        self.exports.export(
557            export.name.0,
558            kind,
559            index,
560            export.ty.as_ref().map(|ty| (&ty.0.kind).into()),
561        );
562        match &export.kind {
563            ComponentExportKind::CoreModule(_) => self.core_module_names.push(name),
564            ComponentExportKind::Func(_) => self.func_names.push(name),
565            ComponentExportKind::Instance(_) => self.instance_names.push(name),
566            ComponentExportKind::Value(_) => self.value_names.push(name),
567            ComponentExportKind::Component(_) => self.component_names.push(name),
568            ComponentExportKind::Type(_) => self.type_names.push(name),
569        }
570        self.flush(Some(self.exports.id()));
571    }
572
573    fn flush(&mut self, section_id: Option<u8>) {
574        if self.current_section_id == section_id {
575            return;
576        }
577
578        if let Some(id) = self.current_section_id {
579            match id {
580                // 0 => custom sections are written immediately
581                // 1 => core modules sections are written immediately
582                2 => {
583                    assert_eq!(id, self.core_instances.id());
584                    self.component.section(&self.core_instances);
585                    self.core_instances = Default::default();
586                }
587                3 => {
588                    assert_eq!(id, self.core_types.id());
589                    self.component.section(&self.core_types);
590                    self.core_types = Default::default();
591                }
592                // 4 => components sections are written immediately
593                5 => {
594                    assert_eq!(id, self.instances.id());
595                    self.component.section(&self.instances);
596                    self.instances = Default::default();
597                }
598                6 => {
599                    assert_eq!(id, self.aliases.id());
600                    self.component.section(&self.aliases);
601                    self.aliases = Default::default();
602                }
603                7 => {
604                    assert_eq!(id, self.types.id());
605                    self.component.section(&self.types);
606                    self.types = Default::default();
607                }
608                8 => {
609                    assert_eq!(id, self.funcs.id());
610                    self.component.section(&self.funcs);
611                    self.funcs = Default::default();
612                }
613                // 9 => start sections are written immediately
614                10 => {
615                    assert_eq!(id, self.imports.id());
616                    self.component.section(&self.imports);
617                    self.imports = Default::default();
618                }
619                11 => {
620                    assert_eq!(id, self.exports.id());
621                    self.component.section(&self.exports);
622                    self.exports = Default::default();
623                }
624                _ => unreachable!("unknown incremental component section id: {}", id),
625            }
626        }
627
628        self.current_section_id = section_id
629    }
630
631    fn encode_names(
632        &mut self,
633        component_id: &Option<Id<'_>>,
634        component_name: &Option<NameAnnotation<'_>>,
635    ) {
636        let mut names = ComponentNameSection::new();
637        if let Some(name) = get_name(component_id, component_name) {
638            names.component(name);
639        }
640
641        let mut funcs = |list: &[Option<&str>], append: fn(&mut ComponentNameSection, &NameMap)| {
642            let mut map = NameMap::new();
643            for (i, entry) in list.iter().enumerate() {
644                if let Some(name) = entry {
645                    map.append(i as u32, name);
646                }
647            }
648            if !map.is_empty() {
649                append(&mut names, &map);
650            }
651        };
652
653        funcs(&self.core_func_names, ComponentNameSection::core_funcs);
654        funcs(&self.core_table_names, ComponentNameSection::core_tables);
655        funcs(&self.core_memory_names, ComponentNameSection::core_memories);
656        funcs(&self.core_global_names, ComponentNameSection::core_globals);
657        funcs(&self.core_tag_names, ComponentNameSection::core_tags);
658        funcs(&self.core_type_names, ComponentNameSection::core_types);
659        funcs(&self.core_module_names, ComponentNameSection::core_modules);
660        funcs(
661            &self.core_instance_names,
662            ComponentNameSection::core_instances,
663        );
664        funcs(&self.func_names, ComponentNameSection::funcs);
665        funcs(&self.value_names, ComponentNameSection::values);
666        funcs(&self.type_names, ComponentNameSection::types);
667        funcs(&self.component_names, ComponentNameSection::components);
668        funcs(&self.instance_names, ComponentNameSection::instances);
669
670        if !names.is_empty() {
671            self.component.section(&names);
672        }
673    }
674
675    fn names_for_component_export_alias(
676        &mut self,
677        kind: ComponentExportAliasKind,
678    ) -> &mut Vec<Option<&'a str>> {
679        match kind {
680            ComponentExportAliasKind::Func => &mut self.func_names,
681            ComponentExportAliasKind::CoreModule => &mut self.core_module_names,
682            ComponentExportAliasKind::Value => &mut self.value_names,
683            ComponentExportAliasKind::Type => &mut self.type_names,
684            ComponentExportAliasKind::Component => &mut self.component_names,
685            ComponentExportAliasKind::Instance => &mut self.instance_names,
686        }
687    }
688
689    fn names_for_component_outer_alias(
690        &mut self,
691        kind: ComponentOuterAliasKind,
692    ) -> &mut Vec<Option<&'a str>> {
693        match kind {
694            ComponentOuterAliasKind::CoreModule => &mut self.core_module_names,
695            ComponentOuterAliasKind::CoreType => &mut self.core_type_names,
696            ComponentOuterAliasKind::Component => &mut self.component_names,
697            ComponentOuterAliasKind::Type => &mut self.type_names,
698        }
699    }
700
701    fn names_for_core_export_alias(&mut self, kind: core::ExportKind) -> &mut Vec<Option<&'a str>> {
702        match kind {
703            core::ExportKind::Func => &mut self.core_func_names,
704            core::ExportKind::Global => &mut self.core_global_names,
705            core::ExportKind::Table => &mut self.core_table_names,
706            core::ExportKind::Memory => &mut self.core_memory_names,
707            core::ExportKind::Tag => &mut self.core_tag_names,
708        }
709    }
710
711    fn names_for_item_kind(&mut self, kind: &ItemSigKind) -> &mut Vec<Option<&'a str>> {
712        match kind {
713            ItemSigKind::CoreModule(_) => &mut self.core_module_names,
714            ItemSigKind::Func(_) => &mut self.func_names,
715            ItemSigKind::Component(_) => &mut self.component_names,
716            ItemSigKind::Instance(_) => &mut self.instance_names,
717            ItemSigKind::Value(_) => &mut self.value_names,
718            ItemSigKind::Type(_) => &mut self.type_names,
719        }
720    }
721}
722
723fn get_name<'a>(id: &Option<Id<'a>>, name: &Option<NameAnnotation<'a>>) -> Option<&'a str> {
724    name.as_ref().map(|n| n.name).or_else(|| {
725        id.and_then(|id| {
726            if id.is_gensym() {
727                None
728            } else {
729                Some(id.name())
730            }
731        })
732    })
733}
734
735impl Custom<'_> {
736    fn to_section(&self) -> wasm_encoder::CustomSection<'_> {
737        let mut ret = Vec::new();
738        for list in self.data.iter() {
739            ret.extend_from_slice(list);
740        }
741        wasm_encoder::CustomSection {
742            name: self.name.into(),
743            data: ret.into(),
744        }
745    }
746}
747
748impl From<&CoreInstantiationArgKind<'_>> for wasm_encoder::ModuleArg {
749    fn from(kind: &CoreInstantiationArgKind) -> Self {
750        match kind {
751            CoreInstantiationArgKind::Instance(i) => {
752                wasm_encoder::ModuleArg::Instance(i.idx.into())
753            }
754            CoreInstantiationArgKind::BundleOfExports(..) => {
755                unreachable!("should be expanded already")
756            }
757        }
758    }
759}
760
761impl From<&CoreItemRef<'_, core::ExportKind>> for (wasm_encoder::ExportKind, u32) {
762    fn from(item: &CoreItemRef<'_, core::ExportKind>) -> Self {
763        match &item.kind {
764            core::ExportKind::Func => (wasm_encoder::ExportKind::Func, item.idx.into()),
765            core::ExportKind::Table => (wasm_encoder::ExportKind::Table, item.idx.into()),
766            core::ExportKind::Memory => (wasm_encoder::ExportKind::Memory, item.idx.into()),
767            core::ExportKind::Global => (wasm_encoder::ExportKind::Global, item.idx.into()),
768            core::ExportKind::Tag => (wasm_encoder::ExportKind::Tag, item.idx.into()),
769        }
770    }
771}
772
773impl<T> From<&ItemRef<'_, T>> for u32 {
774    fn from(i: &ItemRef<'_, T>) -> Self {
775        assert!(i.export_names.is_empty());
776        i.idx.into()
777    }
778}
779
780impl<T> From<&CoreTypeUse<'_, T>> for u32 {
781    fn from(u: &CoreTypeUse<'_, T>) -> Self {
782        match u {
783            CoreTypeUse::Inline(_) => unreachable!("should be expanded already"),
784            CoreTypeUse::Ref(r) => r.idx.into(),
785        }
786    }
787}
788
789impl<T> From<&ComponentTypeUse<'_, T>> for u32 {
790    fn from(u: &ComponentTypeUse<'_, T>) -> Self {
791        match u {
792            ComponentTypeUse::Inline(_) => unreachable!("should be expanded already"),
793            ComponentTypeUse::Ref(r) => r.idx.into(),
794        }
795    }
796}
797
798impl From<&ComponentValType<'_>> for wasm_encoder::ComponentValType {
799    fn from(r: &ComponentValType) -> Self {
800        match r {
801            ComponentValType::Inline(ComponentDefinedType::Primitive(p)) => {
802                Self::Primitive((*p).into())
803            }
804            ComponentValType::Ref(i) => Self::Type(u32::from(*i)),
805            ComponentValType::Inline(_) => unreachable!("should be expanded by now"),
806        }
807    }
808}
809
810impl From<PrimitiveValType> for wasm_encoder::PrimitiveValType {
811    fn from(p: PrimitiveValType) -> Self {
812        match p {
813            PrimitiveValType::Bool => Self::Bool,
814            PrimitiveValType::S8 => Self::S8,
815            PrimitiveValType::U8 => Self::U8,
816            PrimitiveValType::S16 => Self::S16,
817            PrimitiveValType::U16 => Self::U16,
818            PrimitiveValType::S32 => Self::S32,
819            PrimitiveValType::U32 => Self::U32,
820            PrimitiveValType::S64 => Self::S64,
821            PrimitiveValType::U64 => Self::U64,
822            PrimitiveValType::F32 => Self::F32,
823            PrimitiveValType::F64 => Self::F64,
824            PrimitiveValType::Char => Self::Char,
825            PrimitiveValType::String => Self::String,
826            PrimitiveValType::ErrorContext => Self::ErrorContext,
827        }
828    }
829}
830
831impl From<&Refinement<'_>> for u32 {
832    fn from(r: &Refinement) -> Self {
833        match r {
834            Refinement::Index(..) => unreachable!("should be resolved by now"),
835            Refinement::Resolved(i) => *i,
836        }
837    }
838}
839
840impl From<&ItemSigKind<'_>> for wasm_encoder::ComponentTypeRef {
841    fn from(k: &ItemSigKind) -> Self {
842        match k {
843            ItemSigKind::Component(c) => Self::Component(c.into()),
844            ItemSigKind::CoreModule(m) => Self::Module(m.into()),
845            ItemSigKind::Instance(i) => Self::Instance(i.into()),
846            ItemSigKind::Value(v) => Self::Value((&v.0).into()),
847            ItemSigKind::Func(f) => Self::Func(f.into()),
848            ItemSigKind::Type(TypeBounds::Eq(t)) => {
849                Self::Type(wasm_encoder::TypeBounds::Eq((*t).into()))
850            }
851            ItemSigKind::Type(TypeBounds::SubResource) => {
852                Self::Type(wasm_encoder::TypeBounds::SubResource)
853            }
854        }
855    }
856}
857
858impl From<&ComponentType<'_>> for wasm_encoder::ComponentType {
859    fn from(ty: &ComponentType) -> Self {
860        let mut encoded = wasm_encoder::ComponentType::new();
861
862        for decl in &ty.decls {
863            match decl {
864                ComponentTypeDecl::CoreType(t) => {
865                    encode_core_type(encoded.core_type(), &t.def);
866                }
867                ComponentTypeDecl::Type(t) => {
868                    encode_type(encoded.ty(), &t.def);
869                }
870                ComponentTypeDecl::Alias(a) => {
871                    encoded.alias((&a.target).into());
872                }
873                ComponentTypeDecl::Import(i) => {
874                    encoded.import(i.name.0, (&i.item.kind).into());
875                }
876                ComponentTypeDecl::Export(e) => {
877                    encoded.export(e.name.0, (&e.item.kind).into());
878                }
879            }
880        }
881
882        encoded
883    }
884}
885
886impl From<&InstanceType<'_>> for wasm_encoder::InstanceType {
887    fn from(ty: &InstanceType) -> Self {
888        let mut encoded = wasm_encoder::InstanceType::new();
889
890        for decl in &ty.decls {
891            match decl {
892                InstanceTypeDecl::CoreType(t) => {
893                    encode_core_type(encoded.core_type(), &t.def);
894                }
895                InstanceTypeDecl::Type(t) => {
896                    encode_type(encoded.ty(), &t.def);
897                }
898                InstanceTypeDecl::Alias(a) => {
899                    encoded.alias((&a.target).into());
900                }
901                InstanceTypeDecl::Export(e) => {
902                    encoded.export(e.name.0, (&e.item.kind).into());
903                }
904            }
905        }
906
907        encoded
908    }
909}
910
911impl From<&ModuleType<'_>> for wasm_encoder::ModuleType {
912    fn from(ty: &ModuleType) -> Self {
913        let mut encoded = wasm_encoder::ModuleType::new();
914
915        for decl in &ty.decls {
916            match decl {
917                ModuleTypeDecl::Type(t) => {
918                    encoded.ty().subtype(&t.to_subtype());
919                }
920                ModuleTypeDecl::Rec(rec) => {
921                    encoded.ty().rec(rec.types.iter().map(|t| t.to_subtype()));
922                }
923                ModuleTypeDecl::Alias(a) => match &a.target {
924                    AliasTarget::Outer {
925                        outer,
926                        index,
927                        kind: ComponentOuterAliasKind::CoreType,
928                    } => {
929                        encoded.alias_outer_core_type(u32::from(*outer), u32::from(*index));
930                    }
931                    _ => unreachable!("only outer type aliases are supported"),
932                },
933                ModuleTypeDecl::Import(i) => {
934                    encoded.import(i.module, i.field, i.item.to_entity_type());
935                }
936                ModuleTypeDecl::Export(name, item) => {
937                    encoded.export(name, item.to_entity_type());
938                }
939            }
940        }
941
942        encoded
943    }
944}
945
946impl From<&InstantiationArgKind<'_>> for (wasm_encoder::ComponentExportKind, u32) {
947    fn from(kind: &InstantiationArgKind) -> Self {
948        match kind {
949            InstantiationArgKind::Item(i) => i.into(),
950            InstantiationArgKind::BundleOfExports(..) => unreachable!("should be expanded already"),
951        }
952    }
953}
954
955impl From<&ComponentExportKind<'_>> for (wasm_encoder::ComponentExportKind, u32) {
956    fn from(kind: &ComponentExportKind) -> Self {
957        match kind {
958            ComponentExportKind::CoreModule(m) => {
959                (wasm_encoder::ComponentExportKind::Module, m.idx.into())
960            }
961            ComponentExportKind::Func(f) => (wasm_encoder::ComponentExportKind::Func, f.idx.into()),
962            ComponentExportKind::Value(v) => {
963                (wasm_encoder::ComponentExportKind::Value, v.idx.into())
964            }
965            ComponentExportKind::Type(t) => (wasm_encoder::ComponentExportKind::Type, t.idx.into()),
966            ComponentExportKind::Component(c) => {
967                (wasm_encoder::ComponentExportKind::Component, c.idx.into())
968            }
969            ComponentExportKind::Instance(i) => {
970                (wasm_encoder::ComponentExportKind::Instance, i.idx.into())
971            }
972        }
973    }
974}
975
976impl From<ComponentOuterAliasKind> for wasm_encoder::ComponentOuterAliasKind {
977    fn from(kind: ComponentOuterAliasKind) -> Self {
978        match kind {
979            ComponentOuterAliasKind::CoreModule => Self::CoreModule,
980            ComponentOuterAliasKind::CoreType => Self::CoreType,
981            ComponentOuterAliasKind::Type => Self::Type,
982            ComponentOuterAliasKind::Component => Self::Component,
983        }
984    }
985}
986
987impl From<ComponentExportAliasKind> for wasm_encoder::ComponentExportKind {
988    fn from(kind: ComponentExportAliasKind) -> Self {
989        match kind {
990            ComponentExportAliasKind::CoreModule => Self::Module,
991            ComponentExportAliasKind::Func => Self::Func,
992            ComponentExportAliasKind::Value => Self::Value,
993            ComponentExportAliasKind::Type => Self::Type,
994            ComponentExportAliasKind::Component => Self::Component,
995            ComponentExportAliasKind::Instance => Self::Instance,
996        }
997    }
998}
999
1000impl From<&CanonOpt<'_>> for wasm_encoder::CanonicalOption {
1001    fn from(opt: &CanonOpt) -> Self {
1002        match opt {
1003            CanonOpt::StringUtf8 => Self::UTF8,
1004            CanonOpt::StringUtf16 => Self::UTF16,
1005            CanonOpt::StringLatin1Utf16 => Self::CompactUTF16,
1006            CanonOpt::Memory(m) => Self::Memory(m.idx.into()),
1007            CanonOpt::Realloc(f) => Self::Realloc(f.idx.into()),
1008            CanonOpt::PostReturn(f) => Self::PostReturn(f.idx.into()),
1009            CanonOpt::Async => Self::Async,
1010            CanonOpt::Callback(f) => Self::Callback(f.idx.into()),
1011            CanonOpt::CoreType(t) => Self::CoreType(t.idx.into()),
1012            CanonOpt::Gc => Self::Gc,
1013        }
1014    }
1015}
1016
1017impl<'a> From<&AliasTarget<'a>> for wasm_encoder::Alias<'a> {
1018    fn from(target: &AliasTarget<'a>) -> Self {
1019        match target {
1020            AliasTarget::Export {
1021                instance,
1022                name,
1023                kind,
1024            } => wasm_encoder::Alias::InstanceExport {
1025                instance: (*instance).into(),
1026                kind: (*kind).into(),
1027                name,
1028            },
1029            AliasTarget::CoreExport {
1030                instance,
1031                name,
1032                kind,
1033            } => wasm_encoder::Alias::CoreInstanceExport {
1034                instance: (*instance).into(),
1035                kind: (*kind).into(),
1036                name,
1037            },
1038            AliasTarget::Outer { outer, index, kind } => wasm_encoder::Alias::Outer {
1039                count: (*outer).into(),
1040                kind: (*kind).into(),
1041                index: (*index).into(),
1042            },
1043        }
1044    }
1045}