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