1use proc_macro2::{Span, TokenStream};
2use syn::Ident;
3
4use internals::ast::{Container, Data, Field, Style};
5
6pub fn pretend_used(cont: &Container) -> TokenStream {
24 let pretend_fields = pretend_fields_used(cont);
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) -> TokenStream {
52 let type_ident = &cont.ident;
53 let (_, ty_generics, _) = cont.generics.split_for_impl();
54
55 let patterns = match &cont.data {
56 Data::Enum(variants) => variants
57 .iter()
58 .filter_map(|variant| match variant.style {
59 Style::Struct => {
60 let variant_ident = &variant.ident;
61 let pat = struct_pattern(&variant.fields);
62 Some(quote!(#type_ident::#variant_ident #pat))
63 }
64 _ => None,
65 })
66 .collect::<Vec<_>>(),
67 Data::Struct(Style::Struct, fields) => {
68 let pat = struct_pattern(fields);
69 vec![quote!(#type_ident #pat)]
70 }
71 Data::Struct(_, _) => {
72 return quote!();
73 }
74 };
75
76 quote! {
77 match _serde::export::None::<#type_ident #ty_generics> {
78 #(
79 _serde::export::Some(#patterns) => {}
80 )*
81 _ => {}
82 }
83 }
84}
85
86fn pretend_variants_used(cont: &Container) -> TokenStream {
96 let variants = match &cont.data {
97 Data::Enum(variants) => variants,
98 Data::Struct(_, _) => {
99 return quote!();
100 }
101 };
102
103 let type_ident = &cont.ident;
104 let (_, ty_generics, _) = cont.generics.split_for_impl();
105 let turbofish = ty_generics.as_turbofish();
106
107 let cases = variants.iter().map(|variant| {
108 let variant_ident = &variant.ident;
109 let placeholders = &(0..variant.fields.len())
110 .map(|i| Ident::new(&format!("__v{}", i), Span::call_site()))
111 .collect::<Vec<_>>();
112
113 let pat = match variant.style {
114 Style::Struct => {
115 let members = variant.fields.iter().map(|field| &field.member);
116 quote!({ #(#members: #placeholders),* })
117 }
118 Style::Tuple | Style::Newtype => quote!(( #(#placeholders),* )),
119 Style::Unit => quote!(),
120 };
121
122 quote! {
123 match _serde::export::None {
124 _serde::export::Some((#(#placeholders,)*)) => {
125 let _ = #type_ident::#variant_ident #turbofish #pat;
126 }
127 _ => {}
128 }
129 }
130 });
131
132 quote!(#(#cases)*)
133}
134
135fn struct_pattern(fields: &[Field]) -> TokenStream {
136 let members = fields.iter().map(|field| &field.member);
137 let placeholders =
138 (0..fields.len()).map(|i| Ident::new(&format!("__v{}", i), Span::call_site()));
139 quote!({ #(#members: ref #placeholders),* })
140}