ark_crypto_primitives_macros_zypher/
lib.rs1extern 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 _ => 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}