Skip to main content

rustra_macros/
macro_bridge_type.rs

1/// struct/enum에 bridge에 필요한 derive와 serde 설정을 자동 추가하는 속성 매크로입니다.
2///
3/// 다음을 자동으로 추가합니다:
4/// - `#[derive(Debug, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]`
5/// - `#[serde(rename_all = "camelCase")]` (기존 serde rename 속성이 없을 시)
6///
7/// ## 예제
8///
9/// ```rust
10/// use rustra::prelude::*;
11///
12/// #[bridge_type]
13/// #[derive(Clone)]
14/// struct AddNumbersInput { a: i64, b: i64 }
15/// ```
16#[proc_macro_attribute]
17pub fn bridge_type(_attr: TokenStream, item: TokenStream) -> TokenStream {
18    let mut input = parse_macro_input!(item as DeriveInput);
19
20    // Add derive attributes for bridge-required traits
21    input.attrs.push(syn::parse_quote! {
22        #[derive(Debug, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
23    });
24
25    // Add serde rename_all = "camelCase" only if no serde(rename_all = ...) exists
26    let has_serde_rename = input.attrs.iter().any(|attr| {
27        if !attr.path().is_ident("serde") {
28            return false;
29        }
30        let Ok(nested) = attr.parse_args_with(
31            syn::punctuated::Punctuated::<syn::MetaNameValue, syn::Token![,]>::parse_terminated,
32        ) else {
33            return false;
34        };
35        nested.iter().any(|nv| nv.path.is_ident("rename_all"))
36    });
37
38    if !has_serde_rename {
39        input.attrs.push(syn::parse_quote! {
40            #[serde(rename_all = "camelCase")]
41        });
42    }
43
44    quote! { #input }.into()
45}