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