serde_dot_case/
lib.rs

1use convert_case::{Case, Casing};
2use proc_macro::{self, TokenStream};
3use proc_macro2::Span;
4use proc_macro_crate::{crate_name, FoundCrate};
5use quote::quote;
6use syn::{parse_macro_input, Ident, ItemEnum};
7
8#[allow(dead_code)]
9fn import_crate() -> Ident {
10    let found_crate =
11        crate_name("serde-dot-case").expect("serde-dot-case is present in `Cargo.toml`");
12    match found_crate {
13        FoundCrate::Itself => Ident::new("crate", Span::call_site()),
14        FoundCrate::Name(name) => Ident::new(&name, Span::call_site()),
15    }
16}
17
18#[proc_macro_attribute]
19pub fn serde_dot_case(_attr: TokenStream, item: TokenStream) -> TokenStream {
20    let ItemEnum {
21        attrs,
22        vis,
23        enum_token,
24        ident,
25        generics,
26        brace_token: _,
27        variants,
28    } = parse_macro_input!(item);
29    let variants = variants.iter().map(|v| {
30        let name = v.ident.to_string().to_case(Case::Snake).replace('_', ".");
31        quote! {
32            #[serde(rename = #name)]
33            #v
34        }
35    });
36    quote! {
37        #(#attrs)*
38        #vis #enum_token #ident #generics {
39            #(#variants,)*
40        }
41    }
42    .into()
43}