golem_wasm_ast/component/
mod.rs

1// Copyright 2024-2025 Golem Cloud
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#[cfg(feature = "parser")]
16use crate::component::parser::parse_component;
17use crate::core::{
18    Custom, Data, Export, FuncIdx, FuncType, Import, MemIdx, Module, RetainsCustomSection,
19    RetainsInstructions, TryFromExprSource, TypeRef, ValType,
20};
21#[cfg(feature = "metadata")]
22use crate::metadata;
23use crate::{
24    new_component_section_cache, AstCustomization, IndexSpace, Section, SectionCache, SectionIndex,
25    SectionType, Sections,
26};
27use mappable_rc::Mrc;
28use std::fmt::{Debug, Formatter};
29
30#[cfg(feature = "parser")]
31pub mod parser;
32#[cfg(feature = "writer")]
33pub mod writer;
34
35/// The Component Model section nodes.
36///
37/// See [Section] for more information.
38#[allow(clippy::large_enum_variant)]
39#[derive(Debug, Clone, PartialEq)]
40pub enum ComponentSection<Ast: AstCustomization + 'static> {
41    Module(Module<Ast>),
42    CoreInstance(Instance),
43    CoreType(CoreType),
44    Component(Component<Ast>),
45    Instance(ComponentInstance),
46    Alias(Alias),
47    Type(ComponentType),
48    Canon(Canon),
49    Start(ComponentStart),
50    Import(ComponentImport),
51    Export(ComponentExport),
52    Custom(Ast::Custom),
53}
54
55#[allow(unused)]
56impl<Ast: AstCustomization> ComponentSection<Ast> {
57    pub fn as_module(&self) -> &Module<Ast> {
58        match self {
59            ComponentSection::Module(module) => module,
60            _ => panic!("Expected module section, got {}", self.type_name()),
61        }
62    }
63
64    pub fn as_core_instance(&self) -> &Instance {
65        match self {
66            ComponentSection::CoreInstance(instance) => instance,
67            _ => panic!("Expected core instance section, got {}", self.type_name()),
68        }
69    }
70
71    pub fn as_core_type(&self) -> &CoreType {
72        match self {
73            ComponentSection::CoreType(core_type) => core_type,
74            _ => panic!("Expected core type section, got {}", self.type_name()),
75        }
76    }
77
78    pub fn as_component(&self) -> &Component<Ast> {
79        match self {
80            ComponentSection::Component(component) => component,
81            _ => panic!("Expected component section, got {}", self.type_name()),
82        }
83    }
84
85    pub fn as_instance(&self) -> &ComponentInstance {
86        match self {
87            ComponentSection::Instance(component_instance) => component_instance,
88            _ => panic!(
89                "Expected component instance section, got {}",
90                self.type_name()
91            ),
92        }
93    }
94
95    pub fn as_alias(&self) -> &Alias {
96        match self {
97            ComponentSection::Alias(alias) => alias,
98            _ => panic!("Expected alias section, got {}", self.type_name()),
99        }
100    }
101
102    pub fn as_type(&self) -> &ComponentType {
103        match self {
104            ComponentSection::Type(component_type) => component_type,
105            _ => panic!("Expected type section, got {}", self.type_name()),
106        }
107    }
108
109    pub fn as_canon(&self) -> &Canon {
110        match self {
111            ComponentSection::Canon(canon) => canon,
112            _ => panic!("Expected canon section, got {}", self.type_name()),
113        }
114    }
115
116    pub fn as_start(&self) -> &ComponentStart {
117        match self {
118            ComponentSection::Start(start) => start,
119            _ => panic!("Expected start section, got {}", self.type_name()),
120        }
121    }
122
123    pub fn as_import(&self) -> &ComponentImport {
124        match self {
125            ComponentSection::Import(import) => import,
126            _ => panic!("Expected import section, got {}", self.type_name()),
127        }
128    }
129
130    pub fn as_export(&self) -> &ComponentExport {
131        match self {
132            ComponentSection::Export(export) => export,
133            _ => panic!("Expected export section, got {}", self.type_name()),
134        }
135    }
136
137    pub fn as_custom(&self) -> &Ast::Custom {
138        match self {
139            ComponentSection::Custom(custom) => custom,
140            _ => panic!("Expected custom section, got {}", self.type_name()),
141        }
142    }
143
144    pub fn type_name(&self) -> &'static str {
145        match self {
146            ComponentSection::Module(_) => "module",
147            ComponentSection::CoreInstance(_) => "core instance",
148            ComponentSection::CoreType(_) => "core type",
149            ComponentSection::Component(_) => "component",
150            ComponentSection::Instance(_) => "instance",
151            ComponentSection::Alias(_) => "alias",
152            ComponentSection::Type(_) => "type",
153            ComponentSection::Canon(_) => "canonical function",
154            ComponentSection::Start(_) => "start",
155            ComponentSection::Import(_) => "import",
156            ComponentSection::Export(_) => "export",
157            ComponentSection::Custom(_) => "custom",
158        }
159    }
160}
161
162impl<Ast: AstCustomization> Section<ComponentIndexSpace, ComponentSectionType>
163    for ComponentSection<Ast>
164{
165    fn index_space(&self) -> ComponentIndexSpace {
166        match self {
167            ComponentSection::Module(module) => module.index_space(),
168            ComponentSection::CoreInstance(core_instance) => core_instance.index_space(),
169            ComponentSection::CoreType(core_type) => core_type.index_space(),
170            ComponentSection::Component(component) => component.index_space(),
171            ComponentSection::Instance(component_instance) => component_instance.index_space(),
172            ComponentSection::Alias(alias) => alias.index_space(),
173            ComponentSection::Type(component_type) => component_type.index_space(),
174            ComponentSection::Canon(canon) => canon.index_space(),
175            ComponentSection::Start(start) => start.index_space(),
176            ComponentSection::Import(import) => import.index_space(),
177            ComponentSection::Export(export) => export.index_space(),
178            ComponentSection::Custom(custom) => custom.index_space(),
179        }
180    }
181
182    fn section_type(&self) -> ComponentSectionType {
183        match self {
184            ComponentSection::Module(module) => module.section_type(),
185            ComponentSection::CoreInstance(core_instance) => core_instance.section_type(),
186            ComponentSection::CoreType(core_type) => core_type.section_type(),
187            ComponentSection::Component(component) => component.section_type(),
188            ComponentSection::Instance(component_instance) => component_instance.section_type(),
189            ComponentSection::Alias(alias) => alias.section_type(),
190            ComponentSection::Type(component_type) => component_type.section_type(),
191            ComponentSection::Canon(canon) => canon.section_type(),
192            ComponentSection::Start(start) => start.section_type(),
193            ComponentSection::Import(import) => import.section_type(),
194            ComponentSection::Export(export) => export.section_type(),
195            ComponentSection::Custom(custom) => custom.section_type(),
196        }
197    }
198}
199
200/// The Component Model section types.
201///
202/// See [SectionType] for more information.
203#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
204pub enum ComponentSectionType {
205    Module,
206    CoreInstance,
207    CoreType,
208    Component,
209    Instance,
210    Alias,
211    Type,
212    Canon,
213    Start,
214    Import,
215    Export,
216    Custom,
217}
218
219impl SectionType for ComponentSectionType {
220    fn allow_grouping(&self) -> bool {
221        !matches!(
222            self,
223            ComponentSectionType::Module
224                | ComponentSectionType::Component
225                | ComponentSectionType::Start
226                | ComponentSectionType::Custom
227        )
228    }
229}
230
231/// The Component Model index spaces.
232///
233/// See [IndexSpace] for more information.
234#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
235pub enum ComponentIndexSpace {
236    Func,
237    CoreType,
238    Type,
239    Module,
240    Component,
241    CoreInstance,
242    Instance,
243    Value,
244    CoreTable,
245    CoreFunc,
246    CoreGlobal,
247    CoreMem,
248    Start,
249    Custom,
250}
251
252impl IndexSpace for ComponentIndexSpace {
253    type Index = u32;
254}
255
256pub type ComponentFuncIdx = u32;
257pub type ComponentTypeIdx = u32;
258pub type ModuleIdx = u32;
259pub type ComponentIdx = u32;
260
261#[allow(unused)]
262pub type CoreInstanceIdx = u32;
263pub type InstanceIdx = u32;
264pub type ValueIdx = u32;
265
266#[allow(unused)]
267pub type StartIdx = u32;
268
269#[derive(Debug, Clone, PartialEq, Eq)]
270pub enum InstantiationArgRef {
271    Instance(InstanceIdx),
272}
273
274#[derive(Debug, Clone, PartialEq, Eq)]
275pub struct InstantiationArg {
276    pub name: String,
277    pub arg_ref: InstantiationArgRef,
278}
279
280#[derive(Debug, Clone, PartialEq, Eq)]
281pub enum Instance {
282    Instantiate {
283        module_idx: ModuleIdx,
284        args: Vec<InstantiationArg>,
285    },
286    FromExports {
287        exports: Vec<Export>,
288    },
289}
290
291impl Section<ComponentIndexSpace, ComponentSectionType> for Instance {
292    fn index_space(&self) -> ComponentIndexSpace {
293        ComponentIndexSpace::CoreInstance
294    }
295
296    fn section_type(&self) -> ComponentSectionType {
297        ComponentSectionType::CoreInstance
298    }
299}
300
301#[derive(Debug, Clone, PartialEq, Eq)]
302#[cfg_attr(feature = "json", derive(serde::Serialize, serde::Deserialize))]
303#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
304#[cfg_attr(feature = "poem_openapi", derive(poem_openapi::Enum))]
305pub enum ComponentExternalKind {
306    Module,
307    Func,
308    Value,
309    Type,
310    Instance,
311    Component,
312}
313
314#[derive(Debug, Clone, PartialEq, Eq)]
315pub enum OuterAliasKind {
316    CoreModule,
317    CoreType,
318    Type,
319    Component,
320}
321
322#[derive(Debug, Clone, PartialEq, Eq)]
323pub enum ExportKind {
324    Func,
325    Table,
326    Mem,
327    Global,
328}
329
330#[derive(Debug, Clone, PartialEq, Eq)]
331pub struct ComponentInstantiationArg {
332    pub name: String,
333    pub kind: ComponentExternalKind,
334    pub idx: u32,
335}
336
337#[derive(Debug, Clone, PartialEq, Eq)]
338pub enum ComponentInstance {
339    Instantiate {
340        component_idx: ComponentIdx,
341        args: Vec<ComponentInstantiationArg>,
342    },
343    FromExports {
344        exports: Vec<ComponentExport>,
345    },
346}
347
348impl Section<ComponentIndexSpace, ComponentSectionType> for ComponentInstance {
349    fn index_space(&self) -> ComponentIndexSpace {
350        ComponentIndexSpace::Instance
351    }
352
353    fn section_type(&self) -> ComponentSectionType {
354        ComponentSectionType::Instance
355    }
356}
357
358#[derive(Debug, Clone, PartialEq, Eq)]
359pub enum ComponentExternName {
360    Name(String),
361}
362
363impl ComponentExternName {
364    pub fn as_string(&self) -> String {
365        let str: &str = self.into();
366        str.to_string()
367    }
368}
369
370impl<'a> From<&'a ComponentExternName> for &'a str {
371    fn from(value: &'a ComponentExternName) -> Self {
372        match value {
373            ComponentExternName::Name(name) => name,
374        }
375    }
376}
377
378impl PartialEq<String> for ComponentExternName {
379    fn eq(&self, other: &String) -> bool {
380        match self {
381            ComponentExternName::Name(name) => name == other,
382        }
383    }
384}
385
386#[derive(Debug, Clone, PartialEq, Eq)]
387pub enum PrimitiveValueType {
388    Bool,
389    S8,
390    U8,
391    S16,
392    U16,
393    S32,
394    U32,
395    S64,
396    U64,
397    F32,
398    F64,
399    Chr,
400    Str,
401    ErrorContext,
402}
403
404#[derive(Debug, Clone, PartialEq, Eq)]
405pub enum ComponentValType {
406    Primitive(PrimitiveValueType),
407    Defined(ComponentTypeIdx),
408}
409
410#[derive(Debug, Clone, PartialEq, Eq)]
411pub enum TypeBounds {
412    Eq(ComponentTypeIdx),
413    SubResource,
414}
415
416#[derive(Debug, Clone, PartialEq, Eq)]
417pub enum ComponentTypeRef {
418    Module(ComponentTypeIdx),
419    Func(ComponentTypeIdx),
420    Val(ComponentValType),
421    Type(TypeBounds),
422    Instance(ComponentTypeIdx),
423    Component(ComponentTypeIdx),
424}
425
426#[derive(Debug, Clone, PartialEq, Eq)]
427pub struct ComponentExport {
428    pub name: ComponentExternName,
429    pub kind: ComponentExternalKind,
430    pub idx: u32,
431    pub desc: Option<ComponentTypeRef>,
432}
433
434impl Section<ComponentIndexSpace, ComponentSectionType> for ComponentExport {
435    fn index_space(&self) -> ComponentIndexSpace {
436        match self.kind {
437            ComponentExternalKind::Module => ComponentIndexSpace::Module,
438            ComponentExternalKind::Func => ComponentIndexSpace::Func,
439            ComponentExternalKind::Value => ComponentIndexSpace::Value,
440            ComponentExternalKind::Type => ComponentIndexSpace::Type,
441            ComponentExternalKind::Instance => ComponentIndexSpace::Instance,
442            ComponentExternalKind::Component => ComponentIndexSpace::Component,
443        }
444    }
445
446    fn section_type(&self) -> ComponentSectionType {
447        ComponentSectionType::Export
448    }
449}
450
451#[derive(Debug, Clone, PartialEq, Eq)]
452pub struct AliasTarget {
453    pub count: u32,
454    pub index: u32,
455}
456
457#[derive(Debug, Clone, PartialEq, Eq)]
458pub enum Alias {
459    InstanceExport {
460        kind: ComponentExternalKind,
461        instance_idx: InstanceIdx,
462        name: String,
463    },
464    CoreInstanceExport {
465        kind: ExportKind,
466        instance_idx: InstanceIdx,
467        name: String,
468    },
469    Outer {
470        kind: OuterAliasKind,
471        target: AliasTarget,
472    },
473}
474
475impl Section<ComponentIndexSpace, ComponentSectionType> for Alias {
476    fn index_space(&self) -> ComponentIndexSpace {
477        match self {
478            Alias::InstanceExport {
479                kind: ComponentExternalKind::Component,
480                ..
481            } => ComponentIndexSpace::Component,
482            Alias::InstanceExport {
483                kind: ComponentExternalKind::Func,
484                ..
485            } => ComponentIndexSpace::Func,
486            Alias::InstanceExport {
487                kind: ComponentExternalKind::Instance,
488                ..
489            } => ComponentIndexSpace::Instance,
490            Alias::InstanceExport {
491                kind: ComponentExternalKind::Module,
492                ..
493            } => ComponentIndexSpace::Module,
494            Alias::InstanceExport {
495                kind: ComponentExternalKind::Type,
496                ..
497            } => ComponentIndexSpace::Type,
498            Alias::InstanceExport {
499                kind: ComponentExternalKind::Value,
500                ..
501            } => ComponentIndexSpace::Value,
502            Alias::CoreInstanceExport {
503                kind: ExportKind::Func,
504                ..
505            } => ComponentIndexSpace::CoreFunc,
506            Alias::CoreInstanceExport {
507                kind: ExportKind::Global,
508                ..
509            } => ComponentIndexSpace::CoreGlobal,
510            Alias::CoreInstanceExport {
511                kind: ExportKind::Mem,
512                ..
513            } => ComponentIndexSpace::CoreMem,
514            Alias::CoreInstanceExport {
515                kind: ExportKind::Table,
516                ..
517            } => ComponentIndexSpace::CoreTable,
518            Alias::Outer {
519                kind: OuterAliasKind::Component,
520                ..
521            } => ComponentIndexSpace::Component,
522            Alias::Outer {
523                kind: OuterAliasKind::CoreType,
524                ..
525            } => ComponentIndexSpace::CoreType,
526            Alias::Outer {
527                kind: OuterAliasKind::Type,
528                ..
529            } => ComponentIndexSpace::Type,
530            Alias::Outer {
531                kind: OuterAliasKind::CoreModule,
532                ..
533            } => ComponentIndexSpace::Module,
534        }
535    }
536
537    fn section_type(&self) -> ComponentSectionType {
538        ComponentSectionType::Alias
539    }
540}
541
542#[derive(Debug, Clone, PartialEq, Eq)]
543pub enum CanonicalOption {
544    Utf8,
545    Utf16,
546    CompactUtf16,
547    Memory(MemIdx),
548    Realloc(FuncIdx),
549    PostReturn(FuncIdx),
550    Async,
551    Callback(FuncIdx),
552}
553
554#[derive(Debug, Clone, PartialEq, Eq)]
555pub enum Canon {
556    Lift {
557        func_idx: FuncIdx,
558        opts: Vec<CanonicalOption>,
559        function_type: ComponentTypeIdx,
560    },
561    Lower {
562        func_idx: ComponentFuncIdx,
563        opts: Vec<CanonicalOption>,
564    },
565    ResourceNew {
566        type_idx: ComponentTypeIdx,
567    },
568    ResourceDrop {
569        type_idx: ComponentTypeIdx,
570    },
571    ResourceRep {
572        type_idx: ComponentTypeIdx,
573    },
574}
575
576impl Section<ComponentIndexSpace, ComponentSectionType> for Canon {
577    fn index_space(&self) -> ComponentIndexSpace {
578        match self {
579            Canon::Lift { .. } => ComponentIndexSpace::Func,
580            Canon::Lower { .. } => ComponentIndexSpace::CoreFunc,
581            Canon::ResourceNew { .. } => ComponentIndexSpace::CoreFunc,
582            Canon::ResourceDrop { .. } => ComponentIndexSpace::CoreFunc,
583            Canon::ResourceRep { .. } => ComponentIndexSpace::CoreFunc,
584        }
585    }
586
587    fn section_type(&self) -> ComponentSectionType {
588        ComponentSectionType::Canon
589    }
590}
591
592#[derive(Debug, Clone, PartialEq, Eq)]
593pub struct ComponentStart {
594    func_idx: ComponentFuncIdx,
595    args: Vec<ValueIdx>,
596    results: u32,
597}
598
599impl Section<ComponentIndexSpace, ComponentSectionType> for ComponentStart {
600    fn index_space(&self) -> ComponentIndexSpace {
601        ComponentIndexSpace::Start
602    }
603
604    fn section_type(&self) -> ComponentSectionType {
605        ComponentSectionType::Start
606    }
607}
608
609#[derive(Debug, Clone, PartialEq, Eq)]
610pub struct ComponentImport {
611    pub name: ComponentExternName,
612    pub desc: ComponentTypeRef,
613}
614
615impl Section<ComponentIndexSpace, ComponentSectionType> for ComponentImport {
616    fn index_space(&self) -> ComponentIndexSpace {
617        match self.desc {
618            ComponentTypeRef::Module(_) => ComponentIndexSpace::Module,
619            ComponentTypeRef::Func(_) => ComponentIndexSpace::Func,
620            ComponentTypeRef::Val(_) => ComponentIndexSpace::Value,
621            ComponentTypeRef::Type(_) => ComponentIndexSpace::Type,
622            ComponentTypeRef::Instance(_) => ComponentIndexSpace::Instance,
623            ComponentTypeRef::Component(_) => ComponentIndexSpace::Component,
624        }
625    }
626
627    fn section_type(&self) -> ComponentSectionType {
628        ComponentSectionType::Import
629    }
630}
631
632#[derive(Debug, Clone, PartialEq, Eq)]
633pub enum ModuleDeclaration {
634    Type {
635        typ: FuncType,
636    },
637    Export {
638        name: String,
639        desc: TypeRef,
640    },
641    OuterAlias {
642        kind: OuterAliasKind,
643        target: AliasTarget,
644    },
645    Import {
646        import: Import,
647    },
648}
649
650#[derive(Debug, Clone, PartialEq, Eq)]
651pub enum CoreType {
652    Function(FuncType),
653    Module(Vec<ModuleDeclaration>),
654}
655
656impl Section<ComponentIndexSpace, ComponentSectionType> for CoreType {
657    fn index_space(&self) -> ComponentIndexSpace {
658        ComponentIndexSpace::CoreType
659    }
660
661    fn section_type(&self) -> ComponentSectionType {
662        ComponentSectionType::CoreType
663    }
664}
665
666#[derive(Debug, Clone, PartialEq, Eq)]
667pub struct VariantCase {
668    pub name: String,
669    pub typ: Option<ComponentValType>,
670    /// The index of the variant case that is refined by this one.
671    pub refines: Option<u32>,
672}
673
674#[derive(Debug, Clone, PartialEq, Eq)]
675pub enum ComponentDefinedType {
676    Primitive {
677        typ: PrimitiveValueType,
678    },
679    Record {
680        fields: Vec<(String, ComponentValType)>,
681    },
682    Variant {
683        cases: Vec<VariantCase>,
684    },
685    List {
686        elem: ComponentValType,
687    },
688    Tuple {
689        elems: Vec<ComponentValType>,
690    },
691    Flags {
692        names: Vec<String>,
693    },
694    Enum {
695        names: Vec<String>,
696    },
697    Option {
698        typ: ComponentValType,
699    },
700    Result {
701        ok: Option<ComponentValType>,
702        err: Option<ComponentValType>,
703    },
704    Owned {
705        type_idx: ComponentTypeIdx,
706    },
707    Borrowed {
708        type_idx: ComponentTypeIdx,
709    },
710    Future {
711        inner: Option<ComponentValType>,
712    },
713    Stream {
714        inner: Option<ComponentValType>,
715    },
716}
717
718#[derive(Debug, Clone, PartialEq, Eq)]
719pub struct ComponentFuncType {
720    pub params: Vec<(String, ComponentValType)>,
721    pub result: Option<ComponentValType>,
722}
723
724#[derive(Debug, Clone, PartialEq, Eq)]
725pub enum ComponentTypeDeclaration {
726    Core(CoreType),
727    Type(ComponentType),
728    Alias(Alias),
729    Import(ComponentImport),
730    Export {
731        name: ComponentExternName,
732        desc: ComponentTypeRef,
733    },
734}
735
736#[derive(Debug, Clone, PartialEq, Eq)]
737pub struct ComponentTypeDeclarations(Vec<ComponentTypeDeclaration>);
738
739impl ComponentTypeDeclarations {}
740
741#[derive(Debug, Clone, PartialEq, Eq)]
742pub enum InstanceTypeDeclaration {
743    Core(CoreType),
744    Type(ComponentType),
745    Alias(Alias),
746    Export {
747        name: ComponentExternName,
748        desc: ComponentTypeRef,
749    },
750}
751
752#[derive(Debug, Clone, PartialEq, Eq)]
753pub struct InstanceTypeDeclarations(Vec<InstanceTypeDeclaration>);
754
755impl InstanceTypeDeclarations {
756    pub fn find_export(&self, name: &str) -> Option<&ComponentTypeRef> {
757        self.0.iter().find_map(|decl| match decl {
758            InstanceTypeDeclaration::Export {
759                name: ComponentExternName::Name(n),
760                desc,
761            } if n == name => Some(desc),
762            _ => None,
763        })
764    }
765
766    pub fn get_component_type(
767        &self,
768        component_type_idx: ComponentTypeIdx,
769    ) -> Option<&InstanceTypeDeclaration> {
770        let mut idx = 0;
771        let mut result = None;
772        for decl in &self.0 {
773            match decl {
774                InstanceTypeDeclaration::Type(_)
775                | InstanceTypeDeclaration::Alias(Alias::Outer {
776                    kind: OuterAliasKind::Type,
777                    ..
778                })
779                | InstanceTypeDeclaration::Alias(Alias::InstanceExport {
780                    kind: ComponentExternalKind::Type,
781                    ..
782                })
783                | InstanceTypeDeclaration::Export {
784                    desc: ComponentTypeRef::Type(_),
785                    ..
786                } => {
787                    if component_type_idx == idx {
788                        result = Some(decl);
789                        break;
790                    } else {
791                        idx += 1;
792                    }
793                }
794                _ => {}
795            }
796        }
797        result
798    }
799}
800
801#[derive(Debug, Clone, PartialEq, Eq)]
802pub enum ComponentType {
803    Defined(ComponentDefinedType),
804    Func(ComponentFuncType),
805    Component(ComponentTypeDeclarations),
806    Instance(InstanceTypeDeclarations),
807    Resource {
808        representation: ValType,
809        destructor: Option<ComponentFuncIdx>,
810    },
811}
812
813impl Section<ComponentIndexSpace, ComponentSectionType> for ComponentType {
814    fn index_space(&self) -> ComponentIndexSpace {
815        ComponentIndexSpace::Type
816    }
817
818    fn section_type(&self) -> ComponentSectionType {
819        ComponentSectionType::Type
820    }
821}
822
823impl Section<ComponentIndexSpace, ComponentSectionType> for Custom {
824    fn index_space(&self) -> ComponentIndexSpace {
825        ComponentIndexSpace::Custom
826    }
827
828    fn section_type(&self) -> ComponentSectionType {
829        ComponentSectionType::Custom
830    }
831}
832
833type ComponentSectionCache<T, Ast> =
834    SectionCache<T, ComponentIndexSpace, ComponentSectionType, ComponentSection<Ast>>;
835
836type ComponentSectionIndex<Ast> =
837    SectionIndex<ComponentIndexSpace, ComponentSectionType, ComponentSection<Ast>>;
838
839/// The top level node of the Component Model AST
840pub struct Component<Ast: AstCustomization + 'static> {
841    sections: Sections<ComponentIndexSpace, ComponentSectionType, ComponentSection<Ast>>,
842
843    imports: ComponentSectionCache<ComponentImport, Ast>,
844    exports: ComponentSectionCache<ComponentExport, Ast>,
845    core_instances: ComponentSectionCache<Instance, Ast>,
846    instances: ComponentSectionCache<ComponentInstance, Ast>,
847    component_types: ComponentSectionCache<ComponentType, Ast>,
848    core_types: ComponentSectionCache<CoreType, Ast>,
849    canons: ComponentSectionCache<Canon, Ast>,
850    aliases: ComponentSectionCache<Alias, Ast>,
851    components: ComponentSectionCache<Component<Ast>, Ast>,
852    modules: ComponentSectionCache<Module<Ast>, Ast>,
853    customs: ComponentSectionCache<Ast::Custom, Ast>,
854
855    core_instance_index: ComponentSectionIndex<Ast>,
856    instance_index: ComponentSectionIndex<Ast>,
857    component_type_index: ComponentSectionIndex<Ast>,
858    core_func_index: ComponentSectionIndex<Ast>,
859    component_index: ComponentSectionIndex<Ast>,
860    component_func_index: ComponentSectionIndex<Ast>,
861    value_index: ComponentSectionIndex<Ast>,
862    module_index: ComponentSectionIndex<Ast>,
863}
864
865#[cfg(feature = "parser")]
866impl<Ast> Component<Ast>
867where
868    Ast: AstCustomization,
869    Ast::Expr: TryFromExprSource,
870    Ast::Data: From<Data<Ast::Expr>>,
871    Ast::Custom: From<Custom>,
872{
873    /// Parses a Component Model AST from the binary WASM byte array
874    pub fn from_bytes(bytes: &[u8]) -> Result<Self, String> {
875        let parser = wasmparser::Parser::new(0);
876        let (component, _) = parse_component(parser, bytes)?;
877        Ok(component)
878    }
879}
880
881#[cfg(feature = "writer")]
882impl<Ast> Component<Ast>
883where
884    Ast: AstCustomization,
885    Ast::Expr: RetainsInstructions,
886    Ast::Data: Into<Data<Ast::Expr>>,
887    Ast::Custom: Into<Custom>,
888{
889    /// Serializes a WASM Component into a binary WASM byte array
890    pub fn into_bytes(self) -> Result<Vec<u8>, String> {
891        let encoder: wasm_encoder::Component = self.try_into()?;
892        Ok(encoder.finish())
893    }
894}
895
896impl<Ast: AstCustomization> Component<Ast> {
897    /// Creates an empty component
898    pub fn empty() -> Self {
899        Self::new(Sections::new())
900    }
901
902    pub(crate) fn new(
903        sections: Sections<ComponentIndexSpace, ComponentSectionType, ComponentSection<Ast>>,
904    ) -> Self {
905        Self {
906            sections,
907
908            imports: new_component_section_cache!(Import),
909            exports: new_component_section_cache!(Export),
910            core_instances: new_component_section_cache!(CoreInstance),
911            instances: new_component_section_cache!(Instance),
912            component_types: new_component_section_cache!(Type),
913            core_types: new_component_section_cache!(CoreType),
914            canons: new_component_section_cache!(Canon),
915            aliases: new_component_section_cache!(Alias),
916            components: new_component_section_cache!(Component),
917            modules: new_component_section_cache!(Module),
918            customs: new_component_section_cache!(Custom),
919            core_instance_index: SectionIndex::new(ComponentIndexSpace::CoreInstance),
920            instance_index: SectionIndex::new(ComponentIndexSpace::Instance),
921            component_type_index: SectionIndex::new(ComponentIndexSpace::Type),
922            core_func_index: SectionIndex::new(ComponentIndexSpace::CoreFunc),
923            component_index: SectionIndex::new(ComponentIndexSpace::Component),
924            component_func_index: SectionIndex::new(ComponentIndexSpace::Func),
925            value_index: SectionIndex::new(ComponentIndexSpace::Value),
926            module_index: SectionIndex::new(ComponentIndexSpace::Module),
927        }
928    }
929
930    /// Gets all the imports defined in this component
931    pub fn imports(&self) -> Vec<Mrc<ComponentImport>> {
932        self.imports.populate(&self.sections);
933        self.imports.all()
934    }
935
936    /// Gets all the exports defined in this component
937    pub fn exports(&self) -> Vec<Mrc<ComponentExport>> {
938        self.exports.populate(&self.sections);
939        self.exports.all()
940    }
941
942    /// Gets all the core instances defined in this component
943    pub fn core_instances(&self) -> Vec<Mrc<Instance>> {
944        self.core_instances.populate(&self.sections);
945        self.core_instances.all()
946    }
947
948    /// Gets all the component instances defined in this component
949    pub fn instances(&self) -> Vec<Mrc<ComponentInstance>> {
950        self.instances.populate(&self.sections);
951        self.instances.all()
952    }
953
954    /// Gets all the component types defined in this component
955    pub fn component_types(&self) -> Vec<Mrc<ComponentType>> {
956        self.component_types.populate(&self.sections);
957        self.component_types.all()
958    }
959
960    /// Gets all the core types defined in this component
961    pub fn core_types(&self) -> Vec<Mrc<CoreType>> {
962        self.core_types.populate(&self.sections);
963        self.core_types.all()
964    }
965
966    /// Gets all the canonical function definitions of this component
967    pub fn canons(&self) -> Vec<Mrc<Canon>> {
968        self.canons.populate(&self.sections);
969        self.canons.all()
970    }
971
972    /// Gets all the aliases defined in this component
973    pub fn aliases(&self) -> Vec<Mrc<Alias>> {
974        self.aliases.populate(&self.sections);
975        self.aliases.all()
976    }
977
978    /// Gets all the inner components defined in this component
979    pub fn components(&self) -> Vec<Mrc<Component<Ast>>> {
980        self.components.populate(&self.sections);
981        self.components.all()
982    }
983
984    /// Gets all the inner core modules defined in this component
985    pub fn modules(&self) -> Vec<Mrc<Module<Ast>>> {
986        self.modules.populate(&self.sections);
987        self.modules.all()
988    }
989
990    /// Gets all the custom sections defined in this component
991    pub fn customs(&self) -> Vec<Mrc<Ast::Custom>> {
992        self.customs.populate(&self.sections);
993        self.customs.all()
994    }
995
996    /// Returns the core instance referenced by the given index.
997    pub fn get_core_instance(&self, core_instance_idx: CoreInstanceIdx) -> Option<Mrc<Instance>> {
998        self.core_instance_index.populate(&self.sections);
999        match self.core_instance_index.get(&core_instance_idx) {
1000            Some(section) => match &*section {
1001                ComponentSection::CoreInstance(_) => {
1002                    Some(Mrc::map(section, |section| section.as_core_instance()))
1003                }
1004                _ => None,
1005            },
1006            _ => None,
1007        }
1008    }
1009
1010    /// Returns the component instance referenced by the given index.
1011    pub fn get_instance_wrapped(
1012        &self,
1013        instance_idx: InstanceIdx,
1014    ) -> Option<Mrc<ComponentSection<Ast>>> {
1015        self.instance_index.populate(&self.sections);
1016        self.instance_index.get(&instance_idx)
1017    }
1018
1019    /// Returns the component instance referenced by the given index.
1020    pub fn get_instance(&self, instance_idx: InstanceIdx) -> Option<Mrc<ComponentInstance>> {
1021        match self.get_instance_wrapped(instance_idx) {
1022            Some(section) => match &*section {
1023                ComponentSection::Instance(_) => {
1024                    Some(Mrc::map(section, |section| section.as_instance()))
1025                }
1026                _ => None,
1027            },
1028            _ => None,
1029        }
1030    }
1031
1032    /// Returns the component type referenced by the given index.
1033    ///
1034    /// It can be one of the following section types:
1035    /// - ComponentType
1036    /// - Alias
1037    /// - ComponentExport
1038    /// - ComponentImport
1039    pub fn get_component_type(
1040        &self,
1041        component_type_idx: ComponentTypeIdx,
1042    ) -> Option<Mrc<ComponentSection<Ast>>> {
1043        self.component_type_index.populate(&self.sections);
1044        self.component_type_index.get(&component_type_idx)
1045    }
1046
1047    /// Returns the core function referenced by the given index.
1048    ///
1049    /// It can be one of the following section types:
1050    /// - Canon
1051    /// - Alias
1052    pub fn get_core_func(&self, core_func_idx: FuncIdx) -> Option<Mrc<ComponentSection<Ast>>> {
1053        self.core_func_index.populate(&self.sections);
1054        self.core_func_index.get(&core_func_idx)
1055    }
1056
1057    /// Returns the component referenced by the given index.
1058    ///
1059    /// It can be one of the following section types:
1060    /// - Component
1061    /// - Alias
1062    /// - ComponentExport
1063    /// - ComponentImport
1064    pub fn get_component(&self, component_idx: ComponentIdx) -> Option<Mrc<ComponentSection<Ast>>> {
1065        self.component_index.populate(&self.sections);
1066        self.component_index.get(&component_idx)
1067    }
1068
1069    /// Returns the component function referenced by the given index.
1070    ///
1071    /// It can be one of the following section types:
1072    /// - Canon
1073    /// - Alias
1074    /// - ComponentExport
1075    /// - ComponentImport
1076    pub fn get_component_func(
1077        &self,
1078        component_func_idx: ComponentFuncIdx,
1079    ) -> Option<Mrc<ComponentSection<Ast>>> {
1080        self.component_func_index.populate(&self.sections);
1081        self.component_func_index.get(&component_func_idx)
1082    }
1083
1084    /// Returns the value referenced by the given index.
1085    ///
1086    /// It can be one of the following section types:
1087    /// - Alias
1088    /// - ComponentExport
1089    /// - ComponentImport
1090    pub fn get_value(&self, value_idx: ValueIdx) -> Option<Mrc<ComponentSection<Ast>>> {
1091        self.value_index.populate(&self.sections);
1092        self.value_index.get(&value_idx)
1093    }
1094
1095    /// Returns the module referenced by the given index.
1096    ///
1097    /// It can be one of the following section types:
1098    /// - Module
1099    /// - Alias
1100    /// - ComponentExport
1101    /// - ComponentImport
1102    pub fn get_module(&self, module_idx: ModuleIdx) -> Option<Mrc<ComponentSection<Ast>>> {
1103        self.module_index.populate(&self.sections);
1104        self.module_index.get(&module_idx)
1105    }
1106
1107    /// Converts this component into a sequence of component sections.
1108    pub fn into_sections(mut self) -> Vec<Mrc<ComponentSection<Ast>>> {
1109        self.sections.take_all()
1110    }
1111
1112    /// Converts this component into a sequence of grouped component sections, exactly as it would be in the binary WASM format.
1113    pub fn into_grouped(self) -> Vec<(ComponentSectionType, Vec<Mrc<ComponentSection<Ast>>>)> {
1114        self.sections.into_grouped()
1115    }
1116}
1117
1118impl<Ast> Component<Ast>
1119where
1120    Ast: AstCustomization,
1121    Ast::Custom: RetainsCustomSection,
1122{
1123    #[cfg(feature = "metadata")]
1124    pub fn get_metadata(&self) -> Option<metadata::Metadata> {
1125        let mut producers = None;
1126        let mut name = None;
1127
1128        for custom in self.customs() {
1129            if custom.name() == "producers" {
1130                producers = wasm_metadata::Producers::from_bytes(custom.data(), 0).ok();
1131            } else if custom.name() == "name" {
1132                name = wasm_metadata::ModuleNames::from_bytes(custom.data(), 0)
1133                    .ok()
1134                    .and_then(|n| n.get_name().cloned());
1135            } else if custom.name() == "component-name" {
1136                name = wasm_metadata::ModuleNames::from_bytes(custom.data(), 0)
1137                    .ok()
1138                    .and_then(|n| n.get_name().cloned());
1139            }
1140        }
1141
1142        if producers.is_some() || name.is_some() {
1143            Some(metadata::Metadata {
1144                name,
1145                producers: producers.map(|p| p.into()),
1146            })
1147        } else {
1148            None
1149        }
1150    }
1151
1152    /// Collects all the producers sections from this component and its subsections
1153    #[cfg(feature = "metadata")]
1154    pub fn get_all_producers(&self) -> Vec<metadata::Producers> {
1155        let mut result = Vec::new();
1156        if let Some(producers) = self.get_metadata().and_then(|m| m.producers) {
1157            result.push(producers);
1158        }
1159        for module in self.modules() {
1160            if let Some(producers) = module.get_metadata().and_then(|m| m.producers) {
1161                result.push(producers);
1162            }
1163        }
1164        for component in self.components() {
1165            result.append(&mut component.get_all_producers());
1166        }
1167        result
1168    }
1169}
1170
1171impl<Ast: AstCustomization>
1172    From<Sections<ComponentIndexSpace, ComponentSectionType, ComponentSection<Ast>>>
1173    for Component<Ast>
1174{
1175    fn from(
1176        value: Sections<ComponentIndexSpace, ComponentSectionType, ComponentSection<Ast>>,
1177    ) -> Self {
1178        Component::new(value)
1179    }
1180}
1181
1182impl<Ast: AstCustomization> PartialEq for Component<Ast> {
1183    fn eq(&self, other: &Self) -> bool {
1184        self.sections.eq(&other.sections)
1185    }
1186}
1187
1188impl<Ast: AstCustomization> Debug for Component<Ast> {
1189    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1190        self.sections.fmt(f)
1191    }
1192}
1193
1194impl<Ast: AstCustomization> Clone for Component<Ast> {
1195    fn clone(&self) -> Self {
1196        Component::new(self.sections.clone())
1197    }
1198}
1199
1200impl<Ast: AstCustomization> Section<ComponentIndexSpace, ComponentSectionType> for Component<Ast> {
1201    fn index_space(&self) -> ComponentIndexSpace {
1202        ComponentIndexSpace::Component
1203    }
1204
1205    fn section_type(&self) -> ComponentSectionType {
1206        ComponentSectionType::Component
1207    }
1208}