Skip to main content

card_game_derive/
lib.rs

1extern crate proc_macro;
2
3use heck::{ToSnakeCase, ToUpperCamelCase};
4use itertools::Itertools;
5use proc_macro::TokenStream;
6use syn::{
7    DeriveInput, Field, Fields, Ident, Type, TypePath,
8    parse::{Parse, Parser},
9    parse_macro_input,
10    spanned::Spanned,
11    visit_mut::VisitMut,
12};
13
14struct EventManagerArgs {
15    states: StateMapping,
16    events: Vec<EventMapping>,
17}
18
19struct StateMapping {
20    states: Vec<(syn::Type, syn::ExprClosure)>,
21    placeholder: syn::Ident,
22}
23
24#[derive(Clone)]
25struct EventMapping {
26    event_fn: Option<syn::Ident>,
27    event: syn::Type,
28    stackable: syn::Type,
29    resolution: syn::Type,
30    stackable_enum_types: Vec<IdentAndType>,
31    resolution_enum_types: Vec<IdentAndType>,
32}
33
34impl Parse for EventManagerArgs {
35    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
36        let mut states = None;
37        let mut events = None;
38
39        while !input.is_empty() {
40            let key: Ident = input.parse()?;
41            let _ = input.parse::<syn::Token![=]>()?;
42
43            match key.to_string().as_str() {
44                "states" => {
45                    states = Some(input.parse()?);
46                }
47                "events" => {
48                    let content;
49                    syn::parenthesized!(content in input);
50                    let parsed = content
51                        .parse_terminated(EventMapping::parse, syn::Token![,])?
52                        .into_iter()
53                        .collect();
54                    events = Some(parsed);
55                }
56                _ => {
57                    return Err(syn::Error::new_spanned(key, "Unknown key"));
58                }
59            }
60
61            let _ = input.parse::<syn::Token![,]>();
62        }
63
64        Ok(EventManagerArgs {
65            states: states.ok_or_else(|| input.error("missing `states`"))?,
66            events: events.ok_or_else(|| input.error("missing `events`"))?,
67        })
68    }
69}
70
71impl Parse for StateMapping {
72    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
73        let content;
74        syn::parenthesized!(content in input);
75
76        let closures = content
77            .parse_terminated(syn::Expr::parse, syn::Token![,])?
78            .into_iter()
79            .collect::<Vec<_>>();
80
81        input.parse::<syn::Token![as]>()?;
82        let placeholder = input.parse::<Ident>()?;
83
84        let mut states = Vec::new();
85
86        for expr in closures {
87            let closure = match expr {
88                syn::Expr::Closure(closure) => closure,
89                _ => {
90                    return Err(syn::Error::new_spanned(
91                        expr,
92                        "expected a closure like `|state: Type| ...`",
93                    ));
94                }
95            };
96
97            if closure.inputs.len() != 1 {
98                return Err(syn::Error::new_spanned(
99                    &closure.inputs,
100                    "closure must have exactly one parameter",
101                ));
102            }
103
104            // Extract the type: |x: ShopStep|
105            let state_ty = match closure.inputs.first().unwrap() {
106                syn::Pat::Type(syn::PatType { ty, .. }) => match ty.as_ref() {
107                    Type::Reference(syn::TypeReference { elem, .. }) => (**elem).clone(),
108                    _ => {
109                        return Err(syn::Error::new_spanned(
110                            ty,
111                            "expected a reference type like `&StateType`",
112                        ));
113                    }
114                },
115                _ => {
116                    return Err(syn::Error::new_spanned(
117                        &closure.inputs,
118                        "closure parameter must be typed: `|state: Type|`",
119                    ));
120                }
121            };
122
123            states.push((state_ty, closure));
124        }
125
126        Ok(StateMapping {
127            states,
128            placeholder,
129        })
130    }
131}
132
133fn closure_to_item_fn(
134    closure: syn::ExprClosure,
135    fn_name: &str,
136    event_manager_name: Type,
137) -> syn::Result<syn::ItemFn> {
138    // Reject capturing closures
139    if closure.capture.is_some() {
140        return Err(syn::Error::new(
141            closure.span(),
142            "cannot convert capturing closure into function",
143        ));
144    }
145
146    // Convert closure inputs into fn inputs
147    let inputs = closure
148        .inputs
149        .into_iter()
150        .map(|pat| match pat {
151            syn::Pat::Type(pat_ty) => Ok(syn::FnArg::Typed(pat_ty)),
152            _ => Err(syn::Error::new_spanned(
153                pat,
154                "closure parameters must be typed",
155            )),
156        })
157        .collect::<syn::Result<_>>()?;
158
159    let sig = syn::Signature {
160        constness: closure.constness,
161        asyncness: closure.asyncness,
162        unsafety: None,
163        abi: None,
164        fn_token: Default::default(),
165        ident: Ident::new(fn_name, proc_macro2::Span::call_site()),
166        generics: Default::default(),
167        paren_token: Default::default(),
168        inputs,
169        variadic: None,
170        output: syn::ReturnType::Type(
171            syn::token::RArrow::default(),
172            Box::new(syn::parse_quote!(&#event_manager_name)),
173        ),
174    };
175
176    Ok(syn::ItemFn {
177        attrs: Vec::new(),
178        vis: syn::Visibility::Inherited,
179        sig,
180        block: Box::new(match *closure.body {
181            syn::Expr::Block(block) => block.block,
182            expr => syn::Block {
183                brace_token: syn::token::Brace::default(),
184                stmts: vec![syn::Stmt::Expr(expr, None)],
185            },
186        }),
187    })
188}
189
190impl Parse for EventMapping {
191    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
192        let event_fn = if input.peek2(syn::Token![->]) {
193            let event_fn = input.parse::<syn::Ident>()?;
194            let _ = input.parse::<syn::Token![->]>()?;
195            Some(event_fn)
196        } else {
197            None
198        };
199
200        let event = input.parse::<syn::Type>()?;
201        let _ = input.parse::<syn::Token![^]>()?;
202
203        let stackable = input.parse::<syn::Type>()?;
204
205        let stackable_enum_types = if input.peek(syn::token::Brace) {
206            let content;
207            syn::braced!(content in input);
208            content
209                .parse_terminated(IdentAndType::parse, syn::Token![,])?
210                .into_iter()
211                .collect::<Vec<_>>()
212        } else {
213            Vec::new()
214        };
215
216        let _ = input.parse::<syn::Token![=>]>()?;
217        let resolution = input.parse::<syn::Type>()?;
218
219        let resolution_enum_types = if input.peek(syn::token::Brace) {
220            let content;
221            syn::braced!(content in input);
222            content
223                .parse_terminated(IdentAndType::parse, syn::Token![,])?
224                .into_iter()
225                .collect::<Vec<_>>()
226        } else {
227            Vec::new()
228        };
229
230        Ok(EventMapping {
231            event_fn,
232            event,
233            stackable,
234            resolution,
235            stackable_enum_types,
236            resolution_enum_types,
237        })
238    }
239}
240
241#[derive(Clone)]
242struct IdentAndType {
243    ident: Option<Ident>,
244    ty: Type,
245}
246impl Parse for IdentAndType {
247    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
248        if input.peek2(syn::Token![:]) {
249            let ident = input.parse()?;
250            let _ = input.parse::<syn::Token![:]>()?;
251            let ty = input.parse()?;
252            Ok(IdentAndType {
253                ident: Some(ident),
254                ty,
255            })
256        } else {
257            Ok(IdentAndType {
258                ident: None,
259                ty: input.parse()?,
260            })
261        }
262    }
263}
264
265#[proc_macro_attribute]
266pub fn event_manager(args: TokenStream, input: TokenStream) -> TokenStream {
267    let args = parse_macro_input!(args as EventManagerArgs);
268    let mut ast = parse_macro_input!(input as syn::ItemStruct);
269    let struct_name = &ast.ident;
270    let mut impls = Vec::new();
271    if let Fields::Named(ref mut fields) = ast.fields {
272        let mut i: usize = 0;
273        for (state, get_event_manager) in args.states.states.iter() {
274            let get_event_manager = closure_to_item_fn(
275                get_event_manager.clone(),
276                "get_event_manager",
277                syn::parse_quote!(#struct_name),
278            )
279            .expect("failed to make function from closure");
280            let original_state = &state;
281            for event in args.events.iter() {
282                {
283                    let state_str = quote::quote!(#state).to_string();
284                    let state = syn::parse_quote!(card_game::stack::priority::Priority<#state>);
285                    let event_resolution =
286                        substitute_type(&event.resolution, &args.states.placeholder, &state);
287                    let stackable =
288                        substitute_type(&event.stackable, &args.states.placeholder, &state);
289                    let event = &event.event;
290                    let event_name = quote::quote!(#event).to_string();
291                    let field_name = quote::format_ident!(
292                        "{}_during_{}",
293                        event_name.to_snake_case(),
294                        state_str.to_snake_case(),
295                    );
296                    let field_id_name = quote::format_ident!("{}_id", field_name.to_string());
297                    let return_ty: syn::Type = syn::parse_quote!(
298                        card_game::events::EventManager<
299                            #state,
300                            #event,
301                            #event_resolution<#state>,
302                        >
303                    );
304                    let new_field = Field {
305                        attrs: Vec::new(),
306                        mutability: syn::FieldMutability::None,
307                        vis: syn::Visibility::Inherited,
308                        ident: Some(field_name.clone()),
309                        colon_token: Some(<syn::Token![:]>::default()),
310                        ty: return_ty.clone(),
311                    };
312                    fields.named.push(new_field);
313                    impls.push(quote::quote! {
314                        impl #struct_name {
315                            pub fn #field_name(&self) -> &#return_ty {
316                                &self.#field_name
317                            }
318                            pub fn #field_id_name(&self) -> card_game::cards::EventManagerID {
319                                card_game::cards::EventManagerID::new(#i)
320                            }
321                        }
322                        impl card_game::events::Event<#original_state> for #event {
323                            type Stackable = #stackable<#original_state, card_game::events::EventAction<#state, Self, #event_resolution<#state>>>;
324                        }
325                        impl card_game::events::GetEventManager<#event> for #original_state {
326                            type Output = #event_resolution<#state>;
327                            fn event_manager_id(&self) -> card_game::cards::EventManagerID {
328                                #get_event_manager
329                                let event_manager = get_event_manager(self);
330                                event_manager.#field_id_name()
331                            }
332                            fn event_manager(
333                                &self,
334                            ) -> card_game::events::EventManager<card_game::stack::priority::Priority<Self>, #event, Self::Output> {
335                                #get_event_manager
336                                let event_manager = get_event_manager(self);
337                                event_manager
338                                    .#field_name()
339                                    .clone()
340                            }
341                        }
342                        impl card_game::events::AddEventListener<#state, #event> for #struct_name {
343                            type Output = #event_resolution<#state>;
344                            fn add_listener<
345                                Listener: card_game::events::EventListener<#state, #event>,
346                            >(
347                                &mut self,
348                                event_action_id: card_game::events::EventActionID,
349                                listener: Listener,
350                            ) -> (card_game::cards::EventManagerID, card_game::cards::EventManagerIndex) where
351                                <Listener::Action as card_game::events::EventValidAction<
352                                    card_game::stack::priority::PriorityMut<#state>,
353                                    Listener::ActionInput,
354                                >>::Output: Into<Self::Output>,
355                            {
356                                (self.#field_id_name(), self.#field_name.add_listener(event_action_id, listener))
357                            }
358                        }
359                        impl ::std::convert::From<#state> for #event_resolution<#state> {
360                            fn from(value: #state) -> Self {
361                                Self::State(value)
362                            }
363                        }
364                    });
365                }
366                i += 1;
367                {
368                    let state_str = quote::quote!(#state).to_string().to_snake_case();
369                    let priority_state =
370                        syn::parse_quote!(card_game::stack::priority::Priority<#state>);
371                    let original_event = &event.event;
372                    let original_event_name =
373                        quote::quote!(#original_event).to_string().to_snake_case();
374                    let original_priority_event_resolution = substitute_type(
375                        &event.resolution,
376                        &args.states.placeholder,
377                        &priority_state,
378                    );
379                    let state = syn::parse_quote!(card_game::events::EventPriorityStack<#state, #original_event, #original_priority_event_resolution<#priority_state>>);
380                    for ev in args.events.iter() {
381                        let event_name = {
382                            let event = &ev.event;
383                            quote::quote!(#event).to_string().to_snake_case()
384                        };
385                        let event_resolution = &ev.resolution;
386                        let field_name = if *event_resolution == event.resolution {
387                            quote::format_ident!("{}_stack_during_{}", event_name, state_str)
388                        } else {
389                            quote::format_ident!(
390                                "{}_stack_during_{}_{}",
391                                event_name,
392                                state_str,
393                                original_event_name,
394                            )
395                        };
396                        let field_id_name = quote::format_ident!("{}_id", field_name.to_string());
397                        let event = &ev.event;
398                        let event_resolution = substitute_type(
399                            event_resolution,
400                            &args.states.placeholder,
401                            &priority_state,
402                        );
403                        let event_resolution = substitute_type(
404                            &ev.resolution,
405                            &args.states.placeholder,
406                            &syn::parse_quote!(card_game::events::EventAction<
407                                #priority_state,
408                                #event,
409                                #event_resolution,
410                            >),
411                        );
412                        let stack_event_resolution =
413                            substitute_type(&ev.resolution, &args.states.placeholder, &state);
414                        let stackable =
415                            substitute_type(&ev.stackable, &args.states.placeholder, &state);
416                        let return_ty: syn::Type = syn::parse_quote!(
417                            card_game::events::EventManager<
418                                #state,
419                                #event,
420                                #stack_event_resolution<#state>,
421                            >
422                        );
423                        let new_field = Field {
424                            attrs: Vec::new(),
425                            mutability: syn::FieldMutability::None,
426                            vis: syn::Visibility::Inherited,
427                            ident: Some(field_name.clone()),
428                            colon_token: Some(<syn::Token![:]>::default()),
429                            ty: return_ty.clone(),
430                        };
431                        fields.named.push(new_field);
432                        impls.push(quote::quote! {
433                            impl #struct_name {
434                                pub fn #field_name(&self) -> &#return_ty {
435                                    &self.#field_name
436                                }
437                                pub fn #field_id_name(&self) -> card_game::cards::EventManagerID {
438                                    card_game::cards::EventManagerID::new(#i)
439                                }
440                            }
441                            impl card_game::events::Event<
442                                #state
443                            > for #event {
444                                type Stackable = #stackable<#original_state, card_game::events::EventAction<#priority_state, #original_event, #original_priority_event_resolution<#priority_state>>>;
445                            }
446                            impl card_game::events::GetStackEventManager<
447                                #event,
448                                card_game::events::EventAction<card_game::stack::priority::Priority<#original_state>, #original_event, #original_priority_event_resolution<#priority_state>>,
449                            > for #original_state {
450                                type Output = #stack_event_resolution<#state>;
451                                fn event_manager_id(&self) -> card_game::cards::EventManagerID {
452                                    #get_event_manager
453                                    let event_manager = get_event_manager(self);
454                                    event_manager.#field_id_name()
455                                }
456                                fn stack_event_manager(
457                                    &self,
458                                ) -> card_game::events::EventManager<#state, #event, Self::Output> {
459                                    #get_event_manager
460                                    let event_manager = get_event_manager(self);
461                                    event_manager
462                                        .#field_name()
463                                        .clone()
464                                }
465                            }
466                            impl card_game::events::AddEventListener<#state, #event> for #struct_name {
467                                type Output = #stack_event_resolution<#state>;
468                                fn add_listener<
469                                    Listener: card_game::events::EventListener<#state, #event>,
470                                >(
471                                    &mut self,
472                                    event_action_id: card_game::events::EventActionID,
473                                    listener: Listener,
474                                ) -> (card_game::cards::EventManagerID, card_game::cards::EventManagerIndex) where
475                                    <Listener::Action as card_game::events::EventValidAction<
476                                        card_game::stack::priority::PriorityMut<#state>,
477                                        Listener::ActionInput,
478                                    >>::Output: Into<Self::Output>,
479                                {
480                                    (self.#field_id_name(), self.#field_name.add_listener(event_action_id, listener))
481                                }
482                            }
483                            impl ::std::convert::From<#state> for #stack_event_resolution<#state> {
484                                fn from(value: #state) -> Self {
485                                    Self::State(value)
486                                }
487                            }
488                        });
489                    }
490                }
491                i += 1;
492            }
493        }
494        for event in args.events.iter() {
495            let stackable = &event.stackable;
496            let stackable_enum_types = event
497                .stackable_enum_types
498                .iter()
499                .map(|ty| substitute_type(&ty.ty, &args.states.placeholder, &syn::parse_quote!(card_game::stack::priority::PriorityStack<State, IncitingAction>)))
500                .collect::<Vec<_>>();
501            let stackable_enum_variant_names = event
502                .stackable_enum_types
503                .iter()
504                .map(|ty| {
505                    let ident = if let Some(ref ident) = ty.ident {
506                        ident
507                    } else {
508                        type_to_ident(&ty.ty)
509                    };
510                    quote::format_ident!("{}", ident.to_string().to_upper_camel_case())
511                })
512                .collect::<Vec<_>>();
513            let stackable_enum_variant_names_str = stackable_enum_variant_names
514                .iter()
515                .map(|ident| ident.to_string().to_upper_camel_case())
516                .collect::<Vec<_>>();
517            let stackable_enum_variants = event.stackable_enum_types
518                .iter()
519                .map(|ty| {
520                    let ident = if let Some(ref ident) = ty.ident {
521                        ident
522                    } else {
523                        type_to_ident(&ty.ty)
524                    };
525                    let ident = quote::format_ident!("{}", ident.to_string().to_upper_camel_case());
526                    let ty = substitute_type(
527                        &ty.ty,
528                        &args.states.placeholder,
529                        &syn::parse_quote!(card_game::stack::priority::PriorityStack<State, IncitingAction>));
530                    quote::quote!(#ident(#ty))
531                })
532                .collect::<Vec<_>>();
533            let resolution = &event.resolution;
534            let resolution_enum_types = event
535                .resolution_enum_types
536                .iter()
537                .map(|ty| {
538                    substitute_type(&ty.ty, &args.states.placeholder, &syn::parse_quote!(State))
539                })
540                .collect::<Vec<_>>();
541            let resolution_enum_variant_names_str = event
542                .resolution_enum_types
543                .iter()
544                .map(|ty| {
545                    let ident = if let Some(ref ident) = ty.ident {
546                        ident.to_string()
547                    } else {
548                        type_to_ident(&ty.ty).to_string()
549                    };
550                    format!("{}", ident.to_upper_camel_case())
551                })
552                .collect::<Vec<_>>();
553            let resolution_enum_variant_names = resolution_enum_variant_names_str
554                .iter()
555                .map(|name| quote::format_ident!("{name}"))
556                .collect::<Vec<_>>();
557            let resolution_enum_variants = event
558                .resolution_enum_types
559                .iter()
560                .map(|ty| {
561                    let ident = if let Some(ref ident) = ty.ident {
562                        ident.to_string()
563                    } else {
564                        type_to_ident(&ty.ty).to_string()
565                    };
566                    let enum_ty = quote::format_ident!("{}", ident.to_upper_camel_case());
567                    let ty = substitute_type(
568                        &ty.ty,
569                        &args.states.placeholder,
570                        &syn::parse_quote!(State),
571                    );
572                    quote::quote!(#enum_ty(#ty))
573                })
574                .collect::<Vec<_>>();
575            let (
576                events,
577                (
578                    event_resolutions,
579                    (
580                        stackable_event_names,
581                        (
582                            stackable_event_names_str,
583                            (
584                                resolution_triggered_event_variant_names,
585                                (resolution_triggered_event_variant_names_str,
586                                resolution_triggered_event_variant_types),
587                            ),
588                        ),
589                    ),
590                ),
591            ): (Vec<_>, (Vec<_>, (Vec<_>, (Vec<_>, (Vec<_>, (Vec<_>, Vec<_>)))))) = args
592                .events
593                .iter()
594                .map(|args| {
595                    let event = &args.event;
596                    let event_name = quote::quote!(#event).to_string();
597                    let stackable_event_name_str = format!("{}Event", event_name.to_upper_camel_case());
598                    let stackable_event_name = quote::format_ident!("{stackable_event_name_str}");
599                    let resolution_triggered_event_variant_name_str = format!(
600                        "Triggered{}Event",
601                        quote::quote!(#event).to_string().to_upper_camel_case()
602                    );
603                    let resolution_triggered_event_variant_name= quote::format_ident!("{resolution_triggered_event_variant_name_str}");
604                    (
605                        event,
606                        (
607                            &args.resolution,
608                            (
609                                stackable_event_name,
610                                (stackable_event_name_str,
611                                (
612                                    resolution_triggered_event_variant_name,
613                                    (
614                                        resolution_triggered_event_variant_name_str,
615                                        quote::quote!(card_game::events::TriggeredEvent<State, #event>),
616                                    )
617                                )),
618                            ),
619                        ),
620                    )
621                })
622                .unzip();
623            let stackable_event_constraints = quote::quote! {
624                #(
625                    #events: card_game::events::Event<card_game::stack::priority::PriorityMut<
626                        card_game::stack::priority::PriorityStack<State, IncitingAction>,
627                    >>,
628                )*
629            };
630            let resolution_event_constraints = quote::quote! {
631                #(
632                    #events: card_game::events::Event<card_game::stack::priority::PriorityMut<State>>,
633                )*
634            };
635            impls.push(quote::quote! {
636                pub enum #stackable<State, IncitingAction: card_game::stack::actions::IncitingActionInfo<State>>
637                    where #stackable_event_constraints
638                {
639                    #(
640                        #stackable_event_names(card_game::events::EventAction<
641                            card_game::stack::priority::PriorityStack<State, IncitingAction>,
642                            #events,
643                            #event_resolutions<
644                                card_game::stack::priority::PriorityStack<State, IncitingAction>,
645                            >,
646                        >),
647                    )*
648                    #(#stackable_enum_variants),*
649                }
650                impl<State, IncitingAction: card_game::stack::actions::IncitingActionInfo<State>> ::std::fmt::Debug for #stackable<State, IncitingAction>
651                    where #stackable_event_constraints
652                {
653                    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::result::Result<(), ::std::fmt::Error> {
654                        match self {
655                            #(
656                                Self::#stackable_event_names(_) => f.debug_tuple(#stackable_event_names_str).finish_non_exhaustive(),
657                            )*
658                            #(
659                                Self::#stackable_enum_variant_names(_) => f.debug_tuple(#stackable_enum_variant_names_str).finish_non_exhaustive(),
660                            )*
661                        }
662                    }
663                }
664                impl<State, IncitingAction: card_game::stack::actions::IncitingActionInfo<State>> ::std::clone::Clone for #stackable<State, IncitingAction>
665                    where #stackable_event_constraints
666                        #(
667                            #stackable_enum_types: ::std::clone::Clone,
668                        )*
669                {
670                    fn clone(&self) -> Self {
671                        match self {
672                            #(
673                                Self::#stackable_event_names(value) => Self::#stackable_event_names(value.clone()),
674                            )*
675                            #(
676                                Self::#stackable_enum_variant_names(value) => Self::#stackable_enum_variant_names(value.clone()),
677                            )*
678                        }
679                    }
680                }
681                #(
682                    impl<
683                        State,
684                        IncitingAction: card_game::stack::actions::IncitingActionInfo<State>,
685                    > ::std::convert::From<card_game::events::EventAction<
686                        card_game::stack::priority::PriorityStack<State, IncitingAction>,
687                        #events,
688                        #event_resolutions<
689                            card_game::stack::priority::PriorityStack<State, IncitingAction>,
690                        >,
691                    >> for #stackable<State, IncitingAction>
692                        where #stackable_event_constraints
693                    {
694                        fn from(value: card_game::events::EventAction<
695                            card_game::stack::priority::PriorityStack<State, IncitingAction>,
696                            #events,
697                            #event_resolutions<
698                                card_game::stack::priority::PriorityStack<State, IncitingAction>,
699                            >,
700                        >) -> Self {
701                            Self::#stackable_event_names(value)
702                        }
703                    }
704                )*
705                #(
706                    impl<State, IncitingAction: card_game::stack::actions::IncitingActionInfo<State>> ::std::convert::From<#stackable_enum_types> for #stackable<State, IncitingAction>
707                        where #stackable_event_constraints
708                    {
709                        fn from(value: #stackable_enum_types) -> Self {
710                            Self::#stackable_enum_variant_names(value)
711                        }
712                    }
713                )*
714                #[derive(Clone)]
715                pub enum #resolution<State>
716                    where #resolution_event_constraints
717                {
718                    State(State),
719                    #(#resolution_triggered_event_variant_names(#resolution_triggered_event_variant_types),)*
720                    #(#resolution_enum_variants),*
721                }
722                impl<State> ::std::fmt::Debug for #resolution<State>
723                    where #resolution_event_constraints
724                {
725                    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::result::Result<(), ::std::fmt::Error> {
726                        match self {
727                            Self::State(_) => f.debug_tuple("State").finish_non_exhaustive(),
728                            #(
729                                Self::#resolution_triggered_event_variant_names(_) => f.debug_tuple(#resolution_triggered_event_variant_names_str).finish_non_exhaustive(),
730                            )*
731                            #(
732                                Self::#resolution_enum_variant_names(_) => f.debug_tuple(#resolution_enum_variant_names_str).finish_non_exhaustive(),
733                            )*
734                        }
735                    }
736                }
737                #(
738                    impl<State> ::std::convert::From<#resolution_triggered_event_variant_types> for #resolution<State>
739                        where #resolution_event_constraints
740                    {
741                        fn from(value: #resolution_triggered_event_variant_types) -> Self {
742                            Self::#resolution_triggered_event_variant_names(value)
743                        }
744                    }
745                )*
746                #(
747                    impl<State> ::std::convert::From<#resolution_enum_types> for #resolution<State>
748                        where #resolution_event_constraints
749                    {
750                        fn from(value: #resolution_enum_types) -> Self {
751                            Self::#resolution_enum_variant_names(value)
752                        }
753                    }
754                )*
755            });
756            if let Some(ref event_fn) = event.event_fn {
757                let (mut states, mut priority_resolutions): (Vec<_>, Vec<_>) = args
758                    .states
759                    .states
760                    .iter()
761                    .map(|(ty, _)| {
762                        let priority_state: syn::Type =
763                            syn::parse_quote!(card_game::stack::priority::Priority<#ty>);
764                        (
765                            ty,
766                            substitute_type(
767                                &event.resolution,
768                                &args.states.placeholder,
769                                &priority_state,
770                            ),
771                        )
772                    })
773                    .unzip();
774                let (stack_states, (stack_events, stack_priority_resolutions)): (
775                    Vec<_>,
776                    (Vec<_>, Vec<_>),
777                ) = args
778                    .states
779                    .states
780                    .iter()
781                    .cartesian_product(args.events.iter().cloned())
782                    .map(|((ty, _), event): (_, EventMapping)| {
783                        let priority_state: syn::Type =
784                            syn::parse_quote!(card_game::stack::priority::Priority<#ty>);
785                        (
786                            ty,
787                            (
788                                event.event,
789                                substitute_type(
790                                    &event.resolution,
791                                    &args.states.placeholder,
792                                    &priority_state,
793                                ),
794                            ),
795                        )
796                    })
797                    .unzip();
798                let first_state = states.pop().unwrap();
799                let first_priority_resolutions = priority_resolutions.pop().unwrap();
800                let event = &event.event;
801                let listener_constraints = quote::quote! {
802                    card_game::events::EventListenerConstructor<card_game::stack::priority::Priority<#first_state>, #event> +
803                    card_game::events::EventListenerConstructor<
804                        card_game::events::EventPriorityStack<#first_state, #event, #first_priority_resolutions<card_game::stack::priority::Priority<#first_state>>>,
805                        #event,
806                        Input = <Listener as card_game::events::EventListenerConstructor<card_game::stack::priority::Priority<#first_state>, #event>>::Input,
807                    >
808                    #(
809                        + card_game::events::EventListenerConstructor<
810                            card_game::stack::priority::Priority<#states>,
811                            #event,
812                            Input = <Listener as card_game::events::EventListenerConstructor<card_game::stack::priority::Priority<#first_state>, #event>>::Input,
813                        >
814                    )*
815                    #(
816                        + card_game::events::EventListenerConstructor<
817                            card_game::events::EventPriorityStack<#stack_states, #stack_events, #stack_priority_resolutions<card_game::stack::priority::Priority<#stack_states>>>,
818                            #event,
819                            Input = <Listener as card_game::events::EventListenerConstructor<card_game::stack::priority::Priority<#first_state>, #event>>::Input,
820                        >
821                    )*
822                };
823                let trait_constraints = quote::quote! {
824                        <<Listener as card_game::events::EventListener<card_game::stack::priority::Priority<#first_state>, #event>>::Action as card_game::events::EventValidAction<
825                            card_game::stack::priority::PriorityMut<card_game::stack::priority::Priority<#first_state>>,
826                            <Listener as card_game::events::EventListener<card_game::stack::priority::Priority<#first_state>, #event>>::ActionInput,
827                        >>::Output: std::convert::Into<<#struct_name as card_game::events::AddEventListener<card_game::stack::priority::Priority<#first_state>, #event>>::Output>
828                    #(,
829                        <<Listener as card_game::events::EventListener<card_game::stack::priority::Priority<#states>, #event>>::Action as card_game::events::EventValidAction<
830                            card_game::stack::priority::PriorityMut<card_game::stack::priority::Priority<#states>>,
831                            <Listener as card_game::events::EventListener<card_game::stack::priority::Priority<#states>, #event>>::ActionInput,
832                        >>::Output: std::convert::Into<<#struct_name as card_game::events::AddEventListener<card_game::stack::priority::Priority<#states>, #event>>::Output>
833                    )*,
834                        <<Listener as card_game::events::EventListener<
835                            card_game::events::EventPriorityStack<#first_state, #event, #first_priority_resolutions<card_game::stack::priority::Priority<#first_state>>>,
836                            #event,
837                        >>::Action as card_game::events::EventValidAction<
838                            card_game::stack::priority::PriorityMut<card_game::events::EventPriorityStack<#first_state, #event, #first_priority_resolutions<card_game::stack::priority::Priority<#first_state>>>>,
839                            <Listener as card_game::events::EventListener<
840                                card_game::events::EventPriorityStack<#first_state, #event, #first_priority_resolutions<card_game::stack::priority::Priority<#first_state>>>,
841                                #event,
842                            >>::ActionInput,
843                        >>::Output: Into<
844                            <#struct_name as card_game::events::AddEventListener<
845                                card_game::events::EventPriorityStack<#first_state, #event, #first_priority_resolutions<card_game::stack::priority::Priority<#first_state>>>,
846                                #event,
847                            >>::Output,
848                        >
849                    #(,
850                        <<Listener as card_game::events::EventListener<
851                            card_game::events::EventPriorityStack<#stack_states, #stack_events, #stack_priority_resolutions<card_game::stack::priority::Priority<#stack_states>>>,
852                            #event,
853                        >>::Action as card_game::events::EventValidAction<
854                            card_game::stack::priority::PriorityMut<card_game::events::EventPriorityStack<#stack_states, #stack_events, #stack_priority_resolutions<card_game::stack::priority::Priority<#stack_states>>>>,
855                            <Listener as card_game::events::EventListener<
856                                card_game::events::EventPriorityStack<#stack_states, #stack_events, #stack_priority_resolutions<card_game::stack::priority::Priority<#stack_states>>>,
857                                #event,
858                            >>::ActionInput,
859                        >>::Output: Into<
860                            <#struct_name as card_game::events::AddEventListener<
861                                card_game::events::EventPriorityStack<#stack_states, #stack_events, #stack_priority_resolutions<card_game::stack::priority::Priority<#stack_states>>>,
862                                #event,
863                            >>::Output,
864                        >
865                    )*
866                };
867                let trait_name =
868                    quote::format_ident!("{}Event", event_fn.to_string().to_upper_camel_case());
869                impls.push(quote::quote! {
870                    pub trait #trait_name {
871                        fn #event_fn<
872                            Listener: #listener_constraints
873                        >(
874                            self,
875                            input: <Listener as card_game::events::EventListenerConstructor<card_game::stack::priority::Priority<#first_state>, #event>>::Input,
876                        ) -> Self
877                            where #trait_constraints;
878                    }
879                    impl<'a, Kind> #trait_name for card_game::cards::CardKindBuilder<'a, #struct_name, Kind> {
880                        fn #event_fn<
881                            Listener: #listener_constraints
882                        >(
883                            self,
884                            input: <Listener as card_game::events::EventListenerConstructor<card_game::stack::priority::Priority<#first_state>, #event>>::Input,
885                        ) -> Self
886                            where #trait_constraints
887                        {
888                            self
889                                .with_event()
890                                .listen_for::<card_game::stack::priority::Priority<#first_state>, #event, Listener>(input.clone())
891                                #(
892                                    .listen_for::<card_game::stack::priority::Priority<#states>, #event, Listener>(input.clone())
893                                )*
894                                /*.listen_for::<card_game::events::EventPriorityStack<#first_state, #event, #first_priority_resolutions<card_game::stack::priority::Priority<#first_state>>>, #event, Listener>(
895                                    input.clone(),
896                                )*/
897                                #(
898                                    .listen_for::<card_game::events::EventPriorityStack<#stack_states, #stack_events, #stack_priority_resolutions<card_game::stack::priority::Priority<#stack_states>>>, #event, Listener>(
899                                        input.clone(),
900                                    )
901                                )*
902                                .finish_event()
903                        }
904                    }
905                });
906            }
907        }
908        /*let event_manager_id_indexes = fields
909        .named
910        .iter()
911        .enumerate()
912        .map(|(i, field)| {
913            let field = &field.ident;
914            quote::quote!(#i => self.#field.contains_index(event_manager_index))
915        })
916        .collect::<Vec<_>>();*/
917        quote::quote! {
918            #ast
919            /*impl #struct_name {
920                pub fn contains_index(
921                    &self,
922                    event_manager_id: card_game::cards::EventManagerID,
923                    event_manager_index: card_game::cards::EventManagerIndex,
924                ) -> bool {
925                    match event_manager_id.index() {
926                        #(
927                            #event_manager_id_indexes,
928                        )*
929                        _ => false,
930                    }
931                }
932            }*/
933            #(#impls)*
934        }
935        .into()
936    } else {
937        panic!("`event_manager` can only be used with named structs");
938    }
939}
940
941fn substitute_type(ty: &Type, from: &Ident, to: &Type) -> Type {
942    let mut out = ty.clone();
943    TypeSubstituter { from, to }.visit_type_mut(&mut out);
944    out
945}
946
947struct TypeSubstituter<'a> {
948    from: &'a Ident,
949    to: &'a Type,
950}
951
952impl<'a> syn::visit_mut::VisitMut for TypeSubstituter<'a> {
953    fn visit_type_mut(&mut self, node: &mut Type) {
954        match node {
955            Type::Path(TypePath { path, .. })
956                if path.segments.len() == 1 && &path.segments[0].ident == self.from =>
957            {
958                *node = self.to.clone();
959            }
960            _ => {
961                syn::visit_mut::visit_type_mut(self, node);
962            }
963        }
964    }
965}
966
967fn type_to_ident(ty: &Type) -> &Ident {
968    match ty {
969        Type::Path(type_path) => type_path
970            .path
971            .segments
972            .last()
973            .map(|seg| &seg.ident)
974            .unwrap(),
975        _ => unimplemented!(),
976    }
977}