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

View File

@@ -46,14 +46,14 @@ impl Parse for Config {
fn parse(input: ParseStream<'_>) -> Result<Self> {
let call_site = Span::call_site();
let mut opts = Opts::default();
let mut world = None;
let mut source = None;
let mut world = None;
let document = if input.peek(token::Brace) {
if input.peek(token::Brace) {
let content;
syn::braced!(content in input);
let fields = Punctuated::<Opt, Token![,]>::parse_terminated(&content)?;
let mut document = None;
let mut world = None;
for field in fields.into_pairs() {
match field.into_value() {
Opt::Path(s) => {
@@ -63,10 +63,10 @@ impl Parse for Config {
source = Some(Source::Path(s.value()));
}
Opt::World(s) => {
if document.is_some() {
return Err(Error::new(s.span(), "cannot specify second document"));
if world.is_some() {
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) => {
if source.is_some() {
@@ -79,43 +79,17 @@ impl Parse for Config {
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 {
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() {
source = Some(Source::Path(input.parse::<syn::LitStr>()?.value()));
}
parse_doc(&document.value(), &mut world)
};
}
let (resolve, pkg, files) =
parse_source(&source).map_err(|err| Error::new(call_site, format!("{err:?}")))?;
let doc = resolve.packages[pkg]
.documents
.get(&document)
.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}`"))
})?,
};
let world = resolve
.select_world(pkg, world.as_deref())
.map_err(|e| Error::new(call_site, format!("{e:?}")))?;
Ok(Config {
opts,
resolve,
@@ -152,16 +126,6 @@ fn parse_source(source: &Option<Source>) -> anyhow::Result<(Resolve, PackageId,
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 {
syn::custom_keyword!(inline);
syn::custom_keyword!(path);