1use crate::{attr, bound, fallback, private};
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 Err(error) => fallback::ser(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
36fn 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 fieldstr = fields
42 .named
43 .iter()
44 .map(attr::name_of_field)
45 .collect::<Result<Vec<_>>>()?;
46 let index = 0usize..;
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 = ::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "miniserde");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Serialize");
_s
})parse_quote!(miniserde::Serialize);
51 let bounded_where_clause = bound::where_clause_with_bound(&input.generics, bound);
52 let private2 = private;
53
54 Ok({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "allow");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "deprecated");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s,
"non_upper_case_globals");
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "const");
::quote::__private::push_underscore(&mut _s);
::quote::__private::push_colon(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_eq(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "impl");
::quote::ToTokens::to_tokens(&impl_generics, &mut _s);
::quote::__private::push_ident(&mut _s, "miniserde");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Serialize");
::quote::__private::push_ident(&mut _s, "for");
::quote::ToTokens::to_tokens(&ident, &mut _s);
::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
::quote::ToTokens::to_tokens(&bounded_where_clause, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "begin");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_and(&mut _s);
::quote::__private::push_ident(&mut _s, "self");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_ident(&mut _s, "miniserde");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "ser");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Fragment");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "miniserde");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "ser");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Fragment");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Map");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "miniserde");
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&private, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Box");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "new");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "__Map");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "data");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_ident(&mut _s, "self");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "state");
::quote::__private::push_colon(&mut _s);
::quote::__private::parse(&mut _s, "0");
::quote::__private::push_comma(&mut _s);
_s
});
_s
});
_s
});
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "struct");
::quote::__private::push_ident(&mut _s, "__Map");
::quote::ToTokens::to_tokens(&wrapper_impl_generics, &mut _s);
::quote::ToTokens::to_tokens(&where_clause, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "data");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'__a");
::quote::ToTokens::to_tokens(&ident, &mut _s);
::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "state");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_ident(&mut _s, "miniserde");
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&private, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "usize");
::quote::__private::push_comma(&mut _s);
_s
});
::quote::__private::push_ident(&mut _s, "impl");
::quote::ToTokens::to_tokens(&wrapper_impl_generics, &mut _s);
::quote::__private::push_ident(&mut _s, "miniserde");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "ser");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Map");
::quote::__private::push_ident(&mut _s, "for");
::quote::__private::push_ident(&mut _s, "__Map");
::quote::ToTokens::to_tokens(&wrapper_ty_generics, &mut _s);
::quote::ToTokens::to_tokens(&bounded_where_clause, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "next");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_and(&mut _s);
::quote::__private::push_ident(&mut _s, "mut");
::quote::__private::push_ident(&mut _s, "self");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_ident(&mut _s, "miniserde");
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&private, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Option");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "miniserde");
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&private, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Cow");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "miniserde");
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&private, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "str");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_comma(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::__private::push_ident(&mut _s, "dyn");
::quote::__private::push_ident(&mut _s, "miniserde");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Serialize");
_s
});
::quote::__private::push_gt(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "let");
::quote::__private::push_ident(&mut _s, "__state");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_ident(&mut _s, "self");
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "state");
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "self");
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "state");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_ident(&mut _s, "__state");
::quote::__private::push_add(&mut _s);
::quote::__private::parse(&mut _s, "1");
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "match");
::quote::__private::push_ident(&mut _s, "__state");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter =
::quote::__private::ThereIsNoIteratorInRepetition;
#[allow(unused_mut)]
let (mut index, i) = index.quote_into_iter();
let has_iter = has_iter | i;
#[allow(unused_mut)]
let (mut private2, i) = private2.quote_into_iter();
let has_iter = has_iter | i;
#[allow(unused_mut)]
let (mut private2, i) = private2.quote_into_iter();
let has_iter = has_iter | i;
#[allow(unused_mut)]
let (mut fieldstr, i) = fieldstr.quote_into_iter();
let has_iter = has_iter | i;
#[allow(unused_mut)]
let (mut fieldname, i) = fieldname.quote_into_iter();
let has_iter = has_iter | i;
let _: ::quote::__private::HasIterator = has_iter;
while true {
let index =
match index.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
let private2 =
match private2.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
let private2 =
match private2.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
let fieldstr =
match fieldstr.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
let fieldname =
match fieldname.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&index, &mut _s);
::quote::__private::push_fat_arrow(&mut _s);
::quote::__private::push_ident(&mut _s, "miniserde");
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&private2, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Some");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "miniserde");
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&private2, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Cow");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Borrowed");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&fieldstr, &mut _s);
_s
});
::quote::__private::push_comma(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::__private::push_ident(&mut _s, "self");
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "data");
::quote::__private::push_dot(&mut _s);
::quote::ToTokens::to_tokens(&fieldname, &mut _s);
::quote::__private::push_comma(&mut _s);
_s
});
_s
});
::quote::__private::push_comma(&mut _s);
}
}
::quote::__private::push_underscore(&mut _s);
::quote::__private::push_fat_arrow(&mut _s);
::quote::__private::push_ident(&mut _s, "miniserde");
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&private, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "None");
::quote::__private::push_comma(&mut _s);
_s
});
_s
});
_s
});
_s
});
::quote::__private::push_semi(&mut _s);
_s
}quote! {
55 #[allow(deprecated, non_upper_case_globals)]
56 const _: () = {
57 impl #impl_generics miniserde::Serialize for #ident #ty_generics #bounded_where_clause {
58 fn begin(&self) -> miniserde::ser::Fragment {
59 miniserde::ser::Fragment::Map(miniserde::#private::Box::new(__Map {
60 data: self,
61 state: 0,
62 }))
63 }
64 }
65
66 struct __Map #wrapper_impl_generics #where_clause {
67 data: &'__a #ident #ty_generics,
68 state: miniserde::#private::usize,
69 }
70
71 impl #wrapper_impl_generics miniserde::ser::Map for __Map #wrapper_ty_generics #bounded_where_clause {
72 fn next(&mut self) -> miniserde::#private::Option<(miniserde::#private::Cow<miniserde::#private::str>, &dyn miniserde::Serialize)> {
73 let __state = self.state;
74 self.state = __state + 1;
75 match __state {
76 #(
77 #index => miniserde::#private2::Some((
78 miniserde::#private2::Cow::Borrowed(#fieldstr),
79 &self.data.#fieldname,
80 )),
81 )*
82 _ => miniserde::#private::None,
83 }
84 }
85 }
86 };
87 })
88}
89
90fn derive_enum(input: &DeriveInput, enumeration: &DataEnum) -> Result<TokenStream> {
91 if input.generics.lt_token.is_some() || input.generics.where_clause.is_some() {
92 return Err(Error::new(
93 Span::call_site(),
94 "Enums with generics are not supported",
95 ));
96 }
97
98 let ident = &input.ident;
99
100 let var_idents = enumeration
101 .variants
102 .iter()
103 .map(|variant| match variant.fields {
104 Fields::Unit => Ok(&variant.ident),
105 _ => Err(Error::new_spanned(
106 variant,
107 "Invalid variant: only simple enum variants without fields are supported",
108 )),
109 })
110 .collect::<Result<Vec<_>>>()?;
111 let names = enumeration
112 .variants
113 .iter()
114 .map(attr::name_of_variant)
115 .collect::<Result<Vec<_>>>()?;
116 let private2 = private;
117
118 Ok({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "allow");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "deprecated");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s,
"non_upper_case_globals");
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "const");
::quote::__private::push_underscore(&mut _s);
::quote::__private::push_colon(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_eq(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "impl");
::quote::__private::push_ident(&mut _s, "miniserde");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Serialize");
::quote::__private::push_ident(&mut _s, "for");
::quote::ToTokens::to_tokens(&ident, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "begin");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_and(&mut _s);
::quote::__private::push_ident(&mut _s, "self");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_ident(&mut _s, "miniserde");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "ser");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Fragment");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "match");
::quote::__private::push_ident(&mut _s, "self");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter =
::quote::__private::ThereIsNoIteratorInRepetition;
#[allow(unused_mut)]
let (mut ident, i) = ident.quote_into_iter();
let has_iter = has_iter | i;
#[allow(unused_mut)]
let (mut var_idents, i) = var_idents.quote_into_iter();
let has_iter = has_iter | i;
#[allow(unused_mut)]
let (mut private2, i) = private2.quote_into_iter();
let has_iter = has_iter | i;
#[allow(unused_mut)]
let (mut names, i) = names.quote_into_iter();
let has_iter = has_iter | i;
let _: ::quote::__private::HasIterator = has_iter;
while true {
let ident =
match ident.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
let var_idents =
match var_idents.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
let private2 =
match private2.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
let names =
match names.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&ident, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&var_idents, &mut _s);
::quote::__private::push_fat_arrow(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "miniserde");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "ser");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Fragment");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Str");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "miniserde");
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&private2, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Cow");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Borrowed");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&names, &mut _s);
_s
});
_s
});
_s
});
}
}
_s
});
_s
});
_s
});
_s
});
::quote::__private::push_semi(&mut _s);
_s
}quote! {
119 #[allow(deprecated, non_upper_case_globals)]
120 const _: () = {
121 impl miniserde::Serialize for #ident {
122 fn begin(&self) -> miniserde::ser::Fragment {
123 match self {
124 #(
125 #ident::#var_idents => {
126 miniserde::ser::Fragment::Str(miniserde::#private2::Cow::Borrowed(#names))
127 }
128 )*
129 }
130 }
131 }
132 };
133 })
134}