1use proc_macro::TokenStream;
2use quote::{format_ident, quote};
3use syn::{Attribute, Data, DeriveInput, Fields, parse_macro_input};
4
5#[proc_macro_derive(DeserializeOver1)]
6pub fn deserialize_over1(input: TokenStream) -> TokenStream {
7 let input = parse_macro_input!(input as DeriveInput);
9
10 let name = &input.ident;
12 let shadow_name = format_ident!("__{name}Shadow");
13
14 let (shadow_fields, field_calls) = match &input.data {
16 Data::Struct(struct_) => match &struct_.fields {
17 Fields::Named(fields) => {
18 let mut shadow_fields = Vec::with_capacity(fields.named.len());
19 let mut field_calls = Vec::with_capacity(fields.named.len());
20
21 for field in &fields.named {
22 let name = &field.ident;
23 let attrs: Vec<&Attribute> =
24 field.attrs.iter().filter(|&a| a.path().is_ident("serde")).collect();
25
26 shadow_fields.push(quote! {
27 #(#attrs)*
28 pub(crate) #name: Option<toml::Value>
29 });
30 field_calls.push(quote! {
31 if let Some(value) = shadow.#name {
32 self.#name = self.#name.deserialize_over(value).map_err(serde::de::Error::custom)?;
33 }
34 });
35 }
36
37 (shadow_fields, field_calls)
38 }
39 _ => panic!("DeserializeOver1 only supports structs with named fields"),
40 },
41 _ => panic!("DeserializeOver1 only supports structs"),
42 };
43
44 quote! {
45 #[derive(serde::Deserialize)]
46 pub(crate) struct #shadow_name {
47 #(#shadow_fields),*
48 }
49
50 impl #name {
51 #[inline]
52 pub(crate) fn deserialize_over<'de, D>(self, deserializer: D) -> Result<Self, D::Error>
53 where
54 D: serde::Deserializer<'de>,
55 {
56 self.deserialize_over_with::<D>(Self::deserialize_shadow(deserializer)?)
57 }
58
59 #[inline]
60 pub(crate) fn deserialize_shadow<'de, D>(deserializer: D) -> Result<#shadow_name, D::Error>
61 where
62 D: serde::Deserializer<'de>,
63 {
64 #shadow_name::deserialize(deserializer)
65 }
66
67 #[inline]
68 pub(crate) fn deserialize_over_with<'de, D>(mut self, shadow: #shadow_name) -> Result<Self, D::Error>
69 where
70 D: serde::Deserializer<'de>,
71 {
72 #(#field_calls)*
73 Ok(self)
74 }
75 }
76 }
77 .into()
78}
79
80#[proc_macro_derive(DeserializeOver2)]
81pub fn deserialize_over2(input: TokenStream) -> TokenStream {
82 let input = parse_macro_input!(input as DeriveInput);
84
85 let name = &input.ident;
87 let shadow_name = format_ident!("__{name}Shadow");
88
89 let (shadow_fields, field_assignments) = match &input.data {
91 Data::Struct(struct_) => match &struct_.fields {
92 Fields::Named(fields) => {
93 let mut shadow_fields = Vec::with_capacity(fields.named.len());
94 let mut field_assignments = Vec::with_capacity(fields.named.len());
95
96 for field in &fields.named {
97 let (ty, name) = (&field.ty, &field.ident);
98 shadow_fields.push(quote! {
99 pub(crate) #name: Option<#ty>
100 });
101 field_assignments.push(quote! {
102 if let Some(value) = shadow.#name {
103 self.#name = value;
104 }
105 });
106 }
107
108 (shadow_fields, field_assignments)
109 }
110 _ => panic!("DeserializeOver2 only supports structs with named fields"),
111 },
112 _ => panic!("DeserializeOver2 only supports structs"),
113 };
114
115 quote! {
116 #[derive(serde::Deserialize)]
117 pub(crate) struct #shadow_name {
118 #(#shadow_fields),*
119 }
120
121 impl #name {
122 #[inline]
123 pub(crate) fn deserialize_over<'de, D>(mut self, deserializer: D) -> Result<Self, D::Error>
124 where
125 D: serde::Deserializer<'de>
126 {
127 Ok(self.deserialize_over_with(Self::deserialize_shadow(deserializer)?))
128 }
129
130 #[inline]
131 pub(crate) fn deserialize_shadow<'de, D>(deserializer: D) -> Result<#shadow_name, D::Error>
132 where
133 D: serde::Deserializer<'de>
134 {
135 #shadow_name::deserialize(deserializer)
136 }
137
138 #[inline]
139 pub(crate) fn deserialize_over_with(mut self, shadow: #shadow_name) -> Self {
140 #(#field_assignments)*
141 self
142 }
143 }
144 }
145 .into()
146}