///|
/// Parsing for component import/export sections (sections 10 and 11).
///
/// This is still a subset: we primarily parse the framing and enough structure
/// to keep index spaces and types wired up for later validation/linking.
///|
#derive(Debug, Eq)
pub(all) enum Sort {
Core(Int32) // core:sort opcode (0x00..)
Func
Value
Type
Component
Instance
}
///|
#derive(Debug, Eq)
pub(all) struct SortIdx {
sort : Sort
idx : Int32
}
///|
pub impl Show for SortIdx with fn output(self, logger) {
logger.write_string(@types.compact_show_repr(Repr(self).to_string()))
}
///|
#derive(Debug, Eq)
pub(all) enum TypeBound {
Eq(Int32)
SubResource
}
///|
#derive(Debug, Eq)
pub(all) enum ValueBound {
Eq(Int32)
Type(ValType)
}
///|
#derive(Debug, Eq)
pub(all) enum ExternDesc {
CoreModuleType(Int32) // core:typeidx (u32)
FuncType(Int32) // typeidx
Value(ValueBound)
Type(TypeBound)
ComponentType(Int32) // typeidx
InstanceType(Int32) // typeidx
}
///|
pub impl Show for ExternDesc with fn output(self, logger) {
logger.write_string(@types.compact_show_repr(Repr(self).to_string()))
}
///|
#derive(Debug, Eq)
pub(all) enum ImportName {
Plain(Bytes)
WithVersion(Bytes, Bytes)
}
///|
#derive(Debug, Eq)
pub(all) enum ExportName {
Plain(Bytes)
WithVersion(Bytes, Bytes)
}
///|
#derive(Debug, Eq)
pub(all) enum NameAttribute {
Implements(Bytes)
VersionSuffix(Bytes)
ExternalId(Bytes)
}
///|
#derive(Debug, Eq)
pub(all) struct Import {
name : ImportName
attributes : Array[NameAttribute]
desc : ExternDesc
}
///|
#derive(Debug, Eq)
pub(all) struct Export {
name : ExportName
attributes : Array[NameAttribute]
sortidx : SortIdx
desc : ExternDesc?
}
///|
fn parse_attribute(reader : Reader) -> NameAttribute raise ComponentParseError {
match reader.read_u8() {
0 => Implements(reader.read_blob())
1 => VersionSuffix(reader.read_blob())
2 => ExternalId(reader.read_blob())
_ => raise InvalidTypeSection
}
}
///|
fn[A] parse_annotated_name(
reader : Reader,
read_name : (Reader) -> A raise ComponentParseError,
invalid : ComponentParseError,
) -> (A, Array[NameAttribute]) raise ComponentParseError {
let tag = reader.read_u8()
if tag > 2 {
raise invalid
}
let name = read_name(reader)
let attributes = if tag == 2 {
reader.read_vector(parse_attribute)
} else {
[]
}
(name, attributes)
}
///|
fn parse_sort(reader : Reader) -> Sort raise ComponentParseError {
let tag = reader.read_u8()
if tag == 0x00 {
let core_sort = reader.read_u8()
Core(core_sort)
} else if tag == 0x01 {
Func
} else if tag == 0x02 {
Value
} else if tag == 0x03 {
Type
} else if tag == 0x04 {
Component
} else if tag == 0x05 {
Instance
} else {
raise InvalidTypeSection
}
}
///|
fn parse_sortidx(reader : Reader) -> SortIdx raise ComponentParseError {
let sort = parse_sort(reader)
let idx = reader.read_leb_u32()
{ sort, idx, }
}
///|
fn parse_typebound(reader : Reader) -> TypeBound raise ComponentParseError {
let tag = reader.read_u8()
if tag == 0x00 {
Eq(reader.read_typeidx())
} else if tag == 0x01 {
SubResource
} else {
raise InvalidTypeSection
}
}
///|
fn parse_valuebound(reader : Reader) -> ValueBound raise ComponentParseError {
let tag = reader.read_u8()
if tag == 0x00 {
Eq(reader.read_leb_u32())
} else if tag == 0x01 {
Type(parse_valtype(reader))
} else {
raise InvalidTypeSection
}
}
///|
fn parse_externdesc(reader : Reader) -> ExternDesc raise ComponentParseError {
let tag = reader.read_u8()
if tag == 0x00 {
let must_be_core_module = reader.read_u8()
if must_be_core_module != 0x11 {
raise InvalidTypeSection
}
CoreModuleType(reader.read_leb_u32())
} else if tag == 0x01 {
FuncType(reader.read_typeidx())
} else if tag == 0x02 {
Value(parse_valuebound(reader))
} else if tag == 0x03 {
Type(parse_typebound(reader))
} else if tag == 0x04 {
ComponentType(reader.read_typeidx())
} else if tag == 0x05 {
InstanceType(reader.read_typeidx())
} else {
raise InvalidTypeSection
}
}
///|
pub fn parse_import_section(
payload : Bytes,
) -> Array[Import] raise ComponentParseError {
parse_vector_section(
payload,
reader => {
let (name, attributes) = parse_annotated_name(
reader,
Reader::read_blob,
InvalidTypeSection,
)
{ name: Plain(name), attributes, desc: parse_externdesc(reader), }
},
InvalidTypeSection,
)
}
///|
pub fn parse_export_section(
payload : Bytes,
) -> Array[Export] raise ComponentParseError {
parse_vector_section(
payload,
reader => {
let (name, attributes) = parse_annotated_name(
reader,
Reader::read_blob,
InvalidTypeSection,
)
let sortidx = parse_sortidx(reader)
let desc = reader.read_optional(parse_externdesc)
{ name: Plain(name), attributes, sortidx, desc, }
},
InvalidTypeSection,
)
}