Skip to main content

bronzerde_derive/
lib.rs

1//! The `bronzerde_derive` crate provides procedural macros for deriving the `EDeserialize` trait
2//! from the [`bronzerde`](https://crates.io/crates/bronzerde) crate.
3//!
4//! You most likely don't want to use `bronzerde_derive` directly. Instead, use the `bronzerde` crate's
5//! `Deserialize` derive macro, which will automatically use the correct version of `bronzerde_derive`
6//! under the hood.
7use emit::{collect_missing_errors, initialize_from_shadow, ImplDeserGenerics};
8use indexmap::IndexSet;
9use proc_macro::TokenStream;
10use quote::{format_ident, quote};
11use syn::{parse_macro_input, DeriveInput};
12use unsupported::reject_unsupported_inputs;
13
14mod attr;
15mod emit;
16mod filter_attributes;
17mod model;
18mod unsupported;
19
20#[proc_macro_derive(Deserialize, attributes(serde, bronzerde))]
21pub fn derive_deserialize(input: TokenStream) -> TokenStream {
22    let input = parse_macro_input!(input as DeriveInput);
23
24    if let Err(e) = reject_unsupported_inputs(&input) {
25        return e.into_compile_error().into();
26    }
27
28    let name = &input.ident;
29    let shadow_type = model::ShadowType::new(format_ident!("__ImplDeserializeFor{}", name), &input);
30    let shadow_type_ident = &shadow_type.0.ident;
31
32    let shadow_binding = format_ident!("__shadowed");
33    let initialize_from_shadow = initialize_from_shadow(
34        &input.data,
35        &format_ident!("Self"),
36        &shadow_binding,
37        shadow_type_ident,
38    );
39
40    let companion_type =
41        model::PermissiveCompanionType::new(format_ident!("__ImplEDeserializeFor{}", name), &input);
42    let companion_type_ident = &companion_type.ty_.ident;
43    let companion_binding = format_ident!("__companion");
44    let deserializer_generic_ident = format_ident!("__D");
45    let n_errors = format_ident!("__n_errors");
46    let collect_missing_errors = collect_missing_errors(
47        &input.data,
48        companion_type_ident,
49        &companion_binding,
50        &n_errors,
51    );
52
53    let deser_generics = ImplDeserGenerics::new(&input, &IndexSet::new());
54    let (impl_generics, ty_generics, where_clause) = deser_generics.split_for_impl();
55
56    let human_deser_generics =
57        ImplDeserGenerics::new(&input, &companion_type.bronzerde_aware_generics);
58    let (human_impl_generics, human_ty_generics, human_where_clause) =
59        human_deser_generics.split_for_impl();
60
61    let expanded = quote! {
62        const _: () = {
63            #companion_type
64
65            #shadow_type
66
67            #[automatically_derived]
68            impl #human_impl_generics ::bronzerde::EDeserialize<'de> for #name #human_ty_generics
69            #human_where_clause
70            {
71                fn deserialize_for_errors<#deserializer_generic_ident>(__deserializer: #deserializer_generic_ident) -> std::result::Result<(), ()>
72                where
73                    #deserializer_generic_ident: ::bronzerde::_serde::Deserializer<'de>,
74                {
75                    let #n_errors = ::bronzerde::reporter::ErrorReporter::n_errors();
76                    let #companion_binding = <#companion_type_ident #ty_generics as ::bronzerde::_serde::Deserialize>::deserialize(__deserializer)
77                        .map_err(::bronzerde::reporter::ErrorReporter::report)?;
78                    #collect_missing_errors
79                }
80            }
81
82            #[automatically_derived]
83            impl #impl_generics ::bronzerde::_serde::Deserialize<'de> for #name #ty_generics
84            #where_clause
85            {
86                fn deserialize<#deserializer_generic_ident>(__deserializer: #deserializer_generic_ident) -> std::result::Result<Self, #deserializer_generic_ident::Error>
87                where
88                    #deserializer_generic_ident: ::bronzerde::_serde::Deserializer<'de>,
89                {
90                    let #shadow_binding = #shadow_type_ident::deserialize(__deserializer)?;
91                    Ok(#initialize_from_shadow)
92                }
93            }
94        };
95    };
96
97    TokenStream::from(expanded)
98}