implement common default skip content serializer
This commit is contained in:
parent
04ddaa29dc
commit
f69d5e75b3
@ -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 {
|
||||||
|
|||||||
@ -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};
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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 self.#label != #default_function() {
|
|
||||||
if let Some(ref value) = self.#label {
|
if let Some(ref value) = self.#label {
|
||||||
struct_start_event.attr(#label_name, &value)
|
struct_start_event.attr(#label_name, value)
|
||||||
} else {
|
} else {
|
||||||
struct_start_event
|
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());
|
|
||||||
let struct_start_event =
|
|
||||||
if self.#label != #default_function() {
|
|
||||||
if let Some(ref value) = self.#label {
|
if let Some(ref value) = self.#label {
|
||||||
struct_start_event.attr(#label_name, &content)
|
struct_start_event.attr(#label_name, &yaserde_inner)
|
||||||
} else {
|
} else {
|
||||||
struct_start_event
|
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 self.#label != #default_function() {
|
|
||||||
if let Some(ref yaserde_list) = self.#label {
|
if let Some(ref yaserde_list) = self.#label {
|
||||||
for yaserde_item in yaserde_list.iter() {
|
for yaserde_item in yaserde_list.iter() {
|
||||||
#inner
|
#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 {
|
} else {
|
||||||
struct_start_event
|
struct_start_event
|
||||||
}
|
}
|
||||||
} 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
|
|
||||||
};
|
|
||||||
})
|
})
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
Field::FieldOption { .. } => unimplemented!(),
|
||||||
_ => 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);
|
|
||||||
})
|
})
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
Field::FieldVec { .. } => None,
|
||||||
_ => None,
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.filter_map(|x| x)
|
.filter_map(|x| x)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user