ark_serialize_derive/
serialize.rs1use proc_macro2::TokenStream;
2use quote::{quote, ToTokens};
3use syn::{Data, Index, Type};
4
5pub(crate) enum IdentOrIndex {
6 Ident(proc_macro2::Ident),
7 Index(Index),
8}
9
10impl ToTokens for IdentOrIndex {
11 fn to_tokens(&self, tokens: &mut TokenStream) {
12 match self {
13 Self::Ident(ident) => ident.to_tokens(tokens),
14 Self::Index(index) => index.to_tokens(tokens),
15 }
16 }
17}
18
19fn impl_serialize_field(
20 serialize_body: &mut Vec<TokenStream>,
21 serialized_size_body: &mut Vec<TokenStream>,
22 idents: &mut Vec<IdentOrIndex>,
23 ty: &Type,
24) {
25 match ty {
27 Type::Tuple(tuple) => {
28 for (i, elem_ty) in tuple.elems.iter().enumerate() {
29 let index = Index::from(i);
30 idents.push(IdentOrIndex::Index(index));
31 impl_serialize_field(serialize_body, serialized_size_body, idents, elem_ty);
32 idents.pop();
33 }
34 },
35 _ => {
36 serialize_body
37 .push(quote! { CanonicalSerialize::serialize_with_mode(&self.#(#idents).*, &mut writer, compress)?; });
38 serialized_size_body
39 .push(quote! { size += CanonicalSerialize::serialized_size(&self.#(#idents).*, compress); });
40 },
41 }
42}
43
44pub(super) fn impl_canonical_serialize(ast: &syn::DeriveInput) -> TokenStream {
45 let name = &ast.ident;
46
47 let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
48
49 let len = if let Data::Struct(ref data_struct) = ast.data {
50 data_struct.fields.len()
51 } else {
52 panic!(
53 "`CanonicalSerialize` can only be derived for structs, {} is not a struct",
54 name
55 );
56 };
57
58 let mut serialize_body = Vec::<TokenStream>::with_capacity(len);
59 let mut serialized_size_body = Vec::<TokenStream>::with_capacity(len);
60
61 match ast.data {
62 Data::Struct(ref data_struct) => {
63 let mut idents = Vec::<IdentOrIndex>::new();
64
65 for (i, field) in data_struct.fields.iter().enumerate() {
66 match field.ident {
67 None => {
68 let index = Index::from(i);
69 idents.push(IdentOrIndex::Index(index));
70 },
71 Some(ref ident) => {
72 idents.push(IdentOrIndex::Ident(ident.clone()));
73 },
74 }
75
76 impl_serialize_field(
77 &mut serialize_body,
78 &mut serialized_size_body,
79 &mut idents,
80 &field.ty,
81 );
82
83 idents.clear();
84 }
85 },
86 _ => panic!(
87 "`CanonicalSerialize` can only be derived for structs, {} is not a struct",
88 name
89 ),
90 };
91
92 let gen = quote! {
93 impl #impl_generics ark_serialize::CanonicalSerialize for #name #ty_generics #where_clause {
94 #[allow(unused_mut, unused_variables)]
95 fn serialize_with_mode<W: ark_serialize::Write>(&self, mut writer: W, compress: ark_serialize::Compress) -> Result<(), ark_serialize::SerializationError> {
96 #(#serialize_body)*
97 Ok(())
98 }
99 #[allow(unused_mut, unused_variables)]
100 fn serialized_size(&self, compress: ark_serialize::Compress) -> usize {
101 let mut size = 0;
102 #(#serialized_size_body)*
103 size
104 }
105 }
106 };
107 gen
108}