ark_crypto_primitives_macros_zypher/
lib.rs

1extern crate proc_macro;
2use proc_macro::TokenStream;
3use proc_macro2::TokenStream as TokenStream2;
4use quote::quote;
5use syn::{parse_macro_input, Data, DeriveInput, Fields, Index};
6
7#[proc_macro_derive(Absorb)]
8pub fn derive_absorb(input: TokenStream) -> TokenStream {
9    let input = parse_macro_input!(input as DeriveInput);
10
11    let name = input.ident;
12    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
13
14    let len = if let Data::Struct(ref data_struct) = input.data {
15        data_struct.fields.len()
16    } else {
17        panic!(
18            "`Absorb` can only be derived for structs, {} is not a struct",
19            name
20        );
21    };
22
23    let mut to_sponge_bytes = Vec::<TokenStream2>::with_capacity(len);
24    let mut to_sponge_field_elements = Vec::<TokenStream2>::with_capacity(len);
25
26    match input.data {
27        Data::Struct(ref data_struct) => match data_struct.fields {
28            Fields::Named(ref fields) => {
29                let _: Vec<_> = fields
30                    .named
31                    .iter()
32                    .map(|f| {
33                        let name = &f.ident;
34                        to_sponge_bytes.push(quote! {
35                            Absorb::to_sponge_bytes(&self.#name, dest);
36                        });
37                    })
38                    .collect();
39
40                let _: Vec<_> = fields
41                    .named
42                    .iter()
43                    .map(|f| {
44                        let name = &f.ident;
45                        to_sponge_field_elements.push(quote! {
46                            Absorb::to_sponge_field_elements(&self.#name, dest);
47                        });
48                    })
49                    .collect();
50            }
51            Fields::Unnamed(ref fields) => {
52                let _: Vec<_> = fields
53                    .unnamed
54                    .iter()
55                    .enumerate()
56                    .map(|(i, _)| {
57                        let index = Index::from(i);
58                        to_sponge_bytes.push(quote! {
59                            Absorb::to_sponge_bytes(&self.#index, dest);
60                        });
61                    })
62                    .collect();
63
64                let _: Vec<_> = fields
65                    .unnamed
66                    .iter()
67                    .enumerate()
68                    .map(|(i, _)| {
69                        let index = Index::from(i);
70                        to_sponge_field_elements.push(quote! {
71                            Absorb::to_sponge_field_elements(&self.#index, dest);
72                        });
73                    })
74                    .collect();
75            }
76            _ => panic!("Absorb only supports named and unnamed fields"),
77        },
78        // this should be unreachable, we already checked
79        _ => panic!("Absorb only supports structs"),
80    }
81
82    quote! {
83        impl #impl_generics Absorb for #name #ty_generics #where_clause {
84            fn to_sponge_bytes(&self, dest: &mut Vec<u8>) {
85                #( #to_sponge_bytes )*
86            }
87
88            fn to_sponge_field_elements<FieldType: PrimeField>(&self, dest: &mut Vec<FieldType>) {
89                #( #to_sponge_field_elements )*
90            }
91        }
92    }
93    .into()
94}