mirror of https://github.com/aya-rs/aya
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
84 lines
2.3 KiB
Rust
84 lines
2.3 KiB
Rust
use syn::{
|
|
parse::{Parse, ParseStream},
|
|
punctuated::{Pair, Punctuated},
|
|
Error, Ident, LitStr, Result, Token,
|
|
};
|
|
|
|
pub(crate) struct NameValue {
|
|
name: Ident,
|
|
value: LitStr,
|
|
}
|
|
|
|
pub(crate) enum Arg {
|
|
String(NameValue),
|
|
Bool(Ident),
|
|
}
|
|
|
|
pub(crate) struct Args {
|
|
pub(crate) args: Vec<Arg>,
|
|
}
|
|
|
|
impl Parse for Args {
|
|
fn parse(input: ParseStream) -> Result<Args> {
|
|
let args = Punctuated::<Arg, Token![,]>::parse_terminated_with(input, |input| {
|
|
let ident = input.parse::<Ident>()?;
|
|
let lookahead = input.lookahead1();
|
|
if input.is_empty() || lookahead.peek(Token![,]) {
|
|
Ok(Arg::Bool(ident))
|
|
} else if lookahead.peek(Token![=]) {
|
|
let _: Token![=] = input.parse()?;
|
|
Ok(Arg::String(NameValue {
|
|
name: ident,
|
|
value: input.parse()?,
|
|
}))
|
|
} else {
|
|
Err(lookahead.error())
|
|
}
|
|
})?
|
|
.into_pairs()
|
|
.map(|pair| match pair {
|
|
Pair::Punctuated(name_val, _) => name_val,
|
|
Pair::End(name_val) => name_val,
|
|
})
|
|
.collect();
|
|
|
|
Ok(Args { args })
|
|
}
|
|
}
|
|
|
|
pub(crate) fn pop_string_arg(args: &mut Args, name: &str) -> Option<String> {
|
|
args.args
|
|
.iter()
|
|
.position(|arg| matches!(arg, Arg::String(name_val) if name_val.name == name))
|
|
.map(|index| match args.args.remove(index) {
|
|
Arg::String(v) => v.value.value(),
|
|
_ => panic!("impossible variant"),
|
|
})
|
|
}
|
|
|
|
pub(crate) fn pop_bool_arg(args: &mut Args, name: &str) -> bool {
|
|
args.args
|
|
.iter()
|
|
.position(|arg| matches!(arg, Arg::Bool(ident) if ident == name))
|
|
.map(|index| match args.args.remove(index) {
|
|
Arg::Bool(ident) => ident,
|
|
_ => panic!("impossible variant"),
|
|
})
|
|
.is_some()
|
|
}
|
|
|
|
pub(crate) fn err_on_unknown_args(args: &Args) -> Result<()> {
|
|
if let Some(arg) = args.args.first() {
|
|
let tokens = match arg {
|
|
Arg::String(name_val) => name_val.name.clone(),
|
|
Arg::Bool(ident) => ident.clone(),
|
|
};
|
|
return Err(Error::new_spanned(tokens, "invalid argument"));
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
pub(crate) fn name_arg(args: &mut Args) -> Option<String> {
|
|
pop_string_arg(args, "name")
|
|
}
|