use wasmparser::Payload::{
ComponentAliasSection, ComponentExportSection, ComponentTypeSection, Version,
};
use wasmparser::{
ComponentAlias, ComponentExternalKind, ComponentOuterAliasKind, ComponentType,
ComponentTypeRef, Payload,
};
use crate::etypes::{Component, Ctx, Defined};
fn raw_type_export_type<'p, 'a, 'c>(
ctx: &'c Ctx<'p, 'a>,
ce: &'c wasmparser::ComponentExport<'a>,
) -> &'c Defined<'a> {
match ce.ty {
Some(ComponentTypeRef::Component(n)) => match ctx.types.get(n as usize) {
Some(t) => t,
None => {
panic!("malformed component type export: ascription does not refer to a type");
}
},
Some(_) => {
panic!(
"malformed component type export: ascription does not refer to a component type"
);
}
None => match ctx.types.get(ce.index as usize) {
Some(t) => t,
None => {
panic!("malformed component type export: does not refer to a type");
}
},
}
}
pub fn read_component_single_exported_type<'a>(
items: impl Iterator<Item = wasmparser::Result<Payload<'a>>>,
world_name: Option<String>,
) -> Component<'a> {
let mut ctx = Ctx::new(None, false);
let mut selected_type_idx = None;
for x in items {
match x {
Ok(Version { num, encoding, .. }) => {
if encoding != wasmparser::Encoding::Component {
panic!("wasm file is not a component")
}
if num != 0xd {
panic!("unknown component encoding version 0x{:x}\n", num);
}
}
Ok(ComponentTypeSection(ts)) => {
for t in ts {
match t {
Ok(ComponentType::Component(ct)) => {
let ct_ = ctx.elab_component(&ct);
ctx.types.push(Defined::Component(ct_.unwrap()));
}
_ => panic!("non-component type"),
}
}
}
Ok(ComponentExportSection(es)) => {
for e in es {
match e {
Err(_) => panic!("invalid export section"),
Ok(ce) => {
if ce.kind == ComponentExternalKind::Type {
ctx.types.push(raw_type_export_type(&ctx, &ce).clone());
if let Some(world) = world_name.as_ref() {
let name = ce.name.0;
if name.eq_ignore_ascii_case(world) {
selected_type_idx = Some(ctx.types.len() - 1);
}
} else {
selected_type_idx = Some(ctx.types.len() - 1);
}
}
}
}
}
}
Ok(ComponentAliasSection(r#as)) => {
for a in r#as {
match a {
Ok(ComponentAlias::InstanceExport {
kind: ComponentExternalKind::Type,
..
})
| Ok(ComponentAlias::Outer {
kind: ComponentOuterAliasKind::Type,
..
}) => {
panic!("Component outer type aliases are not supported")
}
_ => {}
}
}
}
_ => {}
}
}
match selected_type_idx {
Some(n) => match ctx.types.into_iter().nth(n) {
Some(Defined::Component(c)) => c,
_ => panic!("final export is not component"),
},
None => match &world_name {
Some(name) => panic!("world '{}' not found in component", name),
None => panic!("no exported type"),
},
}
}