Allow inline source and the path attribute in the host bindgen! macro (#6226)
* Allow inline source and the `path` attribute in the host bindgen! macro * Report an error if `world` is passed with `interfaces`
This commit is contained in:
@@ -38,17 +38,13 @@ pub fn expand(input: &Config) -> Result<TokenStream> {
|
|||||||
Ok(contents)
|
Ok(contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Source {
|
|
||||||
Path(String),
|
|
||||||
Inline(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Parse for Config {
|
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 source = None;
|
|
||||||
let mut world = None;
|
let mut world = None;
|
||||||
|
let mut inline = None;
|
||||||
|
let mut path = None;
|
||||||
|
|
||||||
if input.peek(token::Brace) {
|
if input.peek(token::Brace) {
|
||||||
let content;
|
let content;
|
||||||
@@ -57,10 +53,10 @@ impl Parse for Config {
|
|||||||
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) => {
|
||||||
if source.is_some() {
|
if path.is_some() {
|
||||||
return Err(Error::new(s.span(), "cannot specify second source"));
|
return Err(Error::new(s.span(), "cannot specify second path"));
|
||||||
}
|
}
|
||||||
source = Some(Source::Path(s.value()));
|
path = Some(s.value());
|
||||||
}
|
}
|
||||||
Opt::World(s) => {
|
Opt::World(s) => {
|
||||||
if world.is_some() {
|
if world.is_some() {
|
||||||
@@ -69,23 +65,29 @@ impl Parse for Config {
|
|||||||
world = Some(s.value());
|
world = Some(s.value());
|
||||||
}
|
}
|
||||||
Opt::Inline(s) => {
|
Opt::Inline(s) => {
|
||||||
if source.is_some() {
|
if inline.is_some() {
|
||||||
return Err(Error::new(s.span(), "cannot specify second source"));
|
return Err(Error::new(s.span(), "cannot specify second source"));
|
||||||
}
|
}
|
||||||
source = Some(Source::Inline(s.value()));
|
inline = Some(s.value());
|
||||||
}
|
}
|
||||||
Opt::Tracing(val) => opts.tracing = val,
|
Opt::Tracing(val) => opts.tracing = val,
|
||||||
Opt::Async(val) => opts.async_ = val,
|
Opt::Async(val) => opts.async_ = val,
|
||||||
Opt::TrappableErrorType(val) => opts.trappable_error_type = val,
|
Opt::TrappableErrorType(val) => opts.trappable_error_type = val,
|
||||||
Opt::DuplicateIfNecessary(val) => opts.duplicate_if_necessary = val,
|
Opt::DuplicateIfNecessary(val) => opts.duplicate_if_necessary = val,
|
||||||
Opt::Interfaces(s) => {
|
Opt::Interfaces(s) => {
|
||||||
if source.is_some() {
|
if inline.is_some() {
|
||||||
return Err(Error::new(s.span(), "cannot specify a second source"));
|
return Err(Error::new(s.span(), "cannot specify a second source"));
|
||||||
}
|
}
|
||||||
source = Some(Source::Inline(format!(
|
inline = Some(format!("default world interfaces {{ {} }}", s.value()));
|
||||||
"default world interfaces {{ {} }}",
|
|
||||||
s.value()
|
if world.is_some() {
|
||||||
)));
|
return Err(Error::new(
|
||||||
|
s.span(),
|
||||||
|
"cannot specify a world with `interfaces`",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
world = Some("macro-input.interfaces".to_string());
|
||||||
|
|
||||||
opts.only_interfaces = true;
|
opts.only_interfaces = true;
|
||||||
}
|
}
|
||||||
Opt::With(val) => opts.with.extend(val),
|
Opt::With(val) => opts.with.extend(val),
|
||||||
@@ -94,11 +96,12 @@ impl Parse for Config {
|
|||||||
} else {
|
} else {
|
||||||
world = input.parse::<Option<syn::LitStr>>()?.map(|s| s.value());
|
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()));
|
path = Some(input.parse::<syn::LitStr>()?.value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let (resolve, pkg, files) =
|
let (resolve, pkg, files) = parse_source(&path, &inline)
|
||||||
parse_source(&source).map_err(|err| Error::new(call_site, format!("{err:?}")))?;
|
.map_err(|err| Error::new(call_site, format!("{err:?}")))?;
|
||||||
|
|
||||||
let world = resolve
|
let world = resolve
|
||||||
.select_world(pkg, world.as_deref())
|
.select_world(pkg, world.as_deref())
|
||||||
.map_err(|e| Error::new(call_site, format!("{e:?}")))?;
|
.map_err(|e| Error::new(call_site, format!("{e:?}")))?;
|
||||||
@@ -111,11 +114,15 @@ impl Parse for Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_source(source: &Option<Source>) -> anyhow::Result<(Resolve, PackageId, Vec<PathBuf>)> {
|
fn parse_source(
|
||||||
|
path: &Option<String>,
|
||||||
|
inline: &Option<String>,
|
||||||
|
) -> anyhow::Result<(Resolve, PackageId, Vec<PathBuf>)> {
|
||||||
let mut resolve = Resolve::default();
|
let mut resolve = Resolve::default();
|
||||||
let mut files = Vec::new();
|
let mut files = Vec::new();
|
||||||
let root = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
|
let root = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
|
||||||
let mut parse = |path: &Path| -> anyhow::Result<_> {
|
|
||||||
|
let mut parse = |resolve: &mut Resolve, path: &Path| -> anyhow::Result<_> {
|
||||||
if path.is_dir() {
|
if path.is_dir() {
|
||||||
let (pkg, sources) = resolve.push_dir(path)?;
|
let (pkg, sources) = resolve.push_dir(path)?;
|
||||||
files = sources;
|
files = sources;
|
||||||
@@ -126,15 +133,32 @@ fn parse_source(source: &Option<Source>) -> anyhow::Result<(Resolve, PackageId,
|
|||||||
resolve.push(pkg, &Default::default())
|
resolve.push(pkg, &Default::default())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let pkg = match source {
|
|
||||||
Some(Source::Inline(s)) => resolve.push(
|
let path_pkg = if let Some(path) = path {
|
||||||
UnresolvedPackage::parse("macro-input".as_ref(), s)?,
|
Some(parse(&mut resolve, &root.join(&path))?)
|
||||||
&Default::default(),
|
} else {
|
||||||
)?,
|
None
|
||||||
Some(Source::Path(s)) => parse(&root.join(s))?,
|
|
||||||
None => parse(&root.join("wit"))?,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let inline_pkg = if let Some(inline) = inline {
|
||||||
|
let deps = resolve
|
||||||
|
.packages
|
||||||
|
.iter()
|
||||||
|
.map(|(id, p)| (p.name.clone(), id))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Some(resolve.push(
|
||||||
|
UnresolvedPackage::parse("macro-input".as_ref(), &inline)?,
|
||||||
|
&deps,
|
||||||
|
)?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let pkg = inline_pkg
|
||||||
|
.or(path_pkg)
|
||||||
|
.map_or_else(|| parse(&mut resolve, &root.join("wit")), Ok)?;
|
||||||
|
|
||||||
Ok((resolve, pkg, files))
|
Ok((resolve, pkg, files))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user