ensicoin_serializer_derive/
lib.rs

1extern crate proc_macro;
2use crate::proc_macro::TokenStream;
3use quote::quote;
4use syn;
5
6#[proc_macro_derive(Deserialize)]
7pub fn deserialize_macro_derive(input: TokenStream) -> TokenStream {
8    let ast = syn::parse(input).unwrap();
9
10    impl_deserialize_macro(&ast)
11}
12
13fn impl_deserialize_macro(ast: &syn::DeriveInput) -> TokenStream {
14    let name = &ast.ident;
15    let generics = &ast.generics;
16
17    let mut field_list = quote! {};
18    let mut body = quote! {};
19
20    match &ast.data {
21        syn::Data::Struct(data) => {
22            for field in data.fields.iter() {
23                let field_type = &field.ty;
24                match &field.ident {
25                    Some(field_name) => {
26                        body = quote! {
27                            #body
28                            let #field_name = match <#field_type>::deserialize(de) {
29                                Ok(v) => v,
30                                Err(e) => {
31                                    return Err(ensicoin_serializer::Error::Message(format!(
32                                                "Error in reading {} {}: {}",
33                                                stringify!(#name),
34                                                stringify!(#field_name),
35                                                e
36                                    )));
37                                }
38                            };
39                        };
40                        field_list = quote! {#field_list
41                        #field_name,};
42                    }
43                    None => panic!("Can't derive unamed field in {}", name),
44                }
45            }
46        }
47        _ => panic!("Can only derive struts, {} is invalid", name),
48    };
49
50    let gen = quote! {
51        impl #generics Deserialize for #name #generics {
52            fn deserialize(
53                de: &mut ensicoin_serializer::Deserializer,
54            ) -> ensicoin_serializer::Result<Self> {
55                #body
56                Ok(#name {#field_list
57                })
58            }
59       }
60    };
61    gen.into()
62}
63
64#[proc_macro_derive(Serialize)]
65pub fn serialize_macro_derive(input: TokenStream) -> TokenStream {
66    let ast = syn::parse(input).unwrap();
67
68    impl_serialize_macro(&ast)
69}
70
71fn impl_serialize_macro(ast: &syn::DeriveInput) -> TokenStream {
72    let name = &ast.ident;
73    let generics = &ast.generics;
74
75    let mut body = quote! {};
76    match &ast.data {
77        syn::Data::Struct(data) => {
78            for field in data.fields.iter() {
79                match &field.ident {
80                    Some(field_name) => {
81                        body = quote! {
82                            #body
83                            v.extend_from_slice(&self.#field_name.serialize());
84                        }
85                    }
86                    None => panic!("Can't derive unamed field in {}", name),
87                }
88            }
89        }
90        _ => panic!("Can only derive structs, {} is invalid", name),
91    }
92
93    let gen = quote! {
94        impl #generics Serialize for #name #generics {
95            fn serialize(&self) -> bytes::Bytes {
96                let mut v = bytes::Bytes::new();
97                #body
98                v
99            }
100       }
101    };
102    gen.into()
103}