skip serialization if value equals to default

This commit is contained in:
Marc-Antoine Arnaud 2018-12-07 10:21:59 +01:00
parent 9f19057353
commit 28c13f5861
15 changed files with 885 additions and 525 deletions

View File

@ -4,7 +4,7 @@ rust:
- 1.27.0
- 1.28.0
- 1.29.0
- 1.30.0
- 1.31.0
- stable
- beta
- nightly

View File

@ -27,6 +27,7 @@ This library will support XML de/ser-ializing with all specific features.
## Attributes
- [x] **attribute**: this field is defined as an attribute
- [x] **default**: defines the default function to init the field
- [ ] **flatten**: Flatten the contents of the field
- [x] **namespace**: defines the namespace of the field
- [x] **rename**: be able to rename a field

View File

@ -29,8 +29,7 @@ fn de_default_field_string() {
background: String,
}
let content =
"<?xml version=\"1.0\" encoding=\"utf-8\"?><base></base>";
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base />";
convert_and_validate!(
content,
XmlStruct,
@ -53,15 +52,8 @@ fn de_default_field_boolean() {
background: bool,
}
let content =
"<?xml version=\"1.0\" encoding=\"utf-8\"?><base></base>";
convert_and_validate!(
content,
XmlStruct,
XmlStruct {
background: true,
}
);
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base />";
convert_and_validate!(content, XmlStruct, XmlStruct { background: true });
}
#[test]
@ -77,15 +69,8 @@ fn de_default_field_number() {
background: u8,
}
let content =
"<?xml version=\"1.0\" encoding=\"utf-8\"?><base></base>";
convert_and_validate!(
content,
XmlStruct,
XmlStruct {
background: 6,
}
);
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base />";
convert_and_validate!(content, XmlStruct, XmlStruct { background: 6 });
}
#[test]
@ -101,8 +86,7 @@ fn de_default_attribute_string() {
background: String,
}
let content =
"<?xml version=\"1.0\" encoding=\"utf-8\"?><base></base>";
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base />";
convert_and_validate!(
content,
XmlStruct,

View File

@ -121,22 +121,28 @@ fn de_option() {
fn de_option_struct() {
#[derive(YaDeserialize, Debug, PartialEq)]
struct Test {
field: SubTest
field: SubTest,
}
#[derive(YaDeserialize, Debug, PartialEq)]
struct SubTest {
content: Option<String>
content: Option<String>,
}
impl Default for SubTest {
fn default() -> Self {
SubTest {
content: None
}
SubTest { content: None }
}
}
convert_and_validate!(Test, Some(Test{field: SubTest{content: Some("value".to_string())}}), Some("<field><content>value</content></field>"));
convert_and_validate!(
Test,
Some(Test {
field: SubTest {
content: Some("value".to_string())
}
}),
Some("<field><content>value</content></field>")
);
convert_and_validate!(Test, None, None);
}

110
yaserde/tests/se_default.rs Normal file
View File

@ -0,0 +1,110 @@
#[macro_use]
extern crate log;
extern crate xml;
extern crate yaserde;
#[macro_use]
extern crate yaserde_derive;
use std::io::Write;
use yaserde::ser::to_string;
use yaserde::YaSerialize;
macro_rules! convert_and_validate {
($model:expr, $content:expr) => {
let data: Result<String, String> = to_string(&$model);
assert_eq!(data, Ok(String::from($content)));
};
}
#[test]
fn se_default_field_string() {
fn default_string() -> String {
"my_default_value".to_string()
}
#[derive(YaSerialize, PartialEq, Debug)]
#[yaserde(root = "base")]
pub struct XmlStruct {
#[yaserde(default = "default_string")]
background: String,
}
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base />";
convert_and_validate!(
XmlStruct {
background: "my_default_value".to_string(),
},
content
);
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base><background>my_value</background></base>";
convert_and_validate!(
XmlStruct {
background: "my_value".to_string(),
},
content
);
}
#[test]
fn se_default_field_boolean() {
fn default_boolean() -> bool {
true
}
#[derive(YaSerialize, PartialEq, Debug)]
#[yaserde(root = "base")]
pub struct XmlStruct {
#[yaserde(default = "default_boolean")]
background: bool,
}
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base />";
convert_and_validate!(XmlStruct { background: true }, content);
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base><background>false</background></base>";
convert_and_validate!(
XmlStruct {
background: false,
},
content
);
}
#[test]
fn se_default_field_number() {
fn default_number() -> u8 {
6
}
#[derive(YaSerialize, PartialEq, Debug)]
#[yaserde(root = "base")]
pub struct XmlStruct {
#[yaserde(default = "default_number")]
background: u8,
}
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base />";
convert_and_validate!(XmlStruct { background: 6 }, content);
}
#[test]
fn se_default_attribute_string() {
fn default_string() -> String {
"my_default_value".to_string()
}
#[derive(YaSerialize, PartialEq, Debug)]
#[yaserde(root = "base")]
pub struct XmlStruct {
#[yaserde(attribute, default = "default_string")]
background: String,
}
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base />";
convert_and_validate!(
XmlStruct {
background: "my_default_value".to_string(),
},
content
);
}

View File

@ -124,22 +124,28 @@ fn ser_option() {
fn de_option_struct() {
#[derive(YaSerialize, Debug, PartialEq)]
struct Test {
field: SubTest
field: SubTest,
}
#[derive(YaSerialize, Debug, PartialEq)]
struct SubTest {
content: Option<String>
content: Option<String>,
}
impl Default for SubTest {
fn default() -> Self {
SubTest {
content: None
}
SubTest { content: None }
}
}
convert_and_validate!(Test, Some(Test{field: SubTest{content: Some("value".to_string())}}), Some("<field><content>value</content></field>"));
convert_and_validate!(
Test,
Some(Test {
field: SubTest {
content: Some("value".to_string())
}
}),
Some("<field><content>value</content></field>")
);
convert_and_validate!(Test, None, None);
}

View File

@ -104,59 +104,63 @@ fn parse_empty_attributes() {
let attributes = vec![];
let attrs = YaSerdeAttribute::parse(&attributes);
assert_eq!(YaSerdeAttribute {
root: None,
rename: None,
prefix: None,
default: None,
namespaces: BTreeMap::new(),
attribute: false,
text: false,
}, attrs);
assert_eq!(
YaSerdeAttribute {
root: None,
rename: None,
prefix: None,
default: None,
namespaces: BTreeMap::new(),
attribute: false,
text: false,
},
attrs
);
}
#[test]
fn parse_attributes() {
use proc_macro2::{Span, TokenStream};
use std::str::FromStr;
use syn::punctuated::Punctuated;
use syn::token::Bracket;
use syn::token::Pound;
use syn::AttrStyle::Outer;
use syn::{Ident, Path, PathArguments, PathSegment};
use syn::token::Pound;
use syn::token::Bracket;
use syn::punctuated::Punctuated;
let mut punctuated = Punctuated::new();
punctuated.push(PathSegment {
ident: Ident::new("yaserde", Span::call_site()),
arguments: PathArguments::None
arguments: PathArguments::None,
});
let attributes = vec![
Attribute {
pound_token: Pound {
spans: [Span::call_site()]
},
style: Outer,
bracket_token: Bracket {
span: Span::call_site()
},
path: Path {
leading_colon: None,
segments: punctuated
},
tts: TokenStream::from_str("(attribute)").unwrap()
}
];
let attributes = vec![Attribute {
pound_token: Pound {
spans: [Span::call_site()],
},
style: Outer,
bracket_token: Bracket {
span: Span::call_site(),
},
path: Path {
leading_colon: None,
segments: punctuated,
},
tts: TokenStream::from_str("(attribute)").unwrap(),
}];
let attrs = YaSerdeAttribute::parse(&attributes);
assert_eq!(YaSerdeAttribute {
root: None,
rename: None,
prefix: None,
default: None,
namespaces: BTreeMap::new(),
attribute: true,
text: false,
}, attrs);
assert_eq!(
YaSerdeAttribute {
root: None,
rename: None,
prefix: None,
default: None,
namespaces: BTreeMap::new(),
attribute: true,
text: false,
},
attrs
);
}

View File

@ -0,0 +1,24 @@
use proc_macro2::{Span, TokenStream};
use syn::Ident;
pub fn build_default_value(
label: &Option<Ident>,
field_type: &TokenStream,
value: &TokenStream,
default: &Option<String>,
) -> Option<TokenStream> {
if let Some(d) = default {
let default_function = Ident::new(&d, Span::call_site());
Some(quote! {
#[allow(unused_mut)]
let mut #label : #field_type = #default_function();
})
} else {
Some(quote! {
#[allow(unused_mut)]
let mut #label : #field_type = #value;
})
}
}

View File

@ -6,6 +6,7 @@ use std::collections::BTreeMap;
use syn::DataEnum;
use syn::Fields;
use syn::Ident;
use de::build_default_value::build_default_value;
pub fn parse(
data_enum: &DataEnum,
@ -24,95 +25,111 @@ pub fn parse(
.iter()
.map(|field| {
let field_label = &field.ident;
let field_attrs = YaSerdeAttribute::parse(&field.attrs);
match get_field_type(field) {
Some(FieldType::FieldTypeString) => {
build_default_value(field_label, &quote!{String}, &quote!{"".to_string()})
build_default_value(field_label, &quote! {String}, &quote! {"".to_string()}, &field_attrs.default)
}
Some(FieldType::FieldTypeBool) => {
build_default_value(field_label, &quote!{bool}, &quote!{false})
build_default_value(field_label, &quote! {bool}, &quote! {false}, &field_attrs.default)
}
Some(FieldType::FieldTypeI8) => {
build_default_value(field_label, &quote!{i8}, &quote!{0})
build_default_value(field_label, &quote! {i8}, &quote! {0}, &field_attrs.default)
}
Some(FieldType::FieldTypeU8) => {
build_default_value(field_label, &quote!{u8}, &quote!{0})
build_default_value(field_label, &quote! {u8}, &quote! {0}, &field_attrs.default)
}
Some(FieldType::FieldTypeI16) => {
build_default_value(field_label, &quote!{i16}, &quote!{0})
build_default_value(field_label, &quote! {i16}, &quote! {0}, &field_attrs.default)
}
Some(FieldType::FieldTypeU16) => {
build_default_value(field_label, &quote!{u16}, &quote!{0})
build_default_value(field_label, &quote! {u16}, &quote! {0}, &field_attrs.default)
}
Some(FieldType::FieldTypeI32) => {
build_default_value(field_label, &quote!{i32}, &quote!{0})
build_default_value(field_label, &quote! {i32}, &quote! {0}, &field_attrs.default)
}
Some(FieldType::FieldTypeU32) => {
build_default_value(field_label, &quote!{u32}, &quote!{0})
build_default_value(field_label, &quote! {u32}, &quote! {0}, &field_attrs.default)
}
Some(FieldType::FieldTypeI64) => {
build_default_value(field_label, &quote!{i64}, &quote!{0})
build_default_value(field_label, &quote! {i64}, &quote! {0}, &field_attrs.default)
}
Some(FieldType::FieldTypeU64) => {
build_default_value(field_label, &quote!{u64}, &quote!{0})
build_default_value(field_label, &quote! {u64}, &quote! {0}, &field_attrs.default)
}
Some(FieldType::FieldTypeF32) => {
build_default_value(field_label, &quote!{f32}, &quote!{0})
build_default_value(field_label, &quote! {f32}, &quote! {0}, &field_attrs.default)
}
Some(FieldType::FieldTypeF64) => {
build_default_value(field_label, &quote!{f64}, &quote!{0})
build_default_value(field_label, &quote! {f64}, &quote! {0}, &field_attrs.default)
}
Some(FieldType::FieldTypeStruct { struct_name }) => build_default_value(
field_label,
&quote! {#struct_name},
&quote! {#struct_name::default()},
&field_attrs.default,
),
Some(FieldType::FieldTypeOption { .. }) => {
if let Some(d) = &field_attrs.default {
let default_function = Ident::new(&d, Span::call_site());
Some(quote! {
#[allow(unused_mut, non_snake_case, non_camel_case_types)]
let mut #field_label = #default_function();
})
} else {
Some(quote! {
#[allow(unused_mut, non_snake_case, non_camel_case_types)]
let mut #field_label = None;
})
}
}
Some(FieldType::FieldTypeStruct { struct_name }) => Some(quote!{
#[allow(unused_mut)]
let mut #field_label : #struct_name = #struct_name::default();
}),
Some(FieldType::FieldTypeOption { .. }) => Some(quote!{
#[allow(unused_mut)]
let mut #field_label = None;
}),
Some(FieldType::FieldTypeVec { data_type }) => {
let dt = Box::into_raw(data_type);
match unsafe { dt.as_ref() } {
Some(&FieldType::FieldTypeString) => {
build_default_value(field_label, &quote!{Vec<String>}, &quote!{vec![]})
build_default_value(field_label, &quote! {Vec<String>}, &quote! {vec![]}, &field_attrs.default)
}
Some(&FieldType::FieldTypeBool) => {
build_default_value(field_label, &quote!{Vec<bool>}, &quote!{vec![]})
build_default_value(field_label, &quote! {Vec<bool>}, &quote! {vec![]}, &field_attrs.default)
}
Some(&FieldType::FieldTypeI8) => {
build_default_value(field_label, &quote!{Vec<i8>}, &quote!{vec![]})
build_default_value(field_label, &quote! {Vec<i8>}, &quote! {vec![]}, &field_attrs.default)
}
Some(&FieldType::FieldTypeU8) => {
build_default_value(field_label, &quote!{Vec<u8>}, &quote!{vec![]})
build_default_value(field_label, &quote! {Vec<u8>}, &quote! {vec![]}, &field_attrs.default)
}
Some(&FieldType::FieldTypeI16) => {
build_default_value(field_label, &quote!{Vec<i16>}, &quote!{vec![]})
build_default_value(field_label, &quote! {Vec<i16>}, &quote! {vec![]}, &field_attrs.default)
}
Some(&FieldType::FieldTypeU16) => {
build_default_value(field_label, &quote!{Vec<u16>}, &quote!{vec![]})
build_default_value(field_label, &quote! {Vec<u16>}, &quote! {vec![]}, &field_attrs.default)
}
Some(&FieldType::FieldTypeI32) => {
build_default_value(field_label, &quote!{Vec<i32>}, &quote!{vec![]})
build_default_value(field_label, &quote! {Vec<i32>}, &quote! {vec![]}, &field_attrs.default)
}
Some(&FieldType::FieldTypeU32) => {
build_default_value(field_label, &quote!{Vec<u32>}, &quote!{vec![]})
build_default_value(field_label, &quote! {Vec<u32>}, &quote! {vec![]}, &field_attrs.default)
}
Some(&FieldType::FieldTypeI64) => {
build_default_value(field_label, &quote!{Vec<i64>}, &quote!{vec![]})
build_default_value(field_label, &quote! {Vec<i64>}, &quote! {vec![]}, &field_attrs.default)
}
Some(&FieldType::FieldTypeU64) => {
build_default_value(field_label, &quote!{Vec<u64>}, &quote!{vec![]})
build_default_value(field_label, &quote! {Vec<u64>}, &quote! {vec![]}, &field_attrs.default)
}
Some(&FieldType::FieldTypeF32) => {
build_default_value(field_label, &quote!{Vec<f32>}, &quote!{vec![]})
build_default_value(field_label, &quote! {Vec<f32>}, &quote! {vec![]}, &field_attrs.default)
}
Some(&FieldType::FieldTypeF64) => {
build_default_value(field_label, &quote!{Vec<f64>}, &quote!{vec![]})
build_default_value(field_label, &quote! {Vec<f64>}, &quote! {vec![]}, &field_attrs.default)
}
Some(&FieldType::FieldTypeStruct { ref struct_name }) => Some(quote!{
#[allow(unused_mut)]
let mut #field_label : Vec<#struct_name> = vec![];
}),
Some(&FieldType::FieldTypeStruct { ref struct_name }) => build_default_value(
field_label,
&quote! {Vec<#struct_name>},
&quote! {vec![]},
&field_attrs.default,
),
Some(&FieldType::FieldTypeOption { .. })
| Some(&FieldType::FieldTypeVec { .. }) => {
unimplemented!();
@ -158,7 +175,7 @@ pub fn parse(
let label_name = renamed_label.to_string();
match variant.fields {
Fields::Unit => Some(quote!{
Fields::Unit => Some(quote! {
#label_name => {
simple_enum_value = Some(#name::#label);
}
@ -173,7 +190,7 @@ pub fn parse(
tokens
});
quote!{
quote! {
use xml::reader::XmlEvent;
impl YaDeserialize for #name {
@ -232,14 +249,3 @@ pub fn parse(
}
}
}
fn build_default_value(
label: &Option<Ident>,
field_type: &TokenStream,
default: &TokenStream,
) -> Option<TokenStream> {
Some(quote!{
#[allow(unused_mut)]
let mut #label : #field_type = #default;
})
}

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,5 @@
pub mod build_default_value;
pub mod expand_enum;
pub mod expand_struct;

View File

@ -0,0 +1,75 @@
use proc_macro2::{Ident, Span, TokenStream};
pub fn enclose_formatted_characters(
label: &Ident,
label_name: String
) -> TokenStream {
quote! {
let start_event = XmlEvent::start_element(#label_name);
let _ret = writer.write(start_event);
let yas_value = format!("{}", &self.#label);
let data_event = XmlEvent::characters(&yas_value);
let _ret = writer.write(data_event);
let end_event = XmlEvent::end_element();
let _ret = writer.write(end_event);
}
}
pub fn enclose_formatted_characters_for_value(
label: &Ident,
label_name: String
) -> TokenStream {
quote! {
let start_event = XmlEvent::start_element(#label_name);
let _ret = writer.write(start_event);
let value = format!("{}", #label);
let data_event = XmlEvent::characters(&value);
let _ret = writer.write(data_event);
let end_event = XmlEvent::end_element();
let _ret = writer.write(end_event);
}
}
pub fn enclose_characters(
label: &Option<Ident>,
label_name: String
) -> TokenStream {
quote! {
let start_event = XmlEvent::start_element(#label_name);
let _ret = writer.write(start_event);
let value = format!("{}", self.#label);
let data_event = XmlEvent::characters(&value);
let _ret = writer.write(data_event);
let end_event = XmlEvent::end_element();
let _ret = writer.write(end_event);
}
}
pub fn serialize_element(
label: &Option<Ident>,
label_name: String,
default: &Option<String>,
) -> Option<TokenStream> {
let inner = enclose_characters(label, label_name);
if let Some(ref d) = default {
let default_function = Ident::new(&d, Span::call_site());
Some(quote! {
if self.#label != #default_function() {
#inner
}
})
} else {
Some(quote! {
#inner
})
}
}

View File

@ -30,7 +30,7 @@ pub fn serialize(
};
match variant.fields {
Fields::Unit => Some(quote!{
Fields::Unit => Some(quote! {
&#name::#label => {
let data_event = XmlEvent::characters(#label_name);
let _ret = writer.write(data_event);
@ -49,9 +49,9 @@ pub fn serialize(
let field_label = &field.ident;
if field_attrs.text {
return Some(quote!(
let data_event = XmlEvent::characters(&self.#field_label);
let _ret = writer.write(data_event);
));
let data_event = XmlEvent::characters(&self.#field_label);
let _ret = writer.write(data_event);
));
}
let renamed_field_label = match field_attrs.rename {
@ -61,7 +61,7 @@ pub fn serialize(
let field_label_name = renamed_field_label.unwrap().to_string();
match get_field_type(field) {
Some(FieldType::FieldTypeString) => Some(quote!{
Some(FieldType::FieldTypeString) => Some(quote! {
match self {
&#name::#label{ref #field_label, ..} => {
let struct_start_event = XmlEvent::start_element(#field_label_name);
@ -76,7 +76,7 @@ pub fn serialize(
_ => {},
}
}),
Some(FieldType::FieldTypeStruct { .. }) => Some(quote!{
Some(FieldType::FieldTypeStruct { .. }) => Some(quote! {
let struct_start_event = XmlEvent::start_element(#field_label_name);
let _ret = writer.write(struct_start_event);
@ -93,7 +93,7 @@ pub fn serialize(
let struct_end_event = XmlEvent::end_element();
let _ret = writer.write(struct_end_event);
}),
Some(FieldType::FieldTypeVec { .. }) => Some(quote!{
Some(FieldType::FieldTypeVec { .. }) => Some(quote! {
match self {
&#name::#label{ref #field_label, ..} => {
for item in #field_label {
@ -121,7 +121,7 @@ pub fn serialize(
tokens
});
Some(quote!{
Some(quote! {
&#name::#label{..} => {
#enum_fields
}

View File

@ -7,6 +7,8 @@ use std::string::ToString;
use syn::DataStruct;
use syn::Ident;
use ser::element::*;
pub fn serialize(
data_struct: &DataStruct,
name: &Ident,
@ -45,28 +47,68 @@ pub fn serialize(
| Some(FieldType::FieldTypeI64)
| Some(FieldType::FieldTypeU64)
| Some(FieldType::FieldTypeF32)
| Some(FieldType::FieldTypeF64) => Some(quote!{
let struct_start_event = struct_start_event.attr(#label_name, &*{
use std::mem;
unsafe {
let content = format!("{}", self.#label);
let ret : &'static str = mem::transmute(&content as &str);
mem::forget(content);
ret
}
});
}),
Some(FieldType::FieldTypeOption { data_type }) => {
let dt = Box::into_raw(data_type);
match unsafe { dt.as_ref() } {
Some(&FieldType::FieldTypeString) => Some(quote!{
| Some(FieldType::FieldTypeF64) => {
if let Some(ref d) = field_attrs.default {
let default_function = Ident::new(&d, Span::call_site());
Some(quote! {
let struct_start_event =
if let Some(ref value) = self.#label {
struct_start_event.attr(#label_name, &value)
if self.#label != #default_function() {
struct_start_event.attr(#label_name, &*{
use std::mem;
unsafe {
let content = format!("{}", self.#label);
let ret : &'static str = mem::transmute(&content as &str);
mem::forget(content);
ret
}
})
} else {
struct_start_event
};
}),
})
} else {
Some(quote! {
let struct_start_event = struct_start_event.attr(#label_name, &*{
use std::mem;
unsafe {
let content = format!("{}", self.#label);
let ret : &'static str = mem::transmute(&content as &str);
mem::forget(content);
ret
}
});
})
}
},
Some(FieldType::FieldTypeOption { data_type }) => {
let dt = Box::into_raw(data_type);
match unsafe { dt.as_ref() } {
Some(&FieldType::FieldTypeString) => {
if let Some(ref d) = field_attrs.default {
let default_function = Ident::new(&d, Span::call_site());
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
};
})
} 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
};
})
}
},
Some(&FieldType::FieldTypeBool)
| Some(&FieldType::FieldTypeI8)
| Some(&FieldType::FieldTypeU8)
@ -77,52 +119,116 @@ pub fn serialize(
| Some(&FieldType::FieldTypeI64)
| Some(&FieldType::FieldTypeU64)
| Some(&FieldType::FieldTypeF32)
| Some(&FieldType::FieldTypeF64) => Some(quote!{
| Some(&FieldType::FieldTypeF64) => {
if let Some(ref d) = field_attrs.default {
let default_function = Ident::new(&d, Span::call_site());
Some(quote! {
let struct_start_event =
if self.#label != #default_function() {
if let Some(ref value) = self.#label {
struct_start_event.attr(#label_name, &*{
use std::mem;
unsafe {
let content = format!("{}", value);
let ret : &'static str = mem::transmute(&content as &str);
mem::forget(content);
ret
}
})
} 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, &*{
use std::mem;
unsafe {
let content = format!("{}", value);
let ret : &'static str = mem::transmute(&content as &str);
mem::forget(content);
ret
}
})
} else {
struct_start_event
};
})
}
},
Some(&FieldType::FieldTypeVec { .. }) => {
let item_ident = Ident::new("yas_item", Span::call_site());
let inner = enclose_formatted_characters(&item_ident, label_name);
if let Some(ref d) = field_attrs.default {
let default_function = Ident::new(&d, Span::call_site());
Some(quote! {
if self.#label != #default_function() {
if let Some(ref yas_list) = self.#label {
for yas_item in yas_list.iter() {
#inner
}
}
}
})
} else {
Some(quote! {
for yas_item in &self.#label {
#inner
}
})
}
},
_ => unimplemented!(),
}
}
Some(FieldType::FieldTypeStruct { .. }) => {
if let Some(ref d) = field_attrs.default {
let default_function = Ident::new(&d, Span::call_site());
Some(quote! {
let struct_start_event =
if let Some(value) = self.#label {
if self.#label != #default_function() {
struct_start_event.attr(#label_name, &*{
use std::mem;
unsafe {
let content = format!("{}", value);
let ret : &'static str = mem::transmute(&content as &str);
mem::forget(content);
ret
match yaserde::ser::to_string_content(&self.#label) {
Ok(value) => {
unsafe {
let ret : &'static str = mem::transmute(&value as &str);
mem::forget(value);
ret
}
},
Err(msg) => return Err("Unable to serialize content".to_owned()),
}
})
} else {
struct_start_event
};
}),
Some(&FieldType::FieldTypeVec { .. }) => Some(quote!{
for item in &self.#label {
let start_event = XmlEvent::start_element(#label_name);
let _ret = writer.write(start_event);
let data_event = XmlEvent::characters(item);
let _ret = writer.write(data_event);
let end_event = XmlEvent::end_element();
let _ret = writer.write(end_event);
}
}),
_ => unimplemented!(),
}
}
Some(FieldType::FieldTypeStruct { .. }) => Some(quote!{
let struct_start_event = struct_start_event.attr(#label_name, &*{
use std::mem;
match yaserde::ser::to_string_content(&self.#label) {
Ok(value) => {
unsafe {
let ret : &'static str = mem::transmute(&value as &str);
mem::forget(value);
ret
})
} else {
Some(quote! {
let struct_start_event = struct_start_event.attr(#label_name, &*{
use std::mem;
match yaserde::ser::to_string_content(&self.#label) {
Ok(value) => {
unsafe {
let ret : &'static str = mem::transmute(&value as &str);
mem::forget(value);
ret
}
},
Err(msg) => return Err("Unable to serialize content".to_owned()),
}
},
Err(msg) => return Err("Unable to serialize content".to_owned()),
}
});
}),
});
})
}
},
_ => None,
}
})
@ -176,17 +282,8 @@ pub fn serialize(
};
match get_field_type(field) {
Some(FieldType::FieldTypeString) => Some(quote!{
let start_event = XmlEvent::start_element(#label_name);
let _ret = writer.write(start_event);
let data_event = XmlEvent::characters(&self.#label);
let _ret = writer.write(data_event);
let end_event = XmlEvent::end_element();
let _ret = writer.write(end_event);
}),
Some(FieldType::FieldTypeBool)
Some(FieldType::FieldTypeString)
| Some(FieldType::FieldTypeBool)
| Some(FieldType::FieldTypeI8)
| Some(FieldType::FieldTypeU8)
| Some(FieldType::FieldTypeI16)
@ -196,33 +293,13 @@ pub fn serialize(
| Some(FieldType::FieldTypeI64)
| Some(FieldType::FieldTypeU64)
| Some(FieldType::FieldTypeF32)
| Some(FieldType::FieldTypeF64) => Some(quote!{
let start_event = XmlEvent::start_element(#label_name);
let _ret = writer.write(start_event);
let content = format!("{}", &self.#label);
let data_event = XmlEvent::characters(&content);
let _ret = writer.write(data_event);
let end_event = XmlEvent::end_element();
let _ret = writer.write(end_event);
}),
| Some(FieldType::FieldTypeF64) =>
serialize_element(label, label_name, &field_attrs.default),
Some(FieldType::FieldTypeOption { data_type }) => {
let dt = Box::into_raw(data_type);
match unsafe { dt.as_ref() } {
Some(&FieldType::FieldTypeString) => Some(quote!{
if let Some(ref item) = self.#label {
let start_event = XmlEvent::start_element(#label_name);
let _ret = writer.write(start_event);
let data_event = XmlEvent::characters(&item);
let _ret = writer.write(data_event);
let end_event = XmlEvent::end_element();
let _ret = writer.write(end_event);
}
}),
Some(&FieldType::FieldTypeBool)
Some(&FieldType::FieldTypeString)
| Some(&FieldType::FieldTypeBool)
| Some(&FieldType::FieldTypeI8)
| Some(&FieldType::FieldTypeU8)
| Some(&FieldType::FieldTypeI16)
@ -232,35 +309,55 @@ pub fn serialize(
| Some(&FieldType::FieldTypeI64)
| Some(&FieldType::FieldTypeU64)
| Some(&FieldType::FieldTypeF32)
| Some(&FieldType::FieldTypeF64) => Some(quote!{
if let Some(item) = self.#label {
let start_event = XmlEvent::start_element(#label_name);
let _ret = writer.write(start_event);
| Some(&FieldType::FieldTypeF64) => {
let item_ident = Ident::new("yas_item", Span::call_site());
let inner = enclose_formatted_characters_for_value(&item_ident, label_name);
let content = format!("{}", item);
let data_event = XmlEvent::characters(&content);
let _ret = writer.write(data_event);
if let Some(ref d) = field_attrs.default {
let default_function = Ident::new(&d, Span::call_site());
let end_event = XmlEvent::end_element();
let _ret = writer.write(end_event);
Some(quote! {
if self.#label != #default_function() {
if let Some(ref yas_item) = self.#label {
#inner
}
}
})
} else {
Some(quote! {
if let Some(ref yas_item) = self.#label {
#inner
}
})
}
}),
Some(&FieldType::FieldTypeVec { .. }) => Some(quote!{
if let Some(ref items) = &self.#label {
for item in items.iter() {
let start_event = XmlEvent::start_element(#label_name);
let _ret = writer.write(start_event);
},
Some(&FieldType::FieldTypeVec { .. }) => {
let item_ident = Ident::new("yas_item", Span::call_site());
let inner = enclose_formatted_characters_for_value(&item_ident, label_name);
let value = format!("{}", item);
let data_event = XmlEvent::characters(&value);
let _ret = writer.write(data_event);
if let Some(ref d) = field_attrs.default {
let default_function = Ident::new(&d, Span::call_site());
let end_event = XmlEvent::end_element();
let _ret = writer.write(end_event);
}
Some(quote! {
if self.#label != #default_function() {
if let Some(ref yas_items) = &self.#label {
for yas_item in yas_items.iter() {
#inner
}
}
}
})
} else {
Some(quote! {
if let Some(ref yas_items) = &self.#label {
for yas_item in yas_items.iter() {
#inner
}
}
})
}
}),
Some(&FieldType::FieldTypeStruct { .. }) => Some(quote!{
},
Some(&FieldType::FieldTypeStruct { .. }) => Some(quote! {
if let Some(ref item) = &self.#label {
writer.set_start_event_name(Some(#label_name.to_string()));
match item.serialize(writer) {
@ -286,7 +383,7 @@ pub fn serialize(
_ => unimplemented!(),
}
}
Some(FieldType::FieldTypeStruct { .. }) => Some(quote!{
Some(FieldType::FieldTypeStruct { .. }) => Some(quote! {
writer.set_start_event_name(Some(#label_name.to_string()));
match self.#label.serialize(writer) {
Ok(()) => {},
@ -310,18 +407,16 @@ pub fn serialize(
Some(FieldType::FieldTypeVec { data_type }) => {
let dt = Box::into_raw(data_type);
match unsafe { dt.as_ref() } {
Some(&FieldType::FieldTypeString) => Some(quote!{
for item in &self.#label {
let start_event = XmlEvent::start_element(#label_name);
let _ret = writer.write(start_event);
Some(&FieldType::FieldTypeString) => {
let item_ident = Ident::new("yas_item", Span::call_site());
let inner = enclose_formatted_characters_for_value(&item_ident, label_name);
let data_event = XmlEvent::characters(item);
let _ret = writer.write(data_event);
let end_event = XmlEvent::end_element();
let _ret = writer.write(end_event);
}
}),
Some(quote! {
for yas_item in &self.#label {
#inner
}
})
},
Some(&FieldType::FieldTypeBool)
| Some(&FieldType::FieldTypeI8)
| Some(&FieldType::FieldTypeU8)
@ -332,19 +427,17 @@ pub fn serialize(
| Some(&FieldType::FieldTypeI64)
| Some(&FieldType::FieldTypeU64)
| Some(&FieldType::FieldTypeF32)
| Some(&FieldType::FieldTypeF64) => Some(quote!{
for item in &self.#label {
let start_event = XmlEvent::start_element(#label_name);
let _ret = writer.write(start_event);
| Some(&FieldType::FieldTypeF64) => {
let item_ident = Ident::new("yas_item", Span::call_site());
let inner = enclose_formatted_characters_for_value(&item_ident, label_name);
let data_event = XmlEvent::characters(format!("{}", item));
let _ret = writer.write(data_event);
let end_event = XmlEvent::end_element();
let _ret = writer.write(end_event);
}
}),
Some(&FieldType::FieldTypeOption { .. }) => Some(quote!{
Some(quote! {
for yas_item in &self.#label {
#inner
}
})
},
Some(&FieldType::FieldTypeOption { .. }) => Some(quote! {
for item in &self.#label {
if let Some(value) = item {
writer.set_skip_start_end(false);
@ -357,7 +450,7 @@ pub fn serialize(
}
}
}),
Some(&FieldType::FieldTypeStruct { .. }) => Some(quote!{
Some(&FieldType::FieldTypeStruct { .. }) => Some(quote! {
for item in &self.#label {
writer.set_skip_start_end(false);
match item.serialize(writer) {

View File

@ -1,3 +1,5 @@
pub mod element;
pub mod expand_enum;
pub mod expand_struct;