diff --git a/Cargo.lock b/Cargo.lock index 06272cdfbd..f867fe9888 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3795,25 +3795,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "wasmtime-rust" -version = "0.27.0" -dependencies = [ - "anyhow", - "wasmtime", - "wasmtime-rust-macro", - "wasmtime-wasi", -] - -[[package]] -name = "wasmtime-rust-macro" -version = "0.27.0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "wasmtime-wasi" version = "0.27.0" diff --git a/Cargo.toml b/Cargo.toml index 36f80cc666..aaeec98afa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,7 +74,6 @@ members = [ "crates/c-api", "crates/fuzzing", "crates/misc/run-examples", - "crates/misc/rust", "crates/wiggle", "crates/wiggle/generate", "crates/wiggle/macro", diff --git a/crates/misc/rust/Cargo.toml b/crates/misc/rust/Cargo.toml deleted file mode 100644 index cc5be44e2c..0000000000 --- a/crates/misc/rust/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "wasmtime-rust" -version = "0.27.0" -authors = ["Alex Crichton "] -description = "Rust extension for Wasmtime" -license = "Apache-2.0 WITH LLVM-exception" -categories = ["wasm"] -keywords = ["webassembly", "wasm"] -repository = "https://github.com/bytecodealliance/wasmtime" -readme = "README.md" -edition = "2018" - -[lib] -test = false -doctest = false - -[dependencies] -wasmtime-rust-macro = { path = "./macro", version = "0.27.0" } -wasmtime-wasi = { path = "../../wasi", version = "0.27.0" } -wasmtime = { path = "../../wasmtime", version = "0.27.0" } -anyhow = "1.0.19" - -[badges] -maintenance = { status = "actively-developed" } diff --git a/crates/misc/rust/README.md b/crates/misc/rust/README.md deleted file mode 100644 index 498e29160b..0000000000 --- a/crates/misc/rust/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# `wasmtime-rust` - Using WebAssembly from Rust - -This crate is intended to be an example of how to load WebAssembly files from a -native Rust application. You can always use `wasmtime` and its family of crates -directly, but the purpose of this crate is to provide an ergonomic macro: - -```rust -#[wasmtime_rust::wasmtime] -trait WasmMarkdown { - fn render(&mut self, input: &str) -> String; -} - -fn main() -> anyhow::Result<()> { - let mut markdown = WasmMarkdown::load_file("markdown.wasm")?; - println!("{}", markdown.render("# Hello, Rust!")); - - Ok(()) -} -``` - -The `wasmtime` macro defined in the `wasmtime-rust` crate is placed on a `trait` -which includes the set of functionality which a wasm module should export. In -this case we're expecting one `render` function which takes and returns a -string. - -The macro expands to a `struct` with all of the methods on the trait (they must -all be `&mut self`) and one function called `load_file` to actually instantiate -the module. - -Note that this macro is still in early stages of development, so error messages -aren't great yet and all functionality isn't supported yet. - -## Missing features - -Currently if the wasm module imports any symbols outside of the WASI namespace -the module will not load. It's intended that support for this will be added soon -though! diff --git a/crates/misc/rust/macro/Cargo.toml b/crates/misc/rust/macro/Cargo.toml deleted file mode 100644 index 6745a2b542..0000000000 --- a/crates/misc/rust/macro/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "wasmtime-rust-macro" -version = "0.27.0" -authors = ["Alex Crichton "] -description = "Macro support crate for wasmtime-rust" -license = "Apache-2.0 WITH LLVM-exception" -repository = "https://github.com/bytecodealliance/wasmtime" -readme = "README.md" -edition = "2018" - -[lib] -proc-macro = true -test = false -doctest = false - -[dependencies] -proc-macro2 = "1.0" -quote = "1.0" -syn = { version = "1.0", features = ['full'] } - -[badges] -maintenance = { status = "actively-developed" } diff --git a/crates/misc/rust/macro/README.md b/crates/misc/rust/macro/README.md deleted file mode 100644 index 8199860771..0000000000 --- a/crates/misc/rust/macro/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# `wasmtime-rust-macro` - -This is the actual definition of the `#[wasmtime]` macro, but it's intended that -this crate isn't used directly but rather the `wasmtime-rust` crate is used -instead. diff --git a/crates/misc/rust/macro/src/lib.rs b/crates/misc/rust/macro/src/lib.rs deleted file mode 100644 index cbc2fe3c90..0000000000 --- a/crates/misc/rust/macro/src/lib.rs +++ /dev/null @@ -1,184 +0,0 @@ -extern crate proc_macro; - -use proc_macro2::TokenStream; -use quote::quote; -use syn::spanned::Spanned; - -#[proc_macro_attribute] -pub fn wasmtime( - _attr: proc_macro::TokenStream, - item: proc_macro::TokenStream, -) -> proc_macro::TokenStream { - let item = syn::parse_macro_input!(item as syn::ItemTrait); - expand(item).unwrap_or_else(|e| e.to_compile_error()).into() -} - -fn expand(item: syn::ItemTrait) -> syn::Result { - let definition = generate_struct(&item)?; - let load = generate_load(&item)?; - let methods = generate_methods(&item)?; - let name = &item.ident; - - Ok(quote! { - #definition - impl #name { - #load - #methods - } - }) -} - -fn generate_struct(item: &syn::ItemTrait) -> syn::Result { - let vis = &item.vis; - let name = &item.ident; - let root = root(); - Ok(quote! { - #vis struct #name { - instance: #root::wasmtime::Instance, - data: #root::wasmtime_interface_types::ModuleData, - } - }) -} - -fn generate_load(item: &syn::ItemTrait) -> syn::Result { - let vis = &item.vis; - let name = &item.ident; - let root = root(); - Ok(quote! { - #vis fn load_file(path: impl AsRef) -> #root::anyhow::Result<#name> { - Self::load_bytes(std::fs::read(path)?) - } - - #vis fn load_bytes(bytes: impl AsRef<[u8]>) -> #root::anyhow::Result<#name> { - use #root::wasmtime::{Config, Extern, Engine, Store, Instance, Module}; - use #root::anyhow::{bail, format_err}; - - let store = Store::default(); - - let data = #root::wasmtime_interface_types::ModuleData::new(bytes.as_ref())?; - - let module = Module::new(&engine, bytes.as_ref())?; - - let mut imports: Vec = Vec::new(); - if let Some(module_name) = data.find_wasi_module_name() { - let wasi_cx = #root::wasmtime_wasi::WasiCtxBuilder::new().build(); - let wasi = #root::wasmtime_wasi::Wasi::new(&store, wasi_cx); - for i in module.imports().iter() { - if i.module() != module_name { - bail!("unknown import module {}", i.module()); - } - if let Some(export) = wasi.get_export(i.name()) { - imports.push(export.clone().into()); - } else { - bail!("unknown import {}:{}", i.module(), i.name()) - } - } - } - let instance = - Instance::new(&store, &module, &imports).map_err(|t| format_err!("instantiation trap: {:?}", t))?; - - Ok(#name { instance, data }) - } - }) -} - -fn generate_methods(item: &syn::ItemTrait) -> syn::Result { - macro_rules! bail { - ($e:expr, $($fmt:tt)*) => ( - return Err(syn::Error::new($e.span(), format!($($fmt)*))); - ) - } - let mut result = TokenStream::new(); - let root = root(); - let vis = &item.vis; - - for item in item.items.iter() { - let method = match item { - syn::TraitItem::Method(f) => f, - other => bail!(other, "only methods are allowed"), - }; - if let Some(e) = &method.default { - bail!(e, "cannot specify an implementation of methods"); - } - if let Some(t) = &method.sig.constness { - bail!(t, "cannot be `const`"); - } - if let Some(t) = &method.sig.asyncness { - bail!(t, "cannot be `async`"); - } - match &method.sig.inputs.first() { - Some(syn::FnArg::Receiver(_)) => {} - Some(t) => bail!(t, "first arugment needs to be \"self\""), - None => bail!( - method.sig, - "trait method requires at least one argument which needs to be \"self\"" - ), - } - - let mut args = Vec::new(); - for arg in method.sig.inputs.iter() { - let arg = match arg { - syn::FnArg::Receiver(_) => continue, - syn::FnArg::Typed(arg) => arg, - }; - let ident = match &*arg.pat { - syn::Pat::Ident(i) => i, - other => bail!(other, "must use bare idents for arguments"), - }; - if let Some(t) = &ident.by_ref { - bail!(t, "arguments cannot bind by reference"); - } - if let Some(t) = &ident.mutability { - bail!(t, "arguments cannot be mutable"); - } - if let Some((_, t)) = &ident.subpat { - bail!(t, "arguments cannot have sub-bindings"); - } - let ident = &ident.ident; - args.push(quote! { - #root::wasmtime_interface_types::Value::from(#ident) - }); - } - - let convert_ret = match &method.sig.output { - syn::ReturnType::Default => { - quote! { - <() as #root::FromVecValue>::from(results) - } - } - syn::ReturnType::Type(_, ty) => match &**ty { - syn::Type::Tuple(..) => { - quote! { <#ty as #root::FromVecValue>::from(results) } - } - _ => { - quote! { <(#ty,) as #root::FromVecValue>::from(results).map(|t| t.0) } - } - }, - }; - - let sig = &method.sig; - let attrs = &method.attrs; - let name = &method.sig.ident; - - result.extend(quote! { - #(#attrs)* - #vis #sig { - let args = [ - #(#args),* - ]; - let results = self.data.invoke_export( - &self.instance, - stringify!(#name), - &args, - ).expect("wasm execution failed"); - #convert_ret.expect("failed to convert return type") - } - }); - } - - Ok(result) -} - -fn root() -> TokenStream { - quote! { wasmtime_rust::__rt } -} diff --git a/crates/misc/rust/src/lib.rs b/crates/misc/rust/src/lib.rs deleted file mode 100644 index 91b0e011bd..0000000000 --- a/crates/misc/rust/src/lib.rs +++ /dev/null @@ -1,44 +0,0 @@ -pub use wasmtime_rust_macro::wasmtime; - -// modules used by the macro -#[doc(hidden)] -pub mod __rt { - pub use anyhow; - pub use wasmtime; - pub use wasmtime_wasi; - - use std::convert::{TryFrom, TryInto}; - - pub trait FromVecValue: Sized { - fn from(list: Vec) -> anyhow::Result; - } - - macro_rules! tuple { - ($(($($a:ident),*),)*) => ($( - impl<$($a: TryFrom),*> FromVecValue for ($($a,)*) - where $(anyhow::Error: From<$a::Error>,)* - { - #[allow(non_snake_case)] - fn from(list: Vec) -> anyhow::Result { - let mut iter = list.into_iter(); - $( - let $a = iter.next() - .ok_or_else(|| anyhow::format_err!("not enough values"))? - .try_into()?; - )* - if iter.next().is_some() { - anyhow::bail!("too many return values"); - } - Ok(($($a,)*)) - } - } - )*) - } - - tuple! { - (), - (A), - (A, B), - (A, B, C), - } -}