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 proc_macro2::{Ident, TokenStream};
use proc_macro2::Span;
use std::fmt;
use syn;
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)]
pub enum Field {

View File

@ -2,4 +2,4 @@ mod attribute;
mod field;
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 proc_macro2::TokenStream;
use syn::DataEnum;
@ -49,23 +49,22 @@ fn inner_enum_inspector(
let enum_fields: TokenStream = fields
.named
.iter()
.map(|field| YaSerdeField::new(field.clone()))
.filter(|field| !field.is_attribute())
.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!(
let data_event = XmlEvent::characters(&self.#field_label);
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::FieldBool
| 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 proc_macro2::TokenStream;
@ -15,16 +15,13 @@ pub fn serialize(
let build_attributes: TokenStream = data_struct
.fields
.iter()
.map(|field| YaSerdeField::new(field.clone()))
.filter(|field| field.is_attribute())
.map(|field| {
let field_attrs = YaSerdeAttribute::parse(&field.attrs);
if !Field::is_attribute(field) {
return None;
}
let label = field.label();
let label_name = field.renamed_label(root_attributes);
let label = Field::label(field);
let label_name = Field::renamed_label(field, root_attributes);
match Field::from(field) {
match field.get_type() {
Field::FieldString
| Field::FieldBool
| Field::FieldI8
@ -37,50 +34,25 @@ pub fn serialize(
| Field::FieldU64
| Field::FieldF32
| Field::FieldF64 => {
if let Some(ref d) = field_attrs.default {
let default_function = Ident::new(&d, field.span());
Some(quote! {
let content = self.#label.to_string();
let struct_start_event =
if self.#label != #default_function() {
struct_start_event.attr(#label_name, &content)
} else {
struct_start_event
};
Some(field.ser_wrap_default_attribute(
quote!(self.#label.to_string()),
quote!({
struct_start_event.attr(#label_name, &yaserde_inner)
})
} 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::FieldString => {
if let Some(ref d) = field_attrs.default {
let default_function = Ident::new(&d, field.span());
Some(quote! {
let struct_start_event =
if self.#label != #default_function() {
if let Some(ref value) = self.#label {
struct_start_event.attr(#label_name, &value)
} else {
struct_start_event
}
} else {
struct_start_event
};
Some(field.ser_wrap_default_attribute(
quote!({}),
quote!({
if let Some(ref value) = self.#label {
struct_start_event.attr(#label_name, value)
} 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::FieldI8
@ -93,109 +65,57 @@ pub fn serialize(
| Field::FieldU64
| Field::FieldF32
| Field::FieldF64 => {
if let Some(ref d) = field_attrs.default {
let default_function = Ident::new(&d, field.span());
Some(quote! {
let content = self.#label.map_or_else(|| String::new(), |v| v.to_string());
let struct_start_event =
if self.#label != #default_function() {
if let Some(ref value) = self.#label {
struct_start_event.attr(#label_name, &content)
} else {
struct_start_event
}
} else {
struct_start_event
};
Some(field.ser_wrap_default_attribute(
quote!(self.#label.map_or_else(|| String::new(), |v| v.to_string())),
quote!({
if let Some(ref value) = self.#label {
struct_start_event.attr(#label_name, &yaserde_inner)
} 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 { .. } => {
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);
if let Some(ref d) = field_attrs.default {
let default_function = Ident::new(&d, field.span());
Some(quote! {
if self.#label != #default_function() {
if let Some(ref yaserde_list) = self.#label {
for yaserde_item in yaserde_list.iter() {
#inner
}
Some(field.ser_wrap_default_attribute(
quote!({}),
quote!({
if let Some(ref yaserde_list) = self.#label {
for yaserde_item in yaserde_list.iter() {
#inner
}
}
})
} else {
Some(quote! {
for yaserde_item in &self.#label {
#inner
}
})
}
))
}
Field::FieldStruct { .. } => {
if let Some(ref d) = field_attrs.default {
let default_function = Ident::new(&d, field.span());
Some(quote! {
let content = self.#label
Some(field.ser_wrap_default_attribute(
quote!(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 {
if *value != #default_function() {
struct_start_event.attr(#label_name, &content)
} else {
struct_start_event
}
.map_or_else(|| Ok(String::new()), |v| yaserde::ser::to_string_content(v))?),
quote!({
if let Some(ref yaserde_struct) = self.#label {
struct_start_event.attr(#label_name, &yaserde_inner)
} else {
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 { .. } => {
if let Some(ref d) = field_attrs.default {
let default_function = Ident::new(&d, field.span());
Some(quote! {
let content = yaserde::ser::to_string_content(&self.#label)?;
let struct_start_event =
if self.#label != #default_function() {
struct_start_event.attr(#label_name, &content)
} else {
struct_start_event
};
Some(field.ser_wrap_default_attribute(
quote!(yaserde::ser::to_string_content(&self.#label)?),
quote!({
struct_start_event.attr(#label_name, &yaserde_inner)
})
} 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)