1use crate::internals::ast::{Container, Data, Field, Style, Variant};
2use crate::private;
3use proc_macro2::TokenStream;
4use quote::{format_ident, quote};
5
6pub fn pretend_used(cont: &Container, is_packed: bool) -> TokenStream {
24 let pretend_fields = pretend_fields_used(cont, is_packed);
25 let pretend_variants = pretend_variants_used(cont);
26
27 quote! {
28 #pretend_fields
29 #pretend_variants
30 }
31}
32
33fn pretend_fields_used(cont: &Container, is_packed: bool) -> TokenStream {
66 match &cont.data {
67 Data::Enum(variants) => pretend_fields_used_enum(cont, variants),
68 Data::Struct(Style::Struct | Style::Tuple | Style::Newtype, fields) => {
69 if is_packed {
70 pretend_fields_used_struct_packed(cont, fields)
71 } else {
72 pretend_fields_used_struct(cont, fields)
73 }
74 }
75 Data::Struct(Style::Unit, _) => quote!(),
76 }
77}
78
79fn pretend_fields_used_struct(cont: &Container, fields: &[Field]) -> TokenStream {
80 let type_ident = &cont.ident;
81 let (_, ty_generics, _) = cont.generics.split_for_impl();
82
83 let members = fields.iter().map(|field| &field.member);
84 let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
85
86 quote! {
87 match _serde::#private::None::<&#type_ident #ty_generics> {
88 _serde::#private::Some(#type_ident { #(#members: #placeholders),* }) => {}
89 _ => {}
90 }
91 }
92}
93
94fn pretend_fields_used_struct_packed(cont: &Container, fields: &[Field]) -> TokenStream {
95 let type_ident = &cont.ident;
96 let (_, ty_generics, _) = cont.generics.split_for_impl();
97
98 let members = fields.iter().map(|field| &field.member).collect::<Vec<_>>();
99
100 let private2 = private;
101 quote! {
102 match _serde::#private::None::<&#type_ident #ty_generics> {
103 _serde::#private::Some(__v @ #type_ident { #(#members: _),* }) => {
104 #(
105 let _ = _serde::#private2::ptr::addr_of!(__v.#members);
106 )*
107 }
108 _ => {}
109 }
110 }
111}
112
113fn pretend_fields_used_enum(cont: &Container, variants: &[Variant]) -> TokenStream {
114 let type_ident = &cont.ident;
115 let (_, ty_generics, _) = cont.generics.split_for_impl();
116
117 let patterns = variants
118 .iter()
119 .filter_map(|variant| match variant.style {
120 Style::Struct | Style::Tuple | Style::Newtype => {
121 let variant_ident = &variant.ident;
122 let members = variant.fields.iter().map(|field| &field.member);
123 let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
124 Some(quote!(#type_ident::#variant_ident { #(#members: #placeholders),* }))
125 }
126 Style::Unit => None,
127 })
128 .collect::<Vec<_>>();
129
130 let private2 = private;
131 quote! {
132 match _serde::#private::None::<&#type_ident #ty_generics> {
133 #(
134 _serde::#private2::Some(#patterns) => {}
135 )*
136 _ => {}
137 }
138 }
139}
140
141fn pretend_variants_used(cont: &Container) -> TokenStream {
151 let variants = match &cont.data {
152 Data::Enum(variants) => variants,
153 Data::Struct(_, _) => {
154 return quote!();
155 }
156 };
157
158 let type_ident = &cont.ident;
159 let (_, ty_generics, _) = cont.generics.split_for_impl();
160 let turbofish = ty_generics.as_turbofish();
161
162 let cases = variants.iter().map(|variant| {
163 let variant_ident = &variant.ident;
164 let placeholders = &(0..variant.fields.len())
165 .map(|i| format_ident!("__v{}", i))
166 .collect::<Vec<_>>();
167
168 let pat = match variant.style {
169 Style::Struct => {
170 let members = variant.fields.iter().map(|field| &field.member);
171 quote!({ #(#members: #placeholders),* })
172 }
173 Style::Tuple | Style::Newtype => quote!(( #(#placeholders),* )),
174 Style::Unit => quote!(),
175 };
176
177 quote! {
178 match _serde::#private::None {
179 _serde::#private::Some((#(#placeholders,)*)) => {
180 let _ = #type_ident::#variant_ident #turbofish #pat;
181 }
182 _ => {}
183 }
184 }
185 });
186
187 quote!(#(#cases)*)
188}