kabu_core_actors_macros/
lib.rs

1use proc_macro::TokenStream;
2
3use quote::quote;
4use syn::{parse_macro_input, Data, DeriveInput, Field, Fields, PathArguments, Type};
5
6#[proc_macro_derive(Accessor, attributes(accessor))]
7pub fn derive_access(input: TokenStream) -> TokenStream {
8    let input = parse_macro_input!(input as DeriveInput);
9
10    let name = input.ident;
11    let generics = input.generics;
12
13    let data = match input.data {
14        Data::Struct(s) => s,
15        _ => panic!("This macro only works for structs"),
16    };
17
18    let fields = match data.fields {
19        Fields::Named(named) => named,
20        _ => panic!("no named fields"),
21    };
22
23    let mut access_fields: Vec<Field> = Vec::new();
24
25    for field_ in fields.named {
26        for attr in field_.attrs.iter() {
27            if attr.path().is_ident("accessor") {
28                access_fields.push(field_.clone());
29            }
30        }
31    }
32    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
33
34    let traits = access_fields
35        .into_iter()
36        .map(|field| {
37            let field_name = field.ident.expect("Field needs name");
38            let field_type = match field.ty.clone() {
39                Type::Path(type_path) => match &type_path.path.segments[0].arguments.clone() {
40                    PathArguments::AngleBracketed(params) => match &params.args[0] {
41                        syn::GenericArgument::Type(ty) => match &ty {
42                            Type::Path(type_path) => match &type_path.path.segments[0].arguments.clone() {
43                                PathArguments::AngleBracketed(params) => match &params.args[0] {
44                                    syn::GenericArgument::Type(ty) => ty.clone(),
45                                    _ => panic!("Expected type parameter"),
46                                },
47                                _ => panic!("Expected Angle Brackets"),
48                            },
49                            _ => panic!("Expected DataType parameter"),
50                        },
51                        _ => panic!("Excpected type parameter"),
52                    },
53                    _ => panic!("Expected Angle Brackets"),
54                },
55                _ => panic!("Expected Option"),
56            };
57
58            quote! {
59                impl #impl_generics Accessor<#field_type> for #name #ty_generics #where_clause {
60                    fn access(&mut self, value : SharedState<#field_type>) -> &mut Self {
61                        self.#field_name = Some(value);
62                        self
63                    }
64                }
65            }
66        })
67        .collect::<Vec<_>>();
68
69    let expanded = quote! {
70        #(#traits)*
71    };
72    expanded.into()
73}
74
75#[proc_macro_derive(Consumer, attributes(consumer))]
76pub fn derive_consumer(input: TokenStream) -> TokenStream {
77    let input = parse_macro_input!(input as DeriveInput);
78
79    let name = input.ident;
80    let generics = input.generics;
81
82    let data = match input.data {
83        Data::Struct(s) => s,
84        _ => panic!("This macro only works for structs"),
85    };
86
87    let fields = match data.fields {
88        Fields::Named(named) => named,
89        _ => panic!("no named fields"),
90    };
91
92    let mut access_fields: Vec<Field> = Vec::new();
93
94    for field_ in fields.named {
95        for attr in field_.attrs.iter() {
96            if attr.path().is_ident("consumer") {
97                access_fields.push(field_.clone());
98            }
99        }
100    }
101    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
102
103    let traits = access_fields
104        .into_iter()
105        .map(|field| {
106            let field_name = field.ident.expect("Field needs name");
107            let field_type = match field.ty.clone() {
108                Type::Path(type_path) => match &type_path.path.segments[0].arguments.clone() {
109                    PathArguments::AngleBracketed(params) => match &params.args[0] {
110                        syn::GenericArgument::Type(ty) => match &ty {
111                            Type::Path(type_path) => match &type_path.path.segments[0].arguments.clone() {
112                                PathArguments::AngleBracketed(params) => match &params.args[0] {
113                                    syn::GenericArgument::Type(ty) => ty.clone(),
114                                    _ => panic!("Excpected type parameter"),
115                                },
116                                _ => panic!("Expected Angle Brackets"),
117                            },
118                            _ => panic!("Expected DataType parameter"),
119                        },
120                        _ => panic!("Expected type parameter"),
121                    },
122                    _ => panic!("Expected Angle Brackets"),
123                },
124                _ => panic!("Expected Option"),
125            };
126
127            quote! {
128                impl #impl_generics Consumer<#field_type> for #name #ty_generics #where_clause {
129                    fn consume(&mut self, value : Broadcaster<#field_type>) -> &mut Self {
130                        self.#field_name = Some(value);
131                        self
132                    }
133                }
134            }
135        })
136        .collect::<Vec<_>>();
137
138    let expanded = quote! {
139        #(#traits)*
140    };
141    expanded.into()
142}
143
144#[proc_macro_derive(Producer, attributes(producer))]
145pub fn derive_producer(input: TokenStream) -> TokenStream {
146    let input = parse_macro_input!(input as DeriveInput);
147
148    let name = input.ident;
149    let generics = input.generics;
150
151    let data = match input.data {
152        Data::Struct(s) => s,
153        _ => panic!("This macro only works for structs"),
154    };
155
156    let fields = match data.fields {
157        Fields::Named(named) => named,
158        _ => panic!("no named fields"),
159    };
160
161    let mut access_fields: Vec<Field> = Vec::new();
162
163    for field_ in fields.named {
164        for attr in field_.attrs.iter() {
165            if attr.path().is_ident("producer") {
166                access_fields.push(field_.clone());
167            }
168        }
169    }
170    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
171
172    let traits = access_fields
173        .into_iter()
174        .map(|field| {
175            let field_name = field.ident.expect("Field needs name");
176            let field_type = match field.ty.clone() {
177                Type::Path(type_path) => match &type_path.path.segments[0].arguments.clone() {
178                    PathArguments::AngleBracketed(params) => match &params.args[0] {
179                        syn::GenericArgument::Type(ty) => match &ty {
180                            Type::Path(type_path) => match &type_path.path.segments[0].arguments.clone() {
181                                PathArguments::AngleBracketed(params) => match &params.args[0] {
182                                    syn::GenericArgument::Type(ty) => ty.clone(),
183                                    _ => panic!("Expected type parameter"),
184                                },
185                                _ => panic!("Expected Angle Brackets"),
186                            },
187                            _ => panic!("Expected DataType parameter"),
188                        },
189                        _ => panic!("Excected type parameter"),
190                    },
191                    _ => panic!("Expected Angle Brackets"),
192                },
193                _ => panic!("Expected Option"),
194            };
195
196            quote! {
197                impl #impl_generics Producer<#field_type> for #name #ty_generics #where_clause {
198                    fn produce(&mut self, value : Broadcaster<#field_type>) -> &mut Self {
199                        self.#field_name = Some(value);
200                        self
201                    }
202                }
203            }
204        })
205        .collect::<Vec<_>>();
206
207    let expanded = quote! {
208        #(#traits)*
209    };
210
211    expanded.into()
212}