Formatting

This commit is contained in:
etwyniel
2019-11-18 11:15:14 +01:00
parent b7993b516e
commit 5990bba62c
4 changed files with 87 additions and 55 deletions

View File

@@ -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 {

View File

@@ -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};

View File

@@ -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
}
})

View File

@@ -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);