mini_internal/
de.rs

1use crate::{attr, bound, fallback};
2use proc_macro2::{Span, TokenStream};
3use quote::quote;
4use syn::{
5    parse_quote, Data, DataEnum, DataStruct, DeriveInput, Error, Fields, FieldsNamed, Result,
6};
7
8pub fn derive(input: &DeriveInput) -> TokenStream {
9    match try_expand(input) {
10        Ok(expanded) => expanded,
11        // If there are invalid attributes in the input, expand to a Deserialize
12        // impl anyway to minimize spurious secondary errors in other code that
13        // deserializes this type.
14        Err(error) => fallback::de(input, error),
15    }
16}
17
18fn try_expand(input: &DeriveInput) -> Result<TokenStream> {
19    match &input.data {
20        Data::Struct(DataStruct {
21            fields: Fields::Named(fields),
22            ..
23        }) => derive_struct(input, fields),
24        Data::Enum(enumeration) => derive_enum(input, enumeration),
25        Data::Struct(_) => Err(Error::new(
26            Span::call_site(),
27            "currently only structs with named fields are supported",
28        )),
29        Data::Union(_) => Err(Error::new(
30            Span::call_site(),
31            "currently only structs and enums are supported by this derive",
32        )),
33    }
34}
35
36pub fn derive_struct(input: &DeriveInput, fields: &FieldsNamed) -> Result<TokenStream> {
37    let ident = &input.ident;
38    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
39
40    let fieldname = fields.named.iter().map(|f| &f.ident).collect::<Vec<_>>();
41    let fieldty = fields.named.iter().map(|f| &f.ty);
42    let fieldstr = fields
43        .named
44        .iter()
45        .map(attr::name_of_field)
46        .collect::<Result<Vec<_>>>()?;
47
48    let wrapper_generics = bound::with_lifetime_bound(&input.generics, "'__a");
49    let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
50    let bound = parse_quote!(miniserde::Deserialize);
51    let bounded_where_clause = bound::where_clause_with_bound(&input.generics, bound);
52
53    Ok(quote! {
54        #[allow(deprecated, non_upper_case_globals)]
55        const _: () = {
56            #[repr(C)]
57            struct __Visitor #impl_generics #where_clause {
58                __out: miniserde::__private::Option<#ident #ty_generics>,
59            }
60
61            impl #impl_generics miniserde::Deserialize for #ident #ty_generics #bounded_where_clause {
62                fn begin(__out: &mut miniserde::__private::Option<Self>) -> &mut dyn miniserde::de::Visitor {
63                    unsafe {
64                        &mut *{
65                            __out
66                            as *mut miniserde::__private::Option<Self>
67                            as *mut __Visitor #ty_generics
68                        }
69                    }
70                }
71            }
72
73            impl #impl_generics miniserde::de::Visitor for __Visitor #ty_generics #bounded_where_clause {
74                fn map(&mut self) -> miniserde::Result<miniserde::__private::Box<dyn miniserde::de::Map + '_>> {
75                    Ok(miniserde::__private::Box::new(__State {
76                        #(
77                            #fieldname: miniserde::Deserialize::default(),
78                        )*
79                        __out: &mut self.__out,
80                    }))
81                }
82            }
83
84            struct __State #wrapper_impl_generics #where_clause {
85                #(
86                    #fieldname: miniserde::__private::Option<#fieldty>,
87                )*
88                __out: &'__a mut miniserde::__private::Option<#ident #ty_generics>,
89            }
90
91            impl #wrapper_impl_generics miniserde::de::Map for __State #wrapper_ty_generics #bounded_where_clause {
92                fn key(&mut self, __k: &miniserde::__private::str) -> miniserde::Result<&mut dyn miniserde::de::Visitor> {
93                    match __k {
94                        #(
95                            #fieldstr => miniserde::__private::Ok(miniserde::Deserialize::begin(&mut self.#fieldname)),
96                        )*
97                        _ => miniserde::__private::Ok(<dyn miniserde::de::Visitor>::ignore()),
98                    }
99                }
100
101                fn finish(&mut self) -> miniserde::Result<()> {
102                    #(
103                        let #fieldname = self.#fieldname.take().ok_or(miniserde::Error)?;
104                    )*
105                    *self.__out = miniserde::__private::Some(#ident {
106                        #(
107                            #fieldname,
108                        )*
109                    });
110                    miniserde::__private::Ok(())
111                }
112            }
113        };
114    })
115}
116
117pub fn derive_enum(input: &DeriveInput, enumeration: &DataEnum) -> Result<TokenStream> {
118    if input.generics.lt_token.is_some() || input.generics.where_clause.is_some() {
119        return Err(Error::new(
120            Span::call_site(),
121            "Enums with generics are not supported",
122        ));
123    }
124
125    let ident = &input.ident;
126
127    let var_idents = enumeration
128        .variants
129        .iter()
130        .map(|variant| match variant.fields {
131            Fields::Unit => Ok(&variant.ident),
132            _ => Err(Error::new_spanned(
133                variant,
134                "Invalid variant: only simple enum variants without fields are supported",
135            )),
136        })
137        .collect::<Result<Vec<_>>>()?;
138    let names = enumeration
139        .variants
140        .iter()
141        .map(attr::name_of_variant)
142        .collect::<Result<Vec<_>>>()?;
143
144    Ok(quote! {
145        #[allow(deprecated, non_upper_case_globals)]
146        const _: () = {
147            #[repr(C)]
148            struct __Visitor {
149                __out: miniserde::__private::Option<#ident>,
150            }
151
152            impl miniserde::Deserialize for #ident {
153                fn begin(__out: &mut miniserde::__private::Option<Self>) -> &mut dyn miniserde::de::Visitor {
154                    unsafe {
155                        &mut *{
156                            __out
157                            as *mut miniserde::__private::Option<Self>
158                            as *mut __Visitor
159                        }
160                    }
161                }
162            }
163
164            impl miniserde::de::Visitor for __Visitor {
165                fn string(&mut self, s: &miniserde::__private::str) -> miniserde::Result<()> {
166                    let value = match s {
167                        #( #names => #ident::#var_idents, )*
168                        _ => return miniserde::__private::Err(miniserde::Error),
169                    };
170                    self.__out = miniserde::__private::Some(value);
171                    miniserde::__private::Ok(())
172                }
173            }
174        };
175    })
176}