cido-macros 0.2.0

Macros for generating code that enables easier interfacing with cido
Documentation
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 {
  /// Identifier for the event.
  pub name: Ident,
  /// The actual type of the event.
  pub ty: Type,
  /// Options specified by attributes on each enum variant
  pub config: HandlerConfigOptions,
}

#[derive(Debug, ParseMetaItem)]
pub struct EventHandlerTraitInfoParse {
  /// Top level cido struct this event will be used with.
  pub cidomap: TypePath,
  #[deluxe(default)]
  pub error_handler: ErrorFlow,
  pub embed_generated_code: deluxe::Flag,
}

#[derive(Debug, ExtractAttributes)]
#[deluxe(attributes(handler))]
pub struct HandlerConfigOptions {
  /// The path to the event handler function.
  #[deluxe(rename = fn)]
  pub func: Path,
  /// If `generator` is set then this event will spawn events through the provided function.
  pub generator: Option<Path>,
  /// The preprocessor options
  pub preprocessor: Option<Preprocessor>,
}

#[derive(Debug, ParseMetaItem)]
pub struct Preprocessor {
  /// Path to the type of preprocessor cache
  pub cache: Type,
  /// Path to the function that runs the preprocessor
  #[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),
}