ab_code_gen/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
mod actor_messages;
mod module;
mod actor_proxy;

pub use actor_messages::*; 
pub use module::*;
pub use actor_proxy::*;

use convert_case::Casing;
use syn::ReturnType;



#[derive(Clone)]
pub struct MessageHandlerMethod<'a> {
    original: &'a syn::ImplItemFn,
    parameters: Vec<(&'a syn::Ident, &'a syn::Type)>,
}

impl<'b> MessageHandlerMethod<'b> {
    pub fn new(method: &syn::ImplItemFn) -> syn::Result<MessageHandlerMethod> {
        // validate the method signature
        let error = Err(syn::Error::new_spanned(
            method,
            "Message handler methods must have at least one parameter (&self)",
        ));
        if method.sig.inputs.is_empty() {
            return error;
        }
        if let syn::FnArg::Receiver(rec) = method.sig.inputs.first().unwrap() {
            if rec.reference.is_none() {
                return error;
            }
        } else {
            return error;
        }

        let parameters = method
            .sig
            .inputs
            .iter()
            .filter_map(|i| {
                if let syn::FnArg::Typed(t) = i {
                    if let syn::Pat::Ident(p) = t.pat.as_ref() {
                        return Some((&p.ident, t.ty.as_ref()));
                    }
                }
                None
            })
            .collect();

        Ok(MessageHandlerMethod {
            original: method,
            parameters,
        })
    }

    pub fn get_name_snake_case(&self) -> &syn::Ident {
        &self.original.sig.ident
    }

    pub fn get_name_camel_case(&self) -> syn::Ident {
        let name = self.get_name_snake_case();
        syn::Ident::new(
            &name.to_string().to_case(convert_case::Case::UpperCamel),
            name.span(),
        )
    }

    pub fn has_return_type(&self) -> bool {
        matches!(self.original.sig.output, ReturnType::Type(_, _))
    }

    pub fn get_return_type(&self) -> Option<&'b syn::Type> {
        match &self.original.sig.output {
            ReturnType::Type(_, ty) => Some(ty),
            _ => None,
        }
    }
    pub fn get_parameter_names(&self) -> Vec<&syn::Ident> {
        self.parameters.iter().map(|(name, _)| *name).collect()
    }
}