wasmprinter/
component.rs

1use crate::{Naming, Printer, State, name_map};
2use anyhow::{Result, bail};
3use wasmparser::*;
4
5impl Printer<'_, '_> {
6    pub(crate) fn register_component_names(
7        &mut self,
8        state: &mut State,
9        names: ComponentNameSectionReader<'_>,
10    ) -> Result<()> {
11        for section in names {
12            match section? {
13                ComponentName::Component { name, .. } => {
14                    let name = Naming::new(name, 0, "component", None);
15                    state.name = Some(name);
16                }
17                ComponentName::CoreFuncs(n) => {
18                    name_map(&mut state.core.func_names, n, "core-func")?
19                }
20                ComponentName::CoreTypes(n) => {
21                    name_map(&mut state.core.type_names, n, "core-type")?
22                }
23                ComponentName::CoreTables(n) => {
24                    name_map(&mut state.core.table_names, n, "core-table")?
25                }
26                ComponentName::CoreMemories(n) => {
27                    name_map(&mut state.core.memory_names, n, "core-memory")?
28                }
29                ComponentName::CoreGlobals(n) => {
30                    name_map(&mut state.core.global_names, n, "core-global")?
31                }
32                ComponentName::CoreTags(n) => name_map(&mut state.core.tag_names, n, "core-tag")?,
33                ComponentName::CoreModules(n) => {
34                    name_map(&mut state.core.module_names, n, "core-module")?
35                }
36                ComponentName::CoreInstances(n) => {
37                    name_map(&mut state.core.instance_names, n, "core-instance")?
38                }
39                ComponentName::Types(n) => name_map(&mut state.component.type_names, n, "type")?,
40                ComponentName::Instances(n) => {
41                    name_map(&mut state.component.instance_names, n, "instance")?
42                }
43                ComponentName::Components(n) => {
44                    name_map(&mut state.component.component_names, n, "component")?
45                }
46                ComponentName::Funcs(n) => name_map(&mut state.component.func_names, n, "func")?,
47                ComponentName::Values(n) => name_map(&mut state.component.value_names, n, "value")?,
48                ComponentName::Unknown { .. } => (),
49            }
50        }
51        Ok(())
52    }
53
54    pub(crate) fn print_core_types(
55        &mut self,
56        states: &mut Vec<State>,
57        parser: CoreTypeSectionReader<'_>,
58    ) -> Result<()> {
59        for ty in parser.into_iter_with_offsets() {
60            let (offset, ty) = ty?;
61            self.newline(offset)?;
62            self.print_core_type(states, ty)?;
63        }
64
65        Ok(())
66    }
67
68    pub(crate) fn print_core_type(&mut self, states: &mut Vec<State>, ty: CoreType) -> Result<()> {
69        match ty {
70            CoreType::Rec(rec) => {
71                self.print_rec(states.last_mut().unwrap(), None, rec, true)?;
72            }
73            CoreType::Module(decls) => {
74                self.start_group("core type ")?;
75                self.print_name(
76                    &states.last().unwrap().core.type_names,
77                    states.last().unwrap().core.types.len() as u32,
78                )?;
79                self.print_module_type(states, decls.into_vec())?;
80                self.end_group()?; // `core type` itself
81                states.last_mut().unwrap().core.types.push(None);
82            }
83        }
84        Ok(())
85    }
86
87    pub(crate) fn print_component_type_ref(&mut self, state: &State, idx: u32) -> Result<()> {
88        self.start_group("type ")?;
89        self.print_idx(&state.component.type_names, idx)?;
90        self.end_group()?;
91        Ok(())
92    }
93
94    pub(crate) fn print_primitive_val_type(&mut self, ty: &PrimitiveValType) -> Result<()> {
95        match ty {
96            PrimitiveValType::Bool => self.print_type_keyword("bool")?,
97            PrimitiveValType::S8 => self.print_type_keyword("s8")?,
98            PrimitiveValType::U8 => self.print_type_keyword("u8")?,
99            PrimitiveValType::S16 => self.print_type_keyword("s16")?,
100            PrimitiveValType::U16 => self.print_type_keyword("u16")?,
101            PrimitiveValType::S32 => self.print_type_keyword("s32")?,
102            PrimitiveValType::U32 => self.print_type_keyword("u32")?,
103            PrimitiveValType::S64 => self.print_type_keyword("s64")?,
104            PrimitiveValType::U64 => self.print_type_keyword("u64")?,
105            PrimitiveValType::F32 => self.print_type_keyword("f32")?,
106            PrimitiveValType::F64 => self.print_type_keyword("f64")?,
107            PrimitiveValType::Char => self.print_type_keyword("char")?,
108            PrimitiveValType::String => self.print_type_keyword("string")?,
109            PrimitiveValType::ErrorContext => self.print_type_keyword("error-context")?,
110        }
111        Ok(())
112    }
113
114    pub(crate) fn print_record_type(
115        &mut self,
116        state: &State,
117        fields: &[(&str, ComponentValType)],
118    ) -> Result<()> {
119        self.start_group("record")?;
120        for (name, ty) in fields.iter() {
121            self.result.write_str(" ")?;
122            self.start_group("field ")?;
123            self.print_str(name)?;
124            self.result.write_str(" ")?;
125            self.print_component_val_type(state, ty)?;
126            self.end_group()?;
127        }
128        self.end_group()?;
129        Ok(())
130    }
131
132    pub(crate) fn print_variant_type(
133        &mut self,
134        state: &State,
135        cases: &[VariantCase],
136    ) -> Result<()> {
137        self.start_group("variant")?;
138        for case in cases {
139            self.result.write_str(" ")?;
140            self.start_group("case ")?;
141            self.print_str(case.name)?;
142
143            if let Some(ty) = case.ty {
144                self.result.write_str(" ")?;
145                self.print_component_val_type(state, &ty)?;
146            }
147
148            if let Some(refines) = case.refines {
149                self.result.write_str(" ")?;
150                self.start_group("refines ")?;
151                write!(&mut self.result, "{refines}")?;
152                self.end_group()?;
153            }
154            self.end_group()?;
155        }
156        self.end_group()?;
157
158        Ok(())
159    }
160
161    pub(crate) fn print_list_type(
162        &mut self,
163        state: &State,
164        element_ty: &ComponentValType,
165    ) -> Result<()> {
166        self.start_group("list ")?;
167        self.print_component_val_type(state, element_ty)?;
168        self.end_group()?;
169        Ok(())
170    }
171
172    pub(crate) fn print_fixed_size_list_type(
173        &mut self,
174        state: &State,
175        element_ty: &ComponentValType,
176        elements: u32,
177    ) -> Result<()> {
178        self.start_group("list ")?;
179        self.print_component_val_type(state, element_ty)?;
180        self.result.write_str(&format!(" {elements}"))?;
181        self.end_group()?;
182        Ok(())
183    }
184
185    pub(crate) fn print_tuple_type(
186        &mut self,
187        state: &State,
188        tys: &[ComponentValType],
189    ) -> Result<()> {
190        self.start_group("tuple")?;
191        for ty in tys {
192            self.result.write_str(" ")?;
193            self.print_component_val_type(state, ty)?;
194        }
195        self.end_group()?;
196        Ok(())
197    }
198
199    pub(crate) fn print_flag_or_enum_type(&mut self, ty: &str, names: &[&str]) -> Result<()> {
200        self.start_group(ty)?;
201        for name in names {
202            self.result.write_str(" ")?;
203            self.print_str(name)?;
204        }
205        self.end_group()?;
206        Ok(())
207    }
208
209    pub(crate) fn print_option_type(
210        &mut self,
211        state: &State,
212        inner: &ComponentValType,
213    ) -> Result<()> {
214        self.start_group("option ")?;
215        self.print_component_val_type(state, inner)?;
216        self.end_group()?;
217        Ok(())
218    }
219
220    pub(crate) fn print_result_type(
221        &mut self,
222        state: &State,
223        ok: Option<ComponentValType>,
224        err: Option<ComponentValType>,
225    ) -> Result<()> {
226        self.start_group("result")?;
227
228        if let Some(ok) = ok {
229            self.result.write_str(" ")?;
230            self.print_component_val_type(state, &ok)?;
231        }
232
233        if let Some(err) = err {
234            self.result.write_str(" ")?;
235            self.start_group("error ")?;
236            self.print_component_val_type(state, &err)?;
237            self.end_group()?;
238        }
239
240        self.end_group()?;
241
242        Ok(())
243    }
244
245    fn print_future_type(&mut self, state: &State, ty: Option<ComponentValType>) -> Result<()> {
246        self.start_group("future")?;
247
248        if let Some(ty) = ty {
249            self.result.write_str(" ")?;
250            self.print_component_val_type(state, &ty)?;
251        }
252
253        self.end_group()?;
254
255        Ok(())
256    }
257
258    fn print_stream_type(&mut self, state: &State, ty: Option<ComponentValType>) -> Result<()> {
259        self.start_group("stream")?;
260
261        if let Some(ty) = ty {
262            self.result.write_str(" ")?;
263            self.print_component_val_type(state, &ty)?;
264        }
265
266        self.end_group()?;
267
268        Ok(())
269    }
270
271    pub(crate) fn print_defined_type(
272        &mut self,
273        state: &State,
274        ty: &ComponentDefinedType,
275    ) -> Result<()> {
276        match ty {
277            ComponentDefinedType::Primitive(ty) => self.print_primitive_val_type(ty)?,
278            ComponentDefinedType::Record(fields) => self.print_record_type(state, fields)?,
279            ComponentDefinedType::Variant(cases) => self.print_variant_type(state, cases)?,
280            ComponentDefinedType::List(ty) => self.print_list_type(state, ty)?,
281            ComponentDefinedType::FixedSizeList(ty, elements) => {
282                self.print_fixed_size_list_type(state, ty, *elements)?
283            }
284            ComponentDefinedType::Tuple(tys) => self.print_tuple_type(state, tys)?,
285            ComponentDefinedType::Flags(names) => self.print_flag_or_enum_type("flags", names)?,
286            ComponentDefinedType::Enum(cases) => self.print_flag_or_enum_type("enum", cases)?,
287            ComponentDefinedType::Option(ty) => self.print_option_type(state, ty)?,
288            ComponentDefinedType::Result { ok, err } => self.print_result_type(state, *ok, *err)?,
289            ComponentDefinedType::Own(idx) => {
290                self.start_group("own ")?;
291                self.print_idx(&state.component.type_names, *idx)?;
292                self.end_group()?;
293            }
294            ComponentDefinedType::Borrow(idx) => {
295                self.start_group("borrow ")?;
296                self.print_idx(&state.component.type_names, *idx)?;
297                self.end_group()?;
298            }
299            ComponentDefinedType::Future(ty) => self.print_future_type(state, *ty)?,
300            ComponentDefinedType::Stream(ty) => self.print_stream_type(state, *ty)?,
301        }
302
303        Ok(())
304    }
305
306    pub(crate) fn print_component_val_type(
307        &mut self,
308        state: &State,
309        ty: &ComponentValType,
310    ) -> Result<()> {
311        match ty {
312            ComponentValType::Primitive(ty) => self.print_primitive_val_type(ty),
313            ComponentValType::Type(idx) => self.print_idx(&state.component.type_names, *idx),
314        }
315    }
316
317    pub(crate) fn print_module_type(
318        &mut self,
319        states: &mut Vec<State>,
320        decls: Vec<ModuleTypeDeclaration>,
321    ) -> Result<()> {
322        states.push(State::new(Encoding::Module));
323        self.newline_unknown_pos()?;
324        self.start_group("module")?;
325        for decl in decls {
326            self.newline_unknown_pos()?;
327            match decl {
328                ModuleTypeDeclaration::Type(rec) => {
329                    self.print_rec(states.last_mut().unwrap(), None, rec, false)?
330                }
331                ModuleTypeDeclaration::OuterAlias { kind, count, index } => {
332                    self.print_outer_alias(states, kind, count, index)?;
333                }
334                ModuleTypeDeclaration::Export { name, ty } => {
335                    self.start_group("export ")?;
336                    self.print_str(name)?;
337                    self.result.write_str(" ")?;
338                    self.print_import_ty(states.last_mut().unwrap(), &ty, false)?;
339                    self.end_group()?;
340                }
341                ModuleTypeDeclaration::Import(import) => {
342                    self.print_import(states.last_mut().unwrap(), &import, false)?;
343                }
344            }
345        }
346        self.end_group()?;
347        states.pop();
348        Ok(())
349    }
350
351    pub(crate) fn print_component_type<'a>(
352        &mut self,
353        states: &mut Vec<State>,
354        decls: Vec<ComponentTypeDeclaration<'a>>,
355    ) -> Result<()> {
356        states.push(State::new(Encoding::Component));
357        self.newline_unknown_pos()?;
358        self.start_group("component")?;
359        for decl in decls {
360            self.newline_unknown_pos()?;
361            match decl {
362                ComponentTypeDeclaration::CoreType(ty) => self.print_core_type(states, ty)?,
363                ComponentTypeDeclaration::Type(ty) => self.print_component_type_def(states, ty)?,
364                ComponentTypeDeclaration::Alias(alias) => {
365                    self.print_component_alias(states, alias)?;
366                }
367                ComponentTypeDeclaration::Export { name, ty } => {
368                    self.start_group("export ")?;
369                    self.print_component_kind_name(states.last_mut().unwrap(), ty.kind())?;
370                    self.result.write_str(" ")?;
371                    self.print_str(name.0)?;
372                    self.result.write_str(" ")?;
373                    self.print_component_import_ty(states.last_mut().unwrap(), &ty, false)?;
374                    self.end_group()?;
375                }
376                ComponentTypeDeclaration::Import(import) => {
377                    self.print_component_import(states.last_mut().unwrap(), &import, true)?
378                }
379            }
380        }
381        self.end_group()?;
382        states.pop().unwrap();
383        Ok(())
384    }
385
386    pub(crate) fn print_instance_type<'a>(
387        &mut self,
388        states: &mut Vec<State>,
389        decls: Vec<InstanceTypeDeclaration<'a>>,
390    ) -> Result<()> {
391        states.push(State::new(Encoding::Component));
392        self.newline_unknown_pos()?;
393        self.start_group("instance")?;
394        for decl in decls {
395            self.newline_unknown_pos()?;
396            match decl {
397                InstanceTypeDeclaration::CoreType(ty) => self.print_core_type(states, ty)?,
398                InstanceTypeDeclaration::Type(ty) => self.print_component_type_def(states, ty)?,
399                InstanceTypeDeclaration::Alias(alias) => {
400                    self.print_component_alias(states, alias)?;
401                }
402                InstanceTypeDeclaration::Export { name, ty } => {
403                    self.start_group("export ")?;
404                    self.print_component_kind_name(states.last_mut().unwrap(), ty.kind())?;
405                    self.result.write_str(" ")?;
406                    self.print_str(name.0)?;
407                    self.result.write_str(" ")?;
408                    self.print_component_import_ty(states.last_mut().unwrap(), &ty, false)?;
409                    self.end_group()?;
410                }
411            }
412        }
413        self.end_group()?;
414        states.pop().unwrap();
415        Ok(())
416    }
417
418    pub(crate) fn outer_state(states: &[State], count: u32) -> Result<&State> {
419        if count as usize >= states.len() {
420            bail!("invalid outer alias count {}", count);
421        }
422
423        let count: usize = std::cmp::min(count as usize, states.len() - 1);
424        Ok(&states[states.len() - count - 1])
425    }
426
427    pub(crate) fn print_outer_alias(
428        &mut self,
429        states: &mut [State],
430        kind: OuterAliasKind,
431        count: u32,
432        index: u32,
433    ) -> Result<()> {
434        let state = states.last().unwrap();
435        let default_state = State::new(Encoding::Component);
436        let outer = match Self::outer_state(states, count) {
437            Ok(o) => o,
438            Err(e) => {
439                write!(self.result, "(; {e} ;) ")?;
440                &default_state
441            }
442        };
443        self.start_group("alias outer ")?;
444        if let Some(name) = outer.name.as_ref() {
445            name.write(self)?;
446        } else {
447            write!(self.result, "{count}")?;
448        }
449        self.result.write_str(" ")?;
450        match kind {
451            OuterAliasKind::Type => {
452                self.print_idx(&outer.core.type_names, index)?;
453                self.result.write_str(" ")?;
454                self.start_group("type ")?;
455                self.print_name(&state.core.type_names, state.core.types.len() as u32)?;
456            }
457        }
458        self.end_group()?; // kind
459        self.end_group()?; // alias
460
461        let state = states.last_mut().unwrap();
462        match kind {
463            OuterAliasKind::Type => state.core.types.push(None),
464        }
465
466        Ok(())
467    }
468
469    pub(crate) fn print_component_func_type(
470        &mut self,
471        state: &State,
472        ty: &ComponentFuncType,
473    ) -> Result<()> {
474        self.start_group("func")?;
475        for (name, ty) in ty.params.iter() {
476            self.result.write_str(" ")?;
477            self.start_group("param ")?;
478            self.print_str(name)?;
479            self.result.write_str(" ")?;
480            self.print_component_val_type(state, ty)?;
481            self.end_group()?;
482        }
483
484        if let Some(ty) = &ty.result {
485            self.result.write_str(" ")?;
486            self.start_group("result ")?;
487            self.print_component_val_type(state, ty)?;
488            self.end_group()?;
489        }
490
491        self.end_group()?;
492
493        Ok(())
494    }
495
496    pub(crate) fn print_component_type_def<'a>(
497        &mut self,
498        states: &mut Vec<State>,
499        ty: ComponentType<'a>,
500    ) -> Result<()> {
501        self.start_group("type ")?;
502        {
503            let state = states.last_mut().unwrap();
504            self.print_name(&state.component.type_names, state.component.types)?;
505        }
506        match ty {
507            ComponentType::Defined(ty) => {
508                self.result.write_str(" ")?;
509                self.print_defined_type(states.last_mut().unwrap(), &ty)?;
510            }
511            ComponentType::Func(ty) => {
512                self.result.write_str(" ")?;
513                self.print_component_func_type(states.last_mut().unwrap(), &ty)?;
514            }
515            ComponentType::Component(decls) => {
516                self.print_component_type(states, decls.into_vec())?;
517            }
518            ComponentType::Instance(decls) => {
519                self.print_instance_type(states, decls.into_vec())?;
520            }
521            ComponentType::Resource { rep, dtor } => {
522                self.result.write_str(" ")?;
523                self.start_group("resource ")?;
524                self.start_group("rep ")?;
525                self.print_valtype(states.last().unwrap(), rep)?;
526                self.end_group()?;
527                if let Some(dtor) = dtor {
528                    self.result.write_str(" ")?;
529                    self.start_group("dtor ")?;
530                    self.start_group("func ")?;
531                    self.print_idx(&states.last().unwrap().core.func_names, dtor)?;
532                    self.end_group()?;
533                    self.end_group()?;
534                }
535                self.end_group()?;
536            }
537        }
538        self.end_group()?;
539
540        states.last_mut().unwrap().component.types += 1;
541
542        Ok(())
543    }
544
545    pub(crate) fn print_component_types<'a>(
546        &mut self,
547        states: &mut Vec<State>,
548        parser: ComponentTypeSectionReader<'a>,
549    ) -> Result<()> {
550        for ty in parser.into_iter_with_offsets() {
551            let (offset, ty) = ty?;
552            self.newline(offset)?;
553            self.print_component_type_def(states, ty)?;
554        }
555
556        Ok(())
557    }
558
559    pub(crate) fn print_component_imports(
560        &mut self,
561        state: &mut State,
562        parser: ComponentImportSectionReader,
563    ) -> Result<()> {
564        for import in parser.into_iter_with_offsets() {
565            let (offset, import) = import?;
566            self.newline(offset)?;
567            self.print_component_import(state, &import, true)?;
568        }
569
570        Ok(())
571    }
572
573    pub(crate) fn print_component_import(
574        &mut self,
575        state: &mut State,
576        import: &ComponentImport,
577        index: bool,
578    ) -> Result<()> {
579        self.start_group("import ")?;
580        self.print_str(import.name.0)?;
581        self.result.write_str(" ")?;
582        self.print_component_import_ty(state, &import.ty, index)?;
583        self.end_group()?;
584        Ok(())
585    }
586
587    pub(crate) fn print_component_import_ty(
588        &mut self,
589        state: &mut State,
590        ty: &ComponentTypeRef,
591        index: bool,
592    ) -> Result<()> {
593        match ty {
594            ComponentTypeRef::Module(idx) => {
595                self.start_group("core module ")?;
596                if index {
597                    self.print_name(&state.core.module_names, state.core.modules)?;
598                    self.result.write_str(" ")?;
599                    state.core.modules += 1;
600                }
601                self.print_core_type_ref(state, *idx)?;
602                self.end_group()?;
603            }
604            ComponentTypeRef::Func(idx) => {
605                self.start_group("func ")?;
606                if index {
607                    self.print_name(&state.component.func_names, state.component.funcs)?;
608                    self.result.write_str(" ")?;
609                    state.component.funcs += 1;
610                }
611                self.print_component_type_ref(state, *idx)?;
612                self.end_group()?;
613            }
614            ComponentTypeRef::Value(ty) => {
615                self.start_group("value ")?;
616                if index {
617                    self.print_name(&state.component.value_names, state.component.values)?;
618                    self.result.write_str(" ")?;
619                    state.component.values += 1;
620                }
621                match ty {
622                    ComponentValType::Primitive(ty) => self.print_primitive_val_type(ty)?,
623                    ComponentValType::Type(idx) => self.print_component_type_ref(state, *idx)?,
624                }
625                self.end_group()?;
626            }
627            ComponentTypeRef::Type(bounds) => {
628                self.start_group("type ")?;
629                if index {
630                    self.print_name(&state.component.type_names, state.component.types)?;
631                    self.result.write_str(" ")?;
632                    state.component.types += 1;
633                }
634                match bounds {
635                    TypeBounds::Eq(idx) => {
636                        self.start_group("eq ")?;
637                        self.print_idx(&state.component.type_names, *idx)?;
638                        self.end_group()?;
639                    }
640                    TypeBounds::SubResource => {
641                        self.start_group("sub ")?;
642                        self.print_type_keyword("resource")?;
643                        self.end_group()?;
644                    }
645                };
646                self.end_group()?;
647            }
648            ComponentTypeRef::Instance(idx) => {
649                self.start_group("instance ")?;
650                if index {
651                    self.print_name(&state.component.instance_names, state.component.instances)?;
652                    self.result.write_str(" ")?;
653                    state.component.instances += 1;
654                }
655                self.print_component_type_ref(state, *idx)?;
656                self.end_group()?;
657            }
658            ComponentTypeRef::Component(idx) => {
659                self.start_group("component ")?;
660                if index {
661                    self.print_name(&state.component.component_names, state.component.components)?;
662                    self.result.write_str(" ")?;
663                    state.component.components += 1;
664                }
665                self.print_component_type_ref(state, *idx)?;
666                self.end_group()?;
667            }
668        }
669        Ok(())
670    }
671
672    pub(crate) fn print_component_exports(
673        &mut self,
674        state: &mut State,
675        parser: ComponentExportSectionReader,
676    ) -> Result<()> {
677        for export in parser.into_iter_with_offsets() {
678            let (offset, export) = export?;
679            self.newline(offset)?;
680            self.print_component_export(state, &export, true)?;
681        }
682        Ok(())
683    }
684
685    pub(crate) fn print_component_export(
686        &mut self,
687        state: &mut State,
688        export: &ComponentExport,
689        named: bool,
690    ) -> Result<()> {
691        self.start_group("export ")?;
692        if named {
693            self.print_component_kind_name(state, export.kind)?;
694            self.result.write_str(" ")?;
695        }
696        self.print_str(export.name.0)?;
697        self.result.write_str(" ")?;
698        self.print_component_external_kind(state, export.kind, export.index)?;
699        if let Some(ty) = &export.ty {
700            self.result.write_str(" ")?;
701            self.print_component_import_ty(state, &ty, false)?;
702        }
703        self.end_group()?;
704        Ok(())
705    }
706
707    pub(crate) fn print_component_kind_name(
708        &mut self,
709        state: &mut State,
710        kind: ComponentExternalKind,
711    ) -> Result<()> {
712        match kind {
713            ComponentExternalKind::Func => {
714                self.print_name(&state.component.func_names, state.component.funcs)?;
715                state.component.funcs += 1;
716            }
717            ComponentExternalKind::Module => {
718                self.print_name(&state.core.module_names, state.core.modules)?;
719                state.core.modules += 1;
720            }
721            ComponentExternalKind::Value => {
722                self.print_name(&state.component.value_names, state.component.values)?;
723                state.component.values += 1;
724            }
725            ComponentExternalKind::Type => {
726                self.print_name(&state.component.type_names, state.component.types)?;
727                state.component.types += 1;
728            }
729            ComponentExternalKind::Instance => {
730                self.print_name(&state.component.instance_names, state.component.instances)?;
731                state.component.instances += 1;
732            }
733            ComponentExternalKind::Component => {
734                self.print_name(&state.component.component_names, state.component.components)?;
735                state.component.components += 1;
736            }
737        }
738        Ok(())
739    }
740
741    pub(crate) fn start_component_external_kind_group(
742        &mut self,
743        kind: ComponentExternalKind,
744    ) -> Result<()> {
745        match kind {
746            ComponentExternalKind::Module => {
747                self.start_group("core module ")?;
748            }
749            ComponentExternalKind::Component => {
750                self.start_group("component ")?;
751            }
752            ComponentExternalKind::Instance => {
753                self.start_group("instance ")?;
754            }
755            ComponentExternalKind::Func => {
756                self.start_group("func ")?;
757            }
758            ComponentExternalKind::Value => {
759                self.start_group("value ")?;
760            }
761            ComponentExternalKind::Type => {
762                self.start_group("type ")?;
763            }
764        }
765        Ok(())
766    }
767
768    pub(crate) fn print_component_external_kind(
769        &mut self,
770        state: &State,
771        kind: ComponentExternalKind,
772        index: u32,
773    ) -> Result<()> {
774        self.start_component_external_kind_group(kind)?;
775        match kind {
776            ComponentExternalKind::Module => {
777                self.print_idx(&state.core.module_names, index)?;
778            }
779            ComponentExternalKind::Component => {
780                self.print_idx(&state.component.component_names, index)?;
781            }
782            ComponentExternalKind::Instance => {
783                self.print_idx(&state.component.instance_names, index)?;
784            }
785            ComponentExternalKind::Func => {
786                self.print_idx(&state.component.func_names, index)?;
787            }
788            ComponentExternalKind::Value => {
789                self.print_idx(&state.component.value_names, index)?;
790            }
791            ComponentExternalKind::Type => {
792                self.print_idx(&state.component.type_names, index)?;
793            }
794        }
795        self.end_group()?;
796        Ok(())
797    }
798
799    pub(crate) fn print_canonical_options(
800        &mut self,
801        state: &State,
802        options: &[CanonicalOption],
803    ) -> Result<()> {
804        for option in options {
805            self.result.write_str(" ")?;
806            match option {
807                CanonicalOption::UTF8 => self.result.write_str("string-encoding=utf8")?,
808                CanonicalOption::UTF16 => self.result.write_str("string-encoding=utf16")?,
809                CanonicalOption::CompactUTF16 => {
810                    self.result.write_str("string-encoding=latin1+utf16")?
811                }
812                CanonicalOption::Memory(idx) => {
813                    self.start_group("memory ")?;
814                    self.print_idx(&state.core.memory_names, *idx)?;
815                    self.end_group()?;
816                }
817                CanonicalOption::Realloc(idx) => {
818                    self.start_group("realloc ")?;
819                    self.print_idx(&state.core.func_names, *idx)?;
820                    self.end_group()?;
821                }
822                CanonicalOption::PostReturn(idx) => {
823                    self.start_group("post-return ")?;
824                    self.print_idx(&state.core.func_names, *idx)?;
825                    self.end_group()?;
826                }
827                CanonicalOption::Async => self.print_type_keyword("async")?,
828                CanonicalOption::Callback(idx) => {
829                    self.start_group("callback ")?;
830                    self.print_idx(&state.core.func_names, *idx)?;
831                    self.end_group()?;
832                }
833                CanonicalOption::CoreType(idx) => {
834                    self.start_group("core-type ")?;
835                    self.print_idx(&state.core.type_names, *idx)?;
836                    self.end_group()?;
837                }
838                CanonicalOption::Gc => self.result.write_str("gc")?,
839            }
840        }
841        Ok(())
842    }
843
844    fn print_intrinsic(
845        &mut self,
846        state: &mut State,
847        group: &str,
848        body: &dyn Fn(&mut Self, &mut State) -> Result<()>,
849    ) -> Result<()> {
850        self.start_group("core func ")?;
851        self.print_name(&state.core.func_names, state.core.funcs)?;
852        self.result.write_str(" ")?;
853        self.start_group(group)?;
854        body(self, state)?;
855        self.end_group()?;
856        self.end_group()?;
857        debug_assert_eq!(state.core.func_to_type.len(), state.core.funcs as usize);
858        state.core.funcs += 1;
859        state.core.func_to_type.push(None);
860        Ok(())
861    }
862
863    pub(crate) fn print_canonical_functions(
864        &mut self,
865        state: &mut State,
866        parser: ComponentCanonicalSectionReader,
867    ) -> Result<()> {
868        for func in parser.into_iter_with_offsets() {
869            let (offset, func) = func?;
870            self.newline(offset)?;
871            match func {
872                CanonicalFunction::Lift {
873                    core_func_index,
874                    type_index,
875                    options,
876                } => {
877                    self.start_group("func ")?;
878                    self.print_name(&state.component.func_names, state.component.funcs)?;
879                    self.result.write_str(" ")?;
880                    self.start_group("type ")?;
881                    self.print_idx(&state.component.type_names, type_index)?;
882                    self.end_group()?;
883                    self.result.write_str(" ")?;
884                    self.start_group("canon lift ")?;
885                    self.start_group("core func ")?;
886                    self.print_idx(&state.core.func_names, core_func_index)?;
887                    self.end_group()?;
888                    self.print_canonical_options(state, &options)?;
889                    self.end_group()?;
890                    self.end_group()?;
891                    state.component.funcs += 1;
892                }
893                CanonicalFunction::Lower {
894                    func_index,
895                    options,
896                } => {
897                    self.print_intrinsic(state, "canon lower ", &|me, state| {
898                        me.start_group("func ")?;
899                        me.print_idx(&state.component.func_names, func_index)?;
900                        me.end_group()?;
901                        me.print_canonical_options(state, &options)
902                    })?;
903                }
904                CanonicalFunction::ResourceNew { resource } => {
905                    self.print_intrinsic(state, "canon resource.new ", &|me, state| {
906                        me.print_idx(&state.component.type_names, resource)
907                    })?;
908                }
909                CanonicalFunction::ResourceDrop { resource } => {
910                    self.print_intrinsic(state, "canon resource.drop ", &|me, state| {
911                        me.print_idx(&state.component.type_names, resource)
912                    })?;
913                }
914                CanonicalFunction::ResourceDropAsync { resource } => {
915                    self.print_intrinsic(state, "canon resource.drop ", &|me, state| {
916                        me.print_idx(&state.component.type_names, resource)?;
917                        me.print_type_keyword(" async")
918                    })?;
919                }
920                CanonicalFunction::ResourceRep { resource } => {
921                    self.print_intrinsic(state, "canon resource.rep ", &|me, state| {
922                        me.print_idx(&state.component.type_names, resource)
923                    })?;
924                }
925                CanonicalFunction::ThreadSpawnRef { func_ty_index } => {
926                    self.print_intrinsic(state, "canon thread.spawn_ref ", &|me, state| {
927                        me.print_idx(&state.core.type_names, func_ty_index)
928                    })?;
929                }
930                CanonicalFunction::ThreadSpawnIndirect {
931                    func_ty_index,
932                    table_index,
933                } => {
934                    self.print_intrinsic(state, "canon thread.spawn_indirect ", &|me, state| {
935                        me.print_idx(&state.core.type_names, func_ty_index)?;
936                        me.result.write_str(" ")?;
937                        me.start_group("table ")?;
938                        me.print_idx(&state.core.table_names, table_index)?;
939                        me.end_group()
940                    })?;
941                }
942                CanonicalFunction::ThreadAvailableParallelism => {
943                    self.print_intrinsic(state, "canon thread.available_parallelism", &|_, _| {
944                        Ok(())
945                    })?;
946                }
947                CanonicalFunction::BackpressureSet => {
948                    self.print_intrinsic(state, "canon backpressure.set", &|_, _| Ok(()))?;
949                }
950                CanonicalFunction::BackpressureInc => {
951                    self.print_intrinsic(state, "canon backpressure.inc", &|_, _| Ok(()))?;
952                }
953                CanonicalFunction::BackpressureDec => {
954                    self.print_intrinsic(state, "canon backpressure.dec", &|_, _| Ok(()))?;
955                }
956                CanonicalFunction::TaskReturn { result, options } => {
957                    self.print_intrinsic(state, "canon task.return", &|me, state| {
958                        if let Some(ty) = result {
959                            me.result.write_str(" ")?;
960                            me.start_group("result ")?;
961                            me.print_component_val_type(state, &ty)?;
962                            me.end_group()?;
963                        }
964                        me.print_canonical_options(state, &options)?;
965                        Ok(())
966                    })?;
967                }
968                CanonicalFunction::TaskCancel => {
969                    self.print_intrinsic(state, "canon task.cancel", &|_, _| Ok(()))?;
970                }
971                CanonicalFunction::ContextGet(i) => {
972                    self.print_intrinsic(state, "canon context.get", &|me, _state| {
973                        write!(me.result, " i32 {i}")?;
974                        Ok(())
975                    })?;
976                }
977                CanonicalFunction::ContextSet(i) => {
978                    self.print_intrinsic(state, "canon context.set", &|me, _state| {
979                        write!(me.result, " i32 {i}")?;
980                        Ok(())
981                    })?;
982                }
983                CanonicalFunction::ThreadYield { cancellable } => {
984                    self.print_intrinsic(state, "canon thread.yield", &|me, _| {
985                        if cancellable {
986                            me.print_type_keyword(" cancellable")?;
987                        }
988                        Ok(())
989                    })?;
990                }
991                CanonicalFunction::SubtaskDrop => {
992                    self.print_intrinsic(state, "canon subtask.drop", &|_, _| Ok(()))?;
993                }
994                CanonicalFunction::SubtaskCancel { async_ } => {
995                    self.print_intrinsic(state, "canon subtask.cancel", &|me, _| {
996                        if async_ {
997                            me.print_type_keyword(" async")?;
998                        }
999                        Ok(())
1000                    })?;
1001                }
1002                CanonicalFunction::StreamNew { ty } => {
1003                    self.print_intrinsic(state, "canon stream.new ", &|me, state| {
1004                        me.print_idx(&state.component.type_names, ty)
1005                    })?;
1006                }
1007                CanonicalFunction::StreamRead { ty, options } => {
1008                    self.print_intrinsic(state, "canon stream.read ", &|me, state| {
1009                        me.print_idx(&state.component.type_names, ty)?;
1010                        me.print_canonical_options(state, &options)
1011                    })?;
1012                }
1013                CanonicalFunction::StreamWrite { ty, options } => {
1014                    self.print_intrinsic(state, "canon stream.write ", &|me, state| {
1015                        me.print_idx(&state.component.type_names, ty)?;
1016                        me.print_canonical_options(state, &options)
1017                    })?;
1018                }
1019                CanonicalFunction::StreamCancelRead { ty, async_ } => {
1020                    self.print_intrinsic(state, "canon stream.cancel-read ", &|me, state| {
1021                        me.print_idx(&state.component.type_names, ty)?;
1022                        if async_ {
1023                            me.print_type_keyword(" async")?;
1024                        }
1025                        Ok(())
1026                    })?;
1027                }
1028                CanonicalFunction::StreamCancelWrite { ty, async_ } => {
1029                    self.print_intrinsic(state, "canon stream.cancel-write ", &|me, state| {
1030                        me.print_idx(&state.component.type_names, ty)?;
1031                        if async_ {
1032                            me.print_type_keyword(" async")?;
1033                        }
1034                        Ok(())
1035                    })?;
1036                }
1037                CanonicalFunction::StreamDropReadable { ty } => {
1038                    self.print_intrinsic(state, "canon stream.drop-readable ", &|me, state| {
1039                        me.print_idx(&state.component.type_names, ty)
1040                    })?;
1041                }
1042                CanonicalFunction::StreamDropWritable { ty } => {
1043                    self.print_intrinsic(state, "canon stream.drop-writable ", &|me, state| {
1044                        me.print_idx(&state.component.type_names, ty)
1045                    })?;
1046                }
1047                CanonicalFunction::FutureNew { ty } => {
1048                    self.print_intrinsic(state, "canon future.new ", &|me, state| {
1049                        me.print_idx(&state.component.type_names, ty)
1050                    })?;
1051                }
1052                CanonicalFunction::FutureRead { ty, options } => {
1053                    self.print_intrinsic(state, "canon future.read ", &|me, state| {
1054                        me.print_idx(&state.component.type_names, ty)?;
1055                        me.print_canonical_options(state, &options)
1056                    })?;
1057                }
1058                CanonicalFunction::FutureWrite { ty, options } => {
1059                    self.print_intrinsic(state, "canon future.write ", &|me, state| {
1060                        me.print_idx(&state.component.type_names, ty)?;
1061                        me.print_canonical_options(state, &options)
1062                    })?;
1063                }
1064                CanonicalFunction::FutureCancelRead { ty, async_ } => {
1065                    self.print_intrinsic(state, "canon future.cancel-read ", &|me, state| {
1066                        me.print_idx(&state.component.type_names, ty)?;
1067                        if async_ {
1068                            me.print_type_keyword(" async")?;
1069                        }
1070                        Ok(())
1071                    })?;
1072                }
1073                CanonicalFunction::FutureCancelWrite { ty, async_ } => {
1074                    self.print_intrinsic(state, "canon future.cancel-write ", &|me, state| {
1075                        me.print_idx(&state.component.type_names, ty)?;
1076                        if async_ {
1077                            me.print_type_keyword(" async")?;
1078                        }
1079                        Ok(())
1080                    })?;
1081                }
1082                CanonicalFunction::FutureDropReadable { ty } => {
1083                    self.print_intrinsic(state, "canon future.drop-readable ", &|me, state| {
1084                        me.print_idx(&state.component.type_names, ty)
1085                    })?;
1086                }
1087                CanonicalFunction::FutureDropWritable { ty } => {
1088                    self.print_intrinsic(state, "canon future.drop-writable ", &|me, state| {
1089                        me.print_idx(&state.component.type_names, ty)
1090                    })?;
1091                }
1092                CanonicalFunction::ErrorContextNew { options } => {
1093                    self.print_intrinsic(state, "canon error-context.new", &|me, state| {
1094                        me.print_canonical_options(state, &options)
1095                    })?;
1096                }
1097                CanonicalFunction::ErrorContextDebugMessage { options } => {
1098                    self.print_intrinsic(
1099                        state,
1100                        "canon error-context.debug-message",
1101                        &|me, state| me.print_canonical_options(state, &options),
1102                    )?;
1103                }
1104                CanonicalFunction::ErrorContextDrop => {
1105                    self.print_intrinsic(state, "canon error-context.drop", &|_, _| Ok(()))?;
1106                }
1107                CanonicalFunction::WaitableSetNew => {
1108                    self.print_intrinsic(state, "canon waitable-set.new", &|_, _| Ok(()))?;
1109                }
1110                CanonicalFunction::WaitableSetWait {
1111                    cancellable,
1112                    memory,
1113                } => {
1114                    self.print_intrinsic(state, "canon waitable-set.wait ", &|me, state| {
1115                        if cancellable {
1116                            me.result.write_str("cancellable ")?;
1117                        }
1118                        me.start_group("memory ")?;
1119                        me.print_idx(&state.core.memory_names, memory)?;
1120                        me.end_group()
1121                    })?;
1122                }
1123                CanonicalFunction::WaitableSetPoll {
1124                    cancellable,
1125                    memory,
1126                } => {
1127                    self.print_intrinsic(state, "canon waitable-set.poll ", &|me, state| {
1128                        if cancellable {
1129                            me.result.write_str("cancellable ")?;
1130                        }
1131                        me.start_group("memory ")?;
1132                        me.print_idx(&state.core.memory_names, memory)?;
1133                        me.end_group()
1134                    })?;
1135                }
1136                CanonicalFunction::WaitableSetDrop => {
1137                    self.print_intrinsic(state, "canon waitable-set.drop", &|_, _| Ok(()))?;
1138                }
1139                CanonicalFunction::WaitableJoin => {
1140                    self.print_intrinsic(state, "canon waitable.join", &|_, _| Ok(()))?;
1141                }
1142                CanonicalFunction::ThreadIndex => {
1143                    self.print_intrinsic(state, "canon thread.index", &|_, _| Ok(()))?;
1144                }
1145                CanonicalFunction::ThreadNewIndirect {
1146                    func_ty_index,
1147                    table_index,
1148                } => {
1149                    self.print_intrinsic(state, "canon thread.new_indirect ", &|me, state| {
1150                        me.print_idx(&state.core.type_names, func_ty_index)?;
1151                        me.result.write_str(" ")?;
1152                        me.start_group("table ")?;
1153                        me.print_idx(&state.core.table_names, table_index)?;
1154                        me.end_group()
1155                    })?;
1156                }
1157                CanonicalFunction::ThreadSwitchTo { cancellable } => {
1158                    self.print_intrinsic(state, "canon thread.switch-to", &|me, _| {
1159                        if cancellable {
1160                            me.result.write_str(" cancellable")?;
1161                        }
1162                        Ok(())
1163                    })?;
1164                }
1165                CanonicalFunction::ThreadSuspend { cancellable } => {
1166                    self.print_intrinsic(state, "canon thread.suspend", &|me, _| {
1167                        if cancellable {
1168                            me.result.write_str(" cancellable")?;
1169                        }
1170                        Ok(())
1171                    })?;
1172                }
1173                CanonicalFunction::ThreadResumeLater => {
1174                    self.print_intrinsic(state, "canon thread.resume-later", &|_, _| Ok(()))?;
1175                }
1176                CanonicalFunction::ThreadYieldTo { cancellable } => {
1177                    self.print_intrinsic(state, "canon thread.yield-to", &|me, _| {
1178                        if cancellable {
1179                            me.result.write_str(" cancellable")?;
1180                        }
1181                        Ok(())
1182                    })?;
1183                }
1184            }
1185        }
1186
1187        Ok(())
1188    }
1189
1190    pub(crate) fn print_instances(
1191        &mut self,
1192        state: &mut State,
1193        parser: InstanceSectionReader,
1194    ) -> Result<()> {
1195        for instance in parser.into_iter_with_offsets() {
1196            let (offset, instance) = instance?;
1197            self.newline(offset)?;
1198            self.start_group("core instance ")?;
1199            self.print_name(&state.core.instance_names, state.core.instances)?;
1200            match instance {
1201                Instance::Instantiate { module_index, args } => {
1202                    self.result.write_str(" ")?;
1203                    self.start_group("instantiate ")?;
1204                    self.print_idx(&state.core.module_names, module_index)?;
1205                    for arg in args.iter() {
1206                        self.newline(offset)?;
1207                        self.print_instantiation_arg(state, arg)?;
1208                    }
1209                    self.end_group()?;
1210                    state.core.instances += 1;
1211                }
1212                Instance::FromExports(exports) => {
1213                    for export in exports.iter() {
1214                        self.newline(offset)?;
1215                        self.print_export(state, export)?;
1216                    }
1217                    state.core.instances += 1;
1218                }
1219            }
1220            self.end_group()?;
1221        }
1222        Ok(())
1223    }
1224
1225    pub(crate) fn print_component_instances(
1226        &mut self,
1227        state: &mut State,
1228        parser: ComponentInstanceSectionReader,
1229    ) -> Result<()> {
1230        for instance in parser.into_iter_with_offsets() {
1231            let (offset, instance) = instance?;
1232            self.newline(offset)?;
1233            self.start_group("instance ")?;
1234            self.print_name(&state.component.instance_names, state.component.instances)?;
1235            state.component.instances += 1;
1236            match instance {
1237                ComponentInstance::Instantiate {
1238                    component_index,
1239                    args,
1240                } => {
1241                    self.result.write_str(" ")?;
1242                    self.start_group("instantiate ")?;
1243                    self.print_idx(&state.component.component_names, component_index)?;
1244                    for arg in args.iter() {
1245                        self.newline(offset)?;
1246                        self.print_component_instantiation_arg(state, arg)?;
1247                    }
1248                    self.end_group()?;
1249                }
1250                ComponentInstance::FromExports(exports) => {
1251                    for export in exports.iter() {
1252                        self.newline(offset)?;
1253                        self.print_component_export(state, export, false)?;
1254                    }
1255                }
1256            }
1257            self.end_group()?;
1258        }
1259        Ok(())
1260    }
1261
1262    pub(crate) fn print_instantiation_arg(
1263        &mut self,
1264        state: &State,
1265        arg: &InstantiationArg,
1266    ) -> Result<()> {
1267        self.start_group("with ")?;
1268        self.print_str(arg.name)?;
1269        self.result.write_str(" ")?;
1270        match arg.kind {
1271            InstantiationArgKind::Instance => {
1272                self.start_group("instance ")?;
1273                self.print_idx(&state.core.instance_names, arg.index)?;
1274                self.end_group()?;
1275            }
1276        }
1277        self.end_group()?;
1278        Ok(())
1279    }
1280
1281    pub(crate) fn print_component_instantiation_arg(
1282        &mut self,
1283        state: &State,
1284        arg: &ComponentInstantiationArg,
1285    ) -> Result<()> {
1286        self.start_group("with ")?;
1287        self.print_str(arg.name)?;
1288        self.result.write_str(" ")?;
1289        self.print_component_external_kind(state, arg.kind, arg.index)?;
1290        self.end_group()?;
1291        Ok(())
1292    }
1293
1294    pub(crate) fn print_component_start(
1295        &mut self,
1296        state: &mut State,
1297        pos: usize,
1298        start: ComponentStartFunction,
1299    ) -> Result<()> {
1300        self.newline(pos)?;
1301        self.start_group("start ")?;
1302        self.print_idx(&state.component.func_names, start.func_index)?;
1303
1304        for arg in start.arguments.iter() {
1305            self.result.write_str(" ")?;
1306            self.start_group("value ")?;
1307            self.print_idx(&state.component.value_names, *arg)?;
1308            self.end_group()?;
1309        }
1310
1311        for _ in 0..start.results {
1312            self.result.write_str(" ")?;
1313            self.start_group("result ")?;
1314            self.start_group("value ")?;
1315            self.print_name(&state.component.value_names, state.component.values)?;
1316            self.end_group()?;
1317            self.end_group()?;
1318            state.component.values += 1;
1319        }
1320
1321        self.end_group()?; // start
1322
1323        Ok(())
1324    }
1325
1326    pub(crate) fn print_component_aliases(
1327        &mut self,
1328        states: &mut [State],
1329        parser: ComponentAliasSectionReader,
1330    ) -> Result<()> {
1331        for alias in parser.into_iter_with_offsets() {
1332            let (offset, alias) = alias?;
1333            self.newline(offset)?;
1334            self.print_component_alias(states, alias)?;
1335        }
1336        Ok(())
1337    }
1338
1339    pub(crate) fn print_component_alias(
1340        &mut self,
1341        states: &mut [State],
1342        alias: ComponentAlias<'_>,
1343    ) -> Result<()> {
1344        match alias {
1345            ComponentAlias::InstanceExport {
1346                kind,
1347                instance_index,
1348                name,
1349            } => {
1350                let state = states.last_mut().unwrap();
1351                self.start_group("alias export ")?;
1352                self.print_idx(&state.component.instance_names, instance_index)?;
1353                self.result.write_str(" ")?;
1354                self.print_str(name)?;
1355                self.result.write_str(" ")?;
1356                self.start_component_external_kind_group(kind)?;
1357                self.print_component_kind_name(state, kind)?;
1358                self.end_group()?;
1359
1360                self.end_group()?; // alias export
1361            }
1362            ComponentAlias::CoreInstanceExport {
1363                instance_index,
1364                kind,
1365                name,
1366            } => {
1367                let state = states.last_mut().unwrap();
1368                self.start_group("alias core export ")?;
1369                self.print_idx(&state.core.instance_names, instance_index)?;
1370                self.result.write_str(" ")?;
1371                self.print_str(name)?;
1372                self.result.write_str(" ")?;
1373                match kind {
1374                    ExternalKind::Func => {
1375                        self.start_group("core func ")?;
1376                        self.print_name(&state.core.func_names, state.core.funcs)?;
1377                        self.end_group()?;
1378                        debug_assert_eq!(state.core.func_to_type.len(), state.core.funcs as usize);
1379                        state.core.funcs += 1;
1380                        state.core.func_to_type.push(None)
1381                    }
1382                    ExternalKind::Table => {
1383                        self.start_group("core table ")?;
1384                        self.print_name(&state.core.table_names, state.core.tables)?;
1385                        self.end_group()?;
1386                        state.core.tables += 1;
1387                    }
1388                    ExternalKind::Memory => {
1389                        self.start_group("core memory ")?;
1390                        self.print_name(&state.core.memory_names, state.core.memories)?;
1391                        self.end_group()?;
1392                        state.core.memories += 1;
1393                    }
1394                    ExternalKind::Global => {
1395                        self.start_group("core global ")?;
1396                        self.print_name(&state.core.global_names, state.core.globals)?;
1397                        self.end_group()?;
1398                        state.core.globals += 1;
1399                    }
1400                    ExternalKind::Tag => {
1401                        self.start_group("core tag ")?;
1402                        self.print_name(&state.core.tag_names, state.core.tags)?;
1403                        self.end_group()?;
1404                        debug_assert_eq!(state.core.tag_to_type.len(), state.core.tags as usize);
1405                        state.core.tags += 1;
1406                        state.core.tag_to_type.push(None)
1407                    }
1408                }
1409                self.end_group()?; // alias export
1410            }
1411
1412            ComponentAlias::Outer { kind, count, index } => {
1413                let state = states.last().unwrap();
1414                let default_state = State::new(Encoding::Component);
1415                let outer = match Self::outer_state(states, count) {
1416                    Ok(o) => o,
1417                    Err(e) => {
1418                        write!(self.result, "(; {e} ;) ")?;
1419                        &default_state
1420                    }
1421                };
1422                self.start_group("alias outer ")?;
1423                if let Some(name) = outer.name.as_ref() {
1424                    name.write(self)?;
1425                } else {
1426                    write!(self.result, "{count}")?;
1427                }
1428                self.result.write_str(" ")?;
1429                match kind {
1430                    ComponentOuterAliasKind::CoreModule => {
1431                        self.print_idx(&outer.core.module_names, index)?;
1432                        self.result.write_str(" ")?;
1433                        self.start_group("core module ")?;
1434                        self.print_name(&state.core.module_names, state.core.modules)?;
1435                    }
1436                    ComponentOuterAliasKind::CoreType => {
1437                        self.print_idx(&outer.core.type_names, index)?;
1438                        self.result.write_str(" ")?;
1439                        self.start_group("core type ")?;
1440                        self.print_name(&state.core.type_names, state.core.types.len() as u32)?;
1441                    }
1442                    ComponentOuterAliasKind::Type => {
1443                        self.print_idx(&outer.component.type_names, index)?;
1444                        self.result.write_str(" ")?;
1445                        self.start_group("type ")?;
1446                        self.print_name(&state.component.type_names, state.component.types)?;
1447                    }
1448                    ComponentOuterAliasKind::Component => {
1449                        self.print_idx(&outer.component.component_names, index)?;
1450                        self.result.write_str(" ")?;
1451                        self.start_group("component ")?;
1452                        self.print_name(
1453                            &state.component.component_names,
1454                            state.component.components,
1455                        )?;
1456                    }
1457                }
1458                self.end_group()?; // kind
1459                self.end_group()?; // alias
1460
1461                let state = states.last_mut().unwrap();
1462                match kind {
1463                    ComponentOuterAliasKind::CoreModule => state.core.modules += 1,
1464                    ComponentOuterAliasKind::CoreType => state.core.types.push(None),
1465                    ComponentOuterAliasKind::Type => state.component.types += 1,
1466                    ComponentOuterAliasKind::Component => state.component.components += 1,
1467                }
1468            }
1469        }
1470        Ok(())
1471    }
1472}