memorix_client_redis_macros/
lib.rs

1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, Data, DeriveInput, Fields, Type};
4
5#[proc_macro_attribute]
6pub fn serialization(_attr: TokenStream, item: TokenStream) -> TokenStream {
7    let mut input = parse_macro_input!(item as DeriveInput);
8
9    if let Data::Struct(ref mut data) = input.data {
10        if let Fields::Named(ref mut fields) = data.fields {
11            for field in fields.named.iter_mut() {
12                if is_option(&field.ty) {
13                    field
14                        .attrs
15                        .push(syn::parse_quote!(#[serde(skip_serializing_if = "Option::is_none")]));
16                }
17            }
18        }
19    }
20
21    let name = &input.ident;
22    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
23
24    let expanded = quote! {
25        #[derive(::memorix_client_redis::__private::serde::Serialize, ::memorix_client_redis::__private::serde::Deserialize)]
26        #[serde(crate = "::memorix_client_redis::__private::serde")]
27        #input
28
29        impl #impl_generics #name #ty_generics #where_clause {
30            pub fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
31            where
32                S: ::memorix_client_redis::__private::serde::Serializer,
33            {
34                ::memorix_client_redis::__private::serde::Serialize::serialize(self, serializer)
35            }
36
37            pub fn deserialize<'de, D>(deserializer: D) -> Result<Self, D::Error>
38            where
39                D: ::memorix_client_redis::__private::serde::Deserializer<'de>,
40            {
41                ::memorix_client_redis::__private::serde::Deserialize::deserialize(deserializer)
42            }
43        }
44    };
45
46    TokenStream::from(expanded)
47}
48
49fn is_option(ty: &Type) -> bool {
50    if let Type::Path(type_path) = ty {
51        if let Some(segment) = type_path.path.segments.last() {
52            return segment.ident == "Option";
53        }
54    }
55    false
56}