use syn::{
parse::{Parse, ParseStream},
Ident, Lit, Token, Type,
};
#[allow(clippy::large_enum_variant)]
pub enum MetaValue {
Lit(Lit),
Type(Type),
}
impl Parse for MetaValue {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
if input.peek(Lit) {
input.parse().map(Self::Lit)
} else {
input.parse().map(Self::Type)
}
}
}
pub struct MetaNameValue<V> {
pub name: Ident,
pub value: V,
}
impl<V: Parse> Parse for MetaNameValue<V> {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
let ident = input.parse()?;
let _: Token![=] = input.parse()?;
Ok(MetaNameValue { name: ident, value: input.parse()? })
}
}
pub enum Meta<T> {
Word(Ident),
NameValue(MetaNameValue<T>),
}
impl<T: Parse> Meta<T> {
pub fn from_attribute(attr: &syn::Attribute) -> syn::Result<Option<Self>> {
if attr.path.is_ident("ruma_api") {
attr.parse_args().map(Some)
} else {
Ok(None)
}
}
}
impl<T: Parse> Parse for Meta<T> {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
let ident = input.parse()?;
if input.peek(Token![=]) {
let _: Token![=] = input.parse()?;
Ok(Meta::NameValue(MetaNameValue { name: ident, value: input.parse()? }))
} else {
Ok(Meta::Word(ident))
}
}
}