dharitri_sc_codec_derive/
nested_en_derive.rs

1use crate::util::*;
2use proc_macro::TokenStream;
3use quote::quote;
4
5pub fn dep_encode_snippet(value: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {
6    quote! {
7        codec::NestedEncode::dep_encode_or_handle_err(&#value, __dest__, __h__)?;
8    }
9}
10
11fn variant_dep_encode_snippets(
12    name: &syn::Ident,
13    data_enum: &syn::DataEnum,
14) -> Vec<proc_macro2::TokenStream> {
15    let mut previous_disc: Vec<ExplicitDiscriminant> = Vec::new();
16    data_enum
17        .variants
18        .iter()
19        .enumerate()
20        .map(|(variant_index, variant)| {
21            let variant_discriminant = get_discriminant(variant_index, variant, &mut previous_disc);
22            let variant_ident = &variant.ident;
23            let local_var_declarations =
24                fields_decl_syntax(&variant.fields, local_variable_for_field);
25            let variant_field_snippets = fields_snippets(&variant.fields, |index, field| {
26                dep_encode_snippet(&local_variable_for_field(index, field))
27            });
28            quote! {
29                #name::#variant_ident #local_var_declarations => {
30                    codec::NestedEncode::dep_encode_or_handle_err(&#variant_discriminant, __dest__, __h__)?;
31                    #(#variant_field_snippets)*
32                },
33            }
34        })
35        .collect()
36}
37
38pub fn nested_encode_impl(ast: &syn::DeriveInput) -> TokenStream {
39    let name = &ast.ident;
40    let (impl_generics, ty_generics, where_clause) = &ast.generics.split_for_impl();
41    let result = match &ast.data {
42        syn::Data::Struct(data_struct) => {
43            let field_dep_encode_snippets = fields_snippets(&data_struct.fields, |index, field| {
44                dep_encode_snippet(&self_field_expr(index, field))
45            });
46            quote! {
47                impl #impl_generics codec::NestedEncode for #name #ty_generics #where_clause {
48                    fn dep_encode_or_handle_err<O, H>(&self, __dest__: &mut O, __h__: H) -> core::result::Result<(), H::HandledErr>
49                    where
50                        O: codec::NestedEncodeOutput,
51                        H: codec::EncodeErrorHandler,
52                    {
53                        #(#field_dep_encode_snippets)*
54                        core::result::Result::Ok(())
55                    }
56                }
57            }
58        },
59        syn::Data::Enum(data_enum) => {
60            validate_enum_variants(&data_enum.variants);
61
62            let variant_dep_encode_snippets = variant_dep_encode_snippets(name, data_enum);
63
64            quote! {
65                impl #impl_generics codec::NestedEncode for #name #ty_generics #where_clause {
66                    fn dep_encode_or_handle_err<O, H>(&self, __dest__: &mut O, __h__: H) -> core::result::Result<(), H::HandledErr>
67                    where
68                        O: codec::NestedEncodeOutput,
69                        H: codec::EncodeErrorHandler,
70                    {
71                        match self {
72                            #(#variant_dep_encode_snippets)*
73                        };
74                        core::result::Result::Ok(())
75                    }
76                }
77            }
78        },
79        syn::Data::Union(_) => panic!("Union not supported"),
80    };
81
82    result.into()
83}