| 
 | 1 | +/*  | 
 | 2 | +Copyright 2024 The Hyperlight Authors.  | 
 | 3 | +
  | 
 | 4 | +Licensed under the Apache License, Version 2.0 (the "License");  | 
 | 5 | +you may not use this file except in compliance with the License.  | 
 | 6 | +You may obtain a copy of the License at  | 
 | 7 | +
  | 
 | 8 | +    http://www.apache.org/licenses/LICENSE-2.0  | 
 | 9 | +
  | 
 | 10 | +Unless required by applicable law or agreed to in writing, software  | 
 | 11 | +distributed under the License is distributed on an "AS IS" BASIS,  | 
 | 12 | +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  | 
 | 13 | +See the License for the specific language governing permissions and  | 
 | 14 | +limitations under the License.  | 
 | 15 | + */  | 
 | 16 | + | 
 | 17 | +//! Just enough component parsing support to get at the actual types  | 
 | 18 | +
  | 
 | 19 | +use wasmparser::Payload::{ComponentExportSection, ComponentTypeSection, Version};  | 
 | 20 | +use wasmparser::{ComponentExternalKind, ComponentType, ComponentTypeRef, Payload};  | 
 | 21 | + | 
 | 22 | +use crate::etypes::{Component, Ctx, Defined};  | 
 | 23 | + | 
 | 24 | +/// From [`wasmparser::ComponentExport`], elaborate a deftype_e as per  | 
 | 25 | +/// the specification.  | 
 | 26 | +fn raw_type_export_type<'p, 'a, 'c>(  | 
 | 27 | +    ctx: &'c Ctx<'p, 'a>,  | 
 | 28 | +    ce: &'c wasmparser::ComponentExport<'a>,  | 
 | 29 | +) -> &'c Defined<'a> {  | 
 | 30 | +    match ce.ty {  | 
 | 31 | +        Some(ComponentTypeRef::Component(n)) => match ctx.types.get(n as usize) {  | 
 | 32 | +            Some(t) => t,  | 
 | 33 | +            t => panic!("bad component type 1 {:?}", t),  | 
 | 34 | +        },  | 
 | 35 | +        None => match ctx.types.get(ce.index as usize) {  | 
 | 36 | +            Some(t) => t,  | 
 | 37 | +            t => panic!("bad component type 2 {:?}", t),  | 
 | 38 | +        },  | 
 | 39 | +        _ => panic!("non-component ascribed type"),  | 
 | 40 | +    }  | 
 | 41 | +}  | 
 | 42 | + | 
 | 43 | +/// Find the last exported type in a component, since in wasm-encoded  | 
 | 44 | +/// WIT this is typically the main world to use.  This is a very  | 
 | 45 | +/// special case that just lets us pull a type out of a value-level  | 
 | 46 | +/// component easily; it is not a full component typechecker.  | 
 | 47 | +///  | 
 | 48 | +/// TODO: Encode even more assumptions about WIT package structure  | 
 | 49 | +/// (which are already there in rtypes/host/guest) and allow looking  | 
 | 50 | +/// for a specific named world, instead of simply grabbing the last  | 
 | 51 | +/// export.  | 
 | 52 | +pub fn read_component_single_exported_type<'a>(  | 
 | 53 | +    items: impl Iterator<Item = wasmparser::Result<Payload<'a>>>,  | 
 | 54 | +) -> Component<'a> {  | 
 | 55 | +    let mut ctx = Ctx::new(None, false);  | 
 | 56 | +    let mut last_idx = None;  | 
 | 57 | +    for x in items {  | 
 | 58 | +        match x {  | 
 | 59 | +            Ok(Version { .. }) => (),  | 
 | 60 | +            Ok(ComponentTypeSection(ts)) => {  | 
 | 61 | +                for t in ts {  | 
 | 62 | +                    match t {  | 
 | 63 | +                        Ok(ComponentType::Component(ct)) => {  | 
 | 64 | +                            let ct_ = ctx.elab_component(&ct);  | 
 | 65 | +                            ctx.types.push(Defined::Component(ct_.unwrap()));  | 
 | 66 | +                        }  | 
 | 67 | +                        _ => panic!("non-component type"),  | 
 | 68 | +                    }  | 
 | 69 | +                }  | 
 | 70 | +            }  | 
 | 71 | +            Ok(ComponentExportSection(es)) => {  | 
 | 72 | +                for e in es {  | 
 | 73 | +                    match e {  | 
 | 74 | +                        Err(_) => panic!("invalid export section"),  | 
 | 75 | +                        Ok(ce) => {  | 
 | 76 | +                            if ce.kind == ComponentExternalKind::Type {  | 
 | 77 | +                                last_idx = Some(ctx.types.len());  | 
 | 78 | +                                ctx.types.push(raw_type_export_type(&ctx, &ce).clone());  | 
 | 79 | +                            }  | 
 | 80 | +                        }  | 
 | 81 | +                    }  | 
 | 82 | +                }  | 
 | 83 | +            }  | 
 | 84 | +            _ => {}  | 
 | 85 | +        }  | 
 | 86 | +    }  | 
 | 87 | +    match last_idx {  | 
 | 88 | +        None => panic!("no exported type"),  | 
 | 89 | +        Some(n) => match ctx.types.into_iter().nth(n) {  | 
 | 90 | +            Some(Defined::Component(c)) => c,  | 
 | 91 | +            _ => panic!("final export is not component"),  | 
 | 92 | +        },  | 
 | 93 | +    }  | 
 | 94 | +}  | 
0 commit comments