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
84
85
86
87
88
89
90
91
92
93
94
#[macro_use]
extern crate quote;
mod args;
mod dispatcher;
mod encoder;
mod fallible;
mod helper;
mod stub;
use args::MacroArgsRaw;
use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
#[proc_macro_attribute]
pub fn serde_tc(args: TokenStream, input: TokenStream) -> TokenStream {
match expand(TokenStream2::from(args), TokenStream2::from(input)) {
Ok(x) => TokenStream::from(x),
Err(x) => TokenStream::from(x),
}
}
#[proc_macro_attribute]
pub fn serde_tc_full(_args: TokenStream, input: TokenStream) -> TokenStream {
match expand(
quote! {dispatcher, encoder, dict, tuple, async_methods, fallible = anyhow::Error, stub},
TokenStream2::from(input),
) {
Ok(x) => TokenStream::from(x),
Err(x) => TokenStream::from(x),
}
}
#[proc_macro_attribute]
pub fn serde_tc_debug(_args: TokenStream, input: TokenStream) -> TokenStream {
match expand(
quote! {dispatcher, encoder, dict, tuple, async_methods, fallible = anyhow::Error, stub},
TokenStream2::from(input),
) {
Ok(x) => println!("{}", x),
Err(x) => println!("{}", x),
}
TokenStream::new()
}
fn expand(args: TokenStream2, input: TokenStream2) -> Result<TokenStream2, TokenStream2> {
let args: MacroArgsRaw = syn::parse2(args).map_err(|e| e.to_compile_error())?;
let args = args.fill_default_values();
let source_trait = match syn::parse2::<syn::ItemTrait>(input.clone()) {
Ok(x) => x,
Err(_) => {
return Err(
syn::Error::new_spanned(input, "You can use #[serde_tc] only on a trait")
.to_compile_error(),
)
}
};
let dispatcher = dispatcher::generate_dispatcher(&source_trait, &args)?;
let encoder = encoder::generate_encoder(&source_trait, &args)?;
let fallible = fallible::generate_fallible_trait(&source_trait, &args)?;
let stub = if args.stub {
stub::generate_stub(
&source_trait,
&syn::parse2(fallible.clone()).unwrap(),
&args,
)?
} else {
quote! {}
};
let trait_ident = source_trait.ident.clone();
if args.async_methods {
Ok(quote! {
#[async_trait::async_trait]
#source_trait
#[async_trait::async_trait]
#fallible
#dispatcher
#encoder
#stub
impl HttpInterface for dyn #trait_ident {}
})
} else {
Ok(quote! {
#source_trait
#[async_trait::async_trait]
#fallible
#dispatcher
#encoder
#stub
})
}
}