use syn::{
parse::{Parse, ParseStream},
Attribute, LitBool, Token,
};
#[derive(Debug)]
pub(crate) struct ValueOption<K, V> {
pub _key: K,
pub _assign: syn::token::Eq,
pub value: V,
}
impl<K: Parse, V: Parse> Parse for ValueOption<K, V> {
fn parse(input: ParseStream) -> syn::Result<Self> {
let key: K = input.parse()?;
let assign: Token![=] = input.parse()?;
let value: V = input.parse()?;
Ok(ValueOption {
_key: key,
_assign: assign,
value,
})
}
}
#[derive(Debug)]
pub(crate) struct FlagOption<K> {
pub _key: K,
pub value: Option<(syn::token::Eq, LitBool)>,
}
impl<K> FlagOption<K> {
pub fn is_true(&self) -> bool {
self.value.as_ref().map(|x| x.1.value).unwrap_or(true)
}
}
impl<K: Parse> Parse for FlagOption<K> {
fn parse(input: ParseStream) -> syn::Result<Self> {
let key: K = input.parse()?;
let value = input
.peek(Token![=])
.then(|| {
let assign: Token![=] = input.parse()?;
let value: LitBool = input.parse()?;
syn::Result::Ok((assign, value))
})
.transpose()?;
Ok(FlagOption { _key: key, value })
}
}
#[derive(Debug)]
pub struct OptionList<O>(pub Vec<O>);
impl<O: Parse> Parse for OptionList<O> {
fn parse(input: ParseStream) -> syn::Result<Self> {
if input.is_empty() {
return Ok(OptionList(Vec::new()));
}
let mut res = Vec::new();
loop {
res.push(O::parse(input)?);
if input.is_empty() {
return Ok(OptionList(res));
}
input.parse::<Token![,]>()?;
if input.is_empty() {
return Ok(OptionList(res));
}
}
}
}
pub fn take_attributes(
attrs: &mut Vec<Attribute>,
mut extractor: impl FnMut(&Attribute) -> syn::Result<bool>,
) -> syn::Result<()> {
*attrs = attrs
.drain(..)
.filter_map(|attr| {
extractor(&attr)
.map(|handled| if handled { None } else { Some(attr) })
.transpose()
})
.collect::<syn::Result<_>>()?;
Ok(())
}