ab_code_gen/
actor_messages.rs1use proc_macro2::TokenStream;
2use syn::{Ident, Type};
3
4use crate::MessageHandlerMethod;
5
6pub struct MessageEnumVariant<'a> {
7 name: Ident,
8 parameters: Vec<(&'a Ident, &'a Type)>,
9 return_type: Option<&'a Type>,
10}
11
12pub struct MessageEnum<'a> {
13 pub name: Ident,
14 variants: Vec<MessageEnumVariant<'a>>,
15}
16
17impl MessageEnum<'_> {
18 pub fn new<'a>(
19 name: Ident,
20 handler_methods: &[MessageHandlerMethod<'a>],
21 ) -> syn::Result<MessageEnum<'a>> {
22 let mut message_variants = Vec::<MessageEnumVariant>::new();
23
24 for handler_method in handler_methods {
25 let message_variant = MessageEnumVariant::new(handler_method)?;
26 message_variants.push(message_variant);
27 }
28 Ok(MessageEnum {
29 name,
30 variants: message_variants,
31 })
32 }
33
34 pub fn generate(&self) -> syn::Result<TokenStream> {
35 let enum_name = &self.name;
36 let message_variants: Vec<_> = self.variants.iter().map(|m| m.generate()).collect();
37 for message_variant in message_variants.iter() {
38 if message_variant.is_err() {
39 return message_variant.clone();
40 }
41 }
42 let message_variants = message_variants.into_iter().map(|elem| elem.unwrap());
43 let message_enum = quote::quote! {
44 #[derive(Debug)]
45 pub enum #enum_name {
46 #(#message_variants),*
47 }
48 };
49 Ok(message_enum)
50 }
51}
52
53impl MessageEnumVariant<'_> {
54 fn new<'a>(handler_method: &MessageHandlerMethod<'a>) -> syn::Result<MessageEnumVariant<'a>> {
55 let parameters: Vec<(&Ident, &Type)> = handler_method.parameters.clone();
56 let name = handler_method.get_name_camel_case();
57
58 Ok(MessageEnumVariant {
59 name: name.clone(),
60 parameters,
61 return_type: handler_method.get_return_type(),
62 })
63 }
64
65 fn generate(&self) -> syn::Result<TokenStream> {
66 let variant_name = &self.name;
67 let parameters = self.parameters.iter().map(|(name, ty)| {
68 quote::quote! { #name: #ty }
69 });
70 let mut respond_to = TokenStream::new();
72 if let Some(ret_type) = self.return_type {
73 respond_to = quote::quote! {
74 respond_to: tokio::sync::oneshot::Sender<#ret_type>
75 };
76 }
77
78 let message_variant = quote::quote! {
79 #variant_name {
80 #(#parameters,)*
81 #respond_to
82 }
83 };
84 Ok(message_variant)
85 }
86}