skip serialization if value equals to default
This commit is contained in:
parent
9f19057353
commit
28c13f5861
@ -4,7 +4,7 @@ rust:
|
||||
- 1.27.0
|
||||
- 1.28.0
|
||||
- 1.29.0
|
||||
- 1.30.0
|
||||
- 1.31.0
|
||||
- stable
|
||||
- beta
|
||||
- nightly
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
110
yaserde/tests/se_default.rs
Normal 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
|
||||
);
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
24
yaserde_derive/src/de/build_default_value.rs
Normal file
24
yaserde_derive/src/de/build_default_value.rs
Normal 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;
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -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, "e!{String}, "e!{"".to_string()})
|
||||
build_default_value(field_label, "e! {String}, "e! {"".to_string()}, &field_attrs.default)
|
||||
}
|
||||
Some(FieldType::FieldTypeBool) => {
|
||||
build_default_value(field_label, "e!{bool}, "e!{false})
|
||||
build_default_value(field_label, "e! {bool}, "e! {false}, &field_attrs.default)
|
||||
}
|
||||
Some(FieldType::FieldTypeI8) => {
|
||||
build_default_value(field_label, "e!{i8}, "e!{0})
|
||||
build_default_value(field_label, "e! {i8}, "e! {0}, &field_attrs.default)
|
||||
}
|
||||
Some(FieldType::FieldTypeU8) => {
|
||||
build_default_value(field_label, "e!{u8}, "e!{0})
|
||||
build_default_value(field_label, "e! {u8}, "e! {0}, &field_attrs.default)
|
||||
}
|
||||
Some(FieldType::FieldTypeI16) => {
|
||||
build_default_value(field_label, "e!{i16}, "e!{0})
|
||||
build_default_value(field_label, "e! {i16}, "e! {0}, &field_attrs.default)
|
||||
}
|
||||
Some(FieldType::FieldTypeU16) => {
|
||||
build_default_value(field_label, "e!{u16}, "e!{0})
|
||||
build_default_value(field_label, "e! {u16}, "e! {0}, &field_attrs.default)
|
||||
}
|
||||
Some(FieldType::FieldTypeI32) => {
|
||||
build_default_value(field_label, "e!{i32}, "e!{0})
|
||||
build_default_value(field_label, "e! {i32}, "e! {0}, &field_attrs.default)
|
||||
}
|
||||
Some(FieldType::FieldTypeU32) => {
|
||||
build_default_value(field_label, "e!{u32}, "e!{0})
|
||||
build_default_value(field_label, "e! {u32}, "e! {0}, &field_attrs.default)
|
||||
}
|
||||
Some(FieldType::FieldTypeI64) => {
|
||||
build_default_value(field_label, "e!{i64}, "e!{0})
|
||||
build_default_value(field_label, "e! {i64}, "e! {0}, &field_attrs.default)
|
||||
}
|
||||
Some(FieldType::FieldTypeU64) => {
|
||||
build_default_value(field_label, "e!{u64}, "e!{0})
|
||||
build_default_value(field_label, "e! {u64}, "e! {0}, &field_attrs.default)
|
||||
}
|
||||
Some(FieldType::FieldTypeF32) => {
|
||||
build_default_value(field_label, "e!{f32}, "e!{0})
|
||||
build_default_value(field_label, "e! {f32}, "e! {0}, &field_attrs.default)
|
||||
}
|
||||
Some(FieldType::FieldTypeF64) => {
|
||||
build_default_value(field_label, "e!{f64}, "e!{0})
|
||||
build_default_value(field_label, "e! {f64}, "e! {0}, &field_attrs.default)
|
||||
}
|
||||
Some(FieldType::FieldTypeStruct { struct_name }) => build_default_value(
|
||||
field_label,
|
||||
"e! {#struct_name},
|
||||
"e! {#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, "e!{Vec<String>}, "e!{vec![]})
|
||||
build_default_value(field_label, "e! {Vec<String>}, "e! {vec![]}, &field_attrs.default)
|
||||
}
|
||||
Some(&FieldType::FieldTypeBool) => {
|
||||
build_default_value(field_label, "e!{Vec<bool>}, "e!{vec![]})
|
||||
build_default_value(field_label, "e! {Vec<bool>}, "e! {vec![]}, &field_attrs.default)
|
||||
}
|
||||
Some(&FieldType::FieldTypeI8) => {
|
||||
build_default_value(field_label, "e!{Vec<i8>}, "e!{vec![]})
|
||||
build_default_value(field_label, "e! {Vec<i8>}, "e! {vec![]}, &field_attrs.default)
|
||||
}
|
||||
Some(&FieldType::FieldTypeU8) => {
|
||||
build_default_value(field_label, "e!{Vec<u8>}, "e!{vec![]})
|
||||
build_default_value(field_label, "e! {Vec<u8>}, "e! {vec![]}, &field_attrs.default)
|
||||
}
|
||||
Some(&FieldType::FieldTypeI16) => {
|
||||
build_default_value(field_label, "e!{Vec<i16>}, "e!{vec![]})
|
||||
build_default_value(field_label, "e! {Vec<i16>}, "e! {vec![]}, &field_attrs.default)
|
||||
}
|
||||
Some(&FieldType::FieldTypeU16) => {
|
||||
build_default_value(field_label, "e!{Vec<u16>}, "e!{vec![]})
|
||||
build_default_value(field_label, "e! {Vec<u16>}, "e! {vec![]}, &field_attrs.default)
|
||||
}
|
||||
Some(&FieldType::FieldTypeI32) => {
|
||||
build_default_value(field_label, "e!{Vec<i32>}, "e!{vec![]})
|
||||
build_default_value(field_label, "e! {Vec<i32>}, "e! {vec![]}, &field_attrs.default)
|
||||
}
|
||||
Some(&FieldType::FieldTypeU32) => {
|
||||
build_default_value(field_label, "e!{Vec<u32>}, "e!{vec![]})
|
||||
build_default_value(field_label, "e! {Vec<u32>}, "e! {vec![]}, &field_attrs.default)
|
||||
}
|
||||
Some(&FieldType::FieldTypeI64) => {
|
||||
build_default_value(field_label, "e!{Vec<i64>}, "e!{vec![]})
|
||||
build_default_value(field_label, "e! {Vec<i64>}, "e! {vec![]}, &field_attrs.default)
|
||||
}
|
||||
Some(&FieldType::FieldTypeU64) => {
|
||||
build_default_value(field_label, "e!{Vec<u64>}, "e!{vec![]})
|
||||
build_default_value(field_label, "e! {Vec<u64>}, "e! {vec![]}, &field_attrs.default)
|
||||
}
|
||||
Some(&FieldType::FieldTypeF32) => {
|
||||
build_default_value(field_label, "e!{Vec<f32>}, "e!{vec![]})
|
||||
build_default_value(field_label, "e! {Vec<f32>}, "e! {vec![]}, &field_attrs.default)
|
||||
}
|
||||
Some(&FieldType::FieldTypeF64) => {
|
||||
build_default_value(field_label, "e!{Vec<f64>}, "e!{vec![]})
|
||||
build_default_value(field_label, "e! {Vec<f64>}, "e! {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,
|
||||
"e! {Vec<#struct_name>},
|
||||
"e! {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
@ -1,3 +1,5 @@
|
||||
|
||||
pub mod build_default_value;
|
||||
pub mod expand_enum;
|
||||
pub mod expand_struct;
|
||||
|
||||
|
||||
75
yaserde_derive/src/ser/element.rs
Normal file
75
yaserde_derive/src/ser/element.rs
Normal 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
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
|
||||
pub mod element;
|
||||
pub mod expand_enum;
|
||||
pub mod expand_struct;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user