dce_macro/lib.rs
1//! # Dce macros
2//!
3//! ## api(): proc_macro_attribute
4//! An attribute-like macro, you can use it to define api, it will auto bind the controller func.
5//!
6//! **Parameters:**
7//!
8//!- *path `&str`*:\
9//! The route path, it will be the controller func name if omitted, the style like "part1/part2", and support path params like the table below:
10//!
11//! example | matched | unmatched | description
12//! - | - | - | -
13//! {id}/detail | 1/detail | 1<br>1/info | required param, it could be every place in path
14//! fruit/{target?} | fruit<br>fruit/apple | vegetable | optional param, it must be end of the path
15//! fruit/{targets*} | fruit<br>fruit/apple/banana | vegetable | optional vec param, it must be end of the path
16//! fruit/{targets+} | fruit/apple<br>fruit/apple/banana | fruit<br>vegetable | required vec param, it must be end of the path
17//! fruit/{targets+}.\|html | fruit/apple<br>fruit/apple.html | fruit/apple.json | support non suffix or the ".html" suffix but not others
18//! fruit/{targets+}.html\|json | fruit/apple.html<br>fruit/apple/banana.json | fruit/apple | support the ".html" or ".json" suffixes but not non or others
19//!
20//!- *serializer `Vec/struct`*:\
21//! Response body data serializer, use to serialize the `DTO` into `sequences`, like `JsonSerializer{}`. It will be `UnreachableSerializer{}` if not defined.
22//!
23//!- *deserializer `Vec/struct`*:\
24//! Request body data deserializer, use to deserialize the `sequences` into `DTO`, like `JsonSerializer{}`. It will be `UnreachableSerializer{}` if not defined.
25//!
26//!- *id `&str`*:\
27//! Api ID, sometimes you want to use the shorter sign to mark an api, then you can define an id for it. Default value `""`.
28//!
29//!- *omission `bool`*:\
30//! Define it is an omission part, for example `api("home/index", omission = true)` means you must use the path "home" to access it, because the "index" part is omission. Default value `false`.
31//!
32//!- *redirect `&str`*:\
33//! Define the api should redirect to another one. Default value `""`.
34//!
35//!- *name `&str`*:\
36//! Name the api. It will be the last part of path if not defined.
37//!
38//!- *unresponsive `bool`*:\
39//! Define the api should not response, sometimes we want request a tcp or another long connection type service but not need response. Default value `false`.
40//!
41//! The params order is up to down, and you can use assignment expression style define it to break the fixed order.
42//!
43//
44//! ## closed_err!(): proc_macro
45//! A function-like macro to new a `DceErr` enum. Closed err means only print to console but not to response to client the specific error code and message.
46//!
47//! **Parameters:**
48//!
49//! - *code `isize`*:\
50//! The error code, will be `0` if not specified.
51//!
52//! - *template `&str`*:\
53//! The error message or a template.
54//!
55//! - *args `str-like[]`*:\
56//! Template args.
57//!
58//!
59//! ## open_err!(): proc_macro
60//! A function-like macro to new a `DceErr` enum. Openly err means the specific error code and message will respond to client. Params same to `closed_err!()`.
61//!
62
63#[macro_use]
64mod macros;
65mod funcs;
66mod router;
67
68use proc_macro::TokenStream;
69use quote::quote;
70use syn::{parse_macro_input, ItemFn};
71use router::Api;
72use funcs::DceError;
73
74#[proc_macro_attribute]
75pub fn api(args: TokenStream, input: TokenStream) -> TokenStream {
76 let api = parse_macro_input!(args as Api);
77 let input = parse_macro_input!(input as ItemFn);
78 let (input, route_fn_name, return_type, api_scripts) = api.processing(input);
79
80 TokenStream::from(quote!(
81 #input
82 pub fn #route_fn_name<'a>() #return_type { #api_scripts }
83 ))
84}
85
86#[proc_macro]
87pub fn openly_err(args: TokenStream) -> TokenStream {
88 let err = parse_macro_input!(args as DceError);
89 let call = err.gen_func(true);
90 TokenStream::from(quote!(#call))
91}
92
93#[proc_macro]
94pub fn closed_err(args: TokenStream) -> TokenStream {
95 let err = parse_macro_input!(args as DceError);
96 let call = err.gen_func(false);
97 TokenStream::from(quote!(#call))
98}