golem_wasm_ast/component/
parser.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
15use crate::component::*;
16use crate::core::{Data, TryFromExprSource};
17use crate::Sections;
18use wasmparser::{CanonicalFunction, Chunk, Parser, Payload};
19
20impl TryFrom<wasmparser::InstantiationArg<'_>> for InstantiationArg {
21    type Error = String;
22
23    fn try_from(value: wasmparser::InstantiationArg) -> Result<Self, Self::Error> {
24        let arg_ref = match value.kind {
25            wasmparser::InstantiationArgKind::Instance => {
26                InstantiationArgRef::Instance(value.index)
27            }
28        };
29        Ok(InstantiationArg {
30            name: value.name.to_string(),
31            arg_ref,
32        })
33    }
34}
35
36impl TryFrom<wasmparser::Instance<'_>> for Instance {
37    type Error = String;
38
39    fn try_from(value: wasmparser::Instance) -> Result<Self, Self::Error> {
40        match value {
41            wasmparser::Instance::Instantiate { module_index, args } => Ok(Instance::Instantiate {
42                module_idx: module_index,
43                args: args
44                    .iter()
45                    .map(|arg| arg.clone().try_into())
46                    .collect::<Result<Vec<_>, String>>()?,
47            }),
48            wasmparser::Instance::FromExports(exports) => Ok(Instance::FromExports {
49                exports: exports
50                    .iter()
51                    .map(|&export| export.try_into())
52                    .collect::<Result<Vec<_>, String>>()?,
53            }),
54        }
55    }
56}
57
58impl TryFrom<wasmparser::OuterAliasKind> for OuterAliasKind {
59    type Error = String;
60
61    fn try_from(value: wasmparser::OuterAliasKind) -> Result<Self, Self::Error> {
62        match value {
63            wasmparser::OuterAliasKind::Type => Ok(OuterAliasKind::Type),
64        }
65    }
66}
67
68impl TryFrom<wasmparser::ModuleTypeDeclaration<'_>> for ModuleDeclaration {
69    type Error = String;
70
71    fn try_from(value: wasmparser::ModuleTypeDeclaration) -> Result<Self, Self::Error> {
72        match value {
73            wasmparser::ModuleTypeDeclaration::Type(recgroup) => {
74                let subtype = recgroup.into_types().next().ok_or("Empty rec group")?;
75                Ok(ModuleDeclaration::Type {
76                    typ: subtype.try_into()?,
77                })
78            }
79            wasmparser::ModuleTypeDeclaration::Export { name, ty } => {
80                Ok(ModuleDeclaration::Export {
81                    name: name.to_string(),
82                    desc: ty.try_into()?,
83                })
84            }
85            wasmparser::ModuleTypeDeclaration::OuterAlias { kind, count, index } => {
86                Ok(ModuleDeclaration::OuterAlias {
87                    kind: kind.try_into()?,
88                    target: AliasTarget { count, index },
89                })
90            }
91            wasmparser::ModuleTypeDeclaration::Import(import) => Ok(ModuleDeclaration::Import {
92                import: import.try_into()?,
93            }),
94        }
95    }
96}
97
98impl TryFrom<wasmparser::SubType> for FuncType {
99    type Error = String;
100
101    fn try_from(value: wasmparser::SubType) -> Result<Self, Self::Error> {
102        if value.is_final {
103            match value.composite_type.inner {
104                wasmparser::CompositeInnerType::Func(func_type) => Ok(func_type.try_into()?),
105                wasmparser::CompositeInnerType::Array(_) => {
106                    Err("GC proposal is not supported".to_string())
107                }
108                wasmparser::CompositeInnerType::Struct(_) => {
109                    Err("GC proposal is not supported".to_string())
110                }
111                wasmparser::CompositeInnerType::Cont(_) => {
112                    Err("Task switching proposal is not supported".to_string())
113                }
114            }
115        } else {
116            Err("GC proposal is not supported".to_string())
117        }
118    }
119}
120
121impl TryFrom<wasmparser::CoreType<'_>> for CoreType {
122    type Error = String;
123
124    fn try_from(value: wasmparser::CoreType) -> Result<Self, Self::Error> {
125        match value {
126            wasmparser::CoreType::Rec(recgroup) => {
127                let subtype = recgroup.into_types().next().ok_or("Empty rec group")?;
128                Ok(CoreType::Function(subtype.try_into()?))
129            }
130            wasmparser::CoreType::Module(module_type_decl) => Ok(CoreType::Module(
131                module_type_decl
132                    .iter()
133                    .map(|module_decl| module_decl.clone().try_into())
134                    .collect::<Result<Vec<_>, String>>()?,
135            )),
136        }
137    }
138}
139
140impl TryFrom<wasmparser::ComponentExternalKind> for ComponentExternalKind {
141    type Error = String;
142
143    fn try_from(value: wasmparser::ComponentExternalKind) -> Result<Self, Self::Error> {
144        match value {
145            wasmparser::ComponentExternalKind::Module => Ok(ComponentExternalKind::Module),
146            wasmparser::ComponentExternalKind::Func => Ok(ComponentExternalKind::Func),
147            wasmparser::ComponentExternalKind::Value => Ok(ComponentExternalKind::Value),
148            wasmparser::ComponentExternalKind::Type => Ok(ComponentExternalKind::Type),
149            wasmparser::ComponentExternalKind::Instance => Ok(ComponentExternalKind::Instance),
150            wasmparser::ComponentExternalKind::Component => Ok(ComponentExternalKind::Component),
151        }
152    }
153}
154
155impl<'a> TryFrom<wasmparser::ComponentInstantiationArg<'a>> for ComponentInstantiationArg {
156    type Error = String;
157
158    fn try_from(value: wasmparser::ComponentInstantiationArg<'a>) -> Result<Self, Self::Error> {
159        Ok(ComponentInstantiationArg {
160            name: value.name.to_string(),
161            kind: value.kind.try_into()?,
162            idx: value.index,
163        })
164    }
165}
166
167impl TryFrom<wasmparser::ComponentExportName<'_>> for ComponentExternName {
168    type Error = String;
169
170    fn try_from(value: wasmparser::ComponentExportName) -> Result<Self, Self::Error> {
171        Ok(ComponentExternName::Name(value.0.to_string()))
172    }
173}
174
175impl TryFrom<wasmparser::PrimitiveValType> for PrimitiveValueType {
176    type Error = String;
177
178    fn try_from(value: wasmparser::PrimitiveValType) -> Result<Self, Self::Error> {
179        match value {
180            wasmparser::PrimitiveValType::Bool => Ok(PrimitiveValueType::Bool),
181            wasmparser::PrimitiveValType::S8 => Ok(PrimitiveValueType::S8),
182            wasmparser::PrimitiveValType::U8 => Ok(PrimitiveValueType::U8),
183            wasmparser::PrimitiveValType::S16 => Ok(PrimitiveValueType::S16),
184            wasmparser::PrimitiveValType::U16 => Ok(PrimitiveValueType::U16),
185            wasmparser::PrimitiveValType::S32 => Ok(PrimitiveValueType::S32),
186            wasmparser::PrimitiveValType::U32 => Ok(PrimitiveValueType::U32),
187            wasmparser::PrimitiveValType::S64 => Ok(PrimitiveValueType::S64),
188            wasmparser::PrimitiveValType::U64 => Ok(PrimitiveValueType::U64),
189            wasmparser::PrimitiveValType::F32 => Ok(PrimitiveValueType::F32),
190            wasmparser::PrimitiveValType::F64 => Ok(PrimitiveValueType::F64),
191            wasmparser::PrimitiveValType::Char => Ok(PrimitiveValueType::Chr),
192            wasmparser::PrimitiveValType::String => Ok(PrimitiveValueType::Str),
193            wasmparser::PrimitiveValType::ErrorContext => Ok(PrimitiveValueType::ErrorContext),
194        }
195    }
196}
197
198impl TryFrom<wasmparser::ComponentValType> for ComponentValType {
199    type Error = String;
200
201    fn try_from(value: wasmparser::ComponentValType) -> Result<Self, Self::Error> {
202        match value {
203            wasmparser::ComponentValType::Primitive(primitive_val_type) => {
204                Ok(ComponentValType::Primitive(primitive_val_type.try_into()?))
205            }
206            wasmparser::ComponentValType::Type(component_type_idx) => {
207                Ok(ComponentValType::Defined(component_type_idx))
208            }
209        }
210    }
211}
212
213impl TryFrom<wasmparser::TypeBounds> for TypeBounds {
214    type Error = String;
215
216    fn try_from(value: wasmparser::TypeBounds) -> Result<Self, Self::Error> {
217        match value {
218            wasmparser::TypeBounds::Eq(component_type_idx) => {
219                Ok(TypeBounds::Eq(component_type_idx))
220            }
221            wasmparser::TypeBounds::SubResource => Ok(TypeBounds::SubResource),
222        }
223    }
224}
225
226impl TryFrom<wasmparser::ComponentTypeRef> for ComponentTypeRef {
227    type Error = String;
228
229    fn try_from(value: wasmparser::ComponentTypeRef) -> Result<Self, Self::Error> {
230        match value {
231            wasmparser::ComponentTypeRef::Module(module_idx) => {
232                Ok(ComponentTypeRef::Module(module_idx))
233            }
234            wasmparser::ComponentTypeRef::Func(func_idx) => Ok(ComponentTypeRef::Func(func_idx)),
235            wasmparser::ComponentTypeRef::Value(component_val_type) => {
236                Ok(ComponentTypeRef::Val(component_val_type.try_into()?))
237            }
238            wasmparser::ComponentTypeRef::Type(type_bounds) => {
239                Ok(ComponentTypeRef::Type(type_bounds.try_into()?))
240            }
241            wasmparser::ComponentTypeRef::Instance(instance_idx) => {
242                Ok(ComponentTypeRef::Instance(instance_idx))
243            }
244            wasmparser::ComponentTypeRef::Component(component_idx) => {
245                Ok(ComponentTypeRef::Component(component_idx))
246            }
247        }
248    }
249}
250
251impl<'a> TryFrom<wasmparser::ComponentExport<'a>> for ComponentExport {
252    type Error = String;
253
254    fn try_from(value: wasmparser::ComponentExport<'a>) -> Result<Self, Self::Error> {
255        Ok(ComponentExport {
256            name: value.name.try_into()?,
257            kind: value.kind.try_into()?,
258            idx: value.index,
259            desc: match value.ty {
260                Some(ty) => Some(ty.try_into()?),
261                None => None,
262            },
263        })
264    }
265}
266
267impl TryFrom<wasmparser::ComponentInstance<'_>> for ComponentInstance {
268    type Error = String;
269
270    fn try_from(value: wasmparser::ComponentInstance) -> Result<Self, Self::Error> {
271        match value {
272            wasmparser::ComponentInstance::Instantiate {
273                component_index,
274                args,
275            } => Ok(ComponentInstance::Instantiate {
276                component_idx: component_index,
277                args: args
278                    .iter()
279                    .map(|arg| arg.clone().try_into())
280                    .collect::<Result<Vec<_>, String>>()?,
281            }),
282            wasmparser::ComponentInstance::FromExports(exports) => {
283                Ok(ComponentInstance::FromExports {
284                    exports: exports
285                        .iter()
286                        .map(|export| export.clone().try_into())
287                        .collect::<Result<Vec<_>, String>>()?,
288                })
289            }
290        }
291    }
292}
293
294impl TryFrom<wasmparser::ExternalKind> for ExportKind {
295    type Error = String;
296
297    fn try_from(value: wasmparser::ExternalKind) -> Result<Self, Self::Error> {
298        match value {
299            wasmparser::ExternalKind::Func => Ok(ExportKind::Func),
300            wasmparser::ExternalKind::Table => Ok(ExportKind::Table),
301            wasmparser::ExternalKind::Memory => Ok(ExportKind::Mem),
302            wasmparser::ExternalKind::Global => Ok(ExportKind::Global),
303            wasmparser::ExternalKind::Tag => {
304                Err("Exception handling proposal is not supported".to_string())
305            }
306        }
307    }
308}
309
310impl TryFrom<wasmparser::ComponentOuterAliasKind> for OuterAliasKind {
311    type Error = String;
312
313    fn try_from(value: wasmparser::ComponentOuterAliasKind) -> Result<Self, Self::Error> {
314        match value {
315            wasmparser::ComponentOuterAliasKind::CoreModule => Ok(OuterAliasKind::CoreModule),
316            wasmparser::ComponentOuterAliasKind::CoreType => Ok(OuterAliasKind::CoreType),
317            wasmparser::ComponentOuterAliasKind::Type => Ok(OuterAliasKind::Type),
318            wasmparser::ComponentOuterAliasKind::Component => Ok(OuterAliasKind::Component),
319        }
320    }
321}
322
323impl<'a> TryFrom<wasmparser::ComponentAlias<'a>> for Alias {
324    type Error = String;
325
326    fn try_from(value: wasmparser::ComponentAlias<'a>) -> Result<Self, Self::Error> {
327        match value {
328            wasmparser::ComponentAlias::InstanceExport {
329                kind,
330                instance_index,
331                name,
332            } => Ok(Alias::InstanceExport {
333                kind: kind.try_into()?,
334                instance_idx: instance_index,
335                name: name.to_string(),
336            }),
337            wasmparser::ComponentAlias::CoreInstanceExport {
338                kind,
339                instance_index,
340                name,
341            } => Ok(Alias::CoreInstanceExport {
342                kind: kind.try_into()?,
343                instance_idx: instance_index,
344                name: name.to_string(),
345            }),
346            wasmparser::ComponentAlias::Outer { kind, count, index } => Ok(Alias::Outer {
347                kind: kind.try_into()?,
348                target: AliasTarget { count, index },
349            }),
350        }
351    }
352}
353
354impl TryFrom<wasmparser::VariantCase<'_>> for VariantCase {
355    type Error = String;
356
357    fn try_from(value: wasmparser::VariantCase) -> Result<Self, Self::Error> {
358        Ok(VariantCase {
359            name: value.name.to_string(),
360            typ: match value.ty {
361                Some(ty) => Some(ty.try_into()?),
362                None => None,
363            },
364            refines: value.refines,
365        })
366    }
367}
368
369impl TryFrom<wasmparser::ComponentDefinedType<'_>> for ComponentDefinedType {
370    type Error = String;
371
372    fn try_from(value: wasmparser::ComponentDefinedType) -> Result<Self, Self::Error> {
373        match value {
374            wasmparser::ComponentDefinedType::Primitive(primitive_val_type) => {
375                Ok(ComponentDefinedType::Primitive {
376                    typ: primitive_val_type.try_into()?,
377                })
378            }
379            wasmparser::ComponentDefinedType::Record(fields) => Ok(ComponentDefinedType::Record {
380                fields: fields
381                    .iter()
382                    .map(|&(name, typ)| typ.try_into().map(|t| (name.to_string(), t)))
383                    .collect::<Result<Vec<_>, String>>()?,
384            }),
385            wasmparser::ComponentDefinedType::Variant(cases) => Ok(ComponentDefinedType::Variant {
386                cases: cases
387                    .iter()
388                    .map(|case| case.clone().try_into())
389                    .collect::<Result<Vec<_>, String>>()?,
390            }),
391            wasmparser::ComponentDefinedType::List(tpe) => Ok(ComponentDefinedType::List {
392                elem: tpe.try_into()?,
393            }),
394            wasmparser::ComponentDefinedType::Tuple(types) => Ok(ComponentDefinedType::Tuple {
395                elems: types
396                    .iter()
397                    .map(|tpe| (*tpe).try_into())
398                    .collect::<Result<Vec<_>, String>>()?,
399            }),
400            wasmparser::ComponentDefinedType::Flags(names) => Ok(ComponentDefinedType::Flags {
401                names: names
402                    .iter()
403                    .map(|name| name.to_string())
404                    .collect::<Vec<_>>(),
405            }),
406            wasmparser::ComponentDefinedType::Enum(names) => Ok(ComponentDefinedType::Enum {
407                names: names
408                    .iter()
409                    .map(|name| name.to_string())
410                    .collect::<Vec<_>>(),
411            }),
412            wasmparser::ComponentDefinedType::Option(tpe) => Ok(ComponentDefinedType::Option {
413                typ: tpe.try_into()?,
414            }),
415            wasmparser::ComponentDefinedType::Result { ok, err } => {
416                Ok(ComponentDefinedType::Result {
417                    ok: match ok {
418                        Some(tpe) => Some(tpe.try_into()?),
419                        None => None,
420                    },
421                    err: match err {
422                        Some(tpe) => Some(tpe.try_into()?),
423                        None => None,
424                    },
425                })
426            }
427            wasmparser::ComponentDefinedType::Own(component_type_idx) => {
428                Ok(ComponentDefinedType::Owned {
429                    type_idx: component_type_idx,
430                })
431            }
432            wasmparser::ComponentDefinedType::Borrow(component_type_idx) => {
433                Ok(ComponentDefinedType::Borrowed {
434                    type_idx: component_type_idx,
435                })
436            }
437            wasmparser::ComponentDefinedType::Future(tpe) => Ok(ComponentDefinedType::Future {
438                inner: tpe.map(|tpe| tpe.try_into()).transpose()?,
439            }),
440            wasmparser::ComponentDefinedType::Stream(tpe) => Ok(ComponentDefinedType::Stream {
441                inner: tpe.map(|tpe| tpe.try_into()).transpose()?,
442            }),
443        }
444    }
445}
446
447impl TryFrom<wasmparser::ComponentFuncType<'_>> for ComponentFuncType {
448    type Error = String;
449
450    fn try_from(value: wasmparser::ComponentFuncType) -> Result<Self, Self::Error> {
451        Ok(ComponentFuncType {
452            params: value
453                .params
454                .iter()
455                .map(|&(name, typ)| typ.try_into().map(|t| (name.to_string(), t)))
456                .collect::<Result<Vec<_>, String>>()?,
457            result: value.result.map(|ty| ty.try_into()).transpose()?,
458        })
459    }
460}
461
462impl TryFrom<wasmparser::ComponentImportName<'_>> for ComponentExternName {
463    type Error = String;
464
465    fn try_from(value: wasmparser::ComponentImportName) -> Result<Self, Self::Error> {
466        Ok(ComponentExternName::Name(value.0.to_string()))
467    }
468}
469
470impl TryFrom<wasmparser::ComponentImport<'_>> for ComponentImport {
471    type Error = String;
472
473    fn try_from(value: wasmparser::ComponentImport) -> Result<Self, Self::Error> {
474        Ok(ComponentImport {
475            name: value.name.try_into()?,
476            desc: value.ty.try_into()?,
477        })
478    }
479}
480
481impl<'a> TryFrom<wasmparser::ComponentTypeDeclaration<'a>> for ComponentTypeDeclaration {
482    type Error = String;
483
484    fn try_from(value: wasmparser::ComponentTypeDeclaration<'a>) -> Result<Self, Self::Error> {
485        match value {
486            wasmparser::ComponentTypeDeclaration::CoreType(core_type) => {
487                Ok(ComponentTypeDeclaration::Core(core_type.try_into()?))
488            }
489            wasmparser::ComponentTypeDeclaration::Type(tpe) => {
490                Ok(ComponentTypeDeclaration::Type(tpe.try_into()?))
491            }
492            wasmparser::ComponentTypeDeclaration::Alias(alias) => {
493                Ok(ComponentTypeDeclaration::Alias(alias.try_into()?))
494            }
495            wasmparser::ComponentTypeDeclaration::Import(import) => {
496                Ok(ComponentTypeDeclaration::Import(import.try_into()?))
497            }
498            wasmparser::ComponentTypeDeclaration::Export { name, ty } => {
499                Ok(ComponentTypeDeclaration::Export {
500                    name: name.try_into()?,
501                    desc: ty.try_into()?,
502                })
503            }
504        }
505    }
506}
507
508impl<'a> TryFrom<wasmparser::InstanceTypeDeclaration<'a>> for InstanceTypeDeclaration {
509    type Error = String;
510
511    fn try_from(value: wasmparser::InstanceTypeDeclaration<'a>) -> Result<Self, Self::Error> {
512        match value {
513            wasmparser::InstanceTypeDeclaration::CoreType(core_type) => {
514                Ok(InstanceTypeDeclaration::Core(core_type.try_into()?))
515            }
516            wasmparser::InstanceTypeDeclaration::Type(tpe) => {
517                Ok(InstanceTypeDeclaration::Type(tpe.try_into()?))
518            }
519            wasmparser::InstanceTypeDeclaration::Alias(alias) => {
520                Ok(InstanceTypeDeclaration::Alias(alias.try_into()?))
521            }
522            wasmparser::InstanceTypeDeclaration::Export { name, ty } => {
523                Ok(InstanceTypeDeclaration::Export {
524                    name: name.try_into()?,
525                    desc: ty.try_into()?,
526                })
527            }
528        }
529    }
530}
531
532impl TryFrom<wasmparser::ComponentType<'_>> for ComponentType {
533    type Error = String;
534
535    fn try_from(value: wasmparser::ComponentType) -> Result<Self, Self::Error> {
536        match value {
537            wasmparser::ComponentType::Defined(component_defined_type) => {
538                Ok(ComponentType::Defined(component_defined_type.try_into()?))
539            }
540            wasmparser::ComponentType::Func(component_func_type) => {
541                Ok(ComponentType::Func(component_func_type.try_into()?))
542            }
543            wasmparser::ComponentType::Component(component_type_decls) => {
544                Ok(ComponentType::Component(ComponentTypeDeclarations(
545                    component_type_decls
546                        .iter()
547                        .map(|component_type_decl| component_type_decl.clone().try_into())
548                        .collect::<Result<Vec<_>, String>>()?,
549                )))
550            }
551            wasmparser::ComponentType::Instance(instancetype_decls) => {
552                Ok(ComponentType::Instance(InstanceTypeDeclarations(
553                    instancetype_decls
554                        .iter()
555                        .map(|instancetype_decl| instancetype_decl.clone().try_into())
556                        .collect::<Result<Vec<_>, String>>()?,
557                )))
558            }
559            wasmparser::ComponentType::Resource { rep, dtor } => Ok(ComponentType::Resource {
560                representation: rep.try_into()?,
561                destructor: dtor,
562            }),
563        }
564    }
565}
566
567impl TryFrom<wasmparser::CanonicalOption> for CanonicalOption {
568    type Error = String;
569
570    fn try_from(value: wasmparser::CanonicalOption) -> Result<Self, Self::Error> {
571        match value {
572            wasmparser::CanonicalOption::UTF8 => Ok(CanonicalOption::Utf8),
573            wasmparser::CanonicalOption::UTF16 => Ok(CanonicalOption::Utf16),
574            wasmparser::CanonicalOption::CompactUTF16 => Ok(CanonicalOption::CompactUtf16),
575            wasmparser::CanonicalOption::Memory(mem_idx) => Ok(CanonicalOption::Memory(mem_idx)),
576            wasmparser::CanonicalOption::Realloc(func_idx) => {
577                Ok(CanonicalOption::Realloc(func_idx))
578            }
579            wasmparser::CanonicalOption::PostReturn(func_idx) => {
580                Ok(CanonicalOption::PostReturn(func_idx))
581            }
582            wasmparser::CanonicalOption::Async => Ok(CanonicalOption::Async),
583            wasmparser::CanonicalOption::Callback(func_idx) => {
584                Ok(CanonicalOption::Callback(func_idx))
585            }
586        }
587    }
588}
589
590impl TryFrom<wasmparser::CanonicalFunction> for Canon {
591    type Error = String;
592
593    fn try_from(value: wasmparser::CanonicalFunction) -> Result<Self, Self::Error> {
594        match value {
595            wasmparser::CanonicalFunction::Lift {
596                core_func_index,
597                type_index,
598                options,
599            } => Ok(Canon::Lift {
600                func_idx: core_func_index,
601                function_type: type_index,
602                opts: options
603                    .iter()
604                    .map(|&opt| opt.try_into())
605                    .collect::<Result<Vec<_>, String>>()?,
606            }),
607            wasmparser::CanonicalFunction::Lower {
608                func_index,
609                options,
610            } => Ok(Canon::Lower {
611                func_idx: func_index,
612                opts: options
613                    .iter()
614                    .map(|&opt| opt.try_into())
615                    .collect::<Result<Vec<_>, String>>()?,
616            }),
617            wasmparser::CanonicalFunction::ResourceNew { resource } => {
618                Ok(Canon::ResourceNew { type_idx: resource })
619            }
620            wasmparser::CanonicalFunction::ResourceDrop { resource } => {
621                Ok(Canon::ResourceDrop { type_idx: resource })
622            }
623            wasmparser::CanonicalFunction::ResourceRep { resource } => {
624                Ok(Canon::ResourceRep { type_idx: resource })
625            }
626            CanonicalFunction::ThreadSpawn { .. } => {
627                Err("Threads proposal is not supported".to_string())
628            }
629            CanonicalFunction::ResourceDropAsync { .. } => {
630                Err("WASI P3 future and stream support is not supported yet".to_string())
631            }
632            CanonicalFunction::ThreadAvailableParallelism => {
633                Err("WASI P3 future and stream support is not supported yet".to_string())
634            }
635            CanonicalFunction::BackpressureSet => {
636                Err("WASI P3 future and stream support is not supported yet".to_string())
637            }
638            CanonicalFunction::TaskReturn { .. } => {
639                Err("WASI P3 future and stream support is not supported yet".to_string())
640            }
641            CanonicalFunction::Yield { .. } => {
642                Err("WASI P3 future and stream support is not supported yet".to_string())
643            }
644            CanonicalFunction::SubtaskDrop => {
645                Err("WASI P3 future and stream support is not supported yet".to_string())
646            }
647            CanonicalFunction::StreamNew { .. } => {
648                Err("WASI P3 future and stream support is not supported yet".to_string())
649            }
650            CanonicalFunction::StreamRead { .. } => {
651                Err("WASI P3 future and stream support is not supported yet".to_string())
652            }
653            CanonicalFunction::StreamWrite { .. } => {
654                Err("WASI P3 future and stream support is not supported yet".to_string())
655            }
656            CanonicalFunction::StreamCancelRead { .. } => {
657                Err("WASI P3 future and stream support is not supported yet".to_string())
658            }
659            CanonicalFunction::StreamCancelWrite { .. } => {
660                Err("WASI P3 future and stream support is not supported yet".to_string())
661            }
662            CanonicalFunction::StreamCloseReadable { .. } => {
663                Err("WASI P3 future and stream support is not supported yet".to_string())
664            }
665            CanonicalFunction::StreamCloseWritable { .. } => {
666                Err("WASI P3 future and stream support is not supported yet".to_string())
667            }
668            CanonicalFunction::FutureNew { .. } => {
669                Err("WASI P3 future and stream support is not supported yet".to_string())
670            }
671            CanonicalFunction::FutureRead { .. } => {
672                Err("WASI P3 future and stream support is not supported yet".to_string())
673            }
674            CanonicalFunction::FutureWrite { .. } => {
675                Err("WASI P3 future and stream support is not supported yet".to_string())
676            }
677            CanonicalFunction::FutureCancelRead { .. } => {
678                Err("WASI P3 future and stream support is not supported yet".to_string())
679            }
680            CanonicalFunction::FutureCancelWrite { .. } => {
681                Err("WASI P3 future and stream support is not supported yet".to_string())
682            }
683            CanonicalFunction::FutureCloseReadable { .. } => {
684                Err("WASI P3 future and stream support is not supported yet".to_string())
685            }
686            CanonicalFunction::FutureCloseWritable { .. } => {
687                Err("WASI P3 future and stream support is not supported yet".to_string())
688            }
689            CanonicalFunction::ErrorContextNew { .. } => {
690                Err("WASI P3 future and stream support is not supported yet".to_string())
691            }
692            CanonicalFunction::ErrorContextDebugMessage { .. } => {
693                Err("WASI P3 future and stream support is not supported yet".to_string())
694            }
695            CanonicalFunction::ErrorContextDrop => {
696                Err("WASI P3 future and stream support is not supported yet".to_string())
697            }
698            CanonicalFunction::WaitableSetNew => {
699                Err("WASI P3 future and stream support is not supported yet".to_string())
700            }
701            CanonicalFunction::WaitableSetWait { .. } => {
702                Err("WASI P3 future and stream support is not supported yet".to_string())
703            }
704            CanonicalFunction::WaitableSetPoll { .. } => {
705                Err("WASI P3 future and stream support is not supported yet".to_string())
706            }
707            CanonicalFunction::WaitableSetDrop => {
708                Err("WASI P3 future and stream support is not supported yet".to_string())
709            }
710            CanonicalFunction::WaitableJoin => {
711                Err("WASI P3 future and stream support is not supported yet".to_string())
712            }
713        }
714    }
715}
716
717impl TryFrom<wasmparser::ComponentStartFunction> for ComponentStart {
718    type Error = String;
719
720    fn try_from(value: wasmparser::ComponentStartFunction) -> Result<Self, Self::Error> {
721        Ok(ComponentStart {
722            func_idx: value.func_index,
723            args: value.arguments.to_vec(),
724            results: value.results,
725        })
726    }
727}
728
729#[allow(clippy::type_complexity)]
730fn parse_component_sections<Ast>(
731    mut parser: Parser,
732    mut remaining: &[u8],
733) -> Result<
734    (
735        Sections<ComponentIndexSpace, ComponentSectionType, ComponentSection<Ast>>,
736        &[u8],
737    ),
738    String,
739>
740where
741    Ast: AstCustomization,
742    Ast::Expr: TryFromExprSource,
743    Ast::Data: From<Data<Ast::Expr>>,
744    Ast::Custom: From<Custom>,
745{
746    let mut sections = Vec::new();
747    loop {
748        let payload = match parser
749            .parse(remaining, true)
750            .map_err(|e| format!("Error parsing core module: {:?}", e))?
751        {
752            Chunk::Parsed { payload, consumed } => {
753                remaining = &remaining[consumed..];
754                payload
755            }
756            Chunk::NeedMoreData { .. } => {
757                return Err("Unexpected end of component binary".to_string());
758            }
759        };
760        match payload {
761            Payload::Version { .. } => {}
762            Payload::TypeSection(_) => {
763                return Err("Unexpected core type section in component".to_string());
764            }
765
766            Payload::ImportSection(_) => {
767                return Err("Unexpected core import section in component".to_string());
768            }
769
770            Payload::FunctionSection(_) => {
771                return Err("Unexpected core function section in component".to_string());
772            }
773
774            Payload::TableSection(_) => {
775                return Err("Unexpected core table section in component".to_string());
776            }
777
778            Payload::MemorySection(_) => {
779                return Err("Unexpected core memory section in component".to_string());
780            }
781
782            Payload::TagSection(_) => {
783                return Err("Unexpected core tag section in component".to_string());
784            }
785            Payload::GlobalSection(_) => {
786                return Err("Unexpected core global section in component".to_string());
787            }
788
789            Payload::ExportSection(_) => {
790                return Err("Unexpected core export section in component".to_string());
791            }
792
793            Payload::StartSection { .. } => {
794                return Err("Unexpected core start section in component".to_string());
795            }
796
797            Payload::ElementSection(_) => {
798                return Err("Unexpected core element section in component".to_string());
799            }
800
801            Payload::DataCountSection { .. } => {
802                return Err("Unexpected core data count section in component".to_string());
803            }
804
805            Payload::DataSection(_) => {
806                return Err("Unexpected core data section in component".to_string());
807            }
808
809            Payload::CodeSectionStart { .. } => {
810                return Err("Unexpected core code section in component".to_string());
811            }
812
813            Payload::CodeSectionEntry(_) => {
814                return Err("Unexpected core code section in component".to_string());
815            }
816
817            Payload::CustomSection(reader) => sections.push(ComponentSection::Custom(
818                Custom {
819                    name: reader.name().to_string(),
820                    data: reader.data().to_vec(),
821                }
822                .into(),
823            )),
824            Payload::End(_) => {
825                break;
826            }
827            Payload::InstanceSection(reader) => {
828                for instance in reader {
829                    let instance = instance.map_err(|e| {
830                        format!("Error parsing component core instance section: {:?}", e)
831                    })?;
832                    sections.push(ComponentSection::CoreInstance(instance.try_into()?))
833                }
834            }
835            Payload::CoreTypeSection(reader) => {
836                for core_type in reader {
837                    let core_type = core_type.map_err(|e| {
838                        format!("Error parsing component core type section: {:?}", e)
839                    })?;
840                    sections.push(ComponentSection::CoreType(core_type.try_into()?))
841                }
842            }
843            Payload::ModuleSection {
844                parser,
845                unchecked_range,
846            } => {
847                let module: Module<Ast> =
848                    (parser, &remaining[..unchecked_range.len()]).try_into()?;
849                remaining = &remaining[(unchecked_range.end - unchecked_range.start)..];
850                sections.push(ComponentSection::Module(module))
851            }
852            Payload::ComponentSection { parser, .. } => {
853                let (component, new_remaining) = parse_component(parser, remaining)?;
854                remaining = new_remaining;
855                sections.push(ComponentSection::Component(component))
856            }
857            Payload::ComponentInstanceSection(reader) => {
858                for component_instance in reader {
859                    let component_instance = component_instance.map_err(|e| {
860                        format!("Error parsing component instance section: {:?}", e)
861                    })?;
862                    sections.push(ComponentSection::Instance(component_instance.try_into()?))
863                }
864            }
865            Payload::ComponentAliasSection(reader) => {
866                for alias in reader {
867                    let alias = alias
868                        .map_err(|e| format!("Error parsing component alias section: {:?}", e))?;
869                    sections.push(ComponentSection::Alias(alias.try_into()?))
870                }
871            }
872            Payload::ComponentTypeSection(reader) => {
873                for component_type in reader {
874                    let component_type = component_type
875                        .map_err(|e| format!("Error parsing component type section: {:?}", e))?;
876                    sections.push(ComponentSection::Type(component_type.try_into()?))
877                }
878            }
879            Payload::ComponentCanonicalSection(reader) => {
880                for canon in reader {
881                    let canon = canon.map_err(|e| {
882                        format!("Error parsing component canonical section: {:?}", e)
883                    })?;
884                    sections.push(ComponentSection::Canon(canon.try_into()?))
885                }
886            }
887            Payload::ComponentStartSection { start, .. } => {
888                sections.push(ComponentSection::Start(start.try_into()?))
889            }
890            Payload::ComponentImportSection(reader) => {
891                for import in reader {
892                    let import = import
893                        .map_err(|e| format!("Error parsing component import section: {:?}", e))?;
894                    sections.push(ComponentSection::Import(import.try_into()?))
895                }
896            }
897            Payload::ComponentExportSection(reader) => {
898                for export in reader {
899                    let export = export
900                        .map_err(|e| format!("Error parsing component export section: {:?}", e))?;
901                    sections.push(ComponentSection::Export(export.try_into()?))
902                }
903            }
904            Payload::UnknownSection { .. } => {
905                return Err("Unexpected unknown section in component".to_string());
906            }
907            _ => {
908                return Err("Unexpected section in component".to_string());
909            }
910        }
911    }
912
913    Ok((Sections::from_flat(sections), remaining))
914}
915
916pub fn parse_component<Ast>(
917    parser: Parser,
918    remaining: &[u8],
919) -> Result<(Component<Ast>, &[u8]), String>
920where
921    Ast: AstCustomization,
922    Ast::Expr: TryFromExprSource,
923    Ast::Data: From<Data<Ast::Expr>>,
924    Ast::Custom: From<Custom>,
925{
926    let (sections, remaining) = parse_component_sections(parser, remaining)?;
927    Ok((sections.into(), remaining))
928}