whisky_macros/data/
enum_constr.rs1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, Data, DeriveInput, Fields};
4
5pub fn derive_plutus_data_to_json(input: TokenStream) -> TokenStream {
6 let input = parse_macro_input!(input as DeriveInput);
7 let name = &input.ident;
8
9 let implementation = match &input.data {
10 Data::Enum(data_enum) => {
11 let match_arms = data_enum.variants.iter().enumerate().map(|(index, variant)| {
12 let variant_name = &variant.ident;
13 let full_variant_path = quote! { #name::#variant_name };
14
15 match &variant.fields {
16 Fields::Unnamed(fields) if fields.unnamed.len() == 1 => {
17 quote! {
19 #full_variant_path(field) => ::whisky::data::Constr::new(#index as u64, field.clone()).to_json()
20 }
21 }
22 Fields::Unnamed(fields) => {
23 let field_count = fields.unnamed.len();
25 let field_names: Vec<_> = (0..field_count).map(|i| syn::Ident::new(&format!("field{}", i), proc_macro2::Span::call_site())).collect();
26
27 let pattern = quote! { #(#field_names),* };
28 let tuple = quote! { (#(#field_names.clone()),*) };
29
30 quote! {
31 #full_variant_path(#pattern) => ::whisky::data::Constr::new(#index as u64, Box::new(#tuple)).to_json()
32 }
33 }
34 Fields::Named(_) => {
35 panic!("Named fields not supported yet");
37 }
38 Fields::Unit => {
39 quote! {
41 #full_variant_path => ::whisky::data::Constr::new(#index as u64, ()).to_json()
42 }
43 }
44 }
45 });
46
47 quote! {
48 impl ::whisky::data::PlutusDataJson for #name {
49 fn to_json(&self) -> ::serde_json::Value {
50 match self {
51 #(#match_arms,)*
52 }
53 }
54
55 fn to_json_string(&self) -> String {
56 self.to_json().to_string()
57 }
58
59 fn to_constr_field(&self) -> Vec<::serde_json::Value> {
60 vec![self.to_json()]
61 }
62 }
63 }
64 }
65 _ => {
66 panic!("PlutusDataToJson can only be derived for enums");
67 }
68 };
69
70 implementation.into()
71}