derive GameEvent parsing

This commit is contained in:
Robin Appelman 2023-03-11 22:39:31 +01:00
commit f5957059d8
10 changed files with 116 additions and 121 deletions

68
derive/src/events.rs Normal file
View file

@ -0,0 +1,68 @@
use crate::{err, Derivable, DeriveParams};
use proc_macro2::{Ident, TokenStream};
use quote::quote_spanned;
use syn::{Data, DeriveInput, Generics, Result};
pub struct Events;
impl Derivable for Events {
type Params = EventsParam;
fn derive(params: EventsParam) -> Result<TokenStream> {
let enum_ident = params.name;
let span = enum_ident.span();
let variants = params.variants.iter().map(|(variant_name, empty)| {
let span = variant_name.span();
if *empty {
quote_spanned!(span => RawEventType::#variant_name => Self::#variant_name,)
} else {
quote_spanned!(span => RawEventType::#variant_name => Self::#variant_name(parse_event(raw.params).with_raw(raw)?),)
}
});
let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl();
Ok(
quote_spanned!(span => impl #impl_generics #enum_ident #ty_generics #where_clause {
pub fn parse(raw: &RawEvent<'a>) -> Result<Self, GameEventError> {
Ok(match raw.ty {
#(#variants)*
_ => {
todo!("{:?} not parsed yet", raw.ty);
}
})
}
}),
)
}
}
#[derive(Debug)]
pub struct EventsParam {
name: Ident,
generics: Generics,
variants: Vec<(Ident, bool)>,
}
impl DeriveParams for EventsParam {
fn parse(input: &DeriveInput) -> Result<EventsParam> {
let Data::Enum(data) = &input.data else {
return err("only supported on enums", input);
};
let name = input.ident.clone();
let generics = input.generics.clone();
let variants = data
.variants
.iter()
.map(|variant| (variant.ident.clone(), variant.fields.is_empty()))
.collect();
Ok(EventsParam {
name,
generics,
variants,
})
}
}

View file

@ -3,8 +3,10 @@
extern crate proc_macro;
mod event;
mod events;
use crate::event::Event;
use crate::events::Events;
use proc_macro2::TokenStream;
use quote::ToTokens;
use std::fmt::{Debug, Display};
@ -12,12 +14,20 @@ use syn::{parse_macro_input, DeriveInput, Error, Result};
/// Derive the `Event` trait for a struct
#[proc_macro_derive(Event, attributes(event))]
pub fn derive_pod(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
pub fn derive_event(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let expanded = derive_trait::<Event>(parse_macro_input!(input as DeriveInput));
proc_macro::TokenStream::from(expanded)
}
/// Derive the `Events` trait for a struct
#[proc_macro_derive(Events, attributes())]
pub fn derive_events(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let expanded = derive_trait::<Events>(parse_macro_input!(input as DeriveInput));
proc_macro::TokenStream::from(expanded)
}
/// Basic wrapper for error handling
fn derive_trait<Trait: Derivable>(input: DeriveInput) -> TokenStream {
derive_trait_inner::<Trait>(input).unwrap_or_else(|err| err.into_compile_error())