Add a wasmtime::component::bindgen! macro (#5317)
* Import Wasmtime support from the `wit-bindgen` repo This commit imports the `wit-bindgen-gen-host-wasmtime-rust` crate from the `wit-bindgen` repository into the upstream Wasmtime repository. I've chosen to not import the full history here since the crate is relatively small and doesn't have a ton of complexity. While the history of the crate is quite long the current iteration of the crate's history is relatively short so there's not a ton of import there anyway. The thinking is that this can now continue to evolve in-tree. * Refactor `wasmtime-component-macro` a bit Make room for a `wit_bindgen` macro to slot in. * Add initial support for a `bindgen` macro * Add tests for `wasmtime::component::bindgen!` * Improve error forgetting `async` feature * Add end-to-end tests for bindgen * Add an audit of `unicase` * Add a license to the test-helpers crate * Add vet entry for `pulldown-cmark` * Update publish script with new crate * Try to fix publish script * Update audits * Update lock file
This commit is contained in:
@@ -88,7 +88,12 @@ cache = ["dep:wasmtime-cache"]
|
||||
|
||||
# Enables support for "async stores" as well as defining host functions as
|
||||
# `async fn` and calling functions asynchronously.
|
||||
async = ["dep:wasmtime-fiber", "wasmtime-runtime/async", "dep:async-trait"]
|
||||
async = [
|
||||
"dep:wasmtime-fiber",
|
||||
"wasmtime-runtime/async",
|
||||
"dep:async-trait",
|
||||
"wasmtime-component-macro?/async",
|
||||
]
|
||||
|
||||
# Enables support for the pooling instance allocation strategy
|
||||
pooling-allocator = ["wasmtime-runtime/pooling-allocator"]
|
||||
|
||||
126
crates/wasmtime/src/component/error.rs
Normal file
126
crates/wasmtime/src/component/error.rs
Normal file
@@ -0,0 +1,126 @@
|
||||
/// Type alias for the standard library [`Result`](std::result::Result) type
|
||||
/// to specifie [`Error`] as the error payload.
|
||||
pub type Result<A, E> = std::result::Result<A, Error<E>>;
|
||||
|
||||
/// Error type used by the [`bindgen!`](crate::component::bindgen) macro.
|
||||
///
|
||||
/// This error type represents either the typed error `T` specified here or a
|
||||
/// trap, represented with [`anyhow::Error`].
|
||||
pub struct Error<T> {
|
||||
err: anyhow::Error,
|
||||
ty: std::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> Error<T> {
|
||||
/// Creates a new typed version of this error from the `T` specified.
|
||||
///
|
||||
/// This error, if it makes its way to the guest, will be returned to the
|
||||
/// guest and the guest will be able to act upon it.
|
||||
///
|
||||
/// Alternatively errors can be created with [`Error::trap`] which will
|
||||
/// cause the guest to trap and be unable to act upon it.
|
||||
pub fn new(err: T) -> Error<T>
|
||||
where
|
||||
T: std::error::Error + Send + Sync + 'static,
|
||||
{
|
||||
Error {
|
||||
err: err.into(),
|
||||
ty: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a custom "trap" which will abort guest execution and have the
|
||||
/// specified `err` as the payload context returned from the original
|
||||
/// invocation.
|
||||
///
|
||||
/// Note that if `err` here actually has type `T` then the error will not be
|
||||
/// considered a trap and will instead be dynamically detected as a normal
|
||||
/// error to communicate to the original module.
|
||||
pub fn trap(err: impl std::error::Error + Send + Sync + 'static) -> Error<T> {
|
||||
Error {
|
||||
err: anyhow::Error::from(err),
|
||||
ty: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempts to dynamically downcast this error internally to the `T`
|
||||
/// representation.
|
||||
///
|
||||
/// If this error is internally represented as a `T` then `Ok(val)` will be
|
||||
/// returned. If this error is instead represented as a trap then
|
||||
/// `Err(trap)` will be returned instead.
|
||||
pub fn downcast(self) -> anyhow::Result<T>
|
||||
where
|
||||
T: std::error::Error + Send + Sync + 'static,
|
||||
{
|
||||
self.err.downcast::<T>()
|
||||
}
|
||||
|
||||
/// Attempts to dynamically downcast this error to peek at the inner
|
||||
/// contents of `T` if present.
|
||||
pub fn downcast_ref(&self) -> Option<&T>
|
||||
where
|
||||
T: std::error::Error + Send + Sync + 'static,
|
||||
{
|
||||
self.err.downcast_ref::<T>()
|
||||
}
|
||||
|
||||
/// Attempts to dynamically downcast this error to peek at the inner
|
||||
/// contents of `T` if present.
|
||||
pub fn downcast_mut(&mut self) -> Option<&mut T>
|
||||
where
|
||||
T: std::error::Error + Send + Sync + 'static,
|
||||
{
|
||||
self.err.downcast_mut::<T>()
|
||||
}
|
||||
|
||||
/// Converts this error into an `anyhow::Error` which loses the `T` type
|
||||
/// information tagged to this error.
|
||||
pub fn into_inner(self) -> anyhow::Error {
|
||||
self.err
|
||||
}
|
||||
|
||||
/// Same as [`anyhow::Error::context`], attaches a contextual message to
|
||||
/// this error.
|
||||
pub fn context<C>(self, context: C) -> Error<T>
|
||||
where
|
||||
C: std::fmt::Display + Send + Sync + 'static,
|
||||
{
|
||||
self.err.context(context).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::ops::Deref for Error<T> {
|
||||
type Target = dyn std::error::Error + Send + Sync + 'static;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.err.deref()
|
||||
}
|
||||
}
|
||||
impl<T> std::ops::DerefMut for Error<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.err.deref_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::fmt::Display for Error<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.err.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::fmt::Debug for Error<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.err.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::error::Error for Error<T> {}
|
||||
|
||||
impl<T> From<anyhow::Error> for Error<T> {
|
||||
fn from(err: anyhow::Error) -> Error<T> {
|
||||
Error {
|
||||
err,
|
||||
ty: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
//! probably buggy implementation of the component model.
|
||||
|
||||
mod component;
|
||||
mod error;
|
||||
mod func;
|
||||
mod instance;
|
||||
mod linker;
|
||||
@@ -13,6 +14,7 @@ mod store;
|
||||
pub mod types;
|
||||
mod values;
|
||||
pub use self::component::Component;
|
||||
pub use self::error::{Error, Result};
|
||||
pub use self::func::{
|
||||
ComponentNamedList, ComponentType, Func, Lift, Lower, TypedFunc, WasmList, WasmStr,
|
||||
};
|
||||
@@ -20,7 +22,7 @@ pub use self::instance::{ExportInstance, Exports, Instance, InstancePre};
|
||||
pub use self::linker::{Linker, LinkerInstance};
|
||||
pub use self::types::Type;
|
||||
pub use self::values::Val;
|
||||
pub use wasmtime_component_macro::{flags, ComponentType, Lift, Lower};
|
||||
pub use wasmtime_component_macro::{bindgen, flags, ComponentType, Lift, Lower};
|
||||
|
||||
// These items are expected to be used by an eventual
|
||||
// `#[derive(ComponentType)]`, they are not part of Wasmtime's API stability
|
||||
@@ -35,6 +37,8 @@ pub mod __internal {
|
||||
pub use crate::map_maybe_uninit;
|
||||
pub use crate::store::StoreOpaque;
|
||||
pub use anyhow;
|
||||
#[cfg(feature = "async")]
|
||||
pub use async_trait::async_trait;
|
||||
pub use wasmtime_environ;
|
||||
pub use wasmtime_environ::component::{CanonicalAbiInfo, ComponentTypes, InterfaceType};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user