actix_prost_macros/
lib.rs1use enums::process_enum;
2use field::process_field;
3use proc_macro::TokenStream;
4use quote::quote;
5use syn::{Attribute, AttributeArgs, Item};
6
7mod enums;
8mod field;
9mod prost;
10
11fn find_rename_all(attrs: &[syn::NestedMeta]) -> Option<String> {
12 for attr in attrs {
13 match attr {
14 syn::NestedMeta::Meta(syn::Meta::NameValue(meta))
15 if meta.path == syn::parse_quote!(rename_all) =>
16 {
17 if let syn::Lit::Str(s) = &meta.lit {
18 return Some(s.value());
19 }
20 }
21 _ => {}
22 }
23 }
24 None
25}
26
27fn has_other_actix_prost_serde_attributes(item_attributes: &[Attribute]) -> bool {
30 item_attributes
31 .iter()
32 .any(|attribute| attribute.path == syn::parse_quote!(actix_prost_macros::serde))
33}
34
35#[proc_macro_attribute]
36pub fn serde(attrs: TokenStream, item: TokenStream) -> TokenStream {
37 let mut item = syn::parse_macro_input!(item as Item);
38
39 let attrs = syn::parse_macro_input!(attrs as AttributeArgs);
40 let maybe_rename = match find_rename_all(&attrs) {
41 Some(rename) if rename.to_lowercase() == "none" => None,
47 Some(rename) => Some(rename),
48 None => Some("camelCase".to_owned()),
49 };
50
51 match &mut item {
56 syn::Item::Enum(item) if !has_other_actix_prost_serde_attributes(&item.attrs) => {
57 let mut need_serde_as = false;
58 for variant in item.variants.iter_mut() {
59 for field in variant.fields.iter_mut() {
60 let (attr, need) = process_field(field);
61 need_serde_as = need || need_serde_as;
62 if let Some(attr) = attr {
63 field.attrs.push(attr);
64 }
65 }
66 }
67 if need_serde_as {
68 item.attrs.push(syn::parse_quote!(#[serde_with::serde_as]));
69 }
70 item.attrs
71 .push(syn::parse_quote!(#[derive(serde::Serialize, serde::Deserialize)]));
72 process_enum(item, maybe_rename.clone());
73 }
74 syn::Item::Struct(item) if !has_other_actix_prost_serde_attributes(&item.attrs) => {
75 let mut need_serde_as = false;
76 for field in item.fields.iter_mut() {
77 let (attr, need) = process_field(field);
78 need_serde_as = need || need_serde_as;
79 if let Some(attr) = attr {
80 field.attrs.push(attr);
81 }
82 }
83 if need_serde_as {
84 item.attrs.push(syn::parse_quote!(#[serde_with::serde_as]));
85 }
86 item.attrs
87 .push(syn::parse_quote!(#[derive(serde::Serialize, serde::Deserialize)]));
88 if let Some(rename) = maybe_rename {
89 item.attrs
90 .push(syn::parse_quote!(#[serde(rename_all = #rename)]));
91 }
92 }
93 _ => {}
94 }
95 quote!(#item).into()
96}