golem_wasm_ast/component/
parser.rs

1// Copyright 2024-2025 Golem Cloud
2//
3// Licensed under the Golem Source License v1.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://license.golem.cloud/LICENSE
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            wasmparser::ComponentDefinedType::FixedSizeList(_, _) => {
444                Err("Fixed-size lists are not supported".to_string())
445            }
446        }
447    }
448}
449
450impl TryFrom<wasmparser::ComponentFuncType<'_>> for ComponentFuncType {
451    type Error = String;
452
453    fn try_from(value: wasmparser::ComponentFuncType) -> Result<Self, Self::Error> {
454        Ok(ComponentFuncType {
455            params: value
456                .params
457                .iter()
458                .map(|&(name, typ)| typ.try_into().map(|t| (name.to_string(), t)))
459                .collect::<Result<Vec<_>, String>>()?,
460            result: value.result.map(|ty| ty.try_into()).transpose()?,
461        })
462    }
463}
464
465impl TryFrom<wasmparser::ComponentImportName<'_>> for ComponentExternName {
466    type Error = String;
467
468    fn try_from(value: wasmparser::ComponentImportName) -> Result<Self, Self::Error> {
469        Ok(ComponentExternName::Name(value.0.to_string()))
470    }
471}
472
473impl TryFrom<wasmparser::ComponentImport<'_>> for ComponentImport {
474    type Error = String;
475
476    fn try_from(value: wasmparser::ComponentImport) -> Result<Self, Self::Error> {
477        Ok(ComponentImport {
478            name: value.name.try_into()?,
479            desc: value.ty.try_into()?,
480        })
481    }
482}
483
484impl<'a> TryFrom<wasmparser::ComponentTypeDeclaration<'a>> for ComponentTypeDeclaration {
485    type Error = String;
486
487    fn try_from(value: wasmparser::ComponentTypeDeclaration<'a>) -> Result<Self, Self::Error> {
488        match value {
489            wasmparser::ComponentTypeDeclaration::CoreType(core_type) => {
490                Ok(ComponentTypeDeclaration::Core(core_type.try_into()?))
491            }
492            wasmparser::ComponentTypeDeclaration::Type(tpe) => {
493                Ok(ComponentTypeDeclaration::Type(tpe.try_into()?))
494            }
495            wasmparser::ComponentTypeDeclaration::Alias(alias) => {
496                Ok(ComponentTypeDeclaration::Alias(alias.try_into()?))
497            }
498            wasmparser::ComponentTypeDeclaration::Import(import) => {
499                Ok(ComponentTypeDeclaration::Import(import.try_into()?))
500            }
501            wasmparser::ComponentTypeDeclaration::Export { name, ty } => {
502                Ok(ComponentTypeDeclaration::Export {
503                    name: name.try_into()?,
504                    desc: ty.try_into()?,
505                })
506            }
507        }
508    }
509}
510
511impl<'a> TryFrom<wasmparser::InstanceTypeDeclaration<'a>> for InstanceTypeDeclaration {
512    type Error = String;
513
514    fn try_from(value: wasmparser::InstanceTypeDeclaration<'a>) -> Result<Self, Self::Error> {
515        match value {
516            wasmparser::InstanceTypeDeclaration::CoreType(core_type) => {
517                Ok(InstanceTypeDeclaration::Core(core_type.try_into()?))
518            }
519            wasmparser::InstanceTypeDeclaration::Type(tpe) => {
520                Ok(InstanceTypeDeclaration::Type(tpe.try_into()?))
521            }
522            wasmparser::InstanceTypeDeclaration::Alias(alias) => {
523                Ok(InstanceTypeDeclaration::Alias(alias.try_into()?))
524            }
525            wasmparser::InstanceTypeDeclaration::Export { name, ty } => {
526                Ok(InstanceTypeDeclaration::Export {
527                    name: name.try_into()?,
528                    desc: ty.try_into()?,
529                })
530            }
531        }
532    }
533}
534
535impl TryFrom<wasmparser::ComponentType<'_>> for ComponentType {
536    type Error = String;
537
538    fn try_from(value: wasmparser::ComponentType) -> Result<Self, Self::Error> {
539        match value {
540            wasmparser::ComponentType::Defined(component_defined_type) => {
541                Ok(ComponentType::Defined(component_defined_type.try_into()?))
542            }
543            wasmparser::ComponentType::Func(component_func_type) => {
544                Ok(ComponentType::Func(component_func_type.try_into()?))
545            }
546            wasmparser::ComponentType::Component(component_type_decls) => {
547                Ok(ComponentType::Component(ComponentTypeDeclarations(
548                    component_type_decls
549                        .iter()
550                        .map(|component_type_decl| component_type_decl.clone().try_into())
551                        .collect::<Result<Vec<_>, String>>()?,
552                )))
553            }
554            wasmparser::ComponentType::Instance(instancetype_decls) => {
555                Ok(ComponentType::Instance(InstanceTypeDeclarations(
556                    instancetype_decls
557                        .iter()
558                        .map(|instancetype_decl| instancetype_decl.clone().try_into())
559                        .collect::<Result<Vec<_>, String>>()?,
560                )))
561            }
562            wasmparser::ComponentType::Resource { rep, dtor } => Ok(ComponentType::Resource {
563                representation: rep.try_into()?,
564                destructor: dtor,
565            }),
566        }
567    }
568}
569
570impl TryFrom<wasmparser::CanonicalOption> for CanonicalOption {
571    type Error = String;
572
573    fn try_from(value: wasmparser::CanonicalOption) -> Result<Self, Self::Error> {
574        match value {
575            wasmparser::CanonicalOption::UTF8 => Ok(CanonicalOption::Utf8),
576            wasmparser::CanonicalOption::UTF16 => Ok(CanonicalOption::Utf16),
577            wasmparser::CanonicalOption::CompactUTF16 => Ok(CanonicalOption::CompactUtf16),
578            wasmparser::CanonicalOption::Memory(mem_idx) => Ok(CanonicalOption::Memory(mem_idx)),
579            wasmparser::CanonicalOption::Realloc(func_idx) => {
580                Ok(CanonicalOption::Realloc(func_idx))
581            }
582            wasmparser::CanonicalOption::PostReturn(func_idx) => {
583                Ok(CanonicalOption::PostReturn(func_idx))
584            }
585            wasmparser::CanonicalOption::Async => Ok(CanonicalOption::Async),
586            wasmparser::CanonicalOption::Callback(func_idx) => {
587                Ok(CanonicalOption::Callback(func_idx))
588            }
589            wasmparser::CanonicalOption::CoreType(_) => {
590                Err("GC proposal is not supported".to_string())
591            }
592            wasmparser::CanonicalOption::Gc => Err("GC proposal is not supported".to_string()),
593        }
594    }
595}
596
597impl TryFrom<wasmparser::CanonicalFunction> for Canon {
598    type Error = String;
599
600    fn try_from(value: wasmparser::CanonicalFunction) -> Result<Self, Self::Error> {
601        match value {
602            wasmparser::CanonicalFunction::Lift {
603                core_func_index,
604                type_index,
605                options,
606            } => Ok(Canon::Lift {
607                func_idx: core_func_index,
608                function_type: type_index,
609                opts: options
610                    .iter()
611                    .map(|&opt| opt.try_into())
612                    .collect::<Result<Vec<_>, String>>()?,
613            }),
614            wasmparser::CanonicalFunction::Lower {
615                func_index,
616                options,
617            } => Ok(Canon::Lower {
618                func_idx: func_index,
619                opts: options
620                    .iter()
621                    .map(|&opt| opt.try_into())
622                    .collect::<Result<Vec<_>, String>>()?,
623            }),
624            wasmparser::CanonicalFunction::ResourceNew { resource } => {
625                Ok(Canon::ResourceNew { type_idx: resource })
626            }
627            wasmparser::CanonicalFunction::ResourceDrop { resource } => {
628                Ok(Canon::ResourceDrop { type_idx: resource })
629            }
630            wasmparser::CanonicalFunction::ResourceRep { resource } => {
631                Ok(Canon::ResourceRep { type_idx: resource })
632            }
633            CanonicalFunction::ThreadSpawnRef { .. } => {
634                Err("Threads proposal is not supported".to_string())
635            }
636            CanonicalFunction::ResourceDropAsync { .. } => {
637                Err("WASI P3 future and stream support is not supported yet".to_string())
638            }
639            CanonicalFunction::ThreadAvailableParallelism => {
640                Err("WASI P3 future and stream support is not supported yet".to_string())
641            }
642            CanonicalFunction::BackpressureSet => {
643                Err("WASI P3 future and stream support is not supported yet".to_string())
644            }
645            CanonicalFunction::TaskReturn { .. } => {
646                Err("WASI P3 future and stream support is not supported yet".to_string())
647            }
648            CanonicalFunction::Yield { .. } => {
649                Err("WASI P3 future and stream support is not supported yet".to_string())
650            }
651            CanonicalFunction::SubtaskDrop => {
652                Err("WASI P3 future and stream support is not supported yet".to_string())
653            }
654            CanonicalFunction::StreamNew { .. } => {
655                Err("WASI P3 future and stream support is not supported yet".to_string())
656            }
657            CanonicalFunction::StreamRead { .. } => {
658                Err("WASI P3 future and stream support is not supported yet".to_string())
659            }
660            CanonicalFunction::StreamWrite { .. } => {
661                Err("WASI P3 future and stream support is not supported yet".to_string())
662            }
663            CanonicalFunction::StreamCancelRead { .. } => {
664                Err("WASI P3 future and stream support is not supported yet".to_string())
665            }
666            CanonicalFunction::StreamCancelWrite { .. } => {
667                Err("WASI P3 future and stream support is not supported yet".to_string())
668            }
669            CanonicalFunction::StreamDropReadable { .. } => {
670                Err("WASI P3 future and stream support is not supported yet".to_string())
671            }
672            CanonicalFunction::StreamDropWritable { .. } => {
673                Err("WASI P3 future and stream support is not supported yet".to_string())
674            }
675            CanonicalFunction::FutureNew { .. } => {
676                Err("WASI P3 future and stream support is not supported yet".to_string())
677            }
678            CanonicalFunction::FutureRead { .. } => {
679                Err("WASI P3 future and stream support is not supported yet".to_string())
680            }
681            CanonicalFunction::FutureWrite { .. } => {
682                Err("WASI P3 future and stream support is not supported yet".to_string())
683            }
684            CanonicalFunction::FutureCancelRead { .. } => {
685                Err("WASI P3 future and stream support is not supported yet".to_string())
686            }
687            CanonicalFunction::FutureCancelWrite { .. } => {
688                Err("WASI P3 future and stream support is not supported yet".to_string())
689            }
690            CanonicalFunction::FutureDropReadable { .. } => {
691                Err("WASI P3 future and stream support is not supported yet".to_string())
692            }
693            CanonicalFunction::FutureDropWritable { .. } => {
694                Err("WASI P3 future and stream support is not supported yet".to_string())
695            }
696            CanonicalFunction::ErrorContextNew { .. } => {
697                Err("WASI P3 future and stream support is not supported yet".to_string())
698            }
699            CanonicalFunction::ErrorContextDebugMessage { .. } => {
700                Err("WASI P3 future and stream support is not supported yet".to_string())
701            }
702            CanonicalFunction::ErrorContextDrop => {
703                Err("WASI P3 future and stream support is not supported yet".to_string())
704            }
705            CanonicalFunction::WaitableSetNew => {
706                Err("WASI P3 future and stream support is not supported yet".to_string())
707            }
708            CanonicalFunction::WaitableSetWait { .. } => {
709                Err("WASI P3 future and stream support is not supported yet".to_string())
710            }
711            CanonicalFunction::WaitableSetPoll { .. } => {
712                Err("WASI P3 future and stream support is not supported yet".to_string())
713            }
714            CanonicalFunction::WaitableSetDrop => {
715                Err("WASI P3 future and stream support is not supported yet".to_string())
716            }
717            CanonicalFunction::WaitableJoin => {
718                Err("WASI P3 future and stream support is not supported yet".to_string())
719            }
720            CanonicalFunction::ThreadSpawnIndirect { .. } => {
721                Err("Threads proposal is not supported".to_string())
722            }
723            CanonicalFunction::TaskCancel => {
724                Err("WASI P3 future and stream support is not supported yet".to_string())
725            }
726            CanonicalFunction::ContextGet(_) => {
727                Err("WASI P3 future and stream support is not supported yet".to_string())
728            }
729            CanonicalFunction::ContextSet(_) => {
730                Err("WASI P3 future and stream support is not supported yet".to_string())
731            }
732            CanonicalFunction::SubtaskCancel { .. } => {
733                Err("WASI P3 future and stream support is not supported yet".to_string())
734            }
735        }
736    }
737}
738
739impl TryFrom<wasmparser::ComponentStartFunction> for ComponentStart {
740    type Error = String;
741
742    fn try_from(value: wasmparser::ComponentStartFunction) -> Result<Self, Self::Error> {
743        Ok(ComponentStart {
744            func_idx: value.func_index,
745            args: value.arguments.to_vec(),
746            results: value.results,
747        })
748    }
749}
750
751#[allow(clippy::type_complexity)]
752fn parse_component_sections<Ast>(
753    mut parser: Parser,
754    mut remaining: &[u8],
755) -> Result<
756    (
757        Sections<ComponentIndexSpace, ComponentSectionType, ComponentSection<Ast>>,
758        &[u8],
759    ),
760    String,
761>
762where
763    Ast: AstCustomization,
764    Ast::Expr: TryFromExprSource,
765    Ast::Data: From<Data<Ast::Expr>>,
766    Ast::Custom: From<Custom>,
767{
768    let mut sections = Vec::new();
769    loop {
770        let payload = match parser
771            .parse(remaining, true)
772            .map_err(|e| format!("Error parsing core module: {e:?}"))?
773        {
774            Chunk::Parsed { payload, consumed } => {
775                remaining = &remaining[consumed..];
776                payload
777            }
778            Chunk::NeedMoreData { .. } => {
779                return Err("Unexpected end of component binary".to_string());
780            }
781        };
782        match payload {
783            Payload::Version { .. } => {}
784            Payload::TypeSection(_) => {
785                return Err("Unexpected core type section in component".to_string());
786            }
787
788            Payload::ImportSection(_) => {
789                return Err("Unexpected core import section in component".to_string());
790            }
791
792            Payload::FunctionSection(_) => {
793                return Err("Unexpected core function section in component".to_string());
794            }
795
796            Payload::TableSection(_) => {
797                return Err("Unexpected core table section in component".to_string());
798            }
799
800            Payload::MemorySection(_) => {
801                return Err("Unexpected core memory section in component".to_string());
802            }
803
804            Payload::TagSection(_) => {
805                return Err("Unexpected core tag section in component".to_string());
806            }
807            Payload::GlobalSection(_) => {
808                return Err("Unexpected core global section in component".to_string());
809            }
810
811            Payload::ExportSection(_) => {
812                return Err("Unexpected core export section in component".to_string());
813            }
814
815            Payload::StartSection { .. } => {
816                return Err("Unexpected core start section in component".to_string());
817            }
818
819            Payload::ElementSection(_) => {
820                return Err("Unexpected core element section in component".to_string());
821            }
822
823            Payload::DataCountSection { .. } => {
824                return Err("Unexpected core data count section in component".to_string());
825            }
826
827            Payload::DataSection(_) => {
828                return Err("Unexpected core data section in component".to_string());
829            }
830
831            Payload::CodeSectionStart { .. } => {
832                return Err("Unexpected core code section in component".to_string());
833            }
834
835            Payload::CodeSectionEntry(_) => {
836                return Err("Unexpected core code section in component".to_string());
837            }
838
839            Payload::CustomSection(reader) => sections.push(ComponentSection::Custom(
840                Custom {
841                    name: reader.name().to_string(),
842                    data: reader.data().to_vec(),
843                }
844                .into(),
845            )),
846            Payload::End(_) => {
847                break;
848            }
849            Payload::InstanceSection(reader) => {
850                for instance in reader {
851                    let instance = instance.map_err(|e| {
852                        format!("Error parsing component core instance section: {e:?}")
853                    })?;
854                    sections.push(ComponentSection::CoreInstance(instance.try_into()?))
855                }
856            }
857            Payload::CoreTypeSection(reader) => {
858                for core_type in reader {
859                    let core_type = core_type
860                        .map_err(|e| format!("Error parsing component core type section: {e:?}"))?;
861                    sections.push(ComponentSection::CoreType(core_type.try_into()?))
862                }
863            }
864            Payload::ModuleSection {
865                parser,
866                unchecked_range,
867            } => {
868                let module: Module<Ast> =
869                    (parser, &remaining[..unchecked_range.len()]).try_into()?;
870                remaining = &remaining[(unchecked_range.end - unchecked_range.start)..];
871                sections.push(ComponentSection::Module(module))
872            }
873            Payload::ComponentSection { parser, .. } => {
874                let (component, new_remaining) = parse_component(parser, remaining)?;
875                remaining = new_remaining;
876                sections.push(ComponentSection::Component(component))
877            }
878            Payload::ComponentInstanceSection(reader) => {
879                for component_instance in reader {
880                    let component_instance = component_instance
881                        .map_err(|e| format!("Error parsing component instance section: {e:?}"))?;
882                    sections.push(ComponentSection::Instance(component_instance.try_into()?))
883                }
884            }
885            Payload::ComponentAliasSection(reader) => {
886                for alias in reader {
887                    let alias = alias
888                        .map_err(|e| format!("Error parsing component alias section: {e:?}"))?;
889                    sections.push(ComponentSection::Alias(alias.try_into()?))
890                }
891            }
892            Payload::ComponentTypeSection(reader) => {
893                for component_type in reader {
894                    let component_type = component_type
895                        .map_err(|e| format!("Error parsing component type section: {e:?}"))?;
896                    sections.push(ComponentSection::Type(component_type.try_into()?))
897                }
898            }
899            Payload::ComponentCanonicalSection(reader) => {
900                for canon in reader {
901                    let canon = canon
902                        .map_err(|e| format!("Error parsing component canonical section: {e:?}"))?;
903                    sections.push(ComponentSection::Canon(canon.try_into()?))
904                }
905            }
906            Payload::ComponentStartSection { start, .. } => {
907                sections.push(ComponentSection::Start(start.try_into()?))
908            }
909            Payload::ComponentImportSection(reader) => {
910                for import in reader {
911                    let import = import
912                        .map_err(|e| format!("Error parsing component import section: {e:?}"))?;
913                    sections.push(ComponentSection::Import(import.try_into()?))
914                }
915            }
916            Payload::ComponentExportSection(reader) => {
917                for export in reader {
918                    let export = export
919                        .map_err(|e| format!("Error parsing component export section: {e:?}"))?;
920                    sections.push(ComponentSection::Export(export.try_into()?))
921                }
922            }
923            Payload::UnknownSection { .. } => {
924                return Err("Unexpected unknown section in component".to_string());
925            }
926            _ => {
927                return Err("Unexpected section in component".to_string());
928            }
929        }
930    }
931
932    Ok((Sections::from_flat(sections), remaining))
933}
934
935pub fn parse_component<Ast>(
936    parser: Parser,
937    remaining: &[u8],
938) -> Result<(Component<Ast>, &[u8]), String>
939where
940    Ast: AstCustomization,
941    Ast::Expr: TryFromExprSource,
942    Ast::Data: From<Data<Ast::Expr>>,
943    Ast::Custom: From<Custom>,
944{
945    let (sections, remaining) = parse_component_sections(parser, remaining)?;
946    Ok((sections.into(), remaining))
947}