rust_wechat_codegen/
lib.rs1use proc_macro2::{Ident, TokenStream};
2use quote::{format_ident, quote};
3use syn::{parse_macro_input, DeriveInput, LitStr, Meta};
4
5#[proc_macro_derive(ServerResponse, attributes(sr))]
6pub fn server_response(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
7
8 let ast = parse_macro_input!(input as DeriveInput);
9 let struct_name = &ast.ident;
10 let response_struct_name = format_ident!("{}Response", struct_name);
11
12 let mut flatten: TokenStream = quote! {};
13 let mut data_name: Ident = format_ident!("data");
14 ast.attrs.iter().for_each(|a| {
15 if a.path().is_ident("sr") {
16 match &a.meta {
17 Meta::List(meta) => {
18 meta.parse_nested_meta(|nest| {
19 if nest.path.is_ident("flatten") {
20 flatten = quote! {
21 #[serde(flatten)]
22 }
23 } else if nest.path.is_ident("name") {
24 let value = nest.value()?;
25 let s: LitStr = value.parse()?;
26 data_name = format_ident!("{}", s.value());
27 }
28 Ok(())
29 }).unwrap()
30 },
31 _ => {}
32 }
33 }
34 });
35
36 let new_struct = quote! {
37 #[derive(Debug, serde::Serialize, serde::Deserialize)]
38 pub struct #response_struct_name {
39 #flatten
40 pub #data_name: #struct_name,
41 pub errcode: i32,
42 pub errmsg: Option<String>,
43 }
44 };
45
46 let method = quote! {
47 impl #response_struct_name {
48 pub fn is_ok(&self) -> bool {
49 self.errcode == 0
50 }
51
52 pub fn #data_name(self) -> Result<#struct_name, rust_wechat_core::ServerError> {
53 if self.is_ok() {
54 Ok(self.#data_name)
55 } else {
56 let err = rust_wechat_core::ServerError::default().code(self.errcode);
57 if let Some(msg) = self.errmsg {
58 Err(err.message(msg))
59 } else {
60 Err(err)
61 }
62 }
63 }
64
65 pub fn ignore(self) -> Result<(), rust_wechat_core::ServerError> {
66 if self.is_ok() {
67 Ok(())
68 } else {
69 let err = rust_wechat_core::ServerError::default().code(self.errcode);
70 if let Some(msg) = self.errmsg {
71 Err(err.message(msg))
72 } else {
73 Err(err)
74 }
75 }
76 }
77 }
78 };
79
80 let expanded = quote! {
81 #new_struct
82 #method
83 };
84
85 proc_macro::TokenStream::from(expanded)
86}