1extern crate proc_macro;
20use proc_macro::TokenStream;
21use proc_macro2::{Span, TokenStream as TokenStream2};
22use proc_macro_crate::{crate_name, FoundCrate};
23use quote::quote;
24use syn::{Ident, ItemEnum, ItemStruct, ItemUnion};
25
26#[cfg(feature = "async")]
27use darkfi_derive_internal::{async_enum_de, async_enum_ser, async_struct_de, async_struct_ser};
28
29use darkfi_derive_internal::{enum_de, enum_ser, struct_de, struct_ser};
30
31#[proc_macro_derive(SerialEncodable, attributes(skip_serialize))]
32pub fn darkfi_serialize(input: TokenStream) -> TokenStream {
33 let found_crate = crate_name("darkfi-serial").expect("darkfi-serial is found in Cargo.toml");
34
35 let found_crate = match found_crate {
36 FoundCrate::Name(name) => name,
37 FoundCrate::Itself => "crate".to_string(),
38 };
39
40 let cratename = Ident::new(&found_crate, Span::call_site());
41
42 let res: syn::Result<TokenStream2> = if let Ok(input) = syn::parse::<ItemStruct>(input.clone())
43 {
44 let sync_tokens = struct_ser(&input, cratename.clone()).unwrap();
45 #[cfg(feature = "async")]
46 let async_tokens = async_struct_ser(&input, cratename).unwrap();
47 #[cfg(not(feature = "async"))]
48 let async_tokens = quote! {};
49
50 Ok(quote! {
51 #sync_tokens
52 #async_tokens
53 })
54 } else if let Ok(input) = syn::parse::<ItemEnum>(input.clone()) {
55 let sync_tokens = enum_ser(&input, cratename.clone()).unwrap();
56 #[cfg(feature = "async")]
57 let async_tokens = async_enum_ser(&input, cratename).unwrap();
58 #[cfg(not(feature = "async"))]
59 let async_tokens = quote! {};
60
61 Ok(quote! {
62 #sync_tokens
63 #async_tokens
64 })
65 } else if let Ok(_input) = syn::parse::<ItemUnion>(input) {
66 todo!()
67 } else {
68 unreachable!()
70 };
71
72 TokenStream::from(res.unwrap_or_else(|err| err.to_compile_error()))
73}
74
75#[proc_macro_derive(SerialDecodable, attributes(skip_serialize))]
76pub fn darkfi_deserialize(input: TokenStream) -> TokenStream {
77 let found_crate = crate_name("darkfi-serial").expect("darkfi-serial is found in Cargo.toml");
78
79 let found_crate = match found_crate {
80 FoundCrate::Name(name) => name,
81 FoundCrate::Itself => "crate".to_string(),
82 };
83
84 let cratename = Ident::new(&found_crate, Span::call_site());
85
86 let res: syn::Result<TokenStream2> = if let Ok(input) = syn::parse::<ItemStruct>(input.clone())
87 {
88 let sync_tokens = struct_de(&input, cratename.clone()).unwrap();
89 #[cfg(feature = "async")]
90 let async_tokens = async_struct_de(&input, cratename).unwrap();
91 #[cfg(not(feature = "async"))]
92 let async_tokens = quote! {};
93
94 Ok(quote! {
95 #sync_tokens
96 #async_tokens
97 })
98 } else if let Ok(input) = syn::parse::<ItemEnum>(input.clone()) {
99 let sync_tokens = enum_de(&input, cratename.clone()).unwrap();
100 #[cfg(feature = "async")]
101 let async_tokens = async_enum_de(&input, cratename).unwrap();
102 #[cfg(not(feature = "async"))]
103 let async_tokens = quote! {};
104
105 Ok(quote! {
106 #sync_tokens
107 #async_tokens
108 })
109 } else if let Ok(_input) = syn::parse::<ItemUnion>(input) {
110 todo!()
111 } else {
112 unreachable!()
114 };
115
116 TokenStream::from(res.unwrap_or_else(|err| err.to_compile_error()))
117}