use syn::parse::{Parse, ParseStream, Result};
use syn::punctuated::Punctuated;
use syn::Token;
struct Attr {
pub ident: syn::Ident,
pub _eq: syn::Token![=],
pub val: syn::LitStr,
}
impl Parse for Attr {
fn parse(input: ParseStream) -> Result<Self> {
Ok(Attr {
ident: input.parse()?,
_eq: input.parse()?,
val: input.parse()?,
})
}
}
#[derive(Copy, Clone)]
pub enum Language {
C,
Rust,
Typescript,
}
impl Default for Language {
fn default() -> Self {
Language::C
}
}
impl From<syn::LitStr> for Language {
fn from(value: syn::LitStr) -> Self {
match value.value().as_str() {
"ts" | "typescript" | "TYPESCRIPT" => Language::Typescript,
"rs" | "rust" | "RUST" => Language::Rust,
"c" | "C" => Language::C,
_ => Language::default(),
}
}
}
#[derive(Default)]
pub struct Attributes {
pub prefix: Option<syn::LitStr>,
pub file: Option<syn::LitStr>,
pub meta: Option<syn::LitStr>,
pub language: Language,
}
impl Parse for Attributes {
fn parse(i: ParseStream) -> Result<Self> {
let p = Punctuated::<Attr, Token![,]>::parse_terminated_with(i, Attr::parse)?;
let state = Attributes {
..Default::default()
};
let attrs = p.into_iter().fold(state, |mut state, attr| {
if attr.ident == "prefix" {
state.prefix = Some(attr.val);
} else if attr.ident == "language" {
state.language = attr.val.into()
} else if attr.ident == "file" {
state.file = Some(attr.val)
} else if attr.ident == "meta" {
state.meta = Some(attr.val)
}
state
});
Ok(attrs)
}
}