use syn::{
Ident, Result, Token, parenthesized,
parse::{Parse, ParseStream},
punctuated::Punctuated,
};
pub enum OutputSpec {
SingleField(Ident),
TupleFields(Vec<Ident>),
Struct,
}
pub struct ModuleAttrs {
pub output: OutputSpec,
}
impl Parse for ModuleAttrs {
fn parse(input: ParseStream) -> Result<Self> {
let ident: Ident = input.parse()?;
if ident != "output" {
return Err(syn::Error::new(ident.span(), "Expected `output = ...`"));
}
input.parse::<Token![=]>()?;
let output = if input.peek(syn::token::Paren) {
let content;
parenthesized!(content in input);
let fields: Punctuated<Ident, Token![,]> =
content.parse_terminated(Ident::parse, Token![,])?;
OutputSpec::TupleFields(fields.into_iter().collect())
} else {
let name: Ident = input.parse()?;
let name_str = name.to_string();
if name_str
.chars()
.next()
.map(|c| c.is_uppercase())
.unwrap_or(false)
{
OutputSpec::Struct
} else {
OutputSpec::SingleField(name)
}
};
Ok(ModuleAttrs { output })
}
}