Formatting
This commit is contained in:
95
src/de.rs
95
src/de.rs
@@ -1,15 +1,21 @@
|
||||
use crate::attr;
|
||||
use crate::TagType;
|
||||
use crate::bound;
|
||||
use crate::TagType;
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::quote;
|
||||
use syn::{DataEnum, DeriveInput, Ident, Error, Fields, FieldsUnnamed, Result, parse_quote, Variant};
|
||||
use syn::{
|
||||
parse_quote, DataEnum, DeriveInput, Error, Fields, FieldsNamed, FieldsUnnamed, Ident, Result,
|
||||
Variant,
|
||||
};
|
||||
|
||||
pub fn derive(input: &DeriveInput, enumeration: &DataEnum) -> Result<TokenStream> {
|
||||
let tag_type = attr::tag_type(&input.attrs, &enumeration)?;
|
||||
match &tag_type {
|
||||
TagType::External => deserialize_external(input, enumeration),
|
||||
_ => Err(Error::new(Span::call_site(), "Only externally tagged enums are supported")),
|
||||
_ => Err(Error::new(
|
||||
Span::call_site(),
|
||||
"Only externally tagged enums are supported",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,13 +28,22 @@ pub fn deserialize_external(input: &DeriveInput, enumeration: &DataEnum) -> Resu
|
||||
let bound = parse_quote!(miniserde::Deserialize);
|
||||
let bounded_where_clause = bound::where_clause_with_bound(&input.generics, bound);
|
||||
|
||||
let (unit_variants, struct_variants): (Vec<_>, Vec<_>) = enumeration
|
||||
.variants
|
||||
.iter()
|
||||
.partition(|v| if let Fields::Unit = &v.fields {true} else {false});
|
||||
let (unit_variants, struct_variants): (Vec<_>, Vec<_>) =
|
||||
enumeration.variants.iter().partition(|v| {
|
||||
if let Fields::Unit = &v.fields {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
let struct_names = struct_variants
|
||||
.iter()
|
||||
.map(|variant| Ident::new(&format!("__{}_{}_Struct", ident, variant.ident), Span::call_site()))
|
||||
.map(|variant| {
|
||||
Ident::new(
|
||||
&format!("__{}_{}_Struct", ident, variant.ident),
|
||||
Span::call_site(),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let struct_variant_names = struct_variants
|
||||
.iter()
|
||||
@@ -44,17 +59,14 @@ pub fn deserialize_external(input: &DeriveInput, enumeration: &DataEnum) -> Resu
|
||||
.zip(struct_names.iter())
|
||||
.map(|(variant, ident)| variant_as_struct(variant, ident, &input.ident))
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
let unit_variant_idents = unit_variants
|
||||
.iter()
|
||||
.map(|v| &v.ident)
|
||||
.collect::<Vec<_>>();
|
||||
let unit_variant_idents = unit_variants.iter().map(|v| &v.ident).collect::<Vec<_>>();
|
||||
let unit_variant_names = unit_variants
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(attr::name_of_variant)
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
|
||||
Ok(quote!{
|
||||
Ok(quote! {
|
||||
const _: () = {
|
||||
struct __Visitor #impl_generics #where_clause {
|
||||
__out: miniserde::export::Option<#ident #ty_generics>,
|
||||
@@ -123,21 +135,34 @@ pub fn deserialize_external(input: &DeriveInput, enumeration: &DataEnum) -> Resu
|
||||
})
|
||||
}
|
||||
|
||||
pub fn variant_as_struct(variant: &Variant, ident: &Ident, enum_ident: &Ident) -> Result<TokenStream> {
|
||||
pub fn variant_as_struct(
|
||||
variant: &Variant,
|
||||
ident: &Ident,
|
||||
enum_ident: &Ident,
|
||||
) -> Result<TokenStream> {
|
||||
match &variant.fields {
|
||||
Fields::Named(fields) => named_fields_as_struct(variant, fields, ident, enum_ident),
|
||||
Fields::Unnamed(fields) => unnamed_fields_as_struct(variant, fields, ident, enum_ident),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn named_fields_as_struct(
|
||||
variant: &Variant,
|
||||
fields: &FieldsNamed,
|
||||
ident: &Ident,
|
||||
enum_ident: &Ident,
|
||||
) -> Result<TokenStream> {
|
||||
let variant_ident = &variant.ident;
|
||||
let as_enum = match &variant.fields {
|
||||
Fields::Named(fields) => {
|
||||
let fieldname = fields.named.iter().map(|f| &f.ident).collect::<Vec<_>>();
|
||||
quote!{
|
||||
#enum_ident::#variant_ident {
|
||||
#(
|
||||
#fieldname: self.#fieldname,
|
||||
let as_enum = {
|
||||
let fieldname = fields.named.iter().map(|f| &f.ident).collect::<Vec<_>>();
|
||||
quote! {
|
||||
#enum_ident::#variant_ident {
|
||||
#(
|
||||
#fieldname: self.#fieldname,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
Fields::Unnamed(fields) => return unnamed_fields_as_struct(variant, fields, ident, enum_ident),
|
||||
_ => quote!(unimplemented!()),
|
||||
};
|
||||
let as_struct = syn::ItemStruct {
|
||||
attrs: variant.attrs.clone(),
|
||||
@@ -148,7 +173,7 @@ pub fn variant_as_struct(variant: &Variant, ident: &Ident, enum_ident: &Ident) -
|
||||
fields: variant.fields.clone(),
|
||||
semi_token: None,
|
||||
};
|
||||
Ok(quote!{
|
||||
Ok(quote! {
|
||||
#[derive(Deserialize)]
|
||||
#as_struct
|
||||
|
||||
@@ -160,23 +185,25 @@ pub fn variant_as_struct(variant: &Variant, ident: &Ident, enum_ident: &Ident) -
|
||||
})
|
||||
}
|
||||
|
||||
pub fn unnamed_fields_as_struct(variant: &Variant, fields: &FieldsUnnamed, ident: &Ident, enum_ident: &Ident) -> Result<TokenStream> {
|
||||
pub fn unnamed_fields_as_struct(
|
||||
variant: &Variant,
|
||||
fields: &FieldsUnnamed,
|
||||
ident: &Ident,
|
||||
enum_ident: &Ident,
|
||||
) -> Result<TokenStream> {
|
||||
let variant_ident = &variant.ident;
|
||||
let field_idents = (0..fields.unnamed.len())
|
||||
.map(|x| Ident::new(&format!("__f{}", x), Span::call_site()))
|
||||
.collect::<Vec<_>>();
|
||||
let field_types = fields.unnamed
|
||||
.iter()
|
||||
.map(|f| &f.ty)
|
||||
.collect::<Vec<_>>();
|
||||
let as_struct = quote!{
|
||||
let field_types = fields.unnamed.iter().map(|f| &f.ty).collect::<Vec<_>>();
|
||||
let as_struct = quote! {
|
||||
struct #ident {
|
||||
#(#field_idents: #field_types,)*
|
||||
}
|
||||
};
|
||||
let de_impl = if fields.unnamed.len() == 1 {
|
||||
let ty = field_types[0];
|
||||
quote!{
|
||||
quote! {
|
||||
impl miniserde::Deserialize for #ident {
|
||||
fn begin(__out: &mut miniserde::export::Option<Self>) -> &mut dyn miniserde::de::Visitor {
|
||||
<#ty as miniserde::Deserialize>::begin(unsafe {&mut *{__out as *mut miniserde::export::Option<Self> as *mut miniserde::export::Option<#ty>}})
|
||||
@@ -185,7 +212,7 @@ pub fn unnamed_fields_as_struct(variant: &Variant, fields: &FieldsUnnamed, ident
|
||||
}
|
||||
} else {
|
||||
let index = 0usize..;
|
||||
quote!{
|
||||
quote! {
|
||||
struct __Visitor {
|
||||
__out: miniserde::export::Option<#ident>,
|
||||
}
|
||||
@@ -239,7 +266,7 @@ pub fn unnamed_fields_as_struct(variant: &Variant, fields: &FieldsUnnamed, ident
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(quote!{
|
||||
Ok(quote! {
|
||||
#as_struct
|
||||
|
||||
impl #ident {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
extern crate proc_macro;
|
||||
|
||||
pub(crate) mod attr;
|
||||
mod ser;
|
||||
mod de;
|
||||
mod bound;
|
||||
mod de;
|
||||
mod ser;
|
||||
|
||||
use std::convert::From;
|
||||
use syn::{parse_macro_input, Data, DeriveInput, Error};
|
||||
|
||||
39
src/ser.rs
39
src/ser.rs
@@ -1,9 +1,9 @@
|
||||
use crate::attr;
|
||||
use crate::TagType;
|
||||
use crate::bound;
|
||||
use crate::TagType;
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::quote;
|
||||
use syn::{DataEnum, DeriveInput, Ident, Fields, FieldsNamed, FieldsUnnamed, Result, parse_quote};
|
||||
use syn::{parse_quote, DataEnum, DeriveInput, Fields, FieldsNamed, FieldsUnnamed, Ident, Result};
|
||||
|
||||
pub fn derive(input: &DeriveInput, enumeration: &DataEnum) -> Result<TokenStream> {
|
||||
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
||||
@@ -23,7 +23,7 @@ pub fn derive(input: &DeriveInput, enumeration: &DataEnum) -> Result<TokenStream
|
||||
Ok(match &variant.fields {
|
||||
Fields::Unit => {
|
||||
let implementation = serialize_unit(name, &tag_type)?;
|
||||
quote!{
|
||||
quote! {
|
||||
#ident::#var_ident => {#implementation}
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ pub fn derive(input: &DeriveInput, enumeration: &DataEnum) -> Result<TokenStream
|
||||
.map(|field| &field.ident)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
quote!{
|
||||
quote! {
|
||||
#ident::#var_ident{#(#field_ident),*} => {
|
||||
#implementation
|
||||
}
|
||||
@@ -46,17 +46,19 @@ pub fn derive(input: &DeriveInput, enumeration: &DataEnum) -> Result<TokenStream
|
||||
.map(|i| format!("f{}", i))
|
||||
.map(|id| Ident::new(&id, Span::call_site()))
|
||||
.collect::<Vec<_>>();
|
||||
let implementation = serialize_unnamed(input, fields, &field_ident, name, &tag_type)?;
|
||||
quote!{
|
||||
let implementation =
|
||||
serialize_unnamed(input, fields, &field_ident, name, &tag_type)?;
|
||||
quote! {
|
||||
#ident::#var_ident(#(#field_ident),*) => {
|
||||
#implementation
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}).collect::<Result<Vec<_>>>()?;
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
|
||||
Ok(quote!{
|
||||
Ok(quote! {
|
||||
const _: () = {
|
||||
impl #impl_generics miniserde::Serialize for #ident #ty_generics #where_clause {
|
||||
fn begin(&self) -> miniserde::ser::Fragment {
|
||||
@@ -71,7 +73,7 @@ pub fn derive(input: &DeriveInput, enumeration: &DataEnum) -> Result<TokenStream
|
||||
|
||||
fn serialize_unit(variant_name: &str, tag_type: &TagType) -> Result<TokenStream> {
|
||||
Ok(if let TagType::Internal(tag) = &tag_type {
|
||||
quote!{
|
||||
quote! {
|
||||
struct __Map {
|
||||
state: miniserde::export::usize,
|
||||
}
|
||||
@@ -93,7 +95,7 @@ fn serialize_unit(variant_name: &str, tag_type: &TagType) -> Result<TokenStream>
|
||||
miniserde::ser::Fragment::Map(miniserde::export::Box::new(__Map {state: 0}))
|
||||
}
|
||||
} else {
|
||||
quote!{miniserde::ser::Fragment::Str(miniserde::export::Cow::Borrowed(#variant_name))}
|
||||
quote! {miniserde::ser::Fragment::Str(miniserde::export::Cow::Borrowed(#variant_name))}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -126,7 +128,7 @@ fn serialize_named(
|
||||
let cow = quote!(miniserde::export::Cow);
|
||||
let some = quote!(miniserde::export::Some);
|
||||
if let TagType::External = tag_type {
|
||||
Ok(quote!{
|
||||
Ok(quote! {
|
||||
use miniserde::Serialize;
|
||||
#[derive(Serialize)]
|
||||
struct __AsStruct #wrapper_impl_generics #where_clause {
|
||||
@@ -156,12 +158,15 @@ fn serialize_named(
|
||||
})
|
||||
} else {
|
||||
let (start, tag_arm) = if let TagType::Internal(ref tag) = &tag_type {
|
||||
(0, quote!{0 => #some((#cow::Borrowed(#tag), &#variant_name)),})
|
||||
(
|
||||
0,
|
||||
quote! {0 => #some((#cow::Borrowed(#tag), &#variant_name)),},
|
||||
)
|
||||
} else {
|
||||
(1usize, quote!())
|
||||
};
|
||||
let index = 1usize..;
|
||||
Ok(quote!{
|
||||
Ok(quote! {
|
||||
struct __Map #wrapper_impl_generics {
|
||||
#(#field_ident: &'__b #field_type),*,
|
||||
state: miniserde::export::usize,
|
||||
@@ -212,9 +217,9 @@ fn serialize_unnamed(
|
||||
let index = 0usize..;
|
||||
let ex = quote!(miniserde::export);
|
||||
let seq = if field_ident.len() == 1 {
|
||||
quote!{ #(#field_ident.begin())* }
|
||||
quote! { #(#field_ident.begin())* }
|
||||
} else {
|
||||
quote!{
|
||||
quote! {
|
||||
struct __Seq #wrapper_impl_generics #where_clause {
|
||||
#(#field_ident: &'__b #field_type),*,
|
||||
state: miniserde::export::usize,
|
||||
@@ -238,7 +243,7 @@ fn serialize_unnamed(
|
||||
}
|
||||
};
|
||||
Ok(if let TagType::External = tag_type {
|
||||
quote!{
|
||||
quote! {
|
||||
struct __AsStruct #wrapper_impl_generics (#(&'__b #field_type),*) #where_clause;
|
||||
|
||||
impl #wrapper_impl_generics miniserde::Serialize for __AsStruct #wrapper_ty_generics #bounded_where_clause {
|
||||
@@ -269,7 +274,7 @@ fn serialize_unnamed(
|
||||
}))
|
||||
}
|
||||
} else {
|
||||
quote!{
|
||||
quote! {
|
||||
#seq
|
||||
}
|
||||
})
|
||||
|
||||
@@ -63,11 +63,11 @@ fn test_untagged() {
|
||||
fn generic_named() {
|
||||
#[derive(Serialize_enum)]
|
||||
enum Gen<T: Serialize> {
|
||||
A{t: T},
|
||||
A { t: T },
|
||||
B,
|
||||
}
|
||||
use Gen::*;
|
||||
let example = [A{t: "abc"}, B];
|
||||
let example = [A { t: "abc" }, B];
|
||||
let actual = json::to_string(&example[..]);
|
||||
let expected = r#"[{"A":{"t":"abc"}},"B"]"#;
|
||||
assert_eq!(actual, expected);
|
||||
|
||||
Reference in New Issue
Block a user