/// A parsed WebAssembly component module. #[derive(Debug)] #[non_exhaustive] pubstruct Component<'a> { /// Where this `component` was defined pub span: Span, /// An optional identifier this component is known by pub id: Option<Id<'a>>, /// An optional `@name` annotation for this component pub name: Option<NameAnnotation<'a>>, /// What kind of component this was parsed as. pub kind: ComponentKind<'a>,
}
/// The different kinds of ways to define a component. #[derive(Debug)] pubenum ComponentKind<'a> { /// A component defined in the textual s-expression format.
Text(Vec<ComponentField<'a>>), /// A component that had its raw binary bytes defined via the `binary` /// directive.
Binary(Vec<&'a [u8]>),
}
impl<'a> Component<'a> { /// Performs a name resolution pass on this [`Component`], resolving all /// symbolic names to indices. /// /// The WAT format contains a number of shorthands to make it easier to /// write, such as inline exports, inline imports, inline type definitions, /// etc. Additionally it allows using symbolic names such as `$foo` instead /// of using indices. This module will postprocess an AST to remove all of /// this syntactic sugar, preparing the AST for binary emission. This is /// where expansion and name resolution happens. /// /// This function will mutate the AST of this [`Component`] and replace all /// [`Index`](crate::token::Index) arguments with `Index::Num`. This will /// also expand inline exports/imports listed on fields and handle various /// other shorthands of the text format. /// /// If successful the AST was modified to be ready for binary encoding. /// /// # Errors /// /// If an error happens during resolution, such a name resolution error or /// items are found in the wrong order, then an error is returned. pubfn resolve(&mutself) -> std::result::Result<(), crate::Error> { match &mutself.kind {
ComponentKind::Text(fields) => { crate::component::expand::expand(fields);
}
ComponentKind::Binary(_) => {}
} crate::component::resolve::resolve(self)
}
/// Encodes this [`Component`] to its binary form. /// /// This function will take the textual representation in [`Component`] and /// perform all steps necessary to convert it to a binary WebAssembly /// component, suitable for writing to a `*.wasm` file. This function may /// internally modify the [`Component`], for example: /// /// * Name resolution is performed to ensure that `Index::Id` isn't present /// anywhere in the AST. /// /// * Inline shorthands such as imports/exports/types are all expanded to be /// dedicated fields of the component. /// /// * Component fields may be shuffled around to preserve index ordering from /// expansions. /// /// After all of this expansion has happened the component will be converted to /// its binary form and returned as a `Vec<u8>`. This is then suitable to /// hand off to other wasm runtimes and such. /// /// # Errors /// /// This function can return an error for name resolution errors and other /// expansion-related errors. pubfn encode(&mutself) -> std::result::Result<Vec<u8>, crate::Error> { crate::core::EncodeOptions::default().encode_component(self)
}
pub(crate) fn parse_without_component_keyword(
component_keyword_span: Span,
parser: Parser<'a>,
) -> Result<Self> { let id = parser.parse()?; let name = parser.parse()?;
let kind = if parser.peek::<kw::binary>()? {
parser.parse::<kw::binary>()?; letmut data = Vec::new(); while !parser.is_empty() {
data.push(parser.parse()?);
}
ComponentKind::Binary(data)
} else {
ComponentKind::Text(ComponentField::parse_remaining(parser)?)
};
Ok(Component {
span: component_keyword_span,
id,
name,
kind,
})
}
}
/// A listing of all possible fields that can make up a WebAssembly component. #[allow(missing_docs)] #[derive(Debug)] pubenum ComponentField<'a> {
CoreModule(CoreModule<'a>),
CoreInstance(CoreInstance<'a>),
CoreType(CoreType<'a>),
CoreRec(core::Rec<'a>),
Component(NestedComponent<'a>),
Instance(Instance<'a>),
Alias(Alias<'a>), Type(Type<'a>),
CanonicalFunc(CanonicalFunc<'a>),
CoreFunc(CoreFunc<'a>), // Supports inverted forms of other items
Func(Func<'a>), // Supports inverted forms of other items
Start(Start<'a>),
Import(ComponentImport<'a>),
Export(ComponentExport<'a>),
Custom(Custom<'a>),
Producers(Producers<'a>),
}
impl<'a> Parse<'a> for ComponentField<'a> { fn parse(parser: Parser<'a>) -> Result<Self> { if parser.peek::<kw::core>()? { if parser.peek2::<kw::module>()? { return Ok(Self::CoreModule(parser.parse()?));
} if parser.peek2::<kw::instance>()? { return Ok(Self::CoreInstance(parser.parse()?));
} if parser.peek2::<kw::r#type>()? { return Ok(Self::CoreType(parser.parse()?));
} if parser.peek2::<kw::func>()? { return Ok(Self::CoreFunc(parser.parse()?));
} if parser.peek2::<kw::rec>()? {
parser.parse::<kw::core>()?; return Ok(Self::CoreRec(parser.parse()?));
}
} else { if parser.peek::<kw::component>()? { return Ok(Self::Component(parser.parse()?));
} if parser.peek::<kw::instance>()? { return Ok(Self::Instance(parser.parse()?));
} if parser.peek::<kw::alias>()? { return Ok(Self::Alias(parser.parse()?));
} if parser.peek::<kw::r#type>()? { return Ok(Self::Type(Type::parse_maybe_with_inline_exports(parser)?));
} if parser.peek::<kw::import>()? { return Ok(Self::Import(parser.parse()?));
} if parser.peek::<kw::func>()? { return Ok(Self::Func(parser.parse()?));
} if parser.peek::<kw::export>()? { return Ok(Self::Export(parser.parse()?));
} if parser.peek::<kw::start>()? { return Ok(Self::Start(parser.parse()?));
} if parser.peek::<annotation::custom>()? { return Ok(Self::Custom(parser.parse()?));
} if parser.peek::<annotation::producers>()? { return Ok(Self::Producers(parser.parse()?));
}
}
Err(parser.error("expected valid component field"))
}
}
/// A function to call at instantiation time. #[derive(Debug)] pubstruct Start<'a> { /// The function to call. pub func: Index<'a>, /// The arguments to pass to the function. pub args: Vec<ItemRef<'a, kw::value>>, /// Names of the result values. pub results: Vec<Option<Id<'a>>>,
}
impl<'a> Parse<'a> for Start<'a> { fn parse(parser: Parser<'a>) -> Result<Self> {
parser.parse::<kw::start>()?; let func = parser.parse()?; letmut args = Vec::new(); while !parser.is_empty() && !parser.peek2::<kw::result>()? {
args.push(parser.parens(|parser| parser.parse())?);
}
/// A nested WebAssembly component. #[derive(Debug)] pubstruct NestedComponent<'a> { /// Where this `component` was defined pub span: Span, /// An optional identifier this component is known by pub id: Option<Id<'a>>, /// An optional `@name` annotation for this component pub name: Option<NameAnnotation<'a>>, /// If present, inline export annotations which indicate names this /// definition should be exported under. pub exports: InlineExport<'a>, /// What kind of component this was parsed as. pub kind: NestedComponentKind<'a>,
}
/// The different kinds of ways to define a nested component. #[derive(Debug)] pubenum NestedComponentKind<'a> { /// This is actually an inline import of a component
Import { /// The information about where this is being imported from.
import: InlineImport<'a>, /// The type of component being imported.
ty: ComponentTypeUse<'a, ComponentType<'a>>,
}, /// The component is defined inline as a local definition with its fields /// listed here.
Inline(Vec<ComponentField<'a>>),
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.