Remove long-outdated misc/rust crate (#2942)
I had no idea this was still in the repository, much less building! There are much different ways to use wasmtime in Rust nowadays, such as the `wasmtime` crate!
This commit is contained in:
19
Cargo.lock
generated
19
Cargo.lock
generated
@@ -3795,25 +3795,6 @@ dependencies = [
|
|||||||
"winapi",
|
"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]]
|
[[package]]
|
||||||
name = "wasmtime-wasi"
|
name = "wasmtime-wasi"
|
||||||
version = "0.27.0"
|
version = "0.27.0"
|
||||||
|
|||||||
@@ -74,7 +74,6 @@ members = [
|
|||||||
"crates/c-api",
|
"crates/c-api",
|
||||||
"crates/fuzzing",
|
"crates/fuzzing",
|
||||||
"crates/misc/run-examples",
|
"crates/misc/run-examples",
|
||||||
"crates/misc/rust",
|
|
||||||
"crates/wiggle",
|
"crates/wiggle",
|
||||||
"crates/wiggle/generate",
|
"crates/wiggle/generate",
|
||||||
"crates/wiggle/macro",
|
"crates/wiggle/macro",
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "wasmtime-rust"
|
|
||||||
version = "0.27.0"
|
|
||||||
authors = ["Alex Crichton <alex@alexcrichton.com>"]
|
|
||||||
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" }
|
|
||||||
@@ -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!
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "wasmtime-rust-macro"
|
|
||||||
version = "0.27.0"
|
|
||||||
authors = ["Alex Crichton <alex@alexcrichton.com>"]
|
|
||||||
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" }
|
|
||||||
@@ -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.
|
|
||||||
@@ -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<TokenStream> {
|
|
||||||
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<TokenStream> {
|
|
||||||
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<TokenStream> {
|
|
||||||
let vis = &item.vis;
|
|
||||||
let name = &item.ident;
|
|
||||||
let root = root();
|
|
||||||
Ok(quote! {
|
|
||||||
#vis fn load_file(path: impl AsRef<std::path::Path>) -> #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<Extern> = 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<TokenStream> {
|
|
||||||
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 }
|
|
||||||
}
|
|
||||||
@@ -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<wasmtime::Val>) -> anyhow::Result<Self>;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! tuple {
|
|
||||||
($(($($a:ident),*),)*) => ($(
|
|
||||||
impl<$($a: TryFrom<wasmtime::Val>),*> FromVecValue for ($($a,)*)
|
|
||||||
where $(anyhow::Error: From<$a::Error>,)*
|
|
||||||
{
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn from(list: Vec<wasmtime::Val>) -> anyhow::Result<Self> {
|
|
||||||
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),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user