Revision control
Copy as Markdown
Other Tools
use crate::{BinaryReader, ComponentTypeRef, FromReader, Result, SectionLimited};
/// Represents the kind of an external items of a WebAssembly component.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ComponentExternalKind {
/// The external kind is a core module.
Module,
/// The external kind is a function.
Func,
/// The external kind is a value.
Value,
/// The external kind is a type.
Type,
/// The external kind is an instance.
Instance,
/// The external kind is a component.
Component,
}
impl ComponentExternalKind {
pub(crate) fn from_bytes(
byte1: u8,
byte2: Option<u8>,
offset: usize,
) -> Result<ComponentExternalKind> {
Ok(match byte1 {
0x00 => match byte2.unwrap() {
0x11 => ComponentExternalKind::Module,
x => {
return Err(BinaryReader::invalid_leading_byte_error(
x,
"component external kind",
offset + 1,
))
}
},
0x01 => ComponentExternalKind::Func,
0x02 => ComponentExternalKind::Value,
0x03 => ComponentExternalKind::Type,
0x04 => ComponentExternalKind::Component,
0x05 => ComponentExternalKind::Instance,
x => {
return Err(BinaryReader::invalid_leading_byte_error(
x,
"component external kind",
offset,
))
}
})
}
/// Returns a simple string description of this kind.
pub fn desc(&self) -> &'static str {
use ComponentExternalKind::*;
match self {
Module => "module",
Func => "func",
Value => "value",
Type => "type",
Instance => "instance",
Component => "component",
}
}
}
/// Represents an export in a WebAssembly component.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ComponentExport<'a> {
/// The name of the exported item.
pub name: ComponentExportName<'a>,
/// The kind of the export.
pub kind: ComponentExternalKind,
/// The index of the exported item.
pub index: u32,
/// An optionally specified type ascribed to this export.
pub ty: Option<ComponentTypeRef>,
}
/// A reader for the export section of a WebAssembly component.
pub type ComponentExportSectionReader<'a> = SectionLimited<'a, ComponentExport<'a>>;
impl<'a> FromReader<'a> for ComponentExport<'a> {
fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
Ok(ComponentExport {
name: reader.read()?,
kind: reader.read()?,
index: reader.read()?,
ty: match reader.read_u8()? {
0x00 => None,
0x01 => Some(reader.read()?),
other => {
return Err(BinaryReader::invalid_leading_byte_error(
other,
"optional component export type",
reader.original_position() - 1,
))
}
},
})
}
}
impl<'a> FromReader<'a> for ComponentExternalKind {
fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
let offset = reader.original_position();
let byte1 = reader.read_u8()?;
let byte2 = if byte1 == 0x00 {
Some(reader.read_u8()?)
} else {
None
};
ComponentExternalKind::from_bytes(byte1, byte2, offset)
}
}
/// Represents the name of a component export.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[allow(missing_docs)]
pub struct ComponentExportName<'a>(pub &'a str);
impl<'a> FromReader<'a> for ComponentExportName<'a> {
fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
match reader.read_u8()? {
0x00 => {}
// Historically export names used a discriminator byte of 0x01 to
// indicate an "interface" of the form `a:b/c` but nowadays that's
// inferred from string syntax. Ignore 0-vs-1 to continue to parse
// older binaries. Eventually this will go away.
0x01 => {}
x => return reader.invalid_leading_byte(x, "export name"),
}
Ok(ComponentExportName(reader.read_string()?))
}
}