implement common default skip content serializer

This commit is contained in:
Marc-Antoine Arnaud 2020-04-21 18:01:03 +02:00
parent 04ddaa29dc
commit f69d5e75b3
4 changed files with 150 additions and 141 deletions

View File

@ -1,8 +1,98 @@
use crate::common::attribute::YaSerdeAttribute; use crate::common::attribute::YaSerdeAttribute;
use proc_macro2::{Ident, TokenStream}; use proc_macro2::{Ident, TokenStream};
use proc_macro2::Span;
use std::fmt; use std::fmt;
use syn; use syn;
use syn::Type::Path; use syn::Type::Path;
use syn::spanned::Spanned;
#[derive(Debug)]
pub struct YaSerdeField {
syn_field: syn::Field,
attributes: YaSerdeAttribute,
}
impl YaSerdeField {
pub fn new(syn_field: syn::Field) -> Self {
let attributes = YaSerdeAttribute::parse(&syn_field.attrs);
YaSerdeField{
syn_field,
attributes,
}
}
pub fn is_attribute(&self) -> bool {
self.attributes.attribute
}
pub fn is_text_content(&self) -> bool {
self.attributes.text
}
pub fn label(&self) -> Option<Ident> {
self.syn_field.ident.clone()
}
pub fn renamed_label(&self, root_attributes: &YaSerdeAttribute) -> String {
let prefix = if root_attributes.default_namespace == self.attributes.prefix {
"".to_string()
} else {
self.attributes
.prefix
.clone()
.map_or("".to_string(), |prefix| prefix + ":")
};
let label =
self.attributes
.rename
.clone()
.unwrap_or_else(|| self.label().as_ref().unwrap().to_string());
format!("{}{}", prefix, label)
}
pub fn get_type(&self) -> Field {
Field::from(&self.syn_field)
}
pub fn get_span(&self) -> Span {
self.syn_field.span()
}
pub fn get_default_function(&self) -> Option<Ident> {
self.attributes.default.as_ref().map(|default|{
Ident::new(&default, self.get_span())
})
}
pub fn get_skip_serializing_if_function(&self) -> Option<Ident> {
self.attributes.skip_serializing_if.as_ref().map(|skip_serializing_if|{
Ident::new(&skip_serializing_if, self.get_span())
})
}
pub fn ser_wrap_default_attribute(&self, builder: TokenStream, setter: TokenStream) -> TokenStream {
let label = self.label();
if let Some(ref default_function) = self.get_default_function() {
quote! {
let yaserde_inner = #builder;
let struct_start_event =
if self.#label != #default_function() {
#setter
} else {
struct_start_event
};
}
} else {
quote! {
let yaserde_inner = #builder;
let struct_start_event = #setter;
}
}
}
}
#[derive(Debug)] #[derive(Debug)]
pub enum Field { pub enum Field {

View File

@ -2,4 +2,4 @@ mod attribute;
mod field; mod field;
pub use attribute::YaSerdeAttribute; pub use attribute::YaSerdeAttribute;
pub use field::Field; pub use field::{Field, YaSerdeField};

View File

@ -1,4 +1,4 @@
use crate::common::{Field, YaSerdeAttribute}; use crate::common::{Field, YaSerdeAttribute, YaSerdeField};
use crate::ser::{implement_deserializer::implement_deserializer, label::build_label_name}; use crate::ser::{implement_deserializer::implement_deserializer, label::build_label_name};
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use syn::DataEnum; use syn::DataEnum;
@ -49,23 +49,22 @@ fn inner_enum_inspector(
let enum_fields: TokenStream = fields let enum_fields: TokenStream = fields
.named .named
.iter() .iter()
.map(|field| YaSerdeField::new(field.clone()))
.filter(|field| !field.is_attribute())
.map(|field| { .map(|field| {
if Field::is_attribute(field) {
return None;
}
let field_label = Field::label(field); let field_label = field.label();
if Field::is_text_content(field) { if field.is_text_content() {
return Some(quote!( return Some(quote!(
let data_event = XmlEvent::characters(&self.#field_label); let data_event = XmlEvent::characters(&self.#field_label);
writer.write(data_event).map_err(|e| e.to_string())?; writer.write(data_event).map_err(|e| e.to_string())?;
)); ));
} }
let field_label_name = Field::renamed_label(field, root_attributes); let field_label_name = field.renamed_label(root_attributes);
match Field::from(field) { match field.get_type() {
Field::FieldString Field::FieldString
| Field::FieldBool | Field::FieldBool
| Field::FieldU8 | Field::FieldU8

View File

@ -1,4 +1,4 @@
use crate::common::{Field, YaSerdeAttribute}; use crate::common::{Field, YaSerdeAttribute, YaSerdeField};
use crate::ser::{element::*, implement_deserializer::implement_deserializer}; use crate::ser::{element::*, implement_deserializer::implement_deserializer};
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
@ -15,16 +15,13 @@ pub fn serialize(
let build_attributes: TokenStream = data_struct let build_attributes: TokenStream = data_struct
.fields .fields
.iter() .iter()
.map(|field| YaSerdeField::new(field.clone()))
.filter(|field| field.is_attribute())
.map(|field| { .map(|field| {
let field_attrs = YaSerdeAttribute::parse(&field.attrs); let label = field.label();
if !Field::is_attribute(field) { let label_name = field.renamed_label(root_attributes);
return None;
}
let label = Field::label(field); match field.get_type() {
let label_name = Field::renamed_label(field, root_attributes);
match Field::from(field) {
Field::FieldString Field::FieldString
| Field::FieldBool | Field::FieldBool
| Field::FieldI8 | Field::FieldI8
@ -37,50 +34,25 @@ pub fn serialize(
| Field::FieldU64 | Field::FieldU64
| Field::FieldF32 | Field::FieldF32
| Field::FieldF64 => { | Field::FieldF64 => {
if let Some(ref d) = field_attrs.default { Some(field.ser_wrap_default_attribute(
let default_function = Ident::new(&d, field.span()); quote!(self.#label.to_string()),
Some(quote! { quote!({
let content = self.#label.to_string(); struct_start_event.attr(#label_name, &yaserde_inner)
let struct_start_event =
if self.#label != #default_function() {
struct_start_event.attr(#label_name, &content)
} else {
struct_start_event
};
}) })
} else { ))
Some(quote! {
let content = self.#label.to_string();
let struct_start_event = struct_start_event.attr(#label_name, &content);
})
}
} }
Field::FieldOption { data_type } => match *data_type { Field::FieldOption { data_type } => match *data_type {
Field::FieldString => { Field::FieldString => {
if let Some(ref d) = field_attrs.default { Some(field.ser_wrap_default_attribute(
let default_function = Ident::new(&d, field.span()); quote!({}),
Some(quote! { quote!({
let struct_start_event = if let Some(ref value) = self.#label {
if self.#label != #default_function() { struct_start_event.attr(#label_name, value)
if let Some(ref value) = self.#label { } else {
struct_start_event.attr(#label_name, &value) struct_start_event
} else { }
struct_start_event
}
} else {
struct_start_event
};
}) })
} else { ))
Some(quote! {
let struct_start_event =
if let Some(ref value) = self.#label {
struct_start_event.attr(#label_name, &value)
} else {
struct_start_event
};
})
}
} }
Field::FieldBool Field::FieldBool
| Field::FieldI8 | Field::FieldI8
@ -93,109 +65,57 @@ pub fn serialize(
| Field::FieldU64 | Field::FieldU64
| Field::FieldF32 | Field::FieldF32
| Field::FieldF64 => { | Field::FieldF64 => {
if let Some(ref d) = field_attrs.default { Some(field.ser_wrap_default_attribute(
let default_function = Ident::new(&d, field.span()); quote!(self.#label.map_or_else(|| String::new(), |v| v.to_string())),
Some(quote! { quote!({
let content = self.#label.map_or_else(|| String::new(), |v| v.to_string()); if let Some(ref value) = self.#label {
let struct_start_event = struct_start_event.attr(#label_name, &yaserde_inner)
if self.#label != #default_function() { } else {
if let Some(ref value) = self.#label { struct_start_event
struct_start_event.attr(#label_name, &content) }
} else {
struct_start_event
}
} else {
struct_start_event
};
}) })
} else { ))
Some(quote! {
let content = self.#label.map_or_else(|| String::new(), |v| v.to_string());
let struct_start_event =
if let Some(ref value) = self.#label {
struct_start_event.attr(#label_name, &content)
} else {
struct_start_event
};
})
}
} }
Field::FieldVec { .. } => { Field::FieldVec { .. } => {
let item_ident = Ident::new("yaserde_item", field.span()); let item_ident = Ident::new("yaserde_item", field.get_span());
let inner = enclose_formatted_characters(&item_ident, label_name); let inner = enclose_formatted_characters(&item_ident, label_name);
if let Some(ref d) = field_attrs.default { Some(field.ser_wrap_default_attribute(
let default_function = Ident::new(&d, field.span()); quote!({}),
quote!({
Some(quote! { if let Some(ref yaserde_list) = self.#label {
if self.#label != #default_function() { for yaserde_item in yaserde_list.iter() {
if let Some(ref yaserde_list) = self.#label { #inner
for yaserde_item in yaserde_list.iter() {
#inner
}
} }
} }
}) })
} else { ))
Some(quote! {
for yaserde_item in &self.#label {
#inner
}
})
}
} }
Field::FieldStruct { .. } => { Field::FieldStruct { .. } => {
if let Some(ref d) = field_attrs.default { Some(field.ser_wrap_default_attribute(
let default_function = Ident::new(&d, field.span()); quote!(self.#label
Some(quote! {
let content = self.#label
.as_ref() .as_ref()
.map_or_else(|| Ok(String::new()), |v| yaserde::ser::to_string_content(v))?; .map_or_else(|| Ok(String::new()), |v| yaserde::ser::to_string_content(v))?),
let struct_start_event = if let Some(ref value) = self.#label { quote!({
if *value != #default_function() { if let Some(ref yaserde_struct) = self.#label {
struct_start_event.attr(#label_name, &content) struct_start_event.attr(#label_name, &yaserde_inner)
} else {
struct_start_event
}
} else { } else {
struct_start_event struct_start_event
}; }
}) })
} else { ))
Some(quote! {
let content = self.#label
.as_ref()
.map_or_else(|| Ok(String::new()), |v| yaserde::ser::to_string_content(v))?;
let struct_start_event = if let Some(ref value) = self.#label {
struct_start_event.attr(#label_name, &content)
} else {
struct_start_event
};
})
}
} }
_ => unimplemented!(), Field::FieldOption { .. } => unimplemented!(),
}, },
Field::FieldStruct { .. } => { Field::FieldStruct { .. } => {
if let Some(ref d) = field_attrs.default { Some(field.ser_wrap_default_attribute(
let default_function = Ident::new(&d, field.span()); quote!(yaserde::ser::to_string_content(&self.#label)?),
Some(quote! { quote!({
let content = yaserde::ser::to_string_content(&self.#label)?; struct_start_event.attr(#label_name, &yaserde_inner)
let struct_start_event =
if self.#label != #default_function() {
struct_start_event.attr(#label_name, &content)
} else {
struct_start_event
};
}) })
} else { ))
Some(quote! {
let content = yaserde::ser::to_string_content(&self.#label)?;
let struct_start_event = struct_start_event.attr(#label_name, &content);
})
}
} }
_ => None, Field::FieldVec { .. } => None,
} }
}) })
.filter_map(|x| x) .filter_map(|x| x)