use deluxe::{ExtractAttributes, ParseMetaItem};
use proc_macro2::TokenStream;
use syn::{Ident, Path, Type, TypePath};
#[derive(Debug)]
pub struct EventsEnum {
pub name: Ident,
pub cidomap: TypePath,
pub events: Vec<HandlerConfig>,
pub error_handler: ErrorFlow,
pub embed_generated_code: bool,
}
impl EventsEnum {
pub fn parse(args: TokenStream, input: TokenStream) -> deluxe::Result<Self> {
let event_options = deluxe::parse2::<EventHandlerTraitInfoParse>(args)?;
let e = syn::parse2::<syn::ItemEnum>(input)?;
crate::parse::ensure_generics_zero(&e.generics)?;
let mut events = Vec::new();
for mut variant in e.variants {
let config = HandlerConfigOptions::extract_attributes(&mut variant)?;
match variant.fields {
syn::Fields::Unnamed(fields_unnamed) if fields_unnamed.unnamed.len() == 1 => {
if let Some(first_attr) = variant.attrs.first() {
return Err(crate::err(
&first_attr,
"No other attributes are allowed on event variants",
));
}
let ty = fields_unnamed.unnamed.first().unwrap().ty.clone();
let name = variant.ident.clone();
events.push(HandlerConfig { name, ty, config });
}
_ => {
return Err(crate::err(
&variant,
"Event enum only accepts a single unnamed field",
));
}
}
}
Ok(Self {
name: e.ident,
cidomap: event_options.cidomap,
embed_generated_code: event_options.embed_generated_code.is_set(),
error_handler: event_options.error_handler,
events,
})
}
}
#[derive(Debug)]
pub struct HandlerConfig {
pub name: Ident,
pub ty: Type,
pub config: HandlerConfigOptions,
}
#[derive(Debug, ParseMetaItem)]
pub struct EventHandlerTraitInfoParse {
pub cidomap: TypePath,
#[deluxe(default)]
pub error_handler: ErrorFlow,
pub embed_generated_code: deluxe::Flag,
}
#[derive(Debug, ExtractAttributes)]
#[deluxe(attributes(handler))]
pub struct HandlerConfigOptions {
#[deluxe(rename = fn)]
pub func: Path,
pub generator: Option<Path>,
pub preprocessor: Option<Preprocessor>,
}
#[derive(Debug, ParseMetaItem)]
pub struct Preprocessor {
pub cache: Type,
#[deluxe(rename = fn)]
pub func: Path,
}
#[derive(Debug, Default, ParseMetaItem)]
pub enum ErrorFlow {
#[default]
#[deluxe(skip)]
Break,
#[deluxe(rename = continue)]
Continue,
#[deluxe(rename = fn, transparent)]
HandlerFn(Path),
#[deluxe(rename = trait, transparent)]
HandlerTrait(Type),
}