Skip to main content

jaguar_derive/
lib.rs

1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, Data, DeriveInput, Fields};
4
5#[proc_macro_derive(JaguarSerialize)]
6pub fn derive_serialize(input: TokenStream) -> TokenStream {
7    let input = parse_macro_input!(input as DeriveInput);
8    let name = input.ident;
9    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
10
11    let fields = match input.data {
12        Data::Struct(data) => match data.fields {
13            Fields::Named(fields) => fields.named,
14            Fields::Unnamed(fields) => fields.unnamed,
15            Fields::Unit => return quote! {}.into(),
16        },
17        _ => return quote! {}.into(),
18    };
19
20    let field_serialize = fields.iter().map(|field| {
21        let field_name = field.ident.as_ref().unwrap();
22        quote! {
23            self.#field_name.serialize(ser)?;
24        }
25    });
26
27    let expanded = quote! {
28        impl #impl_generics jaguar::JaguarSerialize for #name #ty_generics #where_clause {
29            fn serialize(&self, ser: &mut jaguar::JaguarSerializer) -> Result<(), jaguar::SerError> {
30                #(#field_serialize)*
31                Ok(())
32            }
33        }
34    };
35
36    expanded.into()
37}
38
39#[proc_macro_derive(JaguarDeserialize)]
40pub fn derive_deserialize(input: TokenStream) -> TokenStream {
41    let input = parse_macro_input!(input as DeriveInput);
42    let name = input.ident;
43    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
44
45    let fields = match input.data {
46        Data::Struct(data) => match data.fields {
47            Fields::Named(fields) => fields.named,
48            Fields::Unnamed(fields) => fields.unnamed,
49            Fields::Unit => return quote! {}.into(),
50        },
51        _ => return quote! {}.into(),
52    };
53
54    let field_deserialize = fields.iter().map(|field| {
55        let field_name = field.ident.as_ref().unwrap();
56        let field_type = &field.ty;
57        quote! {
58            let #field_name = <#field_type as jaguar::JaguarDeserialize>::deserialize(de)?;
59        }
60    });
61
62    let field_names = fields.iter().map(|field| {
63        field.ident.as_ref().unwrap()
64    });
65
66    let expanded = quote! {
67        impl<'a> #impl_generics jaguar::JaguarDeserialize<'a> for #name #ty_generics #where_clause {
68            fn deserialize(de: &mut jaguar::JaguarDeserializer<'a>) -> Result<Self, jaguar::SerError> {
69                #(#field_deserialize)*
70                Ok(Self {
71                    #(#field_names,)*
72                })
73            }
74        }
75    };
76
77    expanded.into()
78}