Skip to main content

a3s_boot_macros/
lib.rs

1use proc_macro::TokenStream;
2use syn::parse_macro_input;
3use syn::{Item, ItemImpl, LitStr};
4
5mod controller;
6mod decorators;
7mod dependency;
8mod events;
9mod file_upload;
10mod messaging;
11mod openapi;
12mod openapi_security;
13mod outside;
14mod protocol;
15mod schedule;
16mod util;
17mod validation;
18mod websocket;
19
20pub(crate) use util::{
21    expect_no_extractor_args, is_type_ident, option_inner_type, parse_optional_comma, push_error,
22    set_once,
23};
24
25use controller::expand_controller;
26use dependency::{expand_catch, expand_injectable, expand_module, CatchArgs, ModuleArgs};
27use events::expand_event_listener;
28use messaging::expand_message_controller;
29use outside::*;
30use schedule::expand_schedule;
31use websocket::{expand_websocket_gateway, WebSocketGatewayArgs};
32
33#[proc_macro_attribute]
34pub fn injectable(attr: TokenStream, item: TokenStream) -> TokenStream {
35    if !attr.is_empty() {
36        return syn::Error::new(
37            proc_macro2::TokenStream::from(attr)
38                .into_iter()
39                .next()
40                .unwrap()
41                .span(),
42            "#[injectable] does not accept arguments",
43        )
44        .to_compile_error()
45        .into();
46    }
47
48    let item = parse_macro_input!(item as Item);
49    match item {
50        Item::Struct(item_struct) => expand_injectable(item_struct)
51            .unwrap_or_else(syn::Error::into_compile_error)
52            .into(),
53        item => syn::Error::new_spanned(item, "#[injectable] can only be used on structs")
54            .to_compile_error()
55            .into(),
56    }
57}
58
59#[proc_macro_attribute]
60pub fn module(attr: TokenStream, item: TokenStream) -> TokenStream {
61    let args = parse_macro_input!(attr as ModuleArgs);
62    let item = parse_macro_input!(item as Item);
63
64    match item {
65        Item::Struct(item_struct) => expand_module(args, item_struct)
66            .unwrap_or_else(syn::Error::into_compile_error)
67            .into(),
68        item => syn::Error::new_spanned(item, "#[module] can only be used on structs")
69            .to_compile_error()
70            .into(),
71    }
72}
73
74#[proc_macro_attribute]
75pub fn catch(attr: TokenStream, item: TokenStream) -> TokenStream {
76    let args = parse_macro_input!(attr as CatchArgs);
77    let item = parse_macro_input!(item as Item);
78
79    match item {
80        Item::Struct(item_struct) => expand_catch(args, item_struct)
81            .unwrap_or_else(syn::Error::into_compile_error)
82            .into(),
83        item => syn::Error::new_spanned(item, "#[catch] can only be used on structs")
84            .to_compile_error()
85            .into(),
86    }
87}
88
89#[proc_macro_attribute]
90pub fn controller(attr: TokenStream, item: TokenStream) -> TokenStream {
91    let prefix = parse_macro_input!(attr as LitStr);
92    let item_impl = parse_macro_input!(item as ItemImpl);
93
94    expand_controller(prefix, item_impl)
95        .unwrap_or_else(syn::Error::into_compile_error)
96        .into()
97}
98
99#[proc_macro_attribute]
100pub fn websocket_gateway(attr: TokenStream, item: TokenStream) -> TokenStream {
101    let args = parse_macro_input!(attr as WebSocketGatewayArgs);
102    let item_impl = parse_macro_input!(item as ItemImpl);
103
104    expand_websocket_gateway(args, item_impl)
105        .unwrap_or_else(syn::Error::into_compile_error)
106        .into()
107}
108
109#[proc_macro_attribute]
110pub fn apply_decorators(_attr: TokenStream, item: TokenStream) -> TokenStream {
111    decorator_attribute_outside_controller("apply_decorators", item)
112}
113
114#[proc_macro_attribute]
115pub fn message_controller(attr: TokenStream, item: TokenStream) -> TokenStream {
116    if !attr.is_empty() {
117        return syn::Error::new(
118            proc_macro2::TokenStream::from(attr)
119                .into_iter()
120                .next()
121                .unwrap()
122                .span(),
123            "#[message_controller] does not accept arguments",
124        )
125        .to_compile_error()
126        .into();
127    }
128
129    let item_impl = parse_macro_input!(item as ItemImpl);
130    expand_message_controller(item_impl)
131        .unwrap_or_else(syn::Error::into_compile_error)
132        .into()
133}
134
135#[proc_macro_attribute]
136pub fn event_listener(attr: TokenStream, item: TokenStream) -> TokenStream {
137    if !attr.is_empty() {
138        return syn::Error::new(
139            proc_macro2::TokenStream::from(attr)
140                .into_iter()
141                .next()
142                .unwrap()
143                .span(),
144            "#[event_listener] does not accept arguments",
145        )
146        .to_compile_error()
147        .into();
148    }
149
150    let item_impl = parse_macro_input!(item as ItemImpl);
151    expand_event_listener(item_impl)
152        .unwrap_or_else(syn::Error::into_compile_error)
153        .into()
154}
155
156#[proc_macro_attribute]
157pub fn schedule(attr: TokenStream, item: TokenStream) -> TokenStream {
158    if !attr.is_empty() {
159        return syn::Error::new(
160            proc_macro2::TokenStream::from(attr)
161                .into_iter()
162                .next()
163                .unwrap()
164                .span(),
165            "#[schedule] does not accept arguments",
166        )
167        .to_compile_error()
168        .into();
169    }
170
171    let item_impl = parse_macro_input!(item as ItemImpl);
172    expand_schedule(item_impl)
173        .unwrap_or_else(syn::Error::into_compile_error)
174        .into()
175}
176
177#[proc_macro_attribute]
178pub fn subscribe_message(_attr: TokenStream, item: TokenStream) -> TokenStream {
179    websocket_attribute_outside_gateway("subscribe_message", item)
180}
181
182#[proc_macro_attribute]
183pub fn on_gateway_init(_attr: TokenStream, item: TokenStream) -> TokenStream {
184    websocket_attribute_outside_gateway("on_gateway_init", item)
185}
186
187#[proc_macro_attribute]
188pub fn on_gateway_connection(_attr: TokenStream, item: TokenStream) -> TokenStream {
189    websocket_attribute_outside_gateway("on_gateway_connection", item)
190}
191
192#[proc_macro_attribute]
193pub fn on_gateway_disconnect(_attr: TokenStream, item: TokenStream) -> TokenStream {
194    websocket_attribute_outside_gateway("on_gateway_disconnect", item)
195}
196
197#[proc_macro_attribute]
198pub fn cron(_attr: TokenStream, item: TokenStream) -> TokenStream {
199    schedule_attribute_outside_schedule("cron", item)
200}
201
202#[proc_macro_attribute]
203pub fn interval(_attr: TokenStream, item: TokenStream) -> TokenStream {
204    schedule_attribute_outside_schedule("interval", item)
205}
206
207#[proc_macro_attribute]
208pub fn timeout(_attr: TokenStream, item: TokenStream) -> TokenStream {
209    schedule_attribute_outside_schedule("timeout", item)
210}
211
212#[proc_macro_attribute]
213pub fn message_pattern(_attr: TokenStream, item: TokenStream) -> TokenStream {
214    message_attribute_outside_controller("message_pattern", item)
215}
216
217#[proc_macro_attribute]
218pub fn event_pattern(_attr: TokenStream, item: TokenStream) -> TokenStream {
219    message_attribute_outside_controller("event_pattern", item)
220}
221
222#[proc_macro_attribute]
223pub fn payload(_attr: TokenStream, item: TokenStream) -> TokenStream {
224    protocol_extractor_attribute_outside("payload", item)
225}
226
227#[proc_macro_attribute]
228pub fn message_body(_attr: TokenStream, item: TokenStream) -> TokenStream {
229    protocol_extractor_attribute_outside("message_body", item)
230}
231
232#[proc_macro_attribute]
233pub fn on_event(_attr: TokenStream, item: TokenStream) -> TokenStream {
234    event_attribute_outside_listener("on_event", item)
235}
236
237#[proc_macro_attribute]
238pub fn all(_attr: TokenStream, item: TokenStream) -> TokenStream {
239    route_attribute_outside_controller("all", item)
240}
241
242#[proc_macro_attribute]
243pub fn get(_attr: TokenStream, item: TokenStream) -> TokenStream {
244    route_attribute_outside_controller("get", item)
245}
246
247#[proc_macro_attribute]
248pub fn sse(_attr: TokenStream, item: TokenStream) -> TokenStream {
249    route_attribute_outside_controller("sse", item)
250}
251
252#[proc_macro_attribute]
253pub fn post(_attr: TokenStream, item: TokenStream) -> TokenStream {
254    route_attribute_outside_controller("post", item)
255}
256
257#[proc_macro_attribute]
258pub fn put(_attr: TokenStream, item: TokenStream) -> TokenStream {
259    route_attribute_outside_controller("put", item)
260}
261
262#[proc_macro_attribute]
263pub fn patch(_attr: TokenStream, item: TokenStream) -> TokenStream {
264    route_attribute_outside_controller("patch", item)
265}
266
267#[proc_macro_attribute]
268pub fn delete(_attr: TokenStream, item: TokenStream) -> TokenStream {
269    route_attribute_outside_controller("delete", item)
270}
271
272#[proc_macro_attribute]
273pub fn options(_attr: TokenStream, item: TokenStream) -> TokenStream {
274    route_attribute_outside_controller("options", item)
275}
276
277#[proc_macro_attribute]
278pub fn head(_attr: TokenStream, item: TokenStream) -> TokenStream {
279    route_attribute_outside_controller("head", item)
280}
281
282#[proc_macro_attribute]
283pub fn get_json(_attr: TokenStream, item: TokenStream) -> TokenStream {
284    route_attribute_outside_controller("get_json", item)
285}
286
287#[proc_macro_attribute]
288pub fn post_json(_attr: TokenStream, item: TokenStream) -> TokenStream {
289    route_attribute_outside_controller("post_json", item)
290}
291
292#[proc_macro_attribute]
293pub fn put_json(_attr: TokenStream, item: TokenStream) -> TokenStream {
294    route_attribute_outside_controller("put_json", item)
295}
296
297#[proc_macro_attribute]
298pub fn patch_json(_attr: TokenStream, item: TokenStream) -> TokenStream {
299    route_attribute_outside_controller("patch_json", item)
300}
301
302#[proc_macro_attribute]
303pub fn delete_json(_attr: TokenStream, item: TokenStream) -> TokenStream {
304    route_attribute_outside_controller("delete_json", item)
305}
306
307#[proc_macro_attribute]
308pub fn body(_attr: TokenStream, item: TokenStream) -> TokenStream {
309    extractor_attribute_outside_controller("body", item)
310}
311
312#[proc_macro_attribute]
313pub fn request(_attr: TokenStream, item: TokenStream) -> TokenStream {
314    extractor_attribute_outside_controller("request", item)
315}
316
317#[proc_macro_attribute]
318pub fn param(_attr: TokenStream, item: TokenStream) -> TokenStream {
319    extractor_attribute_outside_controller("param", item)
320}
321
322#[proc_macro_attribute]
323pub fn params(_attr: TokenStream, item: TokenStream) -> TokenStream {
324    extractor_attribute_outside_controller("params", item)
325}
326
327#[proc_macro_attribute]
328pub fn query(_attr: TokenStream, item: TokenStream) -> TokenStream {
329    extractor_attribute_outside_controller("query", item)
330}
331
332#[proc_macro_attribute]
333pub fn header(_attr: TokenStream, item: TokenStream) -> TokenStream {
334    extractor_attribute_outside_controller("header", item)
335}
336
337#[proc_macro_attribute]
338pub fn headers(_attr: TokenStream, item: TokenStream) -> TokenStream {
339    extractor_attribute_outside_controller("headers", item)
340}
341
342#[proc_macro_attribute]
343pub fn cookie(_attr: TokenStream, item: TokenStream) -> TokenStream {
344    extractor_attribute_outside_controller("cookie", item)
345}
346
347#[proc_macro_attribute]
348pub fn cookies(_attr: TokenStream, item: TokenStream) -> TokenStream {
349    extractor_attribute_outside_controller("cookies", item)
350}
351
352#[proc_macro_attribute]
353pub fn host_param(_attr: TokenStream, item: TokenStream) -> TokenStream {
354    extractor_attribute_outside_controller("host_param", item)
355}
356
357#[proc_macro_attribute]
358pub fn ip(_attr: TokenStream, item: TokenStream) -> TokenStream {
359    extractor_attribute_outside_controller("ip", item)
360}
361
362#[proc_macro_attribute]
363pub fn res(_attr: TokenStream, item: TokenStream) -> TokenStream {
364    extractor_attribute_outside_controller("res", item)
365}
366
367#[proc_macro_attribute]
368pub fn session(_attr: TokenStream, item: TokenStream) -> TokenStream {
369    extractor_attribute_outside_controller("session", item)
370}
371
372#[proc_macro_attribute]
373pub fn uploaded_file(_attr: TokenStream, item: TokenStream) -> TokenStream {
374    extractor_attribute_outside_controller("uploaded_file", item)
375}
376
377#[proc_macro_attribute]
378pub fn uploaded_files(_attr: TokenStream, item: TokenStream) -> TokenStream {
379    extractor_attribute_outside_controller("uploaded_files", item)
380}
381
382#[proc_macro_attribute]
383pub fn extract(_attr: TokenStream, item: TokenStream) -> TokenStream {
384    extractor_attribute_outside_controller("extract", item)
385}
386
387#[proc_macro_attribute]
388pub fn host(_attr: TokenStream, item: TokenStream) -> TokenStream {
389    host_attribute_outside_controller("host", item)
390}
391
392#[proc_macro_attribute]
393pub fn version(_attr: TokenStream, item: TokenStream) -> TokenStream {
394    version_attribute_outside_controller("version", item)
395}
396
397#[proc_macro_attribute]
398pub fn versions(_attr: TokenStream, item: TokenStream) -> TokenStream {
399    version_attribute_outside_controller("versions", item)
400}
401
402#[proc_macro_attribute]
403pub fn version_neutral(_attr: TokenStream, item: TokenStream) -> TokenStream {
404    version_attribute_outside_controller("version_neutral", item)
405}
406
407#[proc_macro_attribute]
408pub fn serialize(_attr: TokenStream, item: TokenStream) -> TokenStream {
409    serialization_attribute_outside_controller("serialize", item)
410}
411
412#[proc_macro_attribute]
413pub fn tag(_attr: TokenStream, item: TokenStream) -> TokenStream {
414    openapi_attribute_outside_controller("tag", item)
415}
416
417#[proc_macro_attribute]
418pub fn operation(_attr: TokenStream, item: TokenStream) -> TokenStream {
419    openapi_attribute_outside_controller("operation", item)
420}
421
422#[proc_macro_attribute]
423pub fn response(_attr: TokenStream, item: TokenStream) -> TokenStream {
424    openapi_attribute_outside_controller("response", item)
425}
426
427#[proc_macro_attribute]
428pub fn request_body(_attr: TokenStream, item: TokenStream) -> TokenStream {
429    openapi_attribute_outside_controller("request_body", item)
430}
431
432#[proc_macro_attribute]
433pub fn api_param(_attr: TokenStream, item: TokenStream) -> TokenStream {
434    openapi_attribute_outside_controller("api_param", item)
435}
436
437#[proc_macro_attribute]
438pub fn api_query(_attr: TokenStream, item: TokenStream) -> TokenStream {
439    openapi_attribute_outside_controller("api_query", item)
440}
441
442#[proc_macro_attribute]
443pub fn api_header(_attr: TokenStream, item: TokenStream) -> TokenStream {
444    openapi_attribute_outside_controller("api_header", item)
445}
446
447#[proc_macro_attribute]
448pub fn api_response_header(_attr: TokenStream, item: TokenStream) -> TokenStream {
449    openapi_attribute_outside_controller("api_response_header", item)
450}
451
452#[proc_macro_attribute]
453pub fn api_security(_attr: TokenStream, item: TokenStream) -> TokenStream {
454    openapi_attribute_outside_controller("api_security", item)
455}
456
457#[proc_macro_attribute]
458pub fn api_cookie_auth(_attr: TokenStream, item: TokenStream) -> TokenStream {
459    openapi_attribute_outside_controller("api_cookie_auth", item)
460}
461
462#[proc_macro_attribute]
463pub fn api_key_auth(_attr: TokenStream, item: TokenStream) -> TokenStream {
464    openapi_attribute_outside_controller("api_key_auth", item)
465}
466
467#[proc_macro_attribute]
468pub fn bearer_auth(_attr: TokenStream, item: TokenStream) -> TokenStream {
469    openapi_attribute_outside_controller("bearer_auth", item)
470}
471
472#[proc_macro_attribute]
473pub fn oauth2_auth(_attr: TokenStream, item: TokenStream) -> TokenStream {
474    openapi_attribute_outside_controller("oauth2_auth", item)
475}
476
477#[proc_macro_attribute]
478pub fn open_id_connect_auth(_attr: TokenStream, item: TokenStream) -> TokenStream {
479    openapi_attribute_outside_controller("open_id_connect_auth", item)
480}
481
482#[proc_macro_attribute]
483pub fn api_extra_model(_attr: TokenStream, item: TokenStream) -> TokenStream {
484    openapi_attribute_outside_controller("api_extra_model", item)
485}
486
487#[proc_macro_attribute]
488pub fn api_extension(_attr: TokenStream, item: TokenStream) -> TokenStream {
489    openapi_attribute_outside_controller("api_extension", item)
490}
491
492#[proc_macro_attribute]
493pub fn hide_from_openapi(_attr: TokenStream, item: TokenStream) -> TokenStream {
494    openapi_attribute_outside_controller("hide_from_openapi", item)
495}
496
497#[proc_macro_attribute]
498pub fn redirect(_attr: TokenStream, item: TokenStream) -> TokenStream {
499    response_attribute_outside_controller("redirect", item)
500}
501
502#[proc_macro_attribute]
503pub fn render(_attr: TokenStream, item: TokenStream) -> TokenStream {
504    render_attribute_outside_controller("render", item)
505}
506
507#[proc_macro_attribute]
508pub fn http_code(_attr: TokenStream, item: TokenStream) -> TokenStream {
509    http_code_attribute_outside_controller("http_code", item)
510}
511
512#[proc_macro_attribute]
513pub fn metadata(_attr: TokenStream, item: TokenStream) -> TokenStream {
514    metadata_attribute_outside_controller("metadata", item)
515}
516
517#[proc_macro_attribute]
518pub fn validate(_attr: TokenStream, item: TokenStream) -> TokenStream {
519    validation_attribute_outside_controller("validate", item)
520}
521
522#[proc_macro_attribute]
523pub fn skip_validation(_attr: TokenStream, item: TokenStream) -> TokenStream {
524    validation_attribute_outside_controller("skip_validation", item)
525}
526
527#[proc_macro_derive(ValidationSchema, attributes(serde))]
528pub fn derive_validation_schema(item: TokenStream) -> TokenStream {
529    let item_struct = parse_macro_input!(item as syn::ItemStruct);
530    validation::expand_validation_schema(item_struct)
531        .unwrap_or_else(syn::Error::into_compile_error)
532        .into()
533}
534
535#[proc_macro_attribute]
536pub fn use_guard(_attr: TokenStream, item: TokenStream) -> TokenStream {
537    pipeline_attribute_outside_controller("use_guard", item)
538}
539
540#[proc_macro_attribute]
541pub fn use_interceptor(_attr: TokenStream, item: TokenStream) -> TokenStream {
542    pipeline_attribute_outside_controller("use_interceptor", item)
543}
544
545#[proc_macro_attribute]
546pub fn use_filter(_attr: TokenStream, item: TokenStream) -> TokenStream {
547    pipeline_attribute_outside_controller("use_filter", item)
548}
549
550#[proc_macro_attribute]
551pub fn use_pipe(_attr: TokenStream, item: TokenStream) -> TokenStream {
552    pipeline_attribute_outside_controller("use_pipe", item)
553}
554
555#[proc_macro_attribute]
556pub fn cache_key(_attr: TokenStream, item: TokenStream) -> TokenStream {
557    cache_attribute_outside_controller("cache_key", item)
558}
559
560#[proc_macro_attribute]
561pub fn cache_ttl(_attr: TokenStream, item: TokenStream) -> TokenStream {
562    cache_attribute_outside_controller("cache_ttl", item)
563}