Update world-selection in bindgen! macro (#5779)

* Update world-selection in `bindgen!` macro

Inspired by bytecodealliance/wit-bindgen#494 specifying a world or
document to bindgen is now optional as it's inferred if there's only one
`default world` in a package's documents.

* Add cargo-vet entry
This commit is contained in:
Alex Crichton
2023-02-14 14:54:37 -06:00
committed by GitHub
parent cb150d37ce
commit 255fd6be0a
6 changed files with 34 additions and 55 deletions

4
Cargo.lock generated
View File

@@ -4110,9 +4110,9 @@ dependencies = [
[[package]] [[package]]
name = "wit-parser" name = "wit-parser"
version = "0.6.0" version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e0fe225a32528b42a7037add1b5ed1dff83288f21a067007b34565ce87fc2c7" checksum = "a84965789410bf21087f5a352703142f77b9b4d1478764c3f33a1ea8c7101f40"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"id-arena", "id-arena",

View File

@@ -169,7 +169,7 @@ wasmprinter = "0.2.50"
wasm-encoder = "0.23.0" wasm-encoder = "0.23.0"
wasm-smith = "0.12.1" wasm-smith = "0.12.1"
wasm-mutate = "0.2.17" wasm-mutate = "0.2.17"
wit-parser = "0.6.0" wit-parser = "0.6.1"
windows-sys = "0.45.0" windows-sys = "0.45.0"
env_logger = "0.9" env_logger = "0.9"
rustix = "0.36.7" rustix = "0.36.7"

View File

@@ -46,14 +46,14 @@ impl Parse for Config {
fn parse(input: ParseStream<'_>) -> Result<Self> { fn parse(input: ParseStream<'_>) -> Result<Self> {
let call_site = Span::call_site(); let call_site = Span::call_site();
let mut opts = Opts::default(); let mut opts = Opts::default();
let mut world = None;
let mut source = None; let mut source = None;
let mut world = None;
let document = if input.peek(token::Brace) { if input.peek(token::Brace) {
let content; let content;
syn::braced!(content in input); syn::braced!(content in input);
let fields = Punctuated::<Opt, Token![,]>::parse_terminated(&content)?; let fields = Punctuated::<Opt, Token![,]>::parse_terminated(&content)?;
let mut document = None; let mut world = None;
for field in fields.into_pairs() { for field in fields.into_pairs() {
match field.into_value() { match field.into_value() {
Opt::Path(s) => { Opt::Path(s) => {
@@ -63,10 +63,10 @@ impl Parse for Config {
source = Some(Source::Path(s.value())); source = Some(Source::Path(s.value()));
} }
Opt::World(s) => { Opt::World(s) => {
if document.is_some() { if world.is_some() {
return Err(Error::new(s.span(), "cannot specify second document")); return Err(Error::new(s.span(), "cannot specify second world"));
} }
document = Some(parse_doc(&s.value(), &mut world)); world = Some(s.value());
} }
Opt::Inline(s) => { Opt::Inline(s) => {
if source.is_some() { if source.is_some() {
@@ -79,43 +79,17 @@ impl Parse for Config {
Opt::TrappableErrorType(val) => opts.trappable_error_type = val, Opt::TrappableErrorType(val) => opts.trappable_error_type = val,
} }
} }
match (document, &source) {
(Some(doc), _) => doc,
(None, Some(Source::Inline(_))) => "macro-input".to_string(),
_ => {
return Err(Error::new(
call_site,
"must specify a `world` to generate bindings for",
))
}
}
} else { } else {
let document = input.parse::<syn::LitStr>()?; world = input.parse::<Option<syn::LitStr>>()?.map(|s| s.value());
if input.parse::<Option<syn::token::In>>()?.is_some() { if input.parse::<Option<syn::token::In>>()?.is_some() {
source = Some(Source::Path(input.parse::<syn::LitStr>()?.value())); source = Some(Source::Path(input.parse::<syn::LitStr>()?.value()));
} }
parse_doc(&document.value(), &mut world) }
};
let (resolve, pkg, files) = let (resolve, pkg, files) =
parse_source(&source).map_err(|err| Error::new(call_site, format!("{err:?}")))?; parse_source(&source).map_err(|err| Error::new(call_site, format!("{err:?}")))?;
let doc = resolve.packages[pkg] let world = resolve
.documents .select_world(pkg, world.as_deref())
.get(&document) .map_err(|e| Error::new(call_site, format!("{e:?}")))?;
.copied()
.ok_or_else(|| {
Error::new(call_site, format!("no document named `{document}` found"))
})?;
let world = match &world {
Some(name) => resolve.documents[doc]
.worlds
.get(name)
.copied()
.ok_or_else(|| Error::new(call_site, format!("no world named `{name}` found")))?,
None => resolve.documents[doc].default_world.ok_or_else(|| {
Error::new(call_site, format!("no default world found in `{document}`"))
})?,
};
Ok(Config { Ok(Config {
opts, opts,
resolve, resolve,
@@ -152,16 +126,6 @@ fn parse_source(source: &Option<Source>) -> anyhow::Result<(Resolve, PackageId,
Ok((resolve, pkg, files)) Ok((resolve, pkg, files))
} }
fn parse_doc(s: &str, world: &mut Option<String>) -> String {
match s.find('.') {
Some(pos) => {
*world = Some(s[pos + 1..].to_string());
s[..pos].to_string()
}
None => s.to_string(),
}
}
mod kw { mod kw {
syn::custom_keyword!(inline); syn::custom_keyword!(inline);
syn::custom_keyword!(path); syn::custom_keyword!(path);

View File

@@ -1,20 +1,22 @@
macro_rules! gentest { macro_rules! gentest {
($id:ident $name:tt $path:tt) => { ($id:ident $name:tt $path:tt) => {
mod $id { mod $id {
mod sugar {
wasmtime::component::bindgen!(in $path);
}
mod normal { mod normal {
wasmtime::component::bindgen!($name in $path); wasmtime::component::bindgen!($name in $path);
} }
mod async_ { mod async_ {
wasmtime::component::bindgen!({ wasmtime::component::bindgen!({
world: $name,
path: $path, path: $path,
async: true, async: true,
}); });
} }
mod tracing { mod tracing {
wasmtime::component::bindgen!({ wasmtime::component::bindgen!({
world: $name,
path: $path, path: $path,
world: $name,
tracing: true, tracing: true,
}); });
} }

View File

@@ -84,7 +84,7 @@ pub(crate) use self::store::ComponentStoreData;
/// use wasmtime::component::*; /// use wasmtime::component::*;
/// use wasmtime::{Config, Engine, Store}; /// use wasmtime::{Config, Engine, Store};
/// ///
/// bindgen!("my-component"); /// bindgen!();
/// ///
/// struct MyState { /// struct MyState {
/// name: String, /// name: String,
@@ -170,7 +170,7 @@ pub(crate) use self::store::ComponentStoreData;
/// use wasmtime::component::*; /// use wasmtime::component::*;
/// use wasmtime::{Config, Engine, Store}; /// use wasmtime::{Config, Engine, Store};
/// ///
/// bindgen!("my-component"); /// bindgen!();
/// ///
/// struct MyState { /// struct MyState {
/// // ... /// // ...
@@ -223,6 +223,11 @@ pub(crate) use self::store::ComponentStoreData;
/// ///
/// ```rust,ignore /// ```rust,ignore
/// // Parse the `wit/` folder adjacent to this crate's `Cargo.toml` and look /// // Parse the `wit/` folder adjacent to this crate's `Cargo.toml` and look
/// // for a `default world` in its documents. There must be exactly one
/// // `default world` for this to succeed.
/// bindgen!();
///
/// // Parse the `wit/` folder adjacent to this crate's `Cargo.toml` and look
/// // for the document `foo`, which must have a `default world` contained /// // for the document `foo`, which must have a `default world` contained
/// // within it. /// // within it.
/// bindgen!("foo"); /// bindgen!("foo");
@@ -232,6 +237,7 @@ pub(crate) use self::store::ComponentStoreData;
/// bindgen!("foo.bar"); /// bindgen!("foo.bar");
/// ///
/// // Parse the folder `other/wit/folder` adjacent to `Cargo.toml`. /// // Parse the folder `other/wit/folder` adjacent to `Cargo.toml`.
/// bindgen!(in "other/wit/folder");
/// bindgen!("foo" in "other/wit/folder"); /// bindgen!("foo" in "other/wit/folder");
/// bindgen!("foo.bar" in "other/wit/folder"); /// bindgen!("foo.bar" in "other/wit/folder");
/// ///
@@ -245,8 +251,9 @@ pub(crate) use self::store::ComponentStoreData;
/// ```rust,ignore /// ```rust,ignore
/// bindgen!({ /// bindgen!({
/// world: "foo", // or "foo.bar", same as in `bindgen!("foo")` /// world: "foo", // or "foo.bar", same as in `bindgen!("foo")`
/// // not needed if `path` has one `default world`
/// ///
/// // same as in `bindgen!("foo" in "other/wit/folder") /// // same as in `bindgen!(in "other/wit/folder")
/// path: "other/wit/folder", /// path: "other/wit/folder",
/// ///
/// // Instead of `path` the WIT document can be provided inline if /// // Instead of `path` the WIT document can be provided inline if

View File

@@ -1442,3 +1442,9 @@ criteria = "safe-to-deploy"
version = "0.6.0" version = "0.6.0"
notes = "The Bytecode Alliance is the author of this crate." notes = "The Bytecode Alliance is the author of this crate."
[[audits.wit-parser]]
who = "Alex Crichton <alex@alexcrichton.com>"
criteria = "safe-to-deploy"
version = "0.6.1"
notes = "The Bytecode Alliance is the author of this crate."