Merge pull request #73 from media-io/refactor_code
Restructure unit tests
This commit is contained in:
commit
e3eee45577
@ -137,3 +137,76 @@ fn default_visitor() {
|
|||||||
test_type!(visit_u64, "Unexpected u64 \"\"");
|
test_type!(visit_u64, "Unexpected u64 \"\"");
|
||||||
test_type!(visit_str, "Unexpected str \"\"");
|
test_type!(visit_str, "Unexpected str \"\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
mod testing {
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! test_for_type {
|
||||||
|
($type:ty, $value:expr, $content:expr) => {{
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(rename = "data")]
|
||||||
|
pub struct Data {
|
||||||
|
item: $type,
|
||||||
|
}
|
||||||
|
|
||||||
|
let model = Data { item: $value };
|
||||||
|
|
||||||
|
let content = if let Some(str_value) = $content {
|
||||||
|
String::from("<data><item>") + str_value + "</item></data>"
|
||||||
|
} else {
|
||||||
|
String::from("<data />")
|
||||||
|
};
|
||||||
|
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(&content, model, Data);
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! test_for_attribute_type {
|
||||||
|
($type: ty, $value: expr, $content: expr) => {{
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(rename = "data")]
|
||||||
|
pub struct Data {
|
||||||
|
#[yaserde(attribute)]
|
||||||
|
item: $type,
|
||||||
|
}
|
||||||
|
let model = Data { item: $value };
|
||||||
|
|
||||||
|
let content = if let Some(str_value) = $content {
|
||||||
|
"<data item=\"".to_string() + str_value + "\" />"
|
||||||
|
} else {
|
||||||
|
"<data />".to_string()
|
||||||
|
};
|
||||||
|
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(&content, model, Data);
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! deserialize_and_validate {
|
||||||
|
($content: expr, $model: expr, $struct: tt) => {
|
||||||
|
let loaded: Result<$struct, String> = yaserde::de::from_str($content);
|
||||||
|
assert_eq!(loaded, Ok($model));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! serialize_and_validate {
|
||||||
|
($model: expr, $content: expr) => {
|
||||||
|
let data: Result<String, String> = yaserde::ser::to_string(&$model);
|
||||||
|
|
||||||
|
let content = String::from(r#"<?xml version="1.0" encoding="utf-8"?>"#) + &$content;
|
||||||
|
assert_eq!(
|
||||||
|
data,
|
||||||
|
Ok(
|
||||||
|
String::from(content)
|
||||||
|
.split("\n")
|
||||||
|
.map(|s| s.trim())
|
||||||
|
.collect::<String>()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,93 +0,0 @@
|
|||||||
#[macro_use]
|
|
||||||
extern crate yaserde_derive;
|
|
||||||
|
|
||||||
use std::io::Read;
|
|
||||||
use yaserde::de::from_str;
|
|
||||||
use yaserde::YaDeserialize;
|
|
||||||
|
|
||||||
macro_rules! convert_and_validate {
|
|
||||||
($content: expr, $struct: tt, $model: expr) => {
|
|
||||||
let loaded: Result<$struct, String> = from_str($content);
|
|
||||||
assert_eq!(loaded, Ok($model));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn de_default_field_string() {
|
|
||||||
fn default_string() -> String {
|
|
||||||
"my_default_value".to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(YaDeserialize, 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!(
|
|
||||||
content,
|
|
||||||
XmlStruct,
|
|
||||||
XmlStruct {
|
|
||||||
background: "my_default_value".to_string(),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn de_default_field_boolean() {
|
|
||||||
fn default_boolean() -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(YaDeserialize, 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!(content, XmlStruct, XmlStruct { background: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn de_default_field_number() {
|
|
||||||
fn default_number() -> u8 {
|
|
||||||
6
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(YaDeserialize, 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!(content, XmlStruct, XmlStruct { background: 6 });
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn de_default_attribute_string() {
|
|
||||||
fn default_string() -> String {
|
|
||||||
"my_default_value".to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(YaDeserialize, 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!(
|
|
||||||
content,
|
|
||||||
XmlStruct,
|
|
||||||
XmlStruct {
|
|
||||||
background: "my_default_value".to_string(),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,166 +0,0 @@
|
|||||||
#[macro_use]
|
|
||||||
extern crate yaserde_derive;
|
|
||||||
|
|
||||||
use std::io::Read;
|
|
||||||
use yaserde::de::from_str;
|
|
||||||
use yaserde::YaDeserialize;
|
|
||||||
|
|
||||||
macro_rules! convert_and_validate {
|
|
||||||
($content: expr, $struct: tt, $model: expr) => {
|
|
||||||
let loaded: Result<$struct, String> = from_str($content);
|
|
||||||
assert_eq!(loaded, Ok($model));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn de_root_flatten_struct() {
|
|
||||||
#[derive(Default, PartialEq, Debug, YaDeserialize)]
|
|
||||||
#[yaserde(flatten)]
|
|
||||||
struct Content {
|
|
||||||
binary_data: String,
|
|
||||||
string_data: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
let content = r#"
|
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<binary_data>binary</binary_data>
|
|
||||||
<string_data>string</string_data>
|
|
||||||
"#;
|
|
||||||
|
|
||||||
convert_and_validate!(
|
|
||||||
content,
|
|
||||||
Content,
|
|
||||||
Content {
|
|
||||||
binary_data: "binary".to_string(),
|
|
||||||
string_data: "string".to_string(),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn de_root_flatten_enum() {
|
|
||||||
#[derive(PartialEq, Debug, YaDeserialize)]
|
|
||||||
#[yaserde(flatten)]
|
|
||||||
pub enum Content {
|
|
||||||
Binary(Binary),
|
|
||||||
Data(Data),
|
|
||||||
Unknown,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Content {
|
|
||||||
fn default() -> Self {
|
|
||||||
Content::Unknown
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaDeserialize)]
|
|
||||||
pub struct Binary {
|
|
||||||
binary_data: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaDeserialize)]
|
|
||||||
pub struct Data {
|
|
||||||
string_data: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
let content = r#"
|
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Binary>
|
|
||||||
<binary_data>binary</binary_data>
|
|
||||||
</Binary>
|
|
||||||
"#;
|
|
||||||
|
|
||||||
convert_and_validate!(
|
|
||||||
content,
|
|
||||||
Content,
|
|
||||||
Content::Binary(Binary {
|
|
||||||
binary_data: "binary".to_string(),
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn de_flatten() {
|
|
||||||
#[derive(Default, PartialEq, Debug, YaDeserialize)]
|
|
||||||
struct DateTime {
|
|
||||||
#[yaserde(flatten)]
|
|
||||||
date: Date,
|
|
||||||
time: String,
|
|
||||||
#[yaserde(flatten)]
|
|
||||||
kind: DateKind,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaDeserialize)]
|
|
||||||
struct Date {
|
|
||||||
year: i32,
|
|
||||||
month: i32,
|
|
||||||
day: i32,
|
|
||||||
#[yaserde(flatten)]
|
|
||||||
extra: Extra,
|
|
||||||
#[yaserde(flatten)]
|
|
||||||
optional_extra: Option<OptionalExtra>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaDeserialize)]
|
|
||||||
pub struct Extra {
|
|
||||||
week: i32,
|
|
||||||
century: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaDeserialize)]
|
|
||||||
pub struct OptionalExtra {
|
|
||||||
lunar_day: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, YaDeserialize)]
|
|
||||||
pub enum DateKind {
|
|
||||||
#[yaserde(rename = "holidays")]
|
|
||||||
Holidays(Vec<String>),
|
|
||||||
#[yaserde(rename = "working")]
|
|
||||||
Working,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for DateKind {
|
|
||||||
fn default() -> Self {
|
|
||||||
DateKind::Working
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let content = r#"
|
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<DateTime>
|
|
||||||
<year>2020</year>
|
|
||||||
<month>1</month>
|
|
||||||
<day>1</day>
|
|
||||||
<week>1</week>
|
|
||||||
<century>21</century>
|
|
||||||
<lunar_day>1</lunar_day>
|
|
||||||
<time>10:40:03</time>
|
|
||||||
<holidays>New Year's Day</holidays>
|
|
||||||
<holidays>Novy God Day</holidays>
|
|
||||||
<holidays>Polar Bear Swim Day</holidays>
|
|
||||||
</DateTime>
|
|
||||||
"#;
|
|
||||||
convert_and_validate!(
|
|
||||||
content,
|
|
||||||
DateTime,
|
|
||||||
DateTime {
|
|
||||||
date: Date {
|
|
||||||
year: 2020,
|
|
||||||
month: 1,
|
|
||||||
day: 1,
|
|
||||||
extra: Extra {
|
|
||||||
week: 1,
|
|
||||||
century: 21,
|
|
||||||
},
|
|
||||||
optional_extra: Some(OptionalExtra { lunar_day: 1 }),
|
|
||||||
},
|
|
||||||
time: "10:40:03".to_string(),
|
|
||||||
kind: DateKind::Holidays(vec![
|
|
||||||
"New Year's Day".into(),
|
|
||||||
"Novy God Day".into(),
|
|
||||||
"Polar Bear Swim Day".into()
|
|
||||||
])
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,144 +0,0 @@
|
|||||||
#[macro_use]
|
|
||||||
extern crate yaserde_derive;
|
|
||||||
|
|
||||||
use std::io::Read;
|
|
||||||
use yaserde::de::from_str;
|
|
||||||
use yaserde::YaDeserialize;
|
|
||||||
|
|
||||||
macro_rules! convert_and_validate {
|
|
||||||
($content: expr, $struct: tt, $model: expr) => {
|
|
||||||
let loaded: Result<$struct, String> = from_str($content);
|
|
||||||
assert_eq!(loaded, Ok($model));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn de_struct_namespace() {
|
|
||||||
#[derive(YaDeserialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(
|
|
||||||
root = "book",
|
|
||||||
prefix = "ns",
|
|
||||||
namespace = "ns: http://www.sample.com/ns/domain",
|
|
||||||
namespace = "ns2: http://www.sample.com/ns/domain_2"
|
|
||||||
)]
|
|
||||||
pub struct Book {
|
|
||||||
#[yaserde(prefix = "ns")]
|
|
||||||
author: String,
|
|
||||||
#[yaserde(prefix = "ns2")]
|
|
||||||
title: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
let content = r#"<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<ns:book xmlns:ns="http://www.sample.com/ns/domain" xmlns:ns2="http://www.sample.com/ns/domain_2">
|
|
||||||
<ns:author>Antoine de Saint-Exupéry</ns:author>
|
|
||||||
<ns2:title>Little prince</ns2:title>
|
|
||||||
</ns:book>
|
|
||||||
"#;
|
|
||||||
convert_and_validate!(
|
|
||||||
content,
|
|
||||||
Book,
|
|
||||||
Book {
|
|
||||||
author: String::from("Antoine de Saint-Exupéry"),
|
|
||||||
title: String::from("Little prince"),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let content = r#"<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<ns:book xmlns:ns="http://www.sample.com/ns/domain">
|
|
||||||
<ns:author>Antoine de Saint-Exupéry</ns:author>
|
|
||||||
<ns2:title xmlns:ns2="http://www.sample.com/ns/domain_2">Little prince</ns2:title>
|
|
||||||
</ns:book>
|
|
||||||
"#;
|
|
||||||
convert_and_validate!(
|
|
||||||
content,
|
|
||||||
Book,
|
|
||||||
Book {
|
|
||||||
author: String::from("Antoine de Saint-Exupéry"),
|
|
||||||
title: String::from("Little prince"),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let content = r#"<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<book xmlns="http://www.sample.com/ns/domain">
|
|
||||||
<author>Antoine de Saint-Exupéry</author>
|
|
||||||
<ns2:title xmlns:ns2="http://www.sample.com/ns/domain_2">Little prince</ns2:title>
|
|
||||||
</book>
|
|
||||||
"#;
|
|
||||||
convert_and_validate!(
|
|
||||||
content,
|
|
||||||
Book,
|
|
||||||
Book {
|
|
||||||
author: String::from("Antoine de Saint-Exupéry"),
|
|
||||||
title: String::from("Little prince"),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let content = r#"<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<ns:book xmlns:ns="http://www.sample.com/ns/domain2">
|
|
||||||
<ns:author>Antoine de Saint-Exupéry</ns:author>
|
|
||||||
<ns:title>Little prince</ns:title>
|
|
||||||
</ns:book>"#;
|
|
||||||
let loaded: Result<Book, String> = from_str(content);
|
|
||||||
assert_eq!(
|
|
||||||
loaded,
|
|
||||||
Err("bad namespace for book, found http://www.sample.com/ns/domain2".to_string())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn de_struct_namespace_nested() {
|
|
||||||
#[derive(YaDeserialize, Default, PartialEq, Debug)]
|
|
||||||
#[yaserde(prefix = "nsa", namespace = "nsa: http://www.sample.com/ns/a")]
|
|
||||||
struct A {
|
|
||||||
#[yaserde(prefix = "nsa")]
|
|
||||||
alpha: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(YaDeserialize, Default, PartialEq, Debug)]
|
|
||||||
#[yaserde(prefix = "nsb", namespace = "nsb: http://www.sample.com/ns/b")]
|
|
||||||
struct B {
|
|
||||||
// Note that name `nested` resides in `nsb` though it has a type from `nsa`
|
|
||||||
#[yaserde(prefix = "nsb")]
|
|
||||||
nested: A,
|
|
||||||
}
|
|
||||||
|
|
||||||
convert_and_validate!(
|
|
||||||
r#"
|
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<nsb:B
|
|
||||||
xmlns:nsa="http://www.sample.com/ns/a"
|
|
||||||
xmlns:nsb="http://www.sample.com/ns/b">
|
|
||||||
<nsb:nested>
|
|
||||||
<nsa:alpha>32</nsa:alpha>
|
|
||||||
</nsb:nested>
|
|
||||||
</nsb:B>
|
|
||||||
"#,
|
|
||||||
B,
|
|
||||||
B {
|
|
||||||
nested: A { alpha: 32 }
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn de_enum_namespace() {
|
|
||||||
#[derive(YaDeserialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(
|
|
||||||
root = "root",
|
|
||||||
prefix = "ns",
|
|
||||||
namespace = "ns: http://www.sample.com/ns/domain"
|
|
||||||
)]
|
|
||||||
pub enum XmlStruct {
|
|
||||||
#[yaserde(prefix = "ns")]
|
|
||||||
Item,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for XmlStruct {
|
|
||||||
fn default() -> XmlStruct {
|
|
||||||
XmlStruct::Item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><ns:root xmlns:ns=\"http://www.sample.com/ns/domain\">ns:Item</ns:root>";
|
|
||||||
convert_and_validate!(content, XmlStruct, XmlStruct::Item);
|
|
||||||
}
|
|
||||||
@ -1,144 +0,0 @@
|
|||||||
#[macro_use]
|
|
||||||
extern crate yaserde_derive;
|
|
||||||
|
|
||||||
use std::io::Read;
|
|
||||||
use yaserde::de::from_str;
|
|
||||||
use yaserde::YaDeserialize;
|
|
||||||
|
|
||||||
macro_rules! convert_and_validate {
|
|
||||||
($type: ty, $value: expr, $content: expr) => {{
|
|
||||||
#[derive(YaDeserialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(root = "data")]
|
|
||||||
pub struct Data {
|
|
||||||
item: Option<$type>,
|
|
||||||
}
|
|
||||||
|
|
||||||
let model = Data { item: $value };
|
|
||||||
|
|
||||||
let source = if let Some(content) = $content {
|
|
||||||
String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?><data><item>")
|
|
||||||
+ content
|
|
||||||
+ "</item></data>"
|
|
||||||
} else {
|
|
||||||
String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?><data />")
|
|
||||||
};
|
|
||||||
|
|
||||||
let loaded: Result<Data, String> = from_str(&source);
|
|
||||||
assert_eq!(loaded, Ok(model));
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! convert_and_validate_for_attribute {
|
|
||||||
($type: ty, $value: expr, $content: expr) => {{
|
|
||||||
#[derive(YaDeserialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(root = "data")]
|
|
||||||
pub struct Data {
|
|
||||||
#[yaserde(attribute)]
|
|
||||||
item: Option<$type>,
|
|
||||||
}
|
|
||||||
|
|
||||||
let model = Data { item: $value };
|
|
||||||
|
|
||||||
let source = if let Some(content) = $content {
|
|
||||||
String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?><data item=\"")
|
|
||||||
+ content
|
|
||||||
+ "\"></data>"
|
|
||||||
} else {
|
|
||||||
String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?><data />")
|
|
||||||
};
|
|
||||||
|
|
||||||
let loaded: Result<Data, String> = from_str(&source);
|
|
||||||
assert_eq!(loaded, Ok(model));
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn de_option() {
|
|
||||||
convert_and_validate!(String, Some("test".to_string()), Some("test"));
|
|
||||||
convert_and_validate!(String, None, None);
|
|
||||||
convert_and_validate!(bool, Some(true), Some("true"));
|
|
||||||
convert_and_validate!(bool, None, None);
|
|
||||||
convert_and_validate!(u8, Some(12 as u8), Some("12"));
|
|
||||||
convert_and_validate!(u8, None, None);
|
|
||||||
convert_and_validate!(i8, Some(12 as i8), Some("12"));
|
|
||||||
convert_and_validate!(i8, Some(-12 as i8), Some("-12"));
|
|
||||||
convert_and_validate!(i8, None, None);
|
|
||||||
convert_and_validate!(u16, Some(12 as u16), Some("12"));
|
|
||||||
convert_and_validate!(u16, None, None);
|
|
||||||
convert_and_validate!(i16, Some(12 as i16), Some("12"));
|
|
||||||
convert_and_validate!(i16, Some(-12 as i16), Some("-12"));
|
|
||||||
convert_and_validate!(i16, None, None);
|
|
||||||
convert_and_validate!(u32, Some(12 as u32), Some("12"));
|
|
||||||
convert_and_validate!(u32, None, None);
|
|
||||||
convert_and_validate!(i32, Some(12 as i32), Some("12"));
|
|
||||||
convert_and_validate!(i32, Some(-12 as i32), Some("-12"));
|
|
||||||
convert_and_validate!(i32, None, None);
|
|
||||||
convert_and_validate!(u64, Some(12 as u64), Some("12"));
|
|
||||||
convert_and_validate!(u64, None, None);
|
|
||||||
convert_and_validate!(i64, Some(12 as i64), Some("12"));
|
|
||||||
convert_and_validate!(i64, Some(-12 as i64), Some("-12"));
|
|
||||||
convert_and_validate!(i64, None, None);
|
|
||||||
convert_and_validate!(f32, Some(-12.5_f32 as f32), Some("-12.5"));
|
|
||||||
convert_and_validate!(f32, None, None);
|
|
||||||
convert_and_validate!(f64, Some(-12.5 as f64), Some("-12.5"));
|
|
||||||
convert_and_validate!(f64, None, None);
|
|
||||||
|
|
||||||
convert_and_validate_for_attribute!(String, Some("test".to_string()), Some("test"));
|
|
||||||
convert_and_validate_for_attribute!(String, None, None);
|
|
||||||
convert_and_validate_for_attribute!(bool, Some(true), Some("true"));
|
|
||||||
convert_and_validate_for_attribute!(bool, None, None);
|
|
||||||
convert_and_validate_for_attribute!(u8, Some(12 as u8), Some("12"));
|
|
||||||
convert_and_validate_for_attribute!(u8, None, None);
|
|
||||||
convert_and_validate_for_attribute!(i8, Some(12 as i8), Some("12"));
|
|
||||||
convert_and_validate_for_attribute!(i8, Some(-12 as i8), Some("-12"));
|
|
||||||
convert_and_validate_for_attribute!(i8, None, None);
|
|
||||||
convert_and_validate_for_attribute!(u16, Some(12 as u16), Some("12"));
|
|
||||||
convert_and_validate_for_attribute!(u16, None, None);
|
|
||||||
convert_and_validate_for_attribute!(i16, Some(12 as i16), Some("12"));
|
|
||||||
convert_and_validate_for_attribute!(i16, Some(-12 as i16), Some("-12"));
|
|
||||||
convert_and_validate_for_attribute!(i16, None, None);
|
|
||||||
convert_and_validate_for_attribute!(u32, Some(12 as u32), Some("12"));
|
|
||||||
convert_and_validate_for_attribute!(u32, None, None);
|
|
||||||
convert_and_validate_for_attribute!(i32, Some(12 as i32), Some("12"));
|
|
||||||
convert_and_validate_for_attribute!(i32, Some(-12 as i32), Some("-12"));
|
|
||||||
convert_and_validate_for_attribute!(i32, None, None);
|
|
||||||
convert_and_validate_for_attribute!(u64, Some(12 as u64), Some("12"));
|
|
||||||
convert_and_validate_for_attribute!(u64, None, None);
|
|
||||||
convert_and_validate_for_attribute!(i64, Some(12 as i64), Some("12"));
|
|
||||||
convert_and_validate_for_attribute!(i64, Some(-12 as i64), Some("-12"));
|
|
||||||
convert_and_validate_for_attribute!(i64, None, None);
|
|
||||||
convert_and_validate_for_attribute!(f32, Some(-12.5 as f32), Some("-12.5"));
|
|
||||||
convert_and_validate_for_attribute!(f32, None, None);
|
|
||||||
convert_and_validate_for_attribute!(f64, Some(-12.5 as f64), Some("-12.5"));
|
|
||||||
convert_and_validate_for_attribute!(f64, None, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn de_option_struct() {
|
|
||||||
#[derive(YaDeserialize, Debug, PartialEq)]
|
|
||||||
struct Test {
|
|
||||||
field: SubTest,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(YaDeserialize, Debug, PartialEq)]
|
|
||||||
struct SubTest {
|
|
||||||
content: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for SubTest {
|
|
||||||
fn default() -> Self {
|
|
||||||
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, None, None);
|
|
||||||
}
|
|
||||||
@ -1,81 +0,0 @@
|
|||||||
#[macro_use]
|
|
||||||
extern crate yaserde_derive;
|
|
||||||
|
|
||||||
use std::io::Read;
|
|
||||||
use yaserde::de::from_str;
|
|
||||||
use yaserde::YaDeserialize;
|
|
||||||
|
|
||||||
macro_rules! convert_and_validate {
|
|
||||||
($type:ty, $value:expr, $content:expr) => {{
|
|
||||||
#[derive(YaDeserialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(root = "data")]
|
|
||||||
pub struct Data {
|
|
||||||
item: $type,
|
|
||||||
}
|
|
||||||
|
|
||||||
let model = Data { item: $value };
|
|
||||||
|
|
||||||
let content = String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?><data><item>")
|
|
||||||
+ $content
|
|
||||||
+ "</item></data>";
|
|
||||||
|
|
||||||
let loaded: Result<Data, String> = from_str(&content);
|
|
||||||
assert_eq!(loaded, Ok(model));
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! convert_and_validate_for_attribute {
|
|
||||||
($type:ty, $value:expr, $content:expr) => {{
|
|
||||||
#[derive(YaDeserialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(root = "data")]
|
|
||||||
pub struct Data {
|
|
||||||
#[yaserde(attribute)]
|
|
||||||
item: $type,
|
|
||||||
}
|
|
||||||
|
|
||||||
let model = Data { item: $value };
|
|
||||||
|
|
||||||
let content =
|
|
||||||
String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?><data item=\"") + $content + "\" />";
|
|
||||||
|
|
||||||
let loaded: Result<Data, String> = from_str(&content);
|
|
||||||
assert_eq!(loaded, Ok(model));
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn de_type() {
|
|
||||||
convert_and_validate!(String, "test".to_string(), "test");
|
|
||||||
convert_and_validate!(bool, true, "true");
|
|
||||||
convert_and_validate!(u8, 12 as u8, "12");
|
|
||||||
convert_and_validate!(i8, 12 as i8, "12");
|
|
||||||
convert_and_validate!(i8, -12 as i8, "-12");
|
|
||||||
convert_and_validate!(u16, 12 as u16, "12");
|
|
||||||
convert_and_validate!(i16, 12 as i16, "12");
|
|
||||||
convert_and_validate!(i16, -12 as i16, "-12");
|
|
||||||
convert_and_validate!(u32, 12 as u32, "12");
|
|
||||||
convert_and_validate!(i32, 12 as i32, "12");
|
|
||||||
convert_and_validate!(i32, -12 as i32, "-12");
|
|
||||||
convert_and_validate!(u64, 12 as u64, "12");
|
|
||||||
convert_and_validate!(i64, 12 as i64, "12");
|
|
||||||
convert_and_validate!(i64, -12 as i64, "-12");
|
|
||||||
convert_and_validate!(f32, -12.5_f32 as f32, "-12.5");
|
|
||||||
convert_and_validate!(f64, -12.5 as f64, "-12.5");
|
|
||||||
|
|
||||||
convert_and_validate_for_attribute!(String, "test".to_string(), "test");
|
|
||||||
convert_and_validate_for_attribute!(bool, true, "true");
|
|
||||||
convert_and_validate_for_attribute!(u8, 12 as u8, "12");
|
|
||||||
convert_and_validate_for_attribute!(i8, 12 as i8, "12");
|
|
||||||
convert_and_validate_for_attribute!(i8, -12 as i8, "-12");
|
|
||||||
convert_and_validate_for_attribute!(u16, 12 as u16, "12");
|
|
||||||
convert_and_validate_for_attribute!(i16, 12 as i16, "12");
|
|
||||||
convert_and_validate_for_attribute!(i16, -12 as i16, "-12");
|
|
||||||
convert_and_validate_for_attribute!(u32, 12 as u32, "12");
|
|
||||||
convert_and_validate_for_attribute!(i32, 12 as i32, "12");
|
|
||||||
convert_and_validate_for_attribute!(i32, -12 as i32, "-12");
|
|
||||||
convert_and_validate_for_attribute!(u64, 12 as u64, "12");
|
|
||||||
convert_and_validate_for_attribute!(i64, 12 as i64, "12");
|
|
||||||
convert_and_validate_for_attribute!(i64, -12 as i64, "-12");
|
|
||||||
convert_and_validate_for_attribute!(f32, -12.5 as f32, "-12.5");
|
|
||||||
convert_and_validate_for_attribute!(f64, -12.5 as f64, "-12.5");
|
|
||||||
}
|
|
||||||
112
yaserde/tests/default.rs
Normal file
112
yaserde/tests/default.rs
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
#[macro_use]
|
||||||
|
extern crate yaserde;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate yaserde_derive;
|
||||||
|
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use yaserde::{YaDeserialize, YaSerialize};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_field_string() {
|
||||||
|
fn default_string() -> String {
|
||||||
|
"my_default_value".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(rename = "base")]
|
||||||
|
pub struct XmlStruct {
|
||||||
|
#[yaserde(default = "default_string")]
|
||||||
|
background: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
let model = XmlStruct {
|
||||||
|
background: "my_default_value".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = "<base />";
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
|
||||||
|
let content = "<base><background>my_value</background></base>";
|
||||||
|
let model = XmlStruct {
|
||||||
|
background: "my_value".to_string(),
|
||||||
|
};
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_field_boolean() {
|
||||||
|
fn default_boolean() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(rename = "base")]
|
||||||
|
pub struct XmlStruct {
|
||||||
|
#[yaserde(default = "default_boolean")]
|
||||||
|
background: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = "<base />";
|
||||||
|
let model = XmlStruct { background: true };
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
|
||||||
|
let content = "<base><background>false</background></base>";
|
||||||
|
let model = XmlStruct { background: false };
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_field_number() {
|
||||||
|
fn default_number() -> u8 {
|
||||||
|
6
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(rename = "base")]
|
||||||
|
pub struct XmlStruct {
|
||||||
|
#[yaserde(default = "default_number")]
|
||||||
|
background: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = "<base />";
|
||||||
|
let model = XmlStruct { background: 6 };
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
|
||||||
|
let content = "<base><background>4</background></base>";
|
||||||
|
let model = XmlStruct { background: 4 };
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_attribute_string() {
|
||||||
|
fn default_string() -> String {
|
||||||
|
"my_default_value".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(rename = "base")]
|
||||||
|
pub struct XmlStruct {
|
||||||
|
#[yaserde(attribute, default = "default_string")]
|
||||||
|
background: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = "<base />";
|
||||||
|
let model = XmlStruct {
|
||||||
|
background: "my_default_value".to_string(),
|
||||||
|
};
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
|
||||||
|
let content = r#"<base background="black" />"#;
|
||||||
|
let model = XmlStruct {
|
||||||
|
background: "black".to_string(),
|
||||||
|
};
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
}
|
||||||
300
yaserde/tests/enum.rs
Normal file
300
yaserde/tests/enum.rs
Normal file
@ -0,0 +1,300 @@
|
|||||||
|
#[macro_use]
|
||||||
|
extern crate yaserde;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate yaserde_derive;
|
||||||
|
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use yaserde::{YaDeserialize, YaSerialize};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn basic_enum() {
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(rename = "base")]
|
||||||
|
pub struct XmlStruct {
|
||||||
|
color: Color,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(rename = "color")]
|
||||||
|
pub enum Color {
|
||||||
|
White,
|
||||||
|
Black,
|
||||||
|
#[yaserde(rename = "custom")]
|
||||||
|
Custom {
|
||||||
|
enabled: String,
|
||||||
|
u8_value: u8,
|
||||||
|
i8_value: i8,
|
||||||
|
u16_value: u16,
|
||||||
|
i16_value: i16,
|
||||||
|
u32_value: u32,
|
||||||
|
i32_value: i32,
|
||||||
|
u64_value: u64,
|
||||||
|
i64_value: i64,
|
||||||
|
f32_value: f32,
|
||||||
|
f64_value: f64,
|
||||||
|
color: RGBColor,
|
||||||
|
alpha: Alpha,
|
||||||
|
alphas: Vec<Alpha>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Color {
|
||||||
|
fn default() -> Color {
|
||||||
|
Color::White
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(Color::default(), Color::White);
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
pub struct RGBColor {
|
||||||
|
red: String,
|
||||||
|
green: String,
|
||||||
|
blue: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
pub enum Alpha {
|
||||||
|
Transparent,
|
||||||
|
Opaque,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Alpha {
|
||||||
|
fn default() -> Alpha {
|
||||||
|
Alpha::Transparent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let model = XmlStruct {
|
||||||
|
color: Color::Black,
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = "<base><color>Black</color></base>";
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
|
||||||
|
let model = XmlStruct {
|
||||||
|
color: Color::Custom {
|
||||||
|
enabled: "true".to_string(),
|
||||||
|
u8_value: 8,
|
||||||
|
i8_value: -8,
|
||||||
|
u16_value: 16,
|
||||||
|
i16_value: -16,
|
||||||
|
u32_value: 32,
|
||||||
|
i32_value: -32,
|
||||||
|
u64_value: 64,
|
||||||
|
i64_value: -64,
|
||||||
|
f32_value: 32.0,
|
||||||
|
f64_value: 64.0,
|
||||||
|
color: RGBColor {
|
||||||
|
red: "0".to_string(),
|
||||||
|
green: "128".to_string(),
|
||||||
|
blue: "255".to_string(),
|
||||||
|
},
|
||||||
|
alpha: Alpha::Opaque,
|
||||||
|
alphas: vec![Alpha::Opaque, Alpha::Transparent],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = r#"
|
||||||
|
<base>
|
||||||
|
<color><enabled>true</enabled>
|
||||||
|
<u8_value>8</u8_value>
|
||||||
|
<i8_value>-8</i8_value>
|
||||||
|
<u16_value>16</u16_value>
|
||||||
|
<i16_value>-16</i16_value>
|
||||||
|
<u32_value>32</u32_value>
|
||||||
|
<i32_value>-32</i32_value>
|
||||||
|
<u64_value>64</u64_value>
|
||||||
|
<i64_value>-64</i64_value>
|
||||||
|
<f32_value>32</f32_value>
|
||||||
|
<f64_value>64</f64_value>
|
||||||
|
<color><red>0</red><green>128</green><blue>255</blue></color>
|
||||||
|
<alpha>Opaque</alpha>
|
||||||
|
<alphas>Opaque</alphas>
|
||||||
|
<alphas>Transparent</alphas>
|
||||||
|
</color>
|
||||||
|
</base>"#;
|
||||||
|
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
// TODO
|
||||||
|
// deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn attribute_enum() {
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(rename = "base")]
|
||||||
|
pub struct XmlStruct {
|
||||||
|
#[yaserde(attribute)]
|
||||||
|
color: Color,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(rename = "color")]
|
||||||
|
pub enum Color {
|
||||||
|
#[yaserde(rename = "pink")]
|
||||||
|
Pink,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Color {
|
||||||
|
fn default() -> Color {
|
||||||
|
Color::Pink
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let model = XmlStruct { color: Color::Pink };
|
||||||
|
|
||||||
|
let content = r#"<base color="pink" />"#;
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unnamed_enum() {
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(rename = "base")]
|
||||||
|
pub struct XmlStruct {
|
||||||
|
color: Enum,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
pub struct OtherStruct {
|
||||||
|
fi: i32,
|
||||||
|
se: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
pub enum Enum {
|
||||||
|
Simple,
|
||||||
|
Field(String),
|
||||||
|
FullPath(std::string::String),
|
||||||
|
Integer(i32),
|
||||||
|
UserStruct(OtherStruct),
|
||||||
|
OptionString(Option<String>),
|
||||||
|
OptionUserStruct(Option<OtherStruct>),
|
||||||
|
Strings(Vec<String>),
|
||||||
|
Ints(Vec<i32>),
|
||||||
|
Structs(Vec<OtherStruct>),
|
||||||
|
#[yaserde(rename = "renamed")]
|
||||||
|
ToRename(u32),
|
||||||
|
#[yaserde(rename = "renamed.with.dots")]
|
||||||
|
ToRenameDots(u32),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Enum {
|
||||||
|
fn default() -> Enum {
|
||||||
|
Enum::Simple
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let model = XmlStruct {
|
||||||
|
color: Enum::Field(String::from("some_text")),
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = "<base><color><Field>some_text</Field></color></base>";
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
|
||||||
|
let model = XmlStruct {
|
||||||
|
color: Enum::FullPath(String::from("some_text")),
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = "<base><color><FullPath>some_text</FullPath></color></base>";
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
|
||||||
|
let model = XmlStruct {
|
||||||
|
color: Enum::Integer(56),
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = "<base><color><Integer>56</Integer></color></base>";
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
|
||||||
|
let model = XmlStruct {
|
||||||
|
color: Enum::UserStruct(OtherStruct { fi: 24, se: 42 }),
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = "<base><color><UserStruct><fi>24</fi><se>42</se></UserStruct></color></base>";
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
|
||||||
|
let model = XmlStruct {
|
||||||
|
color: Enum::OptionString(Some(String::from("some_text"))),
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = "<base><color><OptionString>some_text</OptionString></color></base>";
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
|
||||||
|
let model = XmlStruct {
|
||||||
|
color: Enum::OptionString(None),
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = "<base><color /></base>";
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
// TODO
|
||||||
|
// deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
|
||||||
|
let model = XmlStruct {
|
||||||
|
color: Enum::OptionUserStruct(Some(OtherStruct { fi: 12, se: 23 })),
|
||||||
|
};
|
||||||
|
|
||||||
|
let content =
|
||||||
|
"<base><color><OptionUserStruct><fi>12</fi><se>23</se></OptionUserStruct></color></base>";
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
|
||||||
|
let model = XmlStruct {
|
||||||
|
color: Enum::OptionUserStruct(None),
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = "<base><color /></base>";
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
// TODO
|
||||||
|
// deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
|
||||||
|
let model = XmlStruct {
|
||||||
|
color: Enum::Strings(vec![String::from("abc"), String::from("def")]),
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = "<base><color><Strings>abc</Strings><Strings>def</Strings></color></base>";
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
|
||||||
|
let model = XmlStruct {
|
||||||
|
color: Enum::Ints(vec![23, 45]),
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = "<base><color><Ints>23</Ints><Ints>45</Ints></color></base>";
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
|
||||||
|
let model = XmlStruct {
|
||||||
|
color: Enum::Structs(vec![
|
||||||
|
OtherStruct { fi: 12, se: 23 },
|
||||||
|
OtherStruct { fi: 34, se: 45 },
|
||||||
|
]),
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = "<base><color><Structs><fi>12</fi><se>23</se></Structs><Structs><fi>34</fi><se>45</se></Structs></color></base>";
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
|
||||||
|
let model = XmlStruct {
|
||||||
|
color: Enum::ToRename(87),
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = "<base><color><renamed>87</renamed></color></base>";
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
|
||||||
|
let model = XmlStruct {
|
||||||
|
color: Enum::ToRenameDots(84),
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = "<base><color><renamed.with.dots>84</renamed.with.dots></color></base>";
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
}
|
||||||
@ -1,28 +1,15 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
extern crate yaserde;
|
||||||
|
#[macro_use]
|
||||||
extern crate yaserde_derive;
|
extern crate yaserde_derive;
|
||||||
|
|
||||||
use std::io::Write;
|
use std::io::{Read, Write};
|
||||||
use yaserde::ser::to_string;
|
|
||||||
use yaserde::YaSerialize;
|
|
||||||
|
|
||||||
macro_rules! convert_and_validate {
|
use yaserde::{YaDeserialize, YaSerialize};
|
||||||
($model: expr, $content: expr) => {
|
|
||||||
let data: Result<String, String> = to_string(&$model);
|
|
||||||
assert_eq!(
|
|
||||||
data,
|
|
||||||
Ok(
|
|
||||||
String::from($content)
|
|
||||||
.split("\n")
|
|
||||||
.map(|s| s.trim())
|
|
||||||
.collect::<String>()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ser_flatten() {
|
fn basic_flatten() {
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize)]
|
#[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)]
|
||||||
struct DateTime {
|
struct DateTime {
|
||||||
#[yaserde(flatten)]
|
#[yaserde(flatten)]
|
||||||
date: Date,
|
date: Date,
|
||||||
@ -31,7 +18,7 @@ fn ser_flatten() {
|
|||||||
kind: DateKind,
|
kind: DateKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize)]
|
#[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)]
|
||||||
struct Date {
|
struct Date {
|
||||||
year: i32,
|
year: i32,
|
||||||
month: i32,
|
month: i32,
|
||||||
@ -42,18 +29,18 @@ fn ser_flatten() {
|
|||||||
optional_extra: Option<OptionalExtra>,
|
optional_extra: Option<OptionalExtra>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize)]
|
#[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)]
|
||||||
pub struct Extra {
|
pub struct Extra {
|
||||||
week: i32,
|
week: i32,
|
||||||
century: i32,
|
century: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize)]
|
#[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)]
|
||||||
pub struct OptionalExtra {
|
pub struct OptionalExtra {
|
||||||
lunar_day: i32,
|
lunar_day: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, YaSerialize)]
|
#[derive(PartialEq, Debug, YaDeserialize, YaSerialize)]
|
||||||
pub enum DateKind {
|
pub enum DateKind {
|
||||||
#[yaserde(rename = "holidays")]
|
#[yaserde(rename = "holidays")]
|
||||||
Holidays(Vec<String>),
|
Holidays(Vec<String>),
|
||||||
@ -87,7 +74,6 @@ fn ser_flatten() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let content = r#"
|
let content = r#"
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<DateTime>
|
<DateTime>
|
||||||
<year>2020</year>
|
<year>2020</year>
|
||||||
<month>1</month>
|
<month>1</month>
|
||||||
@ -101,12 +87,13 @@ fn ser_flatten() {
|
|||||||
<holidays>Polar Bear Swim Day</holidays>
|
<holidays>Polar Bear Swim Day</holidays>
|
||||||
</DateTime>"#;
|
</DateTime>"#;
|
||||||
|
|
||||||
convert_and_validate!(model, content);
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, DateTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ser_root_flatten_struct() {
|
fn root_flatten_struct() {
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
#[derive(YaDeserialize, YaSerialize, PartialEq, Debug)]
|
||||||
#[yaserde(flatten)]
|
#[yaserde(flatten)]
|
||||||
pub struct Content {
|
pub struct Content {
|
||||||
binary_data: String,
|
binary_data: String,
|
||||||
@ -117,12 +104,15 @@ fn ser_root_flatten_struct() {
|
|||||||
binary_data: "binary".to_string(),
|
binary_data: "binary".to_string(),
|
||||||
string_data: "string".to_string(),
|
string_data: "string".to_string(),
|
||||||
};
|
};
|
||||||
let content = r#"<?xml version="1.0" encoding="utf-8"?><binary_data>binary</binary_data><string_data>string</string_data>"#;
|
|
||||||
convert_and_validate!(model, content);
|
let content = "<binary_data>binary</binary_data><string_data>string</string_data>";
|
||||||
|
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, Content);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ser_root_flatten_enum() {
|
fn root_flatten_enum() {
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
#[derive(YaSerialize, PartialEq, Debug)]
|
||||||
#[yaserde(flatten)]
|
#[yaserde(flatten)]
|
||||||
pub enum Content {
|
pub enum Content {
|
||||||
@ -143,14 +133,14 @@ fn ser_root_flatten_enum() {
|
|||||||
let model = Content::Binary(Binary {
|
let model = Content::Binary(Binary {
|
||||||
binary_data: "binary".to_string(),
|
binary_data: "binary".to_string(),
|
||||||
});
|
});
|
||||||
let content =
|
|
||||||
r#"<?xml version="1.0" encoding="utf-8"?><Binary><binary_data>binary</binary_data></Binary>"#;
|
let content = "<Binary><binary_data>binary</binary_data></Binary>";
|
||||||
convert_and_validate!(model, content);
|
serialize_and_validate!(model, content);
|
||||||
|
|
||||||
let model = Content::Data(Data {
|
let model = Content::Data(Data {
|
||||||
string_data: "string".to_string(),
|
string_data: "string".to_string(),
|
||||||
});
|
});
|
||||||
let content =
|
|
||||||
r#"<?xml version="1.0" encoding="utf-8"?><Data><string_data>string</string_data></Data>"#;
|
let content = "<Data><string_data>string</string_data></Data>";
|
||||||
convert_and_validate!(model, content);
|
serialize_and_validate!(model, content);
|
||||||
}
|
}
|
||||||
442
yaserde/tests/namespace.rs
Normal file
442
yaserde/tests/namespace.rs
Normal file
@ -0,0 +1,442 @@
|
|||||||
|
#[macro_use]
|
||||||
|
extern crate yaserde;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate yaserde_derive;
|
||||||
|
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use yaserde::{YaDeserialize, YaSerialize};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn struct_simple_namespace() {
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(
|
||||||
|
rename = "book",
|
||||||
|
prefix = "ns",
|
||||||
|
namespace = "ns: http://www.sample.com/ns/domain"
|
||||||
|
)]
|
||||||
|
pub struct Book {
|
||||||
|
#[yaserde(prefix = "ns")]
|
||||||
|
author: String,
|
||||||
|
#[yaserde(prefix = "ns")]
|
||||||
|
title: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = r#"
|
||||||
|
<ns:book xmlns:ns="http://www.sample.com/ns/domain">
|
||||||
|
<ns:author>Antoine de Saint-Exupéry</ns:author>
|
||||||
|
<ns:title>Little prince</ns:title>
|
||||||
|
</ns:book>
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let model = Book {
|
||||||
|
author: String::from("Antoine de Saint-Exupéry"),
|
||||||
|
title: String::from("Little prince"),
|
||||||
|
};
|
||||||
|
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, Book);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn struct_multiple_namespaces() {
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(
|
||||||
|
rename = "book",
|
||||||
|
prefix = "ns",
|
||||||
|
namespace = "ns: http://www.sample.com/ns/domain",
|
||||||
|
namespace = "ns2: http://www.sample.com/ns/domain_2"
|
||||||
|
)]
|
||||||
|
pub struct Book {
|
||||||
|
#[yaserde(prefix = "ns")]
|
||||||
|
author: String,
|
||||||
|
#[yaserde(prefix = "ns2")]
|
||||||
|
title: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = r#"
|
||||||
|
<ns:book xmlns:ns="http://www.sample.com/ns/domain" xmlns:ns2="http://www.sample.com/ns/domain_2">
|
||||||
|
<ns:author>Antoine de Saint-Exupéry</ns:author>
|
||||||
|
<ns2:title>Little prince</ns2:title>
|
||||||
|
</ns:book>
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let model = Book {
|
||||||
|
author: String::from("Antoine de Saint-Exupéry"),
|
||||||
|
title: String::from("Little prince"),
|
||||||
|
};
|
||||||
|
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, Book);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn struct_partial_namespace() {
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(
|
||||||
|
rename = "book",
|
||||||
|
prefix = "ns",
|
||||||
|
namespace = "ns: http://www.sample.com/ns/domain"
|
||||||
|
)]
|
||||||
|
pub struct Book {
|
||||||
|
author: String,
|
||||||
|
#[yaserde(prefix = "ns")]
|
||||||
|
title: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = r#"
|
||||||
|
<ns:book xmlns:ns="http://www.sample.com/ns/domain">
|
||||||
|
<author>Antoine de Saint-Exupéry</author>
|
||||||
|
<ns:title>Little prince</ns:title>
|
||||||
|
</ns:book>
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let model = Book {
|
||||||
|
author: String::from("Antoine de Saint-Exupéry"),
|
||||||
|
title: String::from("Little prince"),
|
||||||
|
};
|
||||||
|
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, Book);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn struct_sub_namespace_definition() {
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(
|
||||||
|
rename = "book",
|
||||||
|
prefix = "ns",
|
||||||
|
namespace = "ns: http://www.sample.com/ns/domain",
|
||||||
|
namespace = "ns2: http://www.sample.com/ns/domain_2"
|
||||||
|
)]
|
||||||
|
pub struct Book {
|
||||||
|
#[yaserde(prefix = "ns")]
|
||||||
|
author: String,
|
||||||
|
#[yaserde(prefix = "ns2", namespace = "ns2: http://www.sample.com/ns/domain_2")]
|
||||||
|
title: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = r#"
|
||||||
|
<ns:book xmlns:ns="http://www.sample.com/ns/domain">
|
||||||
|
<ns:author>Antoine de Saint-Exupéry</ns:author>
|
||||||
|
<ns2:title xmlns:ns2="http://www.sample.com/ns/domain_2">Little prince</ns2:title>
|
||||||
|
</ns:book>
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let model = Book {
|
||||||
|
author: String::from("Antoine de Saint-Exupéry"),
|
||||||
|
title: String::from("Little prince"),
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO support namespace for attribute to specify local namespace
|
||||||
|
// serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, Book);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn struct_namespace_nested() {
|
||||||
|
#[derive(Debug, Default, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(prefix = "nsa", namespace = "nsa: http://www.sample.com/ns/a")]
|
||||||
|
struct A {
|
||||||
|
#[yaserde(prefix = "nsa")]
|
||||||
|
alpha: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(prefix = "nsb", namespace = "nsb: http://www.sample.com/ns/b")]
|
||||||
|
struct B {
|
||||||
|
// Note that name `nested` resides in `nsb` though it has a type from `nsa`
|
||||||
|
#[yaserde(prefix = "nsb")]
|
||||||
|
nested: A,
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = r#"
|
||||||
|
<nsb:B xmlns:nsb="http://www.sample.com/ns/b">
|
||||||
|
<nsb:nested xmlns:nsa="http://www.sample.com/ns/a">
|
||||||
|
<nsa:alpha>32</nsa:alpha>
|
||||||
|
</nsb:nested>
|
||||||
|
</nsb:B>
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let model = B {
|
||||||
|
nested: A { alpha: 32 },
|
||||||
|
};
|
||||||
|
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, B);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn struct_namespace_nested_defined_at_root() {
|
||||||
|
#[derive(Debug, Default, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(prefix = "nsa", namespace = "nsa: http://www.sample.com/ns/a")]
|
||||||
|
struct A {
|
||||||
|
#[yaserde(prefix = "nsa")]
|
||||||
|
alpha: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(
|
||||||
|
prefix = "nsb",
|
||||||
|
namespace = "nsb: http://www.sample.com/ns/b"
|
||||||
|
namespace = "nsa: http://www.sample.com/ns/a"
|
||||||
|
)]
|
||||||
|
struct B {
|
||||||
|
// Note that name `nested` resides in `nsb` though it has a type from `nsa`
|
||||||
|
#[yaserde(prefix = "nsb")]
|
||||||
|
nested: A,
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = r#"
|
||||||
|
<nsb:B xmlns:nsa="http://www.sample.com/ns/a" xmlns:nsb="http://www.sample.com/ns/b">
|
||||||
|
<nsb:nested>
|
||||||
|
<nsa:alpha>32</nsa:alpha>
|
||||||
|
</nsb:nested>
|
||||||
|
</nsb:B>
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let model = B {
|
||||||
|
nested: A { alpha: 32 },
|
||||||
|
};
|
||||||
|
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, B);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn struct_attribute_namespace() {
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(
|
||||||
|
rename = "root",
|
||||||
|
namespace = "ns1: http://www.sample.com/ns/domain1",
|
||||||
|
namespace = "ns2: http://www.sample.com/ns/domain2"
|
||||||
|
)]
|
||||||
|
pub struct XmlStruct {
|
||||||
|
#[yaserde(prefix = "ns1")]
|
||||||
|
item_1: String,
|
||||||
|
#[yaserde(attribute, prefix = "ns2")]
|
||||||
|
item_2: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
let model = XmlStruct {
|
||||||
|
item_1: "something 1".to_string(),
|
||||||
|
item_2: "something 2".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = r#"
|
||||||
|
<root xmlns:ns1="http://www.sample.com/ns/domain1" xmlns:ns2="http://www.sample.com/ns/domain2" ns2:item_2="something 2">
|
||||||
|
<ns1:item_1>something 1</ns1:item_1>
|
||||||
|
</root>
|
||||||
|
"#;
|
||||||
|
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn struct_implicit_default_namespace() {
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(
|
||||||
|
rename = "tt",
|
||||||
|
namespace = "http://www.w3.org/ns/ttml",
|
||||||
|
namespace = "ttm: http://www.w3.org/ns/ttml#metadata"
|
||||||
|
)]
|
||||||
|
pub struct XmlStruct {
|
||||||
|
item: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
let model = XmlStruct {
|
||||||
|
item: "something".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = r#"<tt xmlns="http://www.w3.org/ns/ttml" xmlns:ttm="http://www.w3.org/ns/ttml#metadata"><item>something</item></tt>"#;
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
// TODO
|
||||||
|
// deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn struct_explicit_default_namespace() {
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(
|
||||||
|
rename = "tt",
|
||||||
|
default_namespace = "ttml",
|
||||||
|
namespace = "ttml: http://www.w3.org/ns/ttml",
|
||||||
|
namespace = "ttm: http://www.w3.org/ns/ttml#metadata"
|
||||||
|
)]
|
||||||
|
pub struct XmlStruct {
|
||||||
|
item: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
let model = XmlStruct {
|
||||||
|
item: "something".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = r#"<tt xmlns="http://www.w3.org/ns/ttml" xmlns:ttm="http://www.w3.org/ns/ttml#metadata"><item>something</item></tt>"#;
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
// TODO
|
||||||
|
// deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn struct_default_namespace_via_attribute_with_prefix() {
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(
|
||||||
|
rename = "tt",
|
||||||
|
prefix = "TTML",
|
||||||
|
default_namespace = "TTML",
|
||||||
|
namespace = "TTML: http://www.w3.org/ns/ttml",
|
||||||
|
namespace = "ttm: http://www.w3.org/ns/ttml#metadata"
|
||||||
|
)]
|
||||||
|
pub struct XmlStruct {
|
||||||
|
#[yaserde(prefix = "TTML")]
|
||||||
|
item: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
let model = XmlStruct {
|
||||||
|
item: "something".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = r#"<tt xmlns="http://www.w3.org/ns/ttml" xmlns:ttm="http://www.w3.org/ns/ttml#metadata"><item>something</item></tt>"#;
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn enum_namespace() {
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(
|
||||||
|
rename = "root",
|
||||||
|
prefix = "ns",
|
||||||
|
namespace = "ns: http://www.sample.com/ns/domain"
|
||||||
|
)]
|
||||||
|
pub enum XmlStruct {
|
||||||
|
#[yaserde(prefix = "ns")]
|
||||||
|
Item,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for XmlStruct {
|
||||||
|
fn default() -> XmlStruct {
|
||||||
|
XmlStruct::Item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = r#"
|
||||||
|
<ns:root xmlns:ns="http://www.sample.com/ns/domain">
|
||||||
|
ns:Item
|
||||||
|
</ns:root>
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let model = XmlStruct::Item;
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn enum_multi_namespaces() {
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(
|
||||||
|
rename = "root",
|
||||||
|
namespace = "ns1: http://www.sample.com/ns/domain1",
|
||||||
|
namespace = "ns2: http://www.sample.com/ns/domain2"
|
||||||
|
)]
|
||||||
|
pub enum XmlStruct {
|
||||||
|
#[yaserde(prefix = "ns1")]
|
||||||
|
Item1,
|
||||||
|
#[yaserde(prefix = "ns2")]
|
||||||
|
Item2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for XmlStruct {
|
||||||
|
fn default() -> XmlStruct {
|
||||||
|
XmlStruct::Item1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let model = XmlStruct::Item1;
|
||||||
|
let content = r#"
|
||||||
|
<root xmlns:ns1="http://www.sample.com/ns/domain1" xmlns:ns2="http://www.sample.com/ns/domain2">
|
||||||
|
ns1:Item1
|
||||||
|
</root>
|
||||||
|
"#;
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
|
||||||
|
let model = XmlStruct::Item2;
|
||||||
|
let content = r#"
|
||||||
|
<root xmlns:ns1="http://www.sample.com/ns/domain1" xmlns:ns2="http://www.sample.com/ns/domain2">
|
||||||
|
ns2:Item2
|
||||||
|
</root>
|
||||||
|
"#;
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
// TODO
|
||||||
|
// deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn enum_attribute_namespace() {
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(
|
||||||
|
rename = "root",
|
||||||
|
prefix = "ns",
|
||||||
|
namespace = "ns: http://www.sample.com/ns/domain"
|
||||||
|
)]
|
||||||
|
pub enum XmlStruct {
|
||||||
|
#[yaserde(prefix = "ns")]
|
||||||
|
Item,
|
||||||
|
#[yaserde(prefix = "ns")]
|
||||||
|
ItemWithField(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for XmlStruct {
|
||||||
|
fn default() -> XmlStruct {
|
||||||
|
XmlStruct::Item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = r#"
|
||||||
|
<ns:root xmlns:ns="http://www.sample.com/ns/domain">
|
||||||
|
ns:Item
|
||||||
|
</ns:root>
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let model = XmlStruct::Item;
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
|
||||||
|
let model = XmlStruct::ItemWithField("Value".to_string());
|
||||||
|
|
||||||
|
let content = r#"<ns:root xmlns:ns="http://www.sample.com/ns/domain"><ns:ItemWithField>Value</ns:ItemWithField></ns:root>"#;
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
// TODO
|
||||||
|
// deserialize_and_validate!(content, model, XmlStruct);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn struct_bad_namespace() {
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(
|
||||||
|
rename = "book",
|
||||||
|
prefix = "ns",
|
||||||
|
namespace = "ns: http://www.sample.com/ns/domain",
|
||||||
|
namespace = "ns2: http://www.sample.com/ns/domain_2"
|
||||||
|
)]
|
||||||
|
pub struct Book {
|
||||||
|
#[yaserde(prefix = "ns")]
|
||||||
|
author: String,
|
||||||
|
#[yaserde(prefix = "ns2", namespace = "ns2: http://www.sample.com/ns/domain_2")]
|
||||||
|
title: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = r#"
|
||||||
|
<ns:book xmlns:ns="http://www.sample.com/ns/domain2">
|
||||||
|
<ns:author>Antoine de Saint-Exupéry</ns:author>
|
||||||
|
<ns:title>Little prince</ns:title>
|
||||||
|
</ns:book>
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let loaded: Result<Book, String> = yaserde::de::from_str(content);
|
||||||
|
assert_eq!(
|
||||||
|
loaded,
|
||||||
|
Err("bad namespace for book, found http://www.sample.com/ns/domain2".to_string())
|
||||||
|
);
|
||||||
|
}
|
||||||
104
yaserde/tests/option.rs
Normal file
104
yaserde/tests/option.rs
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#[macro_use]
|
||||||
|
extern crate yaserde;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate yaserde_derive;
|
||||||
|
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use yaserde::{YaDeserialize, YaSerialize};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn basic_option_types() {
|
||||||
|
test_for_type!(Option::<String>, Some("test".to_string()), Some("test"));
|
||||||
|
test_for_type!(Option::<String>, None, None);
|
||||||
|
test_for_type!(Option::<bool>, Some(true), Some("true"));
|
||||||
|
test_for_type!(Option::<bool>, None, None);
|
||||||
|
test_for_type!(Option::<u8>, Some(12 as u8), Some("12"));
|
||||||
|
test_for_type!(Option::<u8>, None, None);
|
||||||
|
test_for_type!(Option::<i8>, Some(12 as i8), Some("12"));
|
||||||
|
test_for_type!(Option::<i8>, Some(-12 as i8), Some("-12"));
|
||||||
|
test_for_type!(Option::<i8>, None, None);
|
||||||
|
test_for_type!(Option::<u16>, Some(12 as u16), Some("12"));
|
||||||
|
test_for_type!(Option::<u16>, None, None);
|
||||||
|
test_for_type!(Option::<i16>, Some(12 as i16), Some("12"));
|
||||||
|
test_for_type!(Option::<i16>, Some(-12 as i16), Some("-12"));
|
||||||
|
test_for_type!(Option::<i16>, None, None);
|
||||||
|
test_for_type!(Option::<u32>, Some(12 as u32), Some("12"));
|
||||||
|
test_for_type!(Option::<u32>, None, None);
|
||||||
|
test_for_type!(Option::<i32>, Some(12 as i32), Some("12"));
|
||||||
|
test_for_type!(Option::<i32>, Some(-12 as i32), Some("-12"));
|
||||||
|
test_for_type!(Option::<i32>, None, None);
|
||||||
|
test_for_type!(Option::<u64>, Some(12 as u64), Some("12"));
|
||||||
|
test_for_type!(Option::<u64>, None, None);
|
||||||
|
test_for_type!(Option::<i64>, Some(12 as i64), Some("12"));
|
||||||
|
test_for_type!(Option::<i64>, Some(-12 as i64), Some("-12"));
|
||||||
|
test_for_type!(Option::<i64>, None, None);
|
||||||
|
test_for_type!(Option::<f32>, Some(-12.5 as f32), Some("-12.5"));
|
||||||
|
test_for_type!(Option::<f32>, None, None);
|
||||||
|
test_for_type!(Option::<f64>, Some(-12.5 as f64), Some("-12.5"));
|
||||||
|
test_for_type!(Option::<f64>, None, None);
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// test_for_type!(Option::<Vec::<u8>>, None, None);
|
||||||
|
// test_for_type!(Option::<Vec::<u8>>, Some(vec![0]), Some("0"));
|
||||||
|
// test_for_type!(Option::<Vec::<String>>, None, None);
|
||||||
|
// test_for_type!(Option::<Vec::<String>>, Some(vec!["test".to_string()]), Some("test"));
|
||||||
|
|
||||||
|
test_for_attribute_type!(Option::<String>, Some("test".to_string()), Some("test"));
|
||||||
|
test_for_attribute_type!(Option::<String>, None, None);
|
||||||
|
test_for_attribute_type!(Option::<bool>, Some(true), Some("true"));
|
||||||
|
test_for_attribute_type!(Option::<bool>, None, None);
|
||||||
|
test_for_attribute_type!(Option::<u8>, Some(12 as u8), Some("12"));
|
||||||
|
test_for_attribute_type!(Option::<u8>, None, None);
|
||||||
|
test_for_attribute_type!(Option::<i8>, Some(12 as i8), Some("12"));
|
||||||
|
test_for_attribute_type!(Option::<i8>, Some(-12 as i8), Some("-12"));
|
||||||
|
test_for_attribute_type!(Option::<i8>, None, None);
|
||||||
|
test_for_attribute_type!(Option::<u16>, Some(12 as u16), Some("12"));
|
||||||
|
test_for_attribute_type!(Option::<u16>, None, None);
|
||||||
|
test_for_attribute_type!(Option::<i16>, Some(12 as i16), Some("12"));
|
||||||
|
test_for_attribute_type!(Option::<i16>, Some(-12 as i16), Some("-12"));
|
||||||
|
test_for_attribute_type!(Option::<i16>, None, None);
|
||||||
|
test_for_attribute_type!(Option::<u32>, Some(12 as u32), Some("12"));
|
||||||
|
test_for_attribute_type!(Option::<u32>, None, None);
|
||||||
|
test_for_attribute_type!(Option::<i32>, Some(12 as i32), Some("12"));
|
||||||
|
test_for_attribute_type!(Option::<i32>, Some(-12 as i32), Some("-12"));
|
||||||
|
test_for_attribute_type!(Option::<i32>, None, None);
|
||||||
|
test_for_attribute_type!(Option::<u64>, Some(12 as u64), Some("12"));
|
||||||
|
test_for_attribute_type!(Option::<u64>, None, None);
|
||||||
|
test_for_attribute_type!(Option::<i64>, Some(12 as i64), Some("12"));
|
||||||
|
test_for_attribute_type!(Option::<i64>, Some(-12 as i64), Some("-12"));
|
||||||
|
test_for_attribute_type!(Option::<i64>, None, None);
|
||||||
|
test_for_attribute_type!(Option::<f32>, Some(-12.5 as f32), Some("-12.5"));
|
||||||
|
test_for_attribute_type!(Option::<f32>, None, None);
|
||||||
|
test_for_attribute_type!(Option::<f64>, Some(-12.5 as f64), Some("-12.5"));
|
||||||
|
test_for_attribute_type!(Option::<f64>, None, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn option_struct() {
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
struct Test {
|
||||||
|
field: SubTest,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
struct SubTest {
|
||||||
|
content: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for SubTest {
|
||||||
|
fn default() -> Self {
|
||||||
|
SubTest { content: None }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test_for_type!(
|
||||||
|
Option::<Test>,
|
||||||
|
Some(Test {
|
||||||
|
field: SubTest {
|
||||||
|
content: Some("value".to_string())
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
Some("<field><content>value</content></field>")
|
||||||
|
);
|
||||||
|
test_for_type!(Option::<Test>, None, None);
|
||||||
|
}
|
||||||
@ -1,103 +0,0 @@
|
|||||||
#[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 ser_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 ser_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 ser_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 ser_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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,285 +0,0 @@
|
|||||||
#[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)
|
|
||||||
.split("\n")
|
|
||||||
.map(|s| s.trim())
|
|
||||||
.collect::<String>()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ser_enum() {
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(root = "base")]
|
|
||||||
pub struct XmlStruct {
|
|
||||||
color: Color,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(root = "color")]
|
|
||||||
pub enum Color {
|
|
||||||
White,
|
|
||||||
Black,
|
|
||||||
#[yaserde(rename = "custom")]
|
|
||||||
Custom {
|
|
||||||
enabled: String,
|
|
||||||
u8_value: u8,
|
|
||||||
i8_value: i8,
|
|
||||||
u16_value: u16,
|
|
||||||
i16_value: i16,
|
|
||||||
u32_value: u32,
|
|
||||||
i32_value: i32,
|
|
||||||
u64_value: u64,
|
|
||||||
i64_value: i64,
|
|
||||||
f32_value: f32,
|
|
||||||
f64_value: f64,
|
|
||||||
color: RGBColor,
|
|
||||||
alpha: Alpha,
|
|
||||||
alphas: Vec<Alpha>,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Color {
|
|
||||||
fn default() -> Color {
|
|
||||||
Color::White
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(Color::default(), Color::White);
|
|
||||||
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
|
||||||
pub struct RGBColor {
|
|
||||||
red: String,
|
|
||||||
green: String,
|
|
||||||
blue: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
|
||||||
pub enum Alpha {
|
|
||||||
Transparent,
|
|
||||||
Opaque,
|
|
||||||
}
|
|
||||||
|
|
||||||
let model = XmlStruct {
|
|
||||||
color: Color::Black,
|
|
||||||
};
|
|
||||||
|
|
||||||
let content = r#"<?xml version="1.0" encoding="utf-8"?><base><color>Black</color></base>"#;
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
|
|
||||||
let model = XmlStruct {
|
|
||||||
color: Color::Custom {
|
|
||||||
enabled: "true".to_string(),
|
|
||||||
u8_value: 8,
|
|
||||||
i8_value: -8,
|
|
||||||
u16_value: 16,
|
|
||||||
i16_value: -16,
|
|
||||||
u32_value: 32,
|
|
||||||
i32_value: -32,
|
|
||||||
u64_value: 64,
|
|
||||||
i64_value: -64,
|
|
||||||
f32_value: 32.0,
|
|
||||||
f64_value: 64.0,
|
|
||||||
color: RGBColor {
|
|
||||||
red: "0".to_string(),
|
|
||||||
green: "128".to_string(),
|
|
||||||
blue: "255".to_string(),
|
|
||||||
},
|
|
||||||
alpha: Alpha::Opaque,
|
|
||||||
alphas: vec![Alpha::Opaque, Alpha::Transparent],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let content = r#"<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<base>
|
|
||||||
<color><enabled>true</enabled>
|
|
||||||
<u8_value>8</u8_value>
|
|
||||||
<i8_value>-8</i8_value>
|
|
||||||
<u16_value>16</u16_value>
|
|
||||||
<i16_value>-16</i16_value>
|
|
||||||
<u32_value>32</u32_value>
|
|
||||||
<i32_value>-32</i32_value>
|
|
||||||
<u64_value>64</u64_value>
|
|
||||||
<i64_value>-64</i64_value>
|
|
||||||
<f32_value>32</f32_value>
|
|
||||||
<f64_value>64</f64_value>
|
|
||||||
<color><red>0</red><green>128</green><blue>255</blue></color>
|
|
||||||
<alpha>Opaque</alpha>
|
|
||||||
<alphas>Opaque</alphas>
|
|
||||||
<alphas>Transparent</alphas>
|
|
||||||
</color>
|
|
||||||
</base>"#;
|
|
||||||
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ser_attribute_enum() {
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(root = "base")]
|
|
||||||
pub struct XmlStruct {
|
|
||||||
#[yaserde(attribute)]
|
|
||||||
color: Color,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(root = "color")]
|
|
||||||
pub enum Color {
|
|
||||||
#[yaserde(rename = "pink")]
|
|
||||||
Pink,
|
|
||||||
}
|
|
||||||
|
|
||||||
let model = XmlStruct { color: Color::Pink };
|
|
||||||
|
|
||||||
let content = r#"<?xml version="1.0" encoding="utf-8"?><base color="pink" />"#;
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ser_unnamed_enum() {
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(root = "base")]
|
|
||||||
pub struct XmlStruct {
|
|
||||||
color: Enum,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug, Default)]
|
|
||||||
pub struct OtherStruct {
|
|
||||||
fi: i32,
|
|
||||||
se: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
|
||||||
pub enum Enum {
|
|
||||||
Simple,
|
|
||||||
Field(String),
|
|
||||||
FullPath(std::string::String),
|
|
||||||
Integer(i32),
|
|
||||||
UserStruct(OtherStruct),
|
|
||||||
OptionString(Option<String>),
|
|
||||||
OptionUserStruct(Option<OtherStruct>),
|
|
||||||
Strings(Vec<String>),
|
|
||||||
Ints(Vec<i32>),
|
|
||||||
Structs(Vec<OtherStruct>),
|
|
||||||
#[yaserde(rename = "renamed")]
|
|
||||||
ToRename(u32),
|
|
||||||
#[yaserde(rename = "renamed.with.dots")]
|
|
||||||
ToRenameDots(u32),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Enum {
|
|
||||||
fn default() -> Enum {
|
|
||||||
Enum::Simple
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let model = XmlStruct {
|
|
||||||
color: Enum::Field(String::from("some_text")),
|
|
||||||
};
|
|
||||||
|
|
||||||
let content =
|
|
||||||
r#"<?xml version="1.0" encoding="utf-8"?><base><color><Field>some_text</Field></color></base>"#;
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
|
|
||||||
let model = XmlStruct {
|
|
||||||
color: Enum::FullPath(String::from("some_text")),
|
|
||||||
};
|
|
||||||
|
|
||||||
let content = r#"<?xml version="1.0" encoding="utf-8"?><base><color><FullPath>some_text</FullPath></color></base>"#;
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
|
|
||||||
let model = XmlStruct {
|
|
||||||
color: Enum::Integer(56),
|
|
||||||
};
|
|
||||||
|
|
||||||
let content =
|
|
||||||
r#"<?xml version="1.0" encoding="utf-8"?><base><color><Integer>56</Integer></color></base>"#;
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
|
|
||||||
let model = XmlStruct {
|
|
||||||
color: Enum::UserStruct(OtherStruct { fi: 24, se: 42 }),
|
|
||||||
};
|
|
||||||
|
|
||||||
let content = r#"<?xml version="1.0" encoding="utf-8"?><base><color><UserStruct><fi>24</fi><se>42</se></UserStruct></color></base>"#;
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
|
|
||||||
let model = XmlStruct {
|
|
||||||
color: Enum::OptionString(Some(String::from("some_text"))),
|
|
||||||
};
|
|
||||||
|
|
||||||
let content = r#"<?xml version="1.0" encoding="utf-8"?><base><color><OptionString>some_text</OptionString></color></base>"#;
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
|
|
||||||
let model = XmlStruct {
|
|
||||||
color: Enum::OptionString(None),
|
|
||||||
};
|
|
||||||
|
|
||||||
let content = r#"<?xml version="1.0" encoding="utf-8"?><base><color /></base>"#;
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
|
|
||||||
let model = XmlStruct {
|
|
||||||
color: Enum::OptionUserStruct(Some(OtherStruct { fi: 12, se: 23 })),
|
|
||||||
};
|
|
||||||
|
|
||||||
let content = r#"<?xml version="1.0" encoding="utf-8"?><base><color><OptionUserStruct><fi>12</fi><se>23</se></OptionUserStruct></color></base>"#;
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
|
|
||||||
let model = XmlStruct {
|
|
||||||
color: Enum::OptionUserStruct(None),
|
|
||||||
};
|
|
||||||
|
|
||||||
let content = r#"<?xml version="1.0" encoding="utf-8"?><base><color /></base>"#;
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
|
|
||||||
let model = XmlStruct {
|
|
||||||
color: Enum::Strings(vec![String::from("abc"), String::from("def")]),
|
|
||||||
};
|
|
||||||
|
|
||||||
let content = r#"<?xml version="1.0" encoding="utf-8"?><base><color><Strings>abc</Strings><Strings>def</Strings></color></base>"#;
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
|
|
||||||
let model = XmlStruct {
|
|
||||||
color: Enum::Ints(vec![23, 45]),
|
|
||||||
};
|
|
||||||
|
|
||||||
let content = r#"<?xml version="1.0" encoding="utf-8"?><base><color><Ints>23</Ints><Ints>45</Ints></color></base>"#;
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
|
|
||||||
let model = XmlStruct {
|
|
||||||
color: Enum::Structs(vec![
|
|
||||||
OtherStruct { fi: 12, se: 23 },
|
|
||||||
OtherStruct { fi: 34, se: 45 },
|
|
||||||
]),
|
|
||||||
};
|
|
||||||
|
|
||||||
let content = r#"<?xml version="1.0" encoding="utf-8"?><base><color><Structs><fi>12</fi><se>23</se></Structs><Structs><fi>34</fi><se>45</se></Structs></color></base>"#;
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
|
|
||||||
let model = XmlStruct {
|
|
||||||
color: Enum::ToRename(87),
|
|
||||||
};
|
|
||||||
|
|
||||||
let content =
|
|
||||||
r#"<?xml version="1.0" encoding="utf-8"?><base><color><renamed>87</renamed></color></base>"#;
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
|
|
||||||
let model = XmlStruct {
|
|
||||||
color: Enum::ToRenameDots(84),
|
|
||||||
};
|
|
||||||
|
|
||||||
let content = r#"<?xml version="1.0" encoding="utf-8"?><base><color><renamed.with.dots>84</renamed.with.dots></color></base>"#;
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
}
|
|
||||||
@ -1,235 +0,0 @@
|
|||||||
#[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)
|
|
||||||
.split("\n")
|
|
||||||
.map(|s| s.trim())
|
|
||||||
.collect::<String>()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ser_struct_namespace() {
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(
|
|
||||||
root = "root",
|
|
||||||
prefix = "ns",
|
|
||||||
namespace = "ns: http://www.sample.com/ns/domain"
|
|
||||||
)]
|
|
||||||
pub struct XmlStruct {
|
|
||||||
#[yaserde(prefix = "ns")]
|
|
||||||
item: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
let model = XmlStruct {
|
|
||||||
item: "something".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><ns:root xmlns:ns=\"http://www.sample.com/ns/domain\"><ns:item>something</ns:item></ns:root>";
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ser_enum_namespace() {
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(
|
|
||||||
root = "root",
|
|
||||||
prefix = "ns",
|
|
||||||
namespace = "ns: http://www.sample.com/ns/domain"
|
|
||||||
)]
|
|
||||||
pub enum XmlStruct {
|
|
||||||
#[yaserde(prefix = "ns")]
|
|
||||||
Item,
|
|
||||||
#[yaserde(prefix = "ns")]
|
|
||||||
ItemWithField(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
let model = XmlStruct::Item;
|
|
||||||
|
|
||||||
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><ns:root xmlns:ns=\"http://www.sample.com/ns/domain\">ns:Item</ns:root>";
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
|
|
||||||
let model = XmlStruct::ItemWithField("Value".to_string());
|
|
||||||
|
|
||||||
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><ns:root xmlns:ns=\"http://www.sample.com/ns/domain\"><ns:ItemWithField>Value</ns:ItemWithField></ns:root>";
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ser_struct_multi_namespace() {
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(
|
|
||||||
root = "root",
|
|
||||||
namespace = "ns1: http://www.sample.com/ns/domain1",
|
|
||||||
namespace = "ns2: http://www.sample.com/ns/domain2"
|
|
||||||
)]
|
|
||||||
pub struct XmlStruct {
|
|
||||||
#[yaserde(prefix = "ns1")]
|
|
||||||
item_1: String,
|
|
||||||
#[yaserde(prefix = "ns2")]
|
|
||||||
item_2: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
let model = XmlStruct {
|
|
||||||
item_1: "something 1".to_string(),
|
|
||||||
item_2: "something 2".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><root xmlns:ns1=\"http://www.sample.com/ns/domain1\" xmlns:ns2=\"http://www.sample.com/ns/domain2\"><ns1:item_1>something 1</ns1:item_1><ns2:item_2>something 2</ns2:item_2></root>";
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ser_enum_multi_namespace() {
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(
|
|
||||||
root = "root",
|
|
||||||
namespace = "ns1: http://www.sample.com/ns/domain1",
|
|
||||||
namespace = "ns2: http://www.sample.com/ns/domain2"
|
|
||||||
)]
|
|
||||||
pub enum XmlStruct {
|
|
||||||
#[yaserde(prefix = "ns1")]
|
|
||||||
Item1,
|
|
||||||
#[yaserde(prefix = "ns2")]
|
|
||||||
Item2,
|
|
||||||
}
|
|
||||||
|
|
||||||
let model1 = XmlStruct::Item1;
|
|
||||||
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><root xmlns:ns1=\"http://www.sample.com/ns/domain1\" xmlns:ns2=\"http://www.sample.com/ns/domain2\">ns1:Item1</root>";
|
|
||||||
convert_and_validate!(model1, content);
|
|
||||||
let model2 = XmlStruct::Item2;
|
|
||||||
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><root xmlns:ns1=\"http://www.sample.com/ns/domain1\" xmlns:ns2=\"http://www.sample.com/ns/domain2\">ns2:Item2</root>";
|
|
||||||
convert_and_validate!(model2, content);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ser_struct_attribute_namespace() {
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(
|
|
||||||
root = "root",
|
|
||||||
namespace = "ns1: http://www.sample.com/ns/domain1",
|
|
||||||
namespace = "ns2: http://www.sample.com/ns/domain2"
|
|
||||||
)]
|
|
||||||
pub struct XmlStruct {
|
|
||||||
#[yaserde(prefix = "ns1")]
|
|
||||||
item_1: String,
|
|
||||||
#[yaserde(attribute, prefix = "ns2")]
|
|
||||||
item_2: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
let model = XmlStruct {
|
|
||||||
item_1: "something 1".to_string(),
|
|
||||||
item_2: "something 2".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><root xmlns:ns1=\"http://www.sample.com/ns/domain1\" xmlns:ns2=\"http://www.sample.com/ns/domain2\" ns2:item_2=\"something 2\"><ns1:item_1>something 1</ns1:item_1></root>";
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ser_struct_default_namespace() {
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(
|
|
||||||
root = "tt",
|
|
||||||
namespace = "http://www.w3.org/ns/ttml",
|
|
||||||
namespace = "ttm: http://www.w3.org/ns/ttml#metadata"
|
|
||||||
)]
|
|
||||||
pub struct XmlStruct {
|
|
||||||
item: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
let model = XmlStruct {
|
|
||||||
item: "something".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><tt xmlns=\"http://www.w3.org/ns/ttml\" xmlns:ttm=\"http://www.w3.org/ns/ttml#metadata\"><item>something</item></tt>";
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ser_struct_default_namespace_via_attribute() {
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(
|
|
||||||
root = "tt",
|
|
||||||
default_namespace = "ttml",
|
|
||||||
namespace = "ttml: http://www.w3.org/ns/ttml",
|
|
||||||
namespace = "ttm: http://www.w3.org/ns/ttml#metadata"
|
|
||||||
)]
|
|
||||||
pub struct XmlStruct {
|
|
||||||
item: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
let model = XmlStruct {
|
|
||||||
item: "something".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><tt xmlns=\"http://www.w3.org/ns/ttml\" xmlns:ttm=\"http://www.w3.org/ns/ttml#metadata\"><item>something</item></tt>";
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ser_struct_default_namespace_via_attribute_with_prefix() {
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(
|
|
||||||
root = "tt",
|
|
||||||
prefix = "TTML",
|
|
||||||
default_namespace = "TTML",
|
|
||||||
namespace = "TTML: http://www.w3.org/ns/ttml",
|
|
||||||
namespace = "ttm: http://www.w3.org/ns/ttml#metadata"
|
|
||||||
)]
|
|
||||||
pub struct XmlStruct {
|
|
||||||
#[yaserde(prefix = "TTML")]
|
|
||||||
item: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
let model = XmlStruct {
|
|
||||||
item: "something".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><tt xmlns=\"http://www.w3.org/ns/ttml\" xmlns:ttm=\"http://www.w3.org/ns/ttml#metadata\"><item>something</item></tt>";
|
|
||||||
convert_and_validate!(model, content);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ser_struct_namespace_nested() {
|
|
||||||
#[derive(YaSerialize, Default, PartialEq, Debug)]
|
|
||||||
#[yaserde(prefix = "nsa", namespace = "nsa: http://www.sample.com/ns/a")]
|
|
||||||
struct A {
|
|
||||||
#[yaserde(prefix = "nsa")]
|
|
||||||
alpha: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(YaSerialize, Default, PartialEq, Debug)]
|
|
||||||
#[yaserde(prefix = "nsb", namespace = "nsb: http://www.sample.com/ns/b")]
|
|
||||||
struct B {
|
|
||||||
// Note that name `nested` resides in `nsb` though it has a type from `nsa`
|
|
||||||
#[yaserde(prefix = "nsb")]
|
|
||||||
nested: A,
|
|
||||||
}
|
|
||||||
|
|
||||||
convert_and_validate!(
|
|
||||||
B {
|
|
||||||
nested: A { alpha: 32 }
|
|
||||||
},
|
|
||||||
r#"
|
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<nsb:B xmlns:nsb="http://www.sample.com/ns/b">
|
|
||||||
<nsb:nested xmlns:nsa="http://www.sample.com/ns/a">
|
|
||||||
<nsa:alpha>32</nsa:alpha>
|
|
||||||
</nsb:nested>
|
|
||||||
</nsb:B>
|
|
||||||
"#
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,147 +0,0 @@
|
|||||||
#[macro_use]
|
|
||||||
extern crate yaserde_derive;
|
|
||||||
|
|
||||||
use std::io::Write;
|
|
||||||
use yaserde::ser::to_string;
|
|
||||||
use yaserde::YaSerialize;
|
|
||||||
|
|
||||||
macro_rules! convert_and_validate {
|
|
||||||
($type: ty, $value: expr, $content: expr) => {{
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(root = "data")]
|
|
||||||
pub struct Data {
|
|
||||||
item: Option<$type>,
|
|
||||||
}
|
|
||||||
let model = Data { item: $value };
|
|
||||||
|
|
||||||
let data: Result<String, String> = to_string(&model);
|
|
||||||
|
|
||||||
let content = if let Some(str_value) = $content {
|
|
||||||
"<data><item>".to_string() + str_value + "</item></data>"
|
|
||||||
} else {
|
|
||||||
"<data />".to_string()
|
|
||||||
};
|
|
||||||
|
|
||||||
let content = String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?>") + &content;
|
|
||||||
assert_eq!(data, Ok(content));
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! convert_and_validate_as_attribute {
|
|
||||||
($type: ty, $value: expr, $content: expr) => {{
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(root = "data")]
|
|
||||||
pub struct Data {
|
|
||||||
#[yaserde(attribute)]
|
|
||||||
item: Option<$type>,
|
|
||||||
}
|
|
||||||
let model = Data { item: $value };
|
|
||||||
|
|
||||||
let data: Result<String, String> = to_string(&model);
|
|
||||||
|
|
||||||
let content = if let Some(str_value) = $content {
|
|
||||||
"<data item=\"".to_string() + str_value + "\" />"
|
|
||||||
} else {
|
|
||||||
"<data />".to_string()
|
|
||||||
};
|
|
||||||
|
|
||||||
let content = String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?>") + &content;
|
|
||||||
assert_eq!(data, Ok(content));
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ser_option() {
|
|
||||||
convert_and_validate!(String, Some("test".to_string()), Some("test"));
|
|
||||||
convert_and_validate!(String, None, None);
|
|
||||||
convert_and_validate!(bool, Some(true), Some("true"));
|
|
||||||
convert_and_validate!(bool, None, None);
|
|
||||||
convert_and_validate!(u8, Some(12 as u8), Some("12"));
|
|
||||||
convert_and_validate!(u8, None, None);
|
|
||||||
convert_and_validate!(i8, Some(12 as i8), Some("12"));
|
|
||||||
convert_and_validate!(i8, Some(-12 as i8), Some("-12"));
|
|
||||||
convert_and_validate!(i8, None, None);
|
|
||||||
convert_and_validate!(u16, Some(12 as u16), Some("12"));
|
|
||||||
convert_and_validate!(u16, None, None);
|
|
||||||
convert_and_validate!(i16, Some(12 as i16), Some("12"));
|
|
||||||
convert_and_validate!(i16, Some(-12 as i16), Some("-12"));
|
|
||||||
convert_and_validate!(i16, None, None);
|
|
||||||
convert_and_validate!(u32, Some(12 as u32), Some("12"));
|
|
||||||
convert_and_validate!(u32, None, None);
|
|
||||||
convert_and_validate!(i32, Some(12 as i32), Some("12"));
|
|
||||||
convert_and_validate!(i32, Some(-12 as i32), Some("-12"));
|
|
||||||
convert_and_validate!(i32, None, None);
|
|
||||||
convert_and_validate!(u64, Some(12 as u64), Some("12"));
|
|
||||||
convert_and_validate!(u64, None, None);
|
|
||||||
convert_and_validate!(i64, Some(12 as i64), Some("12"));
|
|
||||||
convert_and_validate!(i64, Some(-12 as i64), Some("-12"));
|
|
||||||
convert_and_validate!(i64, None, None);
|
|
||||||
convert_and_validate!(f32, Some(-12.5 as f32), Some("-12.5"));
|
|
||||||
convert_and_validate!(f32, None, None);
|
|
||||||
convert_and_validate!(f64, Some(-12.5 as f64), Some("-12.5"));
|
|
||||||
convert_and_validate!(f64, None, None);
|
|
||||||
|
|
||||||
convert_and_validate!(Vec<u8>, None, None);
|
|
||||||
convert_and_validate!(Vec<u8>, Some(vec![0]), Some("0"));
|
|
||||||
convert_and_validate!(Vec<String>, None, None);
|
|
||||||
convert_and_validate!(Vec<String>, Some(vec!["test".to_string()]), Some("test"));
|
|
||||||
|
|
||||||
convert_and_validate_as_attribute!(String, Some("test".to_string()), Some("test"));
|
|
||||||
convert_and_validate_as_attribute!(String, None, None);
|
|
||||||
convert_and_validate_as_attribute!(bool, Some(true), Some("true"));
|
|
||||||
convert_and_validate_as_attribute!(bool, None, None);
|
|
||||||
convert_and_validate_as_attribute!(u8, Some(12 as u8), Some("12"));
|
|
||||||
convert_and_validate_as_attribute!(u8, None, None);
|
|
||||||
convert_and_validate_as_attribute!(i8, Some(12 as i8), Some("12"));
|
|
||||||
convert_and_validate_as_attribute!(i8, Some(-12 as i8), Some("-12"));
|
|
||||||
convert_and_validate_as_attribute!(i8, None, None);
|
|
||||||
convert_and_validate_as_attribute!(u16, Some(12 as u16), Some("12"));
|
|
||||||
convert_and_validate_as_attribute!(u16, None, None);
|
|
||||||
convert_and_validate_as_attribute!(i16, Some(12 as i16), Some("12"));
|
|
||||||
convert_and_validate_as_attribute!(i16, Some(-12 as i16), Some("-12"));
|
|
||||||
convert_and_validate_as_attribute!(i16, None, None);
|
|
||||||
convert_and_validate_as_attribute!(u32, Some(12 as u32), Some("12"));
|
|
||||||
convert_and_validate_as_attribute!(u32, None, None);
|
|
||||||
convert_and_validate_as_attribute!(i32, Some(12 as i32), Some("12"));
|
|
||||||
convert_and_validate_as_attribute!(i32, Some(-12 as i32), Some("-12"));
|
|
||||||
convert_and_validate_as_attribute!(i32, None, None);
|
|
||||||
convert_and_validate_as_attribute!(u64, Some(12 as u64), Some("12"));
|
|
||||||
convert_and_validate_as_attribute!(u64, None, None);
|
|
||||||
convert_and_validate_as_attribute!(i64, Some(12 as i64), Some("12"));
|
|
||||||
convert_and_validate_as_attribute!(i64, Some(-12 as i64), Some("-12"));
|
|
||||||
convert_and_validate_as_attribute!(i64, None, None);
|
|
||||||
convert_and_validate_as_attribute!(f32, Some(-12.5 as f32), Some("-12.5"));
|
|
||||||
convert_and_validate_as_attribute!(f32, None, None);
|
|
||||||
convert_and_validate_as_attribute!(f64, Some(-12.5 as f64), Some("-12.5"));
|
|
||||||
convert_and_validate_as_attribute!(f64, None, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn de_option_struct() {
|
|
||||||
#[derive(YaSerialize, Debug, PartialEq)]
|
|
||||||
struct Test {
|
|
||||||
field: SubTest,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(YaSerialize, Debug, PartialEq)]
|
|
||||||
struct SubTest {
|
|
||||||
content: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for SubTest {
|
|
||||||
fn default() -> Self {
|
|
||||||
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, None, None);
|
|
||||||
}
|
|
||||||
@ -1,83 +0,0 @@
|
|||||||
#[macro_use]
|
|
||||||
extern crate yaserde_derive;
|
|
||||||
|
|
||||||
use std::io::Write;
|
|
||||||
use yaserde::ser::to_string;
|
|
||||||
use yaserde::YaSerialize;
|
|
||||||
|
|
||||||
macro_rules! convert_and_validate {
|
|
||||||
($type: ty, $value: expr, $content: expr) => {{
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(root = "data")]
|
|
||||||
pub struct Data {
|
|
||||||
item: $type,
|
|
||||||
}
|
|
||||||
let model = Data { item: $value };
|
|
||||||
|
|
||||||
let data: Result<String, String> = to_string(&model);
|
|
||||||
let content = if $content == "" {
|
|
||||||
String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?><data />")
|
|
||||||
} else {
|
|
||||||
String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?><data><item>")
|
|
||||||
+ $content
|
|
||||||
+ "</item></data>"
|
|
||||||
};
|
|
||||||
assert_eq!(data, Ok(content));
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! convert_and_validate_as_attribute {
|
|
||||||
($type: ty, $value: expr, $content: expr) => {{
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
|
||||||
#[yaserde(root = "data")]
|
|
||||||
pub struct Data {
|
|
||||||
#[yaserde(attribute)]
|
|
||||||
item: $type,
|
|
||||||
}
|
|
||||||
let model = Data { item: $value };
|
|
||||||
|
|
||||||
let data: Result<String, String> = to_string(&model);
|
|
||||||
let content =
|
|
||||||
String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?><data item=\"") + $content + "\" />";
|
|
||||||
assert_eq!(data, Ok(content));
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ser_type() {
|
|
||||||
convert_and_validate!(String, "test".to_string(), "test");
|
|
||||||
convert_and_validate!(bool, true, "true");
|
|
||||||
convert_and_validate!(u8, 12 as u8, "12");
|
|
||||||
convert_and_validate!(i8, 12 as i8, "12");
|
|
||||||
convert_and_validate!(i8, -12 as i8, "-12");
|
|
||||||
convert_and_validate!(u16, 12 as u16, "12");
|
|
||||||
convert_and_validate!(i16, 12 as i16, "12");
|
|
||||||
convert_and_validate!(i16, -12 as i16, "-12");
|
|
||||||
convert_and_validate!(u32, 12 as u32, "12");
|
|
||||||
convert_and_validate!(i32, 12 as i32, "12");
|
|
||||||
convert_and_validate!(i32, -12 as i32, "-12");
|
|
||||||
convert_and_validate!(u64, 12 as u64, "12");
|
|
||||||
convert_and_validate!(i64, 12 as i64, "12");
|
|
||||||
convert_and_validate!(i64, -12 as i64, "-12");
|
|
||||||
convert_and_validate!(f32, -12.5 as f32, "-12.5");
|
|
||||||
convert_and_validate!(f64, -12.5 as f64, "-12.5");
|
|
||||||
convert_and_validate!(Vec<String>, vec![], "");
|
|
||||||
convert_and_validate!(Vec<String>, vec!["test".to_string()], "test");
|
|
||||||
|
|
||||||
convert_and_validate_as_attribute!(String, "test".to_string(), "test");
|
|
||||||
convert_and_validate_as_attribute!(bool, true, "true");
|
|
||||||
convert_and_validate_as_attribute!(u8, 12 as u8, "12");
|
|
||||||
convert_and_validate_as_attribute!(i8, 12 as i8, "12");
|
|
||||||
convert_and_validate_as_attribute!(i8, -12 as i8, "-12");
|
|
||||||
convert_and_validate_as_attribute!(u16, 12 as u16, "12");
|
|
||||||
convert_and_validate_as_attribute!(i16, 12 as i16, "12");
|
|
||||||
convert_and_validate_as_attribute!(i16, -12 as i16, "-12");
|
|
||||||
convert_and_validate_as_attribute!(u32, 12 as u32, "12");
|
|
||||||
convert_and_validate_as_attribute!(i32, 12 as i32, "12");
|
|
||||||
convert_and_validate_as_attribute!(i32, -12 as i32, "-12");
|
|
||||||
convert_and_validate_as_attribute!(u64, 12 as u64, "12");
|
|
||||||
convert_and_validate_as_attribute!(i64, 12 as i64, "12");
|
|
||||||
convert_and_validate_as_attribute!(i64, -12 as i64, "-12");
|
|
||||||
convert_and_validate_as_attribute!(f32, -12.5 as f32, "-12.5");
|
|
||||||
convert_and_validate_as_attribute!(f64, -12.5 as f64, "-12.5");
|
|
||||||
}
|
|
||||||
@ -1,29 +1,15 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
extern crate yaserde;
|
||||||
|
#[macro_use]
|
||||||
extern crate yaserde_derive;
|
extern crate yaserde_derive;
|
||||||
|
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use yaserde::ser::to_string;
|
|
||||||
use yaserde::YaSerialize;
|
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)
|
|
||||||
.split("\n")
|
|
||||||
.map(|s| s.trim())
|
|
||||||
.collect::<String>()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ser_basic() {
|
fn ser_basic() {
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
#[derive(YaSerialize, PartialEq, Debug)]
|
||||||
#[yaserde(root = "base")]
|
#[yaserde(rename = "base")]
|
||||||
pub struct XmlStruct {
|
pub struct XmlStruct {
|
||||||
item: String,
|
item: String,
|
||||||
}
|
}
|
||||||
@ -32,14 +18,14 @@ fn ser_basic() {
|
|||||||
item: "something".to_string(),
|
item: "something".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base><item>something</item></base>";
|
let content = "<base><item>something</item></base>";
|
||||||
convert_and_validate!(model, content);
|
serialize_and_validate!(model, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ser_list_of_items() {
|
fn ser_list_of_items() {
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
#[derive(YaSerialize, PartialEq, Debug)]
|
||||||
#[yaserde(root = "base")]
|
#[yaserde(rename = "base")]
|
||||||
pub struct XmlStruct {
|
pub struct XmlStruct {
|
||||||
items: Vec<String>,
|
items: Vec<String>,
|
||||||
}
|
}
|
||||||
@ -48,17 +34,17 @@ fn ser_list_of_items() {
|
|||||||
items: vec!["something1".to_string(), "something2".to_string()],
|
items: vec!["something1".to_string(), "something2".to_string()],
|
||||||
};
|
};
|
||||||
|
|
||||||
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base><items>something1</items><items>something2</items></base>";
|
let content = "<base><items>something1</items><items>something2</items></base>";
|
||||||
convert_and_validate!(model, content);
|
serialize_and_validate!(model, content);
|
||||||
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
#[derive(YaSerialize, PartialEq, Debug)]
|
||||||
#[yaserde(root = "base")]
|
#[yaserde(rename = "base")]
|
||||||
pub struct XmlStructOfStruct {
|
pub struct XmlStructOfStruct {
|
||||||
items: Vec<SubStruct>,
|
items: Vec<SubStruct>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
#[derive(YaSerialize, PartialEq, Debug)]
|
||||||
#[yaserde(root = "items")]
|
#[yaserde(rename = "items")]
|
||||||
pub struct SubStruct {
|
pub struct SubStruct {
|
||||||
field: String,
|
field: String,
|
||||||
}
|
}
|
||||||
@ -74,14 +60,15 @@ fn ser_list_of_items() {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base><items><field>something1</field></items><items><field>something2</field></items></base>";
|
let content =
|
||||||
convert_and_validate!(model2, content);
|
"<base><items><field>something1</field></items><items><field>something2</field></items></base>";
|
||||||
|
serialize_and_validate!(model2, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ser_attributes() {
|
fn ser_attributes() {
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
#[derive(YaSerialize, PartialEq, Debug)]
|
||||||
#[yaserde(root = "base")]
|
#[yaserde(rename = "base")]
|
||||||
pub struct XmlStruct {
|
pub struct XmlStruct {
|
||||||
#[yaserde(attribute)]
|
#[yaserde(attribute)]
|
||||||
item: String,
|
item: String,
|
||||||
@ -89,7 +76,7 @@ fn ser_attributes() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
#[derive(YaSerialize, PartialEq, Debug)]
|
||||||
#[yaserde(root = "sub")]
|
#[yaserde(rename = "sub")]
|
||||||
pub struct SubStruct {
|
pub struct SubStruct {
|
||||||
#[yaserde(attribute)]
|
#[yaserde(attribute)]
|
||||||
subitem: String,
|
subitem: String,
|
||||||
@ -117,8 +104,8 @@ fn ser_attributes() {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base item=\"something\"><sub subitem=\"sub-something\" /></base>";
|
let content = r#"<base item="something"><sub subitem="sub-something" /></base>"#;
|
||||||
convert_and_validate!(model, content);
|
serialize_and_validate!(model, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -158,24 +145,20 @@ fn ser_attributes_complex() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
convert_and_validate!(
|
serialize_and_validate!(
|
||||||
Struct {
|
Struct {
|
||||||
attr_option_string: None,
|
attr_option_string: None,
|
||||||
attr_option_enum: None,
|
attr_option_enum: None,
|
||||||
},
|
},
|
||||||
r#"
|
"<Struct />"
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Struct />
|
|
||||||
"#
|
|
||||||
);
|
);
|
||||||
|
|
||||||
convert_and_validate!(
|
serialize_and_validate!(
|
||||||
Struct {
|
Struct {
|
||||||
attr_option_string: Some("some value".to_string()),
|
attr_option_string: Some("some value".to_string()),
|
||||||
attr_option_enum: Some(other_mod::AttrEnum::Variant2),
|
attr_option_enum: Some(other_mod::AttrEnum::Variant2),
|
||||||
},
|
},
|
||||||
r#"
|
r#"
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Struct attr_option_string="some value" attr_option_enum="variant 2" />
|
<Struct attr_option_string="some value" attr_option_enum="variant 2" />
|
||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
@ -184,7 +167,7 @@ fn ser_attributes_complex() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn ser_rename() {
|
fn ser_rename() {
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
#[derive(YaSerialize, PartialEq, Debug)]
|
||||||
#[yaserde(root = "base")]
|
#[yaserde(rename = "base")]
|
||||||
pub struct XmlStruct {
|
pub struct XmlStruct {
|
||||||
#[yaserde(attribute, rename = "Item")]
|
#[yaserde(attribute, rename = "Item")]
|
||||||
item: String,
|
item: String,
|
||||||
@ -195,7 +178,7 @@ fn ser_rename() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
#[derive(YaSerialize, PartialEq, Debug)]
|
||||||
#[yaserde(root = "sub")]
|
#[yaserde(rename = "sub")]
|
||||||
pub struct SubStruct {
|
pub struct SubStruct {
|
||||||
#[yaserde(attribute, rename = "sub_item")]
|
#[yaserde(attribute, rename = "sub_item")]
|
||||||
subitem: String,
|
subitem: String,
|
||||||
@ -224,14 +207,14 @@ fn ser_rename() {
|
|||||||
version: "2.0.2".into(),
|
version: "2.0.2".into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base Item=\"something\"><sub sub_item=\"sub_something\" /><maj.min.bug>2.0.2</maj.min.bug></base>";
|
let content = r#"<base Item="something"><sub sub_item="sub_something" /><maj.min.bug>2.0.2</maj.min.bug></base>"#;
|
||||||
convert_and_validate!(model, content);
|
serialize_and_validate!(model, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ser_text_content_with_attributes() {
|
fn ser_text_content_with_attributes() {
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
#[derive(YaSerialize, PartialEq, Debug)]
|
||||||
#[yaserde(root = "base")]
|
#[yaserde(rename = "base")]
|
||||||
pub struct XmlStruct {
|
pub struct XmlStruct {
|
||||||
#[yaserde(attribute, rename = "Item")]
|
#[yaserde(attribute, rename = "Item")]
|
||||||
item: String,
|
item: String,
|
||||||
@ -240,7 +223,7 @@ fn ser_text_content_with_attributes() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
#[derive(YaSerialize, PartialEq, Debug)]
|
||||||
#[yaserde(root = "sub")]
|
#[yaserde(rename = "sub")]
|
||||||
pub struct SubStruct {
|
pub struct SubStruct {
|
||||||
#[yaserde(attribute, rename = "sub_item")]
|
#[yaserde(attribute, rename = "sub_item")]
|
||||||
subitem: String,
|
subitem: String,
|
||||||
@ -273,14 +256,14 @@ fn ser_text_content_with_attributes() {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base Item=\"something\"><sub sub_item=\"sub_something\">text_content</sub></base>";
|
let content = r#"<base Item="something"><sub sub_item="sub_something">text_content</sub></base>"#;
|
||||||
convert_and_validate!(model, content);
|
serialize_and_validate!(model, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ser_name_issue_21() {
|
fn ser_name_issue_21() {
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
#[derive(YaSerialize, PartialEq, Debug)]
|
||||||
#[yaserde(root = "base")]
|
#[yaserde(rename = "base")]
|
||||||
pub struct XmlStruct {
|
pub struct XmlStruct {
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
@ -289,8 +272,8 @@ fn ser_name_issue_21() {
|
|||||||
name: "something".to_string(),
|
name: "something".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base><name>something</name></base>";
|
let content = "<base><name>something</name></base>";
|
||||||
convert_and_validate!(model, content);
|
serialize_and_validate!(model, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -326,6 +309,6 @@ fn ser_custom() {
|
|||||||
month: 1,
|
month: 1,
|
||||||
day: Day { value: 5 },
|
day: Day { value: 5 },
|
||||||
};
|
};
|
||||||
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Date><Year>2020</Year><Month>1</Month><DoubleDay>10</DoubleDay></Date>";
|
let content = "<Date><Year>2020</Year><Month>1</Month><DoubleDay>10</DoubleDay></Date>";
|
||||||
convert_and_validate!(model, content);
|
serialize_and_validate!(model, content);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,30 +1,25 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
extern crate yaserde;
|
||||||
|
#[macro_use]
|
||||||
extern crate yaserde_derive;
|
extern crate yaserde_derive;
|
||||||
|
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use yaserde::ser::to_string;
|
|
||||||
use yaserde::YaSerialize;
|
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)
|
|
||||||
.split("\n")
|
|
||||||
.map(|s| s.trim())
|
|
||||||
.collect::<String>()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ser_skip_serializing_if_for_struct() {
|
fn skip_serializing_if_for_struct() {
|
||||||
|
fn default_string_function() -> String {
|
||||||
|
"mask_default".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(YaSerialize, PartialEq, Debug)]
|
#[derive(YaSerialize, PartialEq, Debug)]
|
||||||
#[yaserde(root = "base")]
|
#[yaserde(rename = "base")]
|
||||||
pub struct XmlStruct {
|
pub struct XmlStruct {
|
||||||
|
#[yaserde(
|
||||||
|
skip_serializing_if = "check_string_function",
|
||||||
|
default = "default_string_function"
|
||||||
|
)]
|
||||||
|
string_with_default_item: String,
|
||||||
#[yaserde(skip_serializing_if = "check_string_function")]
|
#[yaserde(skip_serializing_if = "check_string_function")]
|
||||||
string_item: String,
|
string_item: String,
|
||||||
#[yaserde(skip_serializing_if = "check_bool_function")]
|
#[yaserde(skip_serializing_if = "check_bool_function")]
|
||||||
@ -54,12 +49,13 @@ fn ser_skip_serializing_if_for_struct() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let model = XmlStruct {
|
let model = XmlStruct {
|
||||||
|
string_with_default_item: "mask_default".to_string(),
|
||||||
string_item: "something".to_string(),
|
string_item: "something".to_string(),
|
||||||
bool_item: true,
|
bool_item: true,
|
||||||
f32_item: 0.0,
|
f32_item: 0.0,
|
||||||
option_string_item: Some("something".to_string()),
|
option_string_item: Some("something".to_string()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base />";
|
let content = "<base />";
|
||||||
convert_and_validate!(model, content);
|
serialize_and_validate!(model, content);
|
||||||
}
|
}
|
||||||
46
yaserde/tests/types.rs
Normal file
46
yaserde/tests/types.rs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#[macro_use]
|
||||||
|
extern crate yaserde;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate yaserde_derive;
|
||||||
|
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use yaserde::{YaDeserialize, YaSerialize};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ser_type() {
|
||||||
|
test_for_type!(String, "test".to_string(), Some("test"));
|
||||||
|
test_for_type!(bool, true, Some("true"));
|
||||||
|
test_for_type!(u8, 12 as u8, Some("12"));
|
||||||
|
test_for_type!(i8, 12 as i8, Some("12"));
|
||||||
|
test_for_type!(i8, -12 as i8, Some("-12"));
|
||||||
|
test_for_type!(u16, 12 as u16, Some("12"));
|
||||||
|
test_for_type!(i16, 12 as i16, Some("12"));
|
||||||
|
test_for_type!(i16, -12 as i16, Some("-12"));
|
||||||
|
test_for_type!(u32, 12 as u32, Some("12"));
|
||||||
|
test_for_type!(i32, 12 as i32, Some("12"));
|
||||||
|
test_for_type!(i32, -12 as i32, Some("-12"));
|
||||||
|
test_for_type!(u64, 12 as u64, Some("12"));
|
||||||
|
test_for_type!(i64, 12 as i64, Some("12"));
|
||||||
|
test_for_type!(i64, -12 as i64, Some("-12"));
|
||||||
|
test_for_type!(f32, -12.5 as f32, Some("-12.5"));
|
||||||
|
test_for_type!(f64, -12.5 as f64, Some("-12.5"));
|
||||||
|
test_for_type!(Vec::<String>, vec![], None);
|
||||||
|
test_for_type!(Vec::<String>, vec!["test".to_string()], Some("test"));
|
||||||
|
|
||||||
|
test_for_attribute_type!(String, "test".to_string(), Some("test"));
|
||||||
|
test_for_attribute_type!(bool, true, Some("true"));
|
||||||
|
test_for_attribute_type!(u8, 12 as u8, Some("12"));
|
||||||
|
test_for_attribute_type!(i8, 12 as i8, Some("12"));
|
||||||
|
test_for_attribute_type!(i8, -12 as i8, Some("-12"));
|
||||||
|
test_for_attribute_type!(u16, 12 as u16, Some("12"));
|
||||||
|
test_for_attribute_type!(i16, 12 as i16, Some("12"));
|
||||||
|
test_for_attribute_type!(i16, -12 as i16, Some("-12"));
|
||||||
|
test_for_attribute_type!(u32, 12 as u32, Some("12"));
|
||||||
|
test_for_attribute_type!(i32, 12 as i32, Some("12"));
|
||||||
|
test_for_attribute_type!(i32, -12 as i32, Some("-12"));
|
||||||
|
test_for_attribute_type!(u64, 12 as u64, Some("12"));
|
||||||
|
test_for_attribute_type!(i64, 12 as i64, Some("12"));
|
||||||
|
test_for_attribute_type!(i64, -12 as i64, Some("-12"));
|
||||||
|
test_for_attribute_type!(f32, -12.5 as f32, Some("-12.5"));
|
||||||
|
test_for_attribute_type!(f64, -12.5 as f64, Some("-12.5"));
|
||||||
|
}
|
||||||
@ -1,6 +1,4 @@
|
|||||||
use proc_macro2::token_stream::IntoIter;
|
use proc_macro2::{token_stream::IntoIter, Delimiter, TokenStream, TokenTree};
|
||||||
use proc_macro2::Delimiter;
|
|
||||||
use proc_macro2::TokenTree;
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use syn::Attribute;
|
use syn::Attribute;
|
||||||
|
|
||||||
@ -12,7 +10,6 @@ pub struct YaSerdeAttribute {
|
|||||||
pub flatten: bool,
|
pub flatten: bool,
|
||||||
pub namespaces: BTreeMap<String, String>,
|
pub namespaces: BTreeMap<String, String>,
|
||||||
pub prefix: Option<String>,
|
pub prefix: Option<String>,
|
||||||
pub root: Option<String>,
|
|
||||||
pub rename: Option<String>,
|
pub rename: Option<String>,
|
||||||
pub skip_serializing_if: Option<String>,
|
pub skip_serializing_if: Option<String>,
|
||||||
pub text: bool,
|
pub text: bool,
|
||||||
@ -41,7 +38,6 @@ impl YaSerdeAttribute {
|
|||||||
let mut namespaces = BTreeMap::new();
|
let mut namespaces = BTreeMap::new();
|
||||||
let mut prefix = None;
|
let mut prefix = None;
|
||||||
let mut rename = None;
|
let mut rename = None;
|
||||||
let mut root = None;
|
|
||||||
let mut skip_serializing_if = None;
|
let mut skip_serializing_if = None;
|
||||||
let mut text = false;
|
let mut text = false;
|
||||||
|
|
||||||
@ -84,9 +80,6 @@ impl YaSerdeAttribute {
|
|||||||
"rename" => {
|
"rename" => {
|
||||||
rename = get_value(&mut attr_iter);
|
rename = get_value(&mut attr_iter);
|
||||||
}
|
}
|
||||||
"root" => {
|
|
||||||
root = get_value(&mut attr_iter);
|
|
||||||
}
|
|
||||||
"skip_serializing_if" => {
|
"skip_serializing_if" => {
|
||||||
skip_serializing_if = get_value(&mut attr_iter);
|
skip_serializing_if = get_value(&mut attr_iter);
|
||||||
}
|
}
|
||||||
@ -110,11 +103,49 @@ impl YaSerdeAttribute {
|
|||||||
namespaces,
|
namespaces,
|
||||||
prefix,
|
prefix,
|
||||||
rename,
|
rename,
|
||||||
root,
|
|
||||||
skip_serializing_if,
|
skip_serializing_if,
|
||||||
text,
|
text,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_namespace_matching(
|
||||||
|
&self,
|
||||||
|
prefix: &Option<String>,
|
||||||
|
element_namespace: TokenStream,
|
||||||
|
element_name: TokenStream,
|
||||||
|
take_root_prefix: bool,
|
||||||
|
) -> TokenStream {
|
||||||
|
let configured_prefix = if take_root_prefix {
|
||||||
|
self.prefix.clone()
|
||||||
|
} else {
|
||||||
|
prefix.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
let namespaces_matches: TokenStream = self
|
||||||
|
.namespaces
|
||||||
|
.iter()
|
||||||
|
.map(|(prefix, namespace)| {
|
||||||
|
if configured_prefix == Some(prefix.to_string()) {
|
||||||
|
Some(quote!(#namespace => {}))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter_map(|x| x)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
quote!(
|
||||||
|
if let Some(namespace) = #element_namespace {
|
||||||
|
match namespace.as_str() {
|
||||||
|
#namespaces_matches
|
||||||
|
bad_namespace => {
|
||||||
|
let msg = format!("bad namespace for {}, found {}", #element_name, bad_namespace);
|
||||||
|
return Err(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -130,7 +161,6 @@ fn parse_empty_attributes() {
|
|||||||
flatten: false,
|
flatten: false,
|
||||||
namespaces: BTreeMap::new(),
|
namespaces: BTreeMap::new(),
|
||||||
prefix: None,
|
prefix: None,
|
||||||
root: None,
|
|
||||||
rename: None,
|
rename: None,
|
||||||
skip_serializing_if: None,
|
skip_serializing_if: None,
|
||||||
text: false,
|
text: false,
|
||||||
@ -180,7 +210,6 @@ fn parse_attributes() {
|
|||||||
flatten: false,
|
flatten: false,
|
||||||
namespaces: BTreeMap::new(),
|
namespaces: BTreeMap::new(),
|
||||||
prefix: None,
|
prefix: None,
|
||||||
root: None,
|
|
||||||
rename: None,
|
rename: None,
|
||||||
skip_serializing_if: None,
|
skip_serializing_if: None,
|
||||||
text: false,
|
text: false,
|
||||||
@ -205,7 +234,6 @@ fn parse_attributes_with_values() {
|
|||||||
arguments: PathArguments::None,
|
arguments: PathArguments::None,
|
||||||
});
|
});
|
||||||
|
|
||||||
// #[()]
|
|
||||||
let attributes = vec![Attribute {
|
let attributes = vec![Attribute {
|
||||||
pound_token: Pound {
|
pound_token: Pound {
|
||||||
spans: [Span::call_site()],
|
spans: [Span::call_site()],
|
||||||
@ -234,7 +262,6 @@ fn parse_attributes_with_values() {
|
|||||||
flatten: true,
|
flatten: true,
|
||||||
namespaces,
|
namespaces,
|
||||||
prefix: None,
|
prefix: None,
|
||||||
root: None,
|
|
||||||
rename: None,
|
rename: None,
|
||||||
skip_serializing_if: None,
|
skip_serializing_if: None,
|
||||||
text: false,
|
text: false,
|
||||||
295
yaserde_derive/src/common/field.rs
Normal file
295
yaserde_derive/src/common/field.rs
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
use crate::common::attribute::YaSerdeAttribute;
|
||||||
|
use proc_macro2::Span;
|
||||||
|
use proc_macro2::{Ident, TokenStream};
|
||||||
|
use std::fmt;
|
||||||
|
use syn;
|
||||||
|
use syn::spanned::Spanned;
|
||||||
|
use syn::Type::Path;
|
||||||
|
|
||||||
|
#[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 is_flatten(&self) -> bool {
|
||||||
|
self.attributes.flatten
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub fn get_attributes(&self) -> YaSerdeAttribute {
|
||||||
|
// self.attributes.clone()
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn label(&self) -> Option<Ident> {
|
||||||
|
self.syn_field.ident.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value_label(&self) -> Option<syn::Ident> {
|
||||||
|
self
|
||||||
|
.syn_field
|
||||||
|
.ident
|
||||||
|
.clone()
|
||||||
|
.map(|ident| syn::Ident::new(&format!("__{}_value", ident.to_string()), ident.span()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn renamed_label_without_namespace(&self) -> String {
|
||||||
|
self
|
||||||
|
.attributes
|
||||||
|
.rename
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_else(|| self.label().as_ref().unwrap().to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
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.renamed_label_without_namespace();
|
||||||
|
|
||||||
|
format!("{}{}", prefix, label)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_visitor_ident(&self, struct_name: Option<&syn::Path>) -> Ident {
|
||||||
|
let label = self.renamed_label_without_namespace();
|
||||||
|
|
||||||
|
let struct_id = struct_name.map_or_else(
|
||||||
|
|| "".to_string(),
|
||||||
|
|struct_name| {
|
||||||
|
struct_name
|
||||||
|
.segments
|
||||||
|
.iter()
|
||||||
|
.map(|s| s.ident.to_string())
|
||||||
|
.collect()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Ident::new(
|
||||||
|
&format!("__Visitor_{}_{}", label.replace(".", "_"), struct_id),
|
||||||
|
self.get_span(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 get_namespace_matching(
|
||||||
|
&self,
|
||||||
|
root_attributes: &YaSerdeAttribute,
|
||||||
|
element_namespace: TokenStream,
|
||||||
|
element_name: TokenStream,
|
||||||
|
) -> TokenStream {
|
||||||
|
root_attributes.get_namespace_matching(
|
||||||
|
&self.attributes.prefix,
|
||||||
|
element_namespace,
|
||||||
|
element_name,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ser_wrap_default_attribute(
|
||||||
|
&self,
|
||||||
|
builder: Option<TokenStream>,
|
||||||
|
setter: TokenStream,
|
||||||
|
) -> TokenStream {
|
||||||
|
let label = self.label();
|
||||||
|
|
||||||
|
let yaserde_inner_definition = builder
|
||||||
|
.map(|builder| quote!(let yaserde_inner = #builder;))
|
||||||
|
.unwrap_or(quote!());
|
||||||
|
|
||||||
|
self
|
||||||
|
.get_default_function()
|
||||||
|
.map(|default_function| {
|
||||||
|
quote! {
|
||||||
|
#yaserde_inner_definition
|
||||||
|
let struct_start_event =
|
||||||
|
if self.#label != #default_function() {
|
||||||
|
#setter
|
||||||
|
} else {
|
||||||
|
struct_start_event
|
||||||
|
};
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap_or(quote! {
|
||||||
|
#yaserde_inner_definition
|
||||||
|
let struct_start_event = #setter;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Field {
|
||||||
|
FieldString,
|
||||||
|
FieldBool,
|
||||||
|
FieldI8,
|
||||||
|
FieldU8,
|
||||||
|
FieldI16,
|
||||||
|
FieldU16,
|
||||||
|
FieldI32,
|
||||||
|
FieldU32,
|
||||||
|
FieldI64,
|
||||||
|
FieldU64,
|
||||||
|
FieldF32,
|
||||||
|
FieldF64,
|
||||||
|
FieldOption { data_type: Box<Field> },
|
||||||
|
FieldVec { data_type: Box<Field> },
|
||||||
|
FieldStruct { struct_name: syn::Path },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Field {
|
||||||
|
pub fn get_simple_type_visitor(&self) -> TokenStream {
|
||||||
|
let ident = format_ident!("visit_{}", self.to_string());
|
||||||
|
quote! {#ident}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&syn::Path> for Field {
|
||||||
|
fn from(path: &syn::Path) -> Self {
|
||||||
|
let result = if let Some(segment) = path.segments.last() {
|
||||||
|
match segment.ident.to_string().as_str() {
|
||||||
|
"String" => Some(Field::FieldString),
|
||||||
|
"bool" => Some(Field::FieldBool),
|
||||||
|
"i8" => Some(Field::FieldI8),
|
||||||
|
"u8" => Some(Field::FieldU8),
|
||||||
|
"i16" => Some(Field::FieldI16),
|
||||||
|
"u16" => Some(Field::FieldU16),
|
||||||
|
"i32" => Some(Field::FieldI32),
|
||||||
|
"u32" => Some(Field::FieldU32),
|
||||||
|
"i64" => Some(Field::FieldI64),
|
||||||
|
"u64" => Some(Field::FieldU64),
|
||||||
|
"f32" => Some(Field::FieldF32),
|
||||||
|
"f64" => Some(Field::FieldF64),
|
||||||
|
"Option" => Some(Field::FieldOption {
|
||||||
|
data_type: Box::new(Field::from(segment)),
|
||||||
|
}),
|
||||||
|
"Vec" => Some(Field::FieldVec {
|
||||||
|
data_type: Box::new(Field::from(segment)),
|
||||||
|
}),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
result.unwrap_or_else(|| Field::FieldStruct {
|
||||||
|
struct_name: path.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&syn::Field> for Field {
|
||||||
|
fn from(field: &syn::Field) -> Self {
|
||||||
|
match field.ty {
|
||||||
|
Path(ref path) => Field::from(&path.path),
|
||||||
|
_ => panic!("unable to match {:?}", field.ty),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&syn::PathSegment> for Field {
|
||||||
|
fn from(path_segment: &syn::PathSegment) -> Self {
|
||||||
|
if let syn::PathArguments::AngleBracketed(ref args) = path_segment.arguments {
|
||||||
|
if let Some(tt) = args.args.first() {
|
||||||
|
if let syn::GenericArgument::Type(ref argument) = *tt {
|
||||||
|
if let Path(ref path) = *argument {
|
||||||
|
return Field::from(&path.path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<proc_macro2::TokenStream> for Field {
|
||||||
|
fn into(self) -> proc_macro2::TokenStream {
|
||||||
|
match self {
|
||||||
|
Field::FieldString => quote! {String},
|
||||||
|
Field::FieldBool => quote! {bool},
|
||||||
|
Field::FieldI8 => quote! {i8},
|
||||||
|
Field::FieldU8 => quote! {u8},
|
||||||
|
Field::FieldI16 => quote! {i16},
|
||||||
|
Field::FieldU16 => quote! {u16},
|
||||||
|
Field::FieldI32 => quote! {i32},
|
||||||
|
Field::FieldU32 => quote! {u32},
|
||||||
|
Field::FieldI64 => quote! {i64},
|
||||||
|
Field::FieldU64 => quote! {u64},
|
||||||
|
Field::FieldF32 => quote! {f32},
|
||||||
|
Field::FieldF64 => quote! {f64},
|
||||||
|
_ => panic!("Not a simple type: {:?}", self),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<String> for &Field {
|
||||||
|
fn into(self) -> String {
|
||||||
|
match self {
|
||||||
|
Field::FieldString => "str".to_string(),
|
||||||
|
Field::FieldBool => "bool".to_string(),
|
||||||
|
Field::FieldI8 => "i8".to_string(),
|
||||||
|
Field::FieldU8 => "u8".to_string(),
|
||||||
|
Field::FieldI16 => "i16".to_string(),
|
||||||
|
Field::FieldU16 => "u16".to_string(),
|
||||||
|
Field::FieldI32 => "i32".to_string(),
|
||||||
|
Field::FieldU32 => "u32".to_string(),
|
||||||
|
Field::FieldI64 => "i64".to_string(),
|
||||||
|
Field::FieldU64 => "u64".to_string(),
|
||||||
|
Field::FieldF32 => "f32".to_string(),
|
||||||
|
Field::FieldF64 => "f64".to_string(),
|
||||||
|
_ => panic!("Not a simple type: {:?}", self),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Field {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let string_representation: String = self.into();
|
||||||
|
write!(f, "{}", string_representation)
|
||||||
|
}
|
||||||
|
}
|
||||||
5
yaserde_derive/src/common/mod.rs
Normal file
5
yaserde_derive/src/common/mod.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
mod attribute;
|
||||||
|
mod field;
|
||||||
|
|
||||||
|
pub use attribute::YaSerdeAttribute;
|
||||||
|
pub use field::{Field, YaSerdeField};
|
||||||
@ -1,28 +1,24 @@
|
|||||||
use proc_macro2::{Span, TokenStream};
|
use crate::common::YaSerdeField;
|
||||||
use syn::Ident;
|
use proc_macro2::TokenStream;
|
||||||
|
|
||||||
pub fn build_default_value(
|
pub fn build_default_value(
|
||||||
label: &Option<Ident>,
|
field: &YaSerdeField,
|
||||||
field_type: &TokenStream,
|
field_type: Option<TokenStream>,
|
||||||
value: &TokenStream,
|
value: TokenStream,
|
||||||
default: &Option<String>,
|
|
||||||
) -> Option<TokenStream> {
|
) -> Option<TokenStream> {
|
||||||
let value = default
|
let label = field.get_value_label();
|
||||||
.as_ref()
|
|
||||||
.map(|d| {
|
|
||||||
let default_function = Ident::new(
|
|
||||||
&d,
|
|
||||||
label
|
|
||||||
.as_ref()
|
|
||||||
.map_or(Span::call_site(), |ident| ident.span()),
|
|
||||||
);
|
|
||||||
|
|
||||||
quote!(#default_function())
|
let default_value = field
|
||||||
})
|
.get_default_function()
|
||||||
|
.map(|default_function| quote!(#default_function()))
|
||||||
.unwrap_or_else(|| quote!(#value));
|
.unwrap_or_else(|| quote!(#value));
|
||||||
|
|
||||||
|
let field_type = field_type
|
||||||
|
.map(|field_type| quote!(: #field_type))
|
||||||
|
.unwrap_or(quote!());
|
||||||
|
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
let mut #label : #field_type = #value;
|
let mut #label #field_type = #default_value;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,6 @@
|
|||||||
use crate::attribute::*;
|
use crate::common::{Field, YaSerdeAttribute, YaSerdeField};
|
||||||
use crate::field_type::*;
|
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use syn::spanned::Spanned;
|
use syn::{DataEnum, Fields, Ident};
|
||||||
use syn::DataEnum;
|
|
||||||
use syn::Fields;
|
|
||||||
use syn::Ident;
|
|
||||||
|
|
||||||
pub fn parse(
|
pub fn parse(
|
||||||
data_enum: &DataEnum,
|
data_enum: &DataEnum,
|
||||||
@ -141,9 +137,10 @@ fn build_unnamed_field_visitors(fields: &syn::FieldsUnnamed) -> TokenStream {
|
|||||||
fields
|
fields
|
||||||
.unnamed
|
.unnamed
|
||||||
.iter()
|
.iter()
|
||||||
|
.map(|field| YaSerdeField::new(field.clone()))
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(idx, field)| {
|
.map(|(idx, field)| {
|
||||||
let visitor_label = Ident::new(&format!("__Visitor_{}", idx), field.span());
|
let visitor_label = Ident::new(&format!("__Visitor_{}", idx), field.get_span());
|
||||||
|
|
||||||
let make_visitor =
|
let make_visitor =
|
||||||
|visitor: &TokenStream, field_type: &TokenStream, fn_body: &TokenStream| {
|
|visitor: &TokenStream, field_type: &TokenStream, fn_body: &TokenStream| {
|
||||||
@ -160,9 +157,9 @@ fn build_unnamed_field_visitors(fields: &syn::FieldsUnnamed) -> TokenStream {
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
let simple_type_visitor = |simple_type| {
|
let simple_type_visitor = |simple_type: Field| {
|
||||||
let field_type = get_simple_type_token(&simple_type);
|
let visitor = simple_type.get_simple_type_visitor();
|
||||||
let visitor = get_simple_type_visitor(&simple_type);
|
let field_type = simple_type.into();
|
||||||
|
|
||||||
make_visitor(
|
make_visitor(
|
||||||
&visitor,
|
&visitor,
|
||||||
@ -171,8 +168,8 @@ fn build_unnamed_field_visitors(fields: &syn::FieldsUnnamed) -> TokenStream {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
get_field_type(field).and_then(|f| match f {
|
match field.get_type() {
|
||||||
FieldType::FieldTypeStruct { struct_name } => {
|
Field::FieldStruct { struct_name } => {
|
||||||
let struct_id: String = struct_name
|
let struct_id: String = struct_name
|
||||||
.segments
|
.segments
|
||||||
.iter()
|
.iter()
|
||||||
@ -189,14 +186,12 @@ fn build_unnamed_field_visitors(fields: &syn::FieldsUnnamed) -> TokenStream {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
FieldType::FieldTypeOption { data_type } | FieldType::FieldTypeVec { data_type } => {
|
Field::FieldOption { data_type } | Field::FieldVec { data_type } => match *data_type {
|
||||||
match *data_type {
|
Field::FieldStruct { .. } => None,
|
||||||
FieldType::FieldTypeStruct { .. } => None,
|
simple_type => simple_type_visitor(simple_type),
|
||||||
simple_type => simple_type_visitor(simple_type),
|
},
|
||||||
}
|
|
||||||
}
|
|
||||||
simple_type => simple_type_visitor(simple_type),
|
simple_type => simple_type_visitor(simple_type),
|
||||||
})
|
}
|
||||||
})
|
})
|
||||||
.filter_map(|f| f)
|
.filter_map(|f| f)
|
||||||
.collect()
|
.collect()
|
||||||
@ -209,13 +204,14 @@ fn build_unnamed_visitor_calls(
|
|||||||
fields
|
fields
|
||||||
.unnamed
|
.unnamed
|
||||||
.iter()
|
.iter()
|
||||||
|
.map(|field| YaSerdeField::new(field.clone()))
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(idx, field)| {
|
.map(|(idx, field)| {
|
||||||
let visitor_label = Ident::new(&format!("__Visitor_{}", idx), field.span());
|
let visitor_label = Ident::new(&format!("__Visitor_{}", idx), field.get_span());
|
||||||
|
|
||||||
let call_simple_type_visitor = |simple_type, action| {
|
let call_simple_type_visitor = |simple_type: Field, action| {
|
||||||
let field_type = get_simple_type_token(&simple_type);
|
let visitor = simple_type.get_simple_type_visitor();
|
||||||
let visitor = get_simple_type_visitor(&simple_type);
|
let field_type: TokenStream = simple_type.into();
|
||||||
|
|
||||||
let label_name = format!("field_{}", idx);
|
let label_name = format!("field_{}", idx);
|
||||||
|
|
||||||
@ -279,19 +275,19 @@ fn build_unnamed_visitor_calls(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
get_field_type(field).and_then(|f| match f {
|
match field.get_type() {
|
||||||
FieldType::FieldTypeStruct { struct_name } => call_struct_visitor(struct_name, set_val),
|
Field::FieldStruct { struct_name } => call_struct_visitor(struct_name, set_val),
|
||||||
FieldType::FieldTypeOption { data_type } => match *data_type {
|
Field::FieldOption { data_type } => match *data_type {
|
||||||
FieldType::FieldTypeStruct { struct_name } => call_struct_visitor(struct_name, set_opt),
|
Field::FieldStruct { struct_name } => call_struct_visitor(struct_name, set_opt),
|
||||||
simple_type => call_simple_type_visitor(simple_type, set_opt),
|
simple_type => call_simple_type_visitor(simple_type, set_opt),
|
||||||
},
|
},
|
||||||
FieldType::FieldTypeVec { data_type } => match *data_type {
|
Field::FieldVec { data_type } => match *data_type {
|
||||||
FieldType::FieldTypeStruct { struct_name } => call_struct_visitor(struct_name, set_vec),
|
Field::FieldStruct { struct_name } => call_struct_visitor(struct_name, set_vec),
|
||||||
simple_type => call_simple_type_visitor(simple_type, set_vec),
|
simple_type => call_simple_type_visitor(simple_type, set_vec),
|
||||||
},
|
},
|
||||||
|
|
||||||
simple_type => call_simple_type_visitor(simple_type, set_val),
|
simple_type => call_simple_type_visitor(simple_type, set_val),
|
||||||
})
|
}
|
||||||
})
|
})
|
||||||
.filter_map(|f| f)
|
.filter_map(|f| f)
|
||||||
.collect()
|
.collect()
|
||||||
|
|||||||
@ -1,11 +1,7 @@
|
|||||||
use crate::attribute::*;
|
use crate::common::{Field, YaSerdeAttribute, YaSerdeField};
|
||||||
use crate::de::build_default_value::build_default_value;
|
use crate::de::build_default_value::build_default_value;
|
||||||
use crate::field_type::*;
|
|
||||||
use proc_macro2::{Span, TokenStream};
|
use proc_macro2::{Span, TokenStream};
|
||||||
use std::collections::BTreeMap;
|
use syn::{DataStruct, Ident};
|
||||||
use syn::spanned::Spanned;
|
|
||||||
use syn::DataStruct;
|
|
||||||
use syn::Ident;
|
|
||||||
|
|
||||||
pub fn parse(
|
pub fn parse(
|
||||||
data_struct: &DataStruct,
|
data_struct: &DataStruct,
|
||||||
@ -13,79 +9,43 @@ pub fn parse(
|
|||||||
root: &str,
|
root: &str,
|
||||||
root_attributes: &YaSerdeAttribute,
|
root_attributes: &YaSerdeAttribute,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let namespaces_matches: TokenStream = root_attributes
|
let namespaces_matching = root_attributes.get_namespace_matching(
|
||||||
.namespaces
|
&None,
|
||||||
.iter()
|
quote!(struct_namespace),
|
||||||
.map(|(p, ns)| {
|
quote!(named_element),
|
||||||
if root_attributes.prefix.as_ref() == Some(p) {
|
true,
|
||||||
Some(quote!(#ns => {}))
|
);
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.filter_map(|x| x)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let variables: TokenStream = data_struct
|
let variables: TokenStream = data_struct
|
||||||
.fields
|
.fields
|
||||||
.iter()
|
.iter()
|
||||||
.map(|field| {
|
.map(|field| YaSerdeField::new(field.clone()))
|
||||||
let label = &get_value_label(&field.ident);
|
.map(|field| match field.get_type() {
|
||||||
let field_attrs = YaSerdeAttribute::parse(&field.attrs);
|
Field::FieldStruct { struct_name } => build_default_value(
|
||||||
|
&field,
|
||||||
get_field_type(field).and_then(|f| match f {
|
Some(quote!(#struct_name)),
|
||||||
FieldType::FieldTypeStruct { struct_name } => build_default_value(
|
quote!(#struct_name::default()),
|
||||||
label,
|
),
|
||||||
"e! {#struct_name},
|
Field::FieldOption { .. } => build_default_value(&field, None, quote!(None)),
|
||||||
"e! {#struct_name::default()},
|
Field::FieldVec { data_type } => match *data_type {
|
||||||
&field_attrs.default,
|
Field::FieldStruct { ref struct_name } => {
|
||||||
),
|
build_default_value(&field, Some(quote!(Vec<#struct_name>)), quote!(vec![]))
|
||||||
FieldType::FieldTypeOption { .. } => {
|
}
|
||||||
if let Some(d) = &field_attrs.default {
|
Field::FieldOption { .. } | Field::FieldVec { .. } => {
|
||||||
let default_function = Ident::new(&d, field.span());
|
unimplemented!();
|
||||||
|
|
||||||
Some(quote! {
|
|
||||||
#[allow(unused_mut, non_snake_case, non_camel_case_types)]
|
|
||||||
let mut #label = #default_function();
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Some(quote! {
|
|
||||||
#[allow(unused_mut, non_snake_case, non_camel_case_types)]
|
|
||||||
let mut #label = None;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
FieldType::FieldTypeVec { data_type } => match *data_type {
|
|
||||||
FieldType::FieldTypeStruct { ref struct_name } => build_default_value(
|
|
||||||
label,
|
|
||||||
"e! {Vec<#struct_name>},
|
|
||||||
"e! {vec![]},
|
|
||||||
&field_attrs.default,
|
|
||||||
),
|
|
||||||
FieldType::FieldTypeOption { .. } | FieldType::FieldTypeVec { .. } => {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
simple_type => {
|
|
||||||
let type_token = get_simple_type_token(&simple_type);
|
|
||||||
|
|
||||||
build_default_value(
|
|
||||||
label,
|
|
||||||
"e! {Vec<#type_token>},
|
|
||||||
"e! {vec![]},
|
|
||||||
&field_attrs.default,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
simple_type => {
|
simple_type => {
|
||||||
let type_token = get_simple_type_token(&simple_type);
|
let type_token: TokenStream = simple_type.into();
|
||||||
build_default_value(
|
|
||||||
label,
|
build_default_value(&field, Some(quote!(Vec<#type_token>)), quote!(vec![]))
|
||||||
&type_token,
|
|
||||||
"e! {#type_token::default()},
|
|
||||||
&field_attrs.default,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
|
simple_type => {
|
||||||
|
let type_token: TokenStream = simple_type.into();
|
||||||
|
let value_builder = quote!(#type_token::default());
|
||||||
|
|
||||||
|
build_default_value(&field, Some(type_token), value_builder)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.filter_map(|x| x)
|
.filter_map(|x| x)
|
||||||
.collect();
|
.collect();
|
||||||
@ -93,12 +53,8 @@ pub fn parse(
|
|||||||
let field_visitors: TokenStream = data_struct
|
let field_visitors: TokenStream = data_struct
|
||||||
.fields
|
.fields
|
||||||
.iter()
|
.iter()
|
||||||
|
.map(|field| YaSerdeField::new(field.clone()))
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
let field_attrs = YaSerdeAttribute::parse(&field.attrs);
|
|
||||||
let label_name = field_attrs
|
|
||||||
.rename
|
|
||||||
.unwrap_or_else(|| field.ident.as_ref().unwrap().to_string());
|
|
||||||
|
|
||||||
let struct_visitor = |struct_name: syn::Path| {
|
let struct_visitor = |struct_name: syn::Path| {
|
||||||
let struct_id: String = struct_name
|
let struct_id: String = struct_name
|
||||||
.segments
|
.segments
|
||||||
@ -106,7 +62,7 @@ pub fn parse(
|
|||||||
.map(|s| s.ident.to_string())
|
.map(|s| s.ident.to_string())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let visitor_label = build_visitor_ident(&label_name, field.span(), Some(&struct_name));
|
let visitor_label = field.get_visitor_ident(Some(&struct_name));
|
||||||
|
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
#[allow(non_snake_case, non_camel_case_types)]
|
#[allow(non_snake_case, non_camel_case_types)]
|
||||||
@ -123,10 +79,10 @@ pub fn parse(
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
let simple_type_visitor = |simple_type: FieldType| {
|
let simple_type_visitor = |simple_type: Field| {
|
||||||
let field_type = get_simple_type_token(&simple_type);
|
let visitor = simple_type.get_simple_type_visitor();
|
||||||
let visitor = get_simple_type_visitor(&simple_type);
|
let visitor_label = field.get_visitor_ident(None);
|
||||||
let visitor_label = build_visitor_ident(&label_name, field.span(), None);
|
let field_type: TokenStream = simple_type.into();
|
||||||
|
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
#[allow(non_snake_case, non_camel_case_types)]
|
#[allow(non_snake_case, non_camel_case_types)]
|
||||||
@ -141,20 +97,20 @@ pub fn parse(
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
get_field_type(field).and_then(|f| match f {
|
match field.get_type() {
|
||||||
FieldType::FieldTypeStruct { struct_name } => struct_visitor(struct_name),
|
Field::FieldStruct { struct_name } => struct_visitor(struct_name),
|
||||||
FieldType::FieldTypeOption { data_type } => match *data_type {
|
Field::FieldOption { data_type } => match *data_type {
|
||||||
FieldType::FieldTypeStruct { struct_name } => struct_visitor(struct_name),
|
Field::FieldStruct { struct_name } => struct_visitor(struct_name),
|
||||||
FieldType::FieldTypeOption { .. } | FieldType::FieldTypeVec { .. } => None,
|
Field::FieldOption { .. } | Field::FieldVec { .. } => None,
|
||||||
simple_type => simple_type_visitor(simple_type),
|
simple_type => simple_type_visitor(simple_type),
|
||||||
},
|
},
|
||||||
FieldType::FieldTypeVec { data_type } => match *data_type {
|
Field::FieldVec { data_type } => match *data_type {
|
||||||
FieldType::FieldTypeStruct { struct_name } => struct_visitor(struct_name),
|
Field::FieldStruct { struct_name } => struct_visitor(struct_name),
|
||||||
FieldType::FieldTypeOption { .. } | FieldType::FieldTypeVec { .. } => None,
|
Field::FieldOption { .. } | Field::FieldVec { .. } => None,
|
||||||
simple_type => simple_type_visitor(simple_type),
|
simple_type => simple_type_visitor(simple_type),
|
||||||
},
|
},
|
||||||
simple_type => simple_type_visitor(simple_type),
|
simple_type => simple_type_visitor(simple_type),
|
||||||
})
|
}
|
||||||
})
|
})
|
||||||
.filter_map(|x| x)
|
.filter_map(|x| x)
|
||||||
.collect();
|
.collect();
|
||||||
@ -162,19 +118,11 @@ pub fn parse(
|
|||||||
let call_visitors: TokenStream = data_struct
|
let call_visitors: TokenStream = data_struct
|
||||||
.fields
|
.fields
|
||||||
.iter()
|
.iter()
|
||||||
|
.map(|field| YaSerdeField::new(field.clone()))
|
||||||
|
.filter(|field| !field.is_attribute() || !field.is_flatten())
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
let field_attrs = YaSerdeAttribute::parse(&field.attrs);
|
let value_label = field.get_value_label();
|
||||||
let label = &field.ident;
|
let label_name = field.renamed_label_without_namespace();
|
||||||
let value_label = &get_value_label(&field.ident);
|
|
||||||
|
|
||||||
if field_attrs.attribute || field_attrs.flatten {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let label_name = field_attrs
|
|
||||||
.rename
|
|
||||||
.clone()
|
|
||||||
.unwrap_or_else(|| label.as_ref().unwrap().to_string());
|
|
||||||
|
|
||||||
let visit_struct = |struct_name: syn::Path, action: TokenStream| {
|
let visit_struct = |struct_name: syn::Path, action: TokenStream| {
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
@ -192,30 +140,30 @@ pub fn parse(
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
let visit_simple = |simple_type: FieldType, action: TokenStream| {
|
let visit_simple = |simple_type: Field, action: TokenStream| {
|
||||||
|
let field_visitor = simple_type.get_simple_type_visitor();
|
||||||
|
let field_type: TokenStream = simple_type.into();
|
||||||
build_call_visitor(
|
build_call_visitor(
|
||||||
&get_simple_type_token(&simple_type),
|
&field_type,
|
||||||
&get_simple_type_visitor(&simple_type),
|
&field_visitor,
|
||||||
&action,
|
&action,
|
||||||
&field_attrs,
|
&field,
|
||||||
label,
|
&root_attributes,
|
||||||
&root_attributes.namespaces,
|
|
||||||
field.span(),
|
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let visit_sub = |sub_type: Box<FieldType>, action: TokenStream| match *sub_type {
|
let visit_sub = |sub_type: Box<Field>, action: TokenStream| match *sub_type {
|
||||||
FieldType::FieldTypeOption { .. } | FieldType::FieldTypeVec { .. } => unimplemented!(),
|
Field::FieldOption { .. } | Field::FieldVec { .. } => unimplemented!(),
|
||||||
FieldType::FieldTypeStruct { struct_name } => visit_struct(struct_name, action),
|
Field::FieldStruct { struct_name } => visit_struct(struct_name, action),
|
||||||
simple_type => visit_simple(simple_type, action),
|
simple_type => visit_simple(simple_type, action),
|
||||||
};
|
};
|
||||||
|
|
||||||
get_field_type(field).and_then(|f| match f {
|
match field.get_type() {
|
||||||
FieldType::FieldTypeStruct { struct_name } => visit_struct(struct_name, quote! {= value}),
|
Field::FieldStruct { struct_name } => visit_struct(struct_name, quote! {= value}),
|
||||||
FieldType::FieldTypeOption { data_type } => visit_sub(data_type, quote! {= Some(value)}),
|
Field::FieldOption { data_type } => visit_sub(data_type, quote! {= Some(value)}),
|
||||||
FieldType::FieldTypeVec { data_type } => visit_sub(data_type, quote! {.push(value)}),
|
Field::FieldVec { data_type } => visit_sub(data_type, quote! {.push(value)}),
|
||||||
simple_type => visit_simple(simple_type, quote! {= value}),
|
simple_type => visit_simple(simple_type, quote! {= value}),
|
||||||
})
|
}
|
||||||
})
|
})
|
||||||
.filter_map(|x| x)
|
.filter_map(|x| x)
|
||||||
.collect();
|
.collect();
|
||||||
@ -223,26 +171,23 @@ pub fn parse(
|
|||||||
let call_flatten_visitors: TokenStream = data_struct
|
let call_flatten_visitors: TokenStream = data_struct
|
||||||
.fields
|
.fields
|
||||||
.iter()
|
.iter()
|
||||||
|
.map(|field| YaSerdeField::new(field.clone()))
|
||||||
|
.filter(|field| !field.is_attribute() && field.is_flatten())
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
let field_attrs = YaSerdeAttribute::parse(&field.attrs);
|
let value_label = field.get_value_label();
|
||||||
let value_label = &get_value_label(&field.ident);
|
|
||||||
|
|
||||||
if field_attrs.attribute || !field_attrs.flatten {
|
match field.get_type() {
|
||||||
return None;
|
Field::FieldStruct { .. } => Some(quote! {
|
||||||
}
|
|
||||||
|
|
||||||
get_field_type(field).and_then(|f| match f {
|
|
||||||
FieldType::FieldTypeStruct { .. } => Some(quote! {
|
|
||||||
#value_label = yaserde::de::from_str(&unused_xml_elements)?;
|
#value_label = yaserde::de::from_str(&unused_xml_elements)?;
|
||||||
}),
|
}),
|
||||||
FieldType::FieldTypeOption { data_type } => match *data_type {
|
Field::FieldOption { data_type } => match *data_type {
|
||||||
FieldType::FieldTypeStruct { .. } => Some(quote! {
|
Field::FieldStruct { .. } => Some(quote! {
|
||||||
#value_label = yaserde::de::from_str(&unused_xml_elements).ok();
|
#value_label = yaserde::de::from_str(&unused_xml_elements).ok();
|
||||||
}),
|
}),
|
||||||
field_type => unimplemented!("\"flatten\" is not implemented for {:?}", field_type),
|
field_type => unimplemented!(r#""flatten" is not implemented for {:?}"#, field_type),
|
||||||
},
|
},
|
||||||
field_type => unimplemented!("\"flatten\" is not implemented for {:?}", field_type),
|
field_type => unimplemented!(r#""flatten" is not implemented for {:?}"#, field_type),
|
||||||
})
|
}
|
||||||
})
|
})
|
||||||
.filter_map(|x| x)
|
.filter_map(|x| x)
|
||||||
.collect();
|
.collect();
|
||||||
@ -250,19 +195,12 @@ pub fn parse(
|
|||||||
let attributes_loading: TokenStream = data_struct
|
let attributes_loading: 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.get_value_label();
|
||||||
if !field_attrs.attribute {
|
let label_name = field.renamed_label_without_namespace();
|
||||||
return None;
|
let visitor_label = build_visitor_ident(&label_name, field.get_span(), None);
|
||||||
}
|
|
||||||
|
|
||||||
let label = &get_value_label(&field.ident);
|
|
||||||
|
|
||||||
let label_name = field_attrs
|
|
||||||
.rename
|
|
||||||
.unwrap_or_else(|| field.ident.as_ref().unwrap().to_string());
|
|
||||||
|
|
||||||
let visitor_label = build_visitor_ident(&label_name, field.span(), None);
|
|
||||||
|
|
||||||
let visit = |action: &TokenStream, visitor: &TokenStream, visitor_label: &Ident| {
|
let visit = |action: &TokenStream, visitor: &TokenStream, visitor_label: &Ident| {
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
@ -290,31 +228,31 @@ pub fn parse(
|
|||||||
visit(
|
visit(
|
||||||
&action,
|
&action,
|
||||||
"e! {visit_str},
|
"e! {visit_str},
|
||||||
&build_visitor_ident(&label_name, field.span(), Some(&struct_name)),
|
&build_visitor_ident(&label_name, field.get_span(), Some(&struct_name)),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let visit_simple = |simple_type: FieldType, action: TokenStream| {
|
let visit_simple = |simple_type: Field, action: TokenStream| {
|
||||||
visit(
|
visit(
|
||||||
&action,
|
&action,
|
||||||
&get_simple_type_visitor(&simple_type),
|
&simple_type.get_simple_type_visitor(),
|
||||||
&visitor_label,
|
&visitor_label,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let visit_sub = |sub_type: Box<FieldType>, action: TokenStream| match *sub_type {
|
let visit_sub = |sub_type: Box<Field>, action: TokenStream| match *sub_type {
|
||||||
FieldType::FieldTypeOption { .. } | FieldType::FieldTypeVec { .. } => unimplemented!(),
|
Field::FieldOption { .. } | Field::FieldVec { .. } => unimplemented!(),
|
||||||
FieldType::FieldTypeStruct { struct_name } => visit_struct(struct_name, action),
|
Field::FieldStruct { struct_name } => visit_struct(struct_name, action),
|
||||||
simple_type => visit_simple(simple_type, action),
|
simple_type => visit_simple(simple_type, action),
|
||||||
};
|
};
|
||||||
|
|
||||||
get_field_type(field).and_then(|f| match f {
|
match field.get_type() {
|
||||||
FieldType::FieldTypeString => visit_string(),
|
Field::FieldString => visit_string(),
|
||||||
FieldType::FieldTypeOption { data_type } => visit_sub(data_type, quote! {= Some(value)}),
|
Field::FieldOption { data_type } => visit_sub(data_type, quote! {= Some(value)}),
|
||||||
FieldType::FieldTypeVec { .. } => unimplemented!(),
|
Field::FieldVec { .. } => unimplemented!(),
|
||||||
FieldType::FieldTypeStruct { struct_name } => visit_struct(struct_name, quote! {= value}),
|
Field::FieldStruct { struct_name } => visit_struct(struct_name, quote! {= value}),
|
||||||
simple_type => visit_simple(simple_type, quote! {= value}),
|
simple_type => visit_simple(simple_type, quote! {= value}),
|
||||||
})
|
}
|
||||||
})
|
})
|
||||||
.filter_map(|x| x)
|
.filter_map(|x| x)
|
||||||
.collect();
|
.collect();
|
||||||
@ -322,28 +260,26 @@ pub fn parse(
|
|||||||
let set_text: TokenStream = data_struct
|
let set_text: TokenStream = data_struct
|
||||||
.fields
|
.fields
|
||||||
.iter()
|
.iter()
|
||||||
|
.map(|field| YaSerdeField::new(field.clone()))
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
let label = &get_value_label(&field.ident);
|
let label = field.get_value_label();
|
||||||
let field_attrs = YaSerdeAttribute::parse(&field.attrs);
|
|
||||||
|
|
||||||
let set_text = |action: &TokenStream| {
|
let set_text = |action: &TokenStream| {
|
||||||
if field_attrs.text {
|
if field.is_text_content() {
|
||||||
Some(quote! {#label = #action;})
|
Some(quote! {#label = #action;})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
get_field_type(field).and_then(|f| match f {
|
match field.get_type() {
|
||||||
FieldType::FieldTypeString => set_text("e! {text_content.to_owned()}),
|
Field::FieldString => set_text("e! {text_content.to_owned()}),
|
||||||
FieldType::FieldTypeStruct { .. }
|
Field::FieldStruct { .. } | Field::FieldOption { .. } | Field::FieldVec { .. } => None,
|
||||||
| FieldType::FieldTypeOption { .. }
|
|
||||||
| FieldType::FieldTypeVec { .. } => None,
|
|
||||||
simple_type => {
|
simple_type => {
|
||||||
let type_token = get_simple_type_token(&simple_type);
|
let type_token: TokenStream = simple_type.into();
|
||||||
set_text("e! {#type_token::from_str(text_content).unwrap()})
|
set_text("e! {#type_token::from_str(text_content).unwrap()})
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
})
|
})
|
||||||
.filter_map(|x| x)
|
.filter_map(|x| x)
|
||||||
.collect();
|
.collect();
|
||||||
@ -351,15 +287,13 @@ pub fn parse(
|
|||||||
let struct_builder: TokenStream = data_struct
|
let struct_builder: TokenStream = data_struct
|
||||||
.fields
|
.fields
|
||||||
.iter()
|
.iter()
|
||||||
|
.map(|field| YaSerdeField::new(field.clone()))
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
let label = &field.ident;
|
let label = &field.label();
|
||||||
let value_label = &get_value_label(&field.ident);
|
let value_label = field.get_value_label();
|
||||||
|
|
||||||
get_field_type(field).map(|_| {
|
quote! { #label: #value_label, }
|
||||||
quote! { #label: #value_label, }
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.filter_map(|x| x)
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let (init_unused, write_unused, visit_unused) = if call_flatten_visitors.is_empty() {
|
let (init_unused, write_unused, visit_unused) = if call_flatten_visitors.is_empty() {
|
||||||
@ -390,15 +324,7 @@ pub fn parse(
|
|||||||
debug!("Struct: start to parse {:?}", named_element);
|
debug!("Struct: start to parse {:?}", named_element);
|
||||||
|
|
||||||
if reader.depth() == 0 {
|
if reader.depth() == 0 {
|
||||||
if let Some(ref namespace) = struct_namespace {
|
#namespaces_matching
|
||||||
match namespace.as_str() {
|
|
||||||
#namespaces_matches
|
|
||||||
bad_ns => {
|
|
||||||
let msg = format!("bad namespace for {}, found {}", named_element, bad_ns);
|
|
||||||
return Err(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#variables
|
#variables
|
||||||
@ -472,47 +398,24 @@ fn build_call_visitor(
|
|||||||
field_type: &TokenStream,
|
field_type: &TokenStream,
|
||||||
visitor: &TokenStream,
|
visitor: &TokenStream,
|
||||||
action: &TokenStream,
|
action: &TokenStream,
|
||||||
field_attrs: &YaSerdeAttribute,
|
field: &YaSerdeField,
|
||||||
label: &Option<Ident>,
|
root_attributes: &YaSerdeAttribute,
|
||||||
namespaces: &BTreeMap<String, String>,
|
|
||||||
span: Span,
|
|
||||||
) -> Option<TokenStream> {
|
) -> Option<TokenStream> {
|
||||||
let prefix = field_attrs.prefix.clone();
|
let value_label = field.get_value_label();
|
||||||
|
let label_name = field.renamed_label_without_namespace();
|
||||||
|
let visitor_label = build_visitor_ident(&label_name, field.get_span(), None);
|
||||||
|
|
||||||
// let label = &field.ident;
|
let namespaces_matching = field.get_namespace_matching(
|
||||||
let value_label = get_value_label(label);
|
root_attributes,
|
||||||
let label_name = field_attrs
|
quote!(name.namespace.as_ref()),
|
||||||
.rename
|
quote!(name.local_name.as_str()),
|
||||||
.clone()
|
);
|
||||||
.unwrap_or_else(|| label.as_ref().unwrap().to_string());
|
|
||||||
|
|
||||||
let visitor_label = build_visitor_ident(&label_name, span, None);
|
|
||||||
|
|
||||||
let namespaces_matches: TokenStream = namespaces
|
|
||||||
.iter()
|
|
||||||
.map(|(p, ns)| {
|
|
||||||
if prefix == Some(p.to_string()) {
|
|
||||||
Some(quote!(#ns => {}))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.filter_map(|x| x)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
#label_name => {
|
#label_name => {
|
||||||
let visitor = #visitor_label{};
|
let visitor = #visitor_label{};
|
||||||
|
|
||||||
if let Some(namespace) = name.namespace.as_ref() {
|
#namespaces_matching
|
||||||
match namespace.as_str() {
|
|
||||||
#namespaces_matches
|
|
||||||
bad_ns => {
|
|
||||||
let msg = format!("bad field namespace for {}, found {}", name.local_name.as_str(), bad_ns);
|
|
||||||
return Err(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let result = reader.read_inner_value::<#field_type, _>(|reader| {
|
let result = reader.read_inner_value::<#field_type, _>(|reader| {
|
||||||
if let Ok(XmlEvent::Characters(s)) = reader.peek() {
|
if let Ok(XmlEvent::Characters(s)) = reader.peek() {
|
||||||
@ -531,12 +434,6 @@ fn build_call_visitor(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_value_label(ident: &Option<syn::Ident>) -> Option<syn::Ident> {
|
|
||||||
ident
|
|
||||||
.clone()
|
|
||||||
.map(|ident| syn::Ident::new(&format!("__{}_value", ident.to_string()), ident.span()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_visitor_ident(label: &str, span: Span, struct_name: Option<&syn::Path>) -> Ident {
|
fn build_visitor_ident(label: &str, span: Span, struct_name: Option<&syn::Path>) -> Ident {
|
||||||
let struct_id = struct_name.map_or_else(
|
let struct_id = struct_name.map_or_else(
|
||||||
|| "".to_string(),
|
|| "".to_string(),
|
||||||
|
|||||||
@ -2,7 +2,7 @@ pub mod build_default_value;
|
|||||||
pub mod expand_enum;
|
pub mod expand_enum;
|
||||||
pub mod expand_struct;
|
pub mod expand_struct;
|
||||||
|
|
||||||
use crate::attribute;
|
use crate::common::YaSerdeAttribute;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use syn;
|
use syn;
|
||||||
use syn::Ident;
|
use syn::Ident;
|
||||||
@ -12,14 +12,19 @@ pub fn expand_derive_deserialize(ast: &syn::DeriveInput) -> Result<TokenStream,
|
|||||||
let attrs = &ast.attrs;
|
let attrs = &ast.attrs;
|
||||||
let data = &ast.data;
|
let data = &ast.data;
|
||||||
|
|
||||||
let root_attrs = attribute::YaSerdeAttribute::parse(attrs);
|
let root_attributes = YaSerdeAttribute::parse(attrs);
|
||||||
let root = root_attrs.clone().root.unwrap_or_else(|| name.to_string());
|
let root_name = root_attributes
|
||||||
|
.clone()
|
||||||
|
.rename
|
||||||
|
.unwrap_or_else(|| name.to_string());
|
||||||
|
|
||||||
let impl_block = match *data {
|
let impl_block = match *data {
|
||||||
syn::Data::Struct(ref data_struct) => {
|
syn::Data::Struct(ref data_struct) => {
|
||||||
expand_struct::parse(data_struct, name, &root, &root_attrs)
|
expand_struct::parse(data_struct, name, &root_name, &root_attributes)
|
||||||
|
}
|
||||||
|
syn::Data::Enum(ref data_enum) => {
|
||||||
|
expand_enum::parse(data_enum, name, &root_name, &root_attributes)
|
||||||
}
|
}
|
||||||
syn::Data::Enum(ref data_enum) => expand_enum::parse(data_enum, name, &root, &root_attrs),
|
|
||||||
syn::Data::Union(ref _data_union) => unimplemented!(),
|
syn::Data::Union(ref _data_union) => unimplemented!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,102 +0,0 @@
|
|||||||
use syn;
|
|
||||||
use syn::Type::Path;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum FieldType {
|
|
||||||
FieldTypeString,
|
|
||||||
FieldTypeBool,
|
|
||||||
FieldTypeI8,
|
|
||||||
FieldTypeU8,
|
|
||||||
FieldTypeI16,
|
|
||||||
FieldTypeU16,
|
|
||||||
FieldTypeI32,
|
|
||||||
FieldTypeU32,
|
|
||||||
FieldTypeI64,
|
|
||||||
FieldTypeU64,
|
|
||||||
FieldTypeF32,
|
|
||||||
FieldTypeF64,
|
|
||||||
FieldTypeOption { data_type: Box<FieldType> },
|
|
||||||
FieldTypeVec { data_type: Box<FieldType> },
|
|
||||||
FieldTypeStruct { struct_name: syn::Path },
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FieldType {
|
|
||||||
fn from_ident(path: &syn::Path) -> Option<FieldType> {
|
|
||||||
match path.segments.last() {
|
|
||||||
Some(t) => match t.ident.to_string().as_str() {
|
|
||||||
"String" => Some(FieldType::FieldTypeString),
|
|
||||||
"bool" => Some(FieldType::FieldTypeBool),
|
|
||||||
"i8" => Some(FieldType::FieldTypeI8),
|
|
||||||
"u8" => Some(FieldType::FieldTypeU8),
|
|
||||||
"i16" => Some(FieldType::FieldTypeI16),
|
|
||||||
"u16" => Some(FieldType::FieldTypeU16),
|
|
||||||
"i32" => Some(FieldType::FieldTypeI32),
|
|
||||||
"u32" => Some(FieldType::FieldTypeU32),
|
|
||||||
"i64" => Some(FieldType::FieldTypeI64),
|
|
||||||
"u64" => Some(FieldType::FieldTypeU64),
|
|
||||||
"f32" => Some(FieldType::FieldTypeF32),
|
|
||||||
"f64" => Some(FieldType::FieldTypeF64),
|
|
||||||
"Option" => get_sub_type(t).map(|data_type| FieldType::FieldTypeOption {
|
|
||||||
data_type: Box::new(FieldType::from_ident(&data_type).unwrap()),
|
|
||||||
}),
|
|
||||||
"Vec" => get_sub_type(t).map(|data_type| FieldType::FieldTypeVec {
|
|
||||||
data_type: Box::new(FieldType::from_ident(&data_type).unwrap()),
|
|
||||||
}),
|
|
||||||
_ => Some(FieldType::FieldTypeStruct {
|
|
||||||
struct_name: path.clone(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_field_type(field: &syn::Field) -> Option<FieldType> {
|
|
||||||
match field.ty {
|
|
||||||
Path(ref path) => FieldType::from_ident(&path.path),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_sub_type(t: &syn::PathSegment) -> Option<syn::Path> {
|
|
||||||
if let syn::PathArguments::AngleBracketed(ref args) = t.arguments {
|
|
||||||
if let Some(tt) = args.args.first() {
|
|
||||||
if let syn::GenericArgument::Type(ref argument) = *tt {
|
|
||||||
if let Path(ref path) = *argument {
|
|
||||||
return Some(path.path.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_simple_type_token(field_type: &FieldType) -> proc_macro2::TokenStream {
|
|
||||||
match field_type {
|
|
||||||
FieldType::FieldTypeString => quote! {String},
|
|
||||||
FieldType::FieldTypeBool => quote! {bool},
|
|
||||||
FieldType::FieldTypeI8 => quote! {i8},
|
|
||||||
FieldType::FieldTypeU8 => quote! {u8},
|
|
||||||
FieldType::FieldTypeI16 => quote! {i16},
|
|
||||||
FieldType::FieldTypeU16 => quote! {u16},
|
|
||||||
FieldType::FieldTypeI32 => quote! {i32},
|
|
||||||
FieldType::FieldTypeU32 => quote! {u32},
|
|
||||||
FieldType::FieldTypeI64 => quote! {i64},
|
|
||||||
FieldType::FieldTypeU64 => quote! {u64},
|
|
||||||
FieldType::FieldTypeF32 => quote! {f32},
|
|
||||||
FieldType::FieldTypeF64 => quote! {f64},
|
|
||||||
_ => panic!("Not a simple type: {:?}", field_type),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_simple_type_visitor(field_type: &FieldType) -> proc_macro2::TokenStream {
|
|
||||||
let ident = format_ident!(
|
|
||||||
"visit_{}",
|
|
||||||
get_simple_type_token(field_type)
|
|
||||||
.to_string()
|
|
||||||
.replace("String", "str")
|
|
||||||
);
|
|
||||||
|
|
||||||
quote! {#ident}
|
|
||||||
}
|
|
||||||
@ -6,9 +6,8 @@ extern crate proc_macro2;
|
|||||||
extern crate quote;
|
extern crate quote;
|
||||||
extern crate syn;
|
extern crate syn;
|
||||||
|
|
||||||
mod attribute;
|
mod common;
|
||||||
mod de;
|
mod de;
|
||||||
mod field_type;
|
|
||||||
mod ser;
|
mod ser;
|
||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use crate::attribute::*;
|
use crate::common::YaSerdeField;
|
||||||
use proc_macro2::{Ident, Span, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
|
|
||||||
pub fn enclose_formatted_characters(label: &Ident, label_name: String) -> TokenStream {
|
pub fn enclose_formatted_characters(label: &Ident, label_name: String) -> TokenStream {
|
||||||
enclose_xml_event(label_name, quote!(format!("{}", &self.#label)))
|
enclose_xml_event(label_name, quote!(format!("{}", &self.#label)))
|
||||||
@ -13,7 +13,7 @@ pub fn enclose_characters(label: &Option<Ident>, label_name: String) -> TokenStr
|
|||||||
enclose_xml_event(label_name, quote!(format!("{}", self.#label)))
|
enclose_xml_event(label_name, quote!(format!("{}", self.#label)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enclose_xml_event(label_name: String, yaserde_format: TokenStream) -> TokenStream {
|
fn enclose_xml_event(label_name: String, yaserde_format: TokenStream) -> TokenStream {
|
||||||
quote! {
|
quote! {
|
||||||
let start_event = XmlEvent::start_element(#label_name);
|
let start_event = XmlEvent::start_element(#label_name);
|
||||||
writer.write(start_event).map_err(|e| e.to_string())?;
|
writer.write(start_event).map_err(|e| e.to_string())?;
|
||||||
@ -41,34 +41,23 @@ pub fn serialize_element(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn condition_generator(label: &Option<Ident>, attributes: &YaSerdeAttribute) -> TokenStream {
|
pub fn condition_generator(label: &Option<Ident>, field: &YaSerdeField) -> TokenStream {
|
||||||
let mut conditions = None;
|
let default_condition = field
|
||||||
|
.get_default_function()
|
||||||
|
.map(|default_function| quote!(self.#label != #default_function()));
|
||||||
|
|
||||||
if let Some(ref d) = attributes.default {
|
field
|
||||||
let default_function = Ident::new(
|
.get_skip_serializing_if_function()
|
||||||
&d,
|
.map(|skip_if_function| {
|
||||||
label
|
if let Some(prev_conditions) = &default_condition {
|
||||||
.as_ref()
|
quote!(if !self.#skip_if_function(&self.#label) && #prev_conditions)
|
||||||
.map_or(Span::call_site(), |ident| ident.span()),
|
} else {
|
||||||
);
|
quote!(if !self.#skip_if_function(&self.#label))
|
||||||
|
}
|
||||||
conditions = Some(quote!(self.#label != #default_function()))
|
})
|
||||||
}
|
.unwrap_or_else(|| {
|
||||||
|
default_condition
|
||||||
if let Some(ref s) = attributes.skip_serializing_if {
|
.map(|condition| quote!(if #condition))
|
||||||
let skip_if_function = Ident::new(
|
.unwrap_or(quote!())
|
||||||
&s,
|
})
|
||||||
label
|
|
||||||
.as_ref()
|
|
||||||
.map_or(Span::call_site(), |ident| ident.span()),
|
|
||||||
);
|
|
||||||
|
|
||||||
conditions = if let Some(prev_conditions) = conditions {
|
|
||||||
Some(quote!(!#skip_if_function() && #prev_conditions))
|
|
||||||
} else {
|
|
||||||
Some(quote!(!self.#skip_if_function(&self.#label)))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
conditions.map(|c| quote!(if #c)).unwrap_or(quote!())
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
use crate::attribute::*;
|
use crate::common::{Field, YaSerdeAttribute, YaSerdeField};
|
||||||
use crate::field_type::*;
|
|
||||||
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::spanned::Spanned;
|
|
||||||
use syn::DataEnum;
|
use syn::DataEnum;
|
||||||
use syn::Fields;
|
use syn::Fields;
|
||||||
use syn::Ident;
|
use syn::Ident;
|
||||||
@ -51,39 +49,33 @@ 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| {
|
||||||
let field_attrs = YaSerdeAttribute::parse(&field.attrs);
|
let field_label = field.label();
|
||||||
if field_attrs.attribute {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let field_label = &field.ident;
|
if field.is_text_content() {
|
||||||
if field_attrs.text {
|
|
||||||
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 renamed_field_label = match field_attrs.rename {
|
let field_label_name = field.renamed_label(root_attributes);
|
||||||
Some(value) => Some(Ident::new(&value.replace("\"", ""), field.span())),
|
|
||||||
None => field.ident.clone(),
|
|
||||||
};
|
|
||||||
let field_label_name = renamed_field_label.unwrap().to_string();
|
|
||||||
|
|
||||||
match get_field_type(field) {
|
match field.get_type() {
|
||||||
Some(FieldType::FieldTypeString)
|
Field::FieldString
|
||||||
| Some(FieldType::FieldTypeBool)
|
| Field::FieldBool
|
||||||
| Some(FieldType::FieldTypeU8)
|
| Field::FieldU8
|
||||||
| Some(FieldType::FieldTypeI8)
|
| Field::FieldI8
|
||||||
| Some(FieldType::FieldTypeU16)
|
| Field::FieldU16
|
||||||
| Some(FieldType::FieldTypeI16)
|
| Field::FieldI16
|
||||||
| Some(FieldType::FieldTypeU32)
|
| Field::FieldU32
|
||||||
| Some(FieldType::FieldTypeI32)
|
| Field::FieldI32
|
||||||
| Some(FieldType::FieldTypeF32)
|
| Field::FieldF32
|
||||||
| Some(FieldType::FieldTypeU64)
|
| Field::FieldU64
|
||||||
| Some(FieldType::FieldTypeI64)
|
| Field::FieldI64
|
||||||
| Some(FieldType::FieldTypeF64) => Some({
|
| Field::FieldF64 => Some({
|
||||||
quote! {
|
quote! {
|
||||||
match self {
|
match self {
|
||||||
&#name::#label{ref #field_label, ..} => {
|
&#name::#label{ref #field_label, ..} => {
|
||||||
@ -101,7 +93,7 @@ fn inner_enum_inspector(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
Some(FieldType::FieldTypeStruct { .. }) => Some(quote! {
|
Field::FieldStruct { .. } => Some(quote! {
|
||||||
match self {
|
match self {
|
||||||
&#name::#label{ref #field_label, ..} => {
|
&#name::#label{ref #field_label, ..} => {
|
||||||
writer.set_start_event_name(Some(#field_label_name.to_string()));
|
writer.set_start_event_name(Some(#field_label_name.to_string()));
|
||||||
@ -111,7 +103,7 @@ fn inner_enum_inspector(
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
Some(FieldType::FieldTypeVec { .. }) => Some(quote! {
|
Field::FieldVec { .. } => Some(quote! {
|
||||||
match self {
|
match self {
|
||||||
&#name::#label{ref #field_label, ..} => {
|
&#name::#label{ref #field_label, ..} => {
|
||||||
for item in #field_label {
|
for item in #field_label {
|
||||||
@ -123,7 +115,7 @@ fn inner_enum_inspector(
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
_ => None,
|
Field::FieldOption { .. } => None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.filter_map(|x| x)
|
.filter_map(|x| x)
|
||||||
@ -139,12 +131,9 @@ fn inner_enum_inspector(
|
|||||||
let enum_fields: TokenStream = fields
|
let enum_fields: TokenStream = fields
|
||||||
.unnamed
|
.unnamed
|
||||||
.iter()
|
.iter()
|
||||||
|
.map(|field| YaSerdeField::new(field.clone()))
|
||||||
|
.filter(|field| !field.is_attribute())
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
let field_attrs = YaSerdeAttribute::parse(&field.attrs);
|
|
||||||
if field_attrs.attribute {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let write_element = |action: &TokenStream| {
|
let write_element = |action: &TokenStream| {
|
||||||
quote! {
|
quote! {
|
||||||
let struct_start_event = XmlEvent::start_element(#label_name);
|
let struct_start_event = XmlEvent::start_element(#label_name);
|
||||||
@ -176,7 +165,7 @@ fn inner_enum_inspector(
|
|||||||
|
|
||||||
let write_sub_type = |data_type| {
|
let write_sub_type = |data_type| {
|
||||||
write_element(match data_type {
|
write_element(match data_type {
|
||||||
FieldType::FieldTypeString => &write_string_chars,
|
Field::FieldString => &write_string_chars,
|
||||||
_ => &serialize,
|
_ => &serialize,
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
@ -192,8 +181,8 @@ fn inner_enum_inspector(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match get_field_type(field) {
|
match field.get_type() {
|
||||||
Some(FieldType::FieldTypeOption { data_type }) => {
|
Field::FieldOption { data_type } => {
|
||||||
let write = write_sub_type(*data_type);
|
let write = write_sub_type(*data_type);
|
||||||
|
|
||||||
Some(match_field("e! {
|
Some(match_field("e! {
|
||||||
@ -202,7 +191,7 @@ fn inner_enum_inspector(
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
Some(FieldType::FieldTypeVec { data_type }) => {
|
Field::FieldVec { data_type } => {
|
||||||
let write = write_sub_type(*data_type);
|
let write = write_sub_type(*data_type);
|
||||||
|
|
||||||
Some(match_field("e! {
|
Some(match_field("e! {
|
||||||
@ -211,14 +200,9 @@ fn inner_enum_inspector(
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
Some(FieldType::FieldTypeStruct { .. }) => {
|
Field::FieldStruct { .. } => Some(write_element(&match_field(&serialize))),
|
||||||
Some(write_element(&match_field(&serialize)))
|
Field::FieldString => Some(match_field(&write_element(&write_string_chars))),
|
||||||
}
|
_simple_type => Some(match_field(&write_simple_type)),
|
||||||
Some(FieldType::FieldTypeString) => {
|
|
||||||
Some(match_field(&write_element(&write_string_chars)))
|
|
||||||
}
|
|
||||||
Some(_simple_type) => Some(match_field(&write_simple_type)),
|
|
||||||
_ => None,
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.filter_map(|x| x)
|
.filter_map(|x| x)
|
||||||
|
|||||||
@ -1,10 +1,7 @@
|
|||||||
use crate::attribute::*;
|
use crate::common::{Field, YaSerdeAttribute, YaSerdeField};
|
||||||
use crate::field_type::*;
|
|
||||||
use crate::ser::{
|
use crate::ser::{element::*, implement_deserializer::implement_deserializer};
|
||||||
element::*, implement_deserializer::implement_deserializer, label::build_label_name,
|
|
||||||
};
|
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use syn::spanned::Spanned;
|
|
||||||
use syn::DataStruct;
|
use syn::DataStruct;
|
||||||
use syn::Ident;
|
use syn::Ident;
|
||||||
|
|
||||||
@ -17,193 +14,98 @@ 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_attrs.attribute {
|
let label_name = field.renamed_label(root_attributes);
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let label = &field.ident;
|
match field.get_type() {
|
||||||
|
Field::FieldString
|
||||||
let label_name = build_label_name(
|
| Field::FieldBool
|
||||||
&label.as_ref().unwrap(),
|
| Field::FieldI8
|
||||||
&field_attrs,
|
| Field::FieldU8
|
||||||
&root_attributes.default_namespace,
|
| Field::FieldI16
|
||||||
);
|
| Field::FieldU16
|
||||||
|
| Field::FieldI32
|
||||||
get_field_type(field).and_then(|f| match f {
|
| Field::FieldU32
|
||||||
FieldType::FieldTypeString
|
| Field::FieldI64
|
||||||
| FieldType::FieldTypeBool
|
| Field::FieldU64
|
||||||
| FieldType::FieldTypeI8
|
| Field::FieldF32
|
||||||
| FieldType::FieldTypeU8
|
| Field::FieldF64 => Some(field.ser_wrap_default_attribute(
|
||||||
| FieldType::FieldTypeI16
|
Some(quote!(self.#label.to_string())),
|
||||||
| FieldType::FieldTypeU16
|
quote!({
|
||||||
| FieldType::FieldTypeI32
|
struct_start_event.attr(#label_name, &yaserde_inner)
|
||||||
| FieldType::FieldTypeU32
|
}),
|
||||||
| FieldType::FieldTypeI64
|
)),
|
||||||
| FieldType::FieldTypeU64
|
Field::FieldOption { data_type } => match *data_type {
|
||||||
| FieldType::FieldTypeF32
|
Field::FieldString => Some(field.ser_wrap_default_attribute(
|
||||||
| FieldType::FieldTypeF64 => {
|
None,
|
||||||
if let Some(ref d) = field_attrs.default {
|
quote!({
|
||||||
let default_function = Ident::new(&d, field.span());
|
if let Some(ref value) = self.#label {
|
||||||
Some(quote! {
|
struct_start_event.attr(#label_name, value)
|
||||||
let content = self.#label.to_string();
|
} else {
|
||||||
let struct_start_event =
|
struct_start_event
|
||||||
if self.#label != #default_function() {
|
}
|
||||||
struct_start_event.attr(#label_name, &content)
|
}),
|
||||||
} else {
|
)),
|
||||||
struct_start_event
|
Field::FieldBool
|
||||||
};
|
| Field::FieldI8
|
||||||
})
|
| Field::FieldU8
|
||||||
} else {
|
| Field::FieldI16
|
||||||
Some(quote! {
|
| Field::FieldU16
|
||||||
let content = self.#label.to_string();
|
| Field::FieldI32
|
||||||
let struct_start_event = struct_start_event.attr(#label_name, &content);
|
| Field::FieldU32
|
||||||
})
|
| Field::FieldI64
|
||||||
}
|
| Field::FieldU64
|
||||||
}
|
| Field::FieldF32
|
||||||
FieldType::FieldTypeOption { data_type } => match *data_type {
|
| Field::FieldF64 => Some(field.ser_wrap_default_attribute(
|
||||||
FieldType::FieldTypeString => {
|
Some(quote!(self.#label.map_or_else(|| String::new(), |v| v.to_string()))),
|
||||||
if let Some(ref d) = field_attrs.default {
|
quote!({
|
||||||
let default_function = Ident::new(&d, field.span());
|
if let Some(ref value) = self.#label {
|
||||||
Some(quote! {
|
struct_start_event.attr(#label_name, &yaserde_inner)
|
||||||
let struct_start_event =
|
} else {
|
||||||
if self.#label != #default_function() {
|
struct_start_event
|
||||||
if let Some(ref value) = self.#label {
|
}
|
||||||
struct_start_event.attr(#label_name, &value)
|
}),
|
||||||
} else {
|
)),
|
||||||
struct_start_event
|
Field::FieldVec { .. } => {
|
||||||
}
|
let item_ident = Ident::new("yaserde_item", field.get_span());
|
||||||
} 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
|
|
||||||
};
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FieldType::FieldTypeBool
|
|
||||||
| FieldType::FieldTypeI8
|
|
||||||
| FieldType::FieldTypeU8
|
|
||||||
| FieldType::FieldTypeI16
|
|
||||||
| FieldType::FieldTypeU16
|
|
||||||
| FieldType::FieldTypeI32
|
|
||||||
| FieldType::FieldTypeU32
|
|
||||||
| FieldType::FieldTypeI64
|
|
||||||
| FieldType::FieldTypeU64
|
|
||||||
| FieldType::FieldTypeF32
|
|
||||||
| FieldType::FieldTypeF64 => {
|
|
||||||
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
|
|
||||||
};
|
|
||||||
})
|
|
||||||
} 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
|
|
||||||
};
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FieldType::FieldTypeVec { .. } => {
|
|
||||||
let item_ident = Ident::new("yaserde_item", field.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());
|
None,
|
||||||
|
quote!({
|
||||||
Some(quote! {
|
if let Some(ref yaserde_list) = self.#label {
|
||||||
if self.#label != #default_function() {
|
for yaserde_item in yaserde_list.iter() {
|
||||||
if let Some(ref yaserde_list) = self.#label {
|
#inner
|
||||||
for yaserde_item in yaserde_list.iter() {
|
|
||||||
#inner
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}),
|
||||||
} else {
|
))
|
||||||
Some(quote! {
|
|
||||||
for yaserde_item in &self.#label {
|
|
||||||
#inner
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
FieldType::FieldTypeStruct { .. } => {
|
Field::FieldStruct { .. } => Some(field.ser_wrap_default_attribute(
|
||||||
if let Some(ref d) = field_attrs.default {
|
Some(quote!(self.#label
|
||||||
let default_function = Ident::new(&d, field.span());
|
|
||||||
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
|
)),
|
||||||
};
|
Field::FieldOption { .. } => unimplemented!(),
|
||||||
})
|
|
||||||
} 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!(),
|
|
||||||
},
|
},
|
||||||
FieldType::FieldTypeStruct { .. } => {
|
Field::FieldStruct { .. } => Some(field.ser_wrap_default_attribute(
|
||||||
if let Some(ref d) = field_attrs.default {
|
Some(quote!(yaserde::ser::to_string_content(&self.#label)?)),
|
||||||
let default_function = Ident::new(&d, field.span());
|
quote!({
|
||||||
Some(quote! {
|
struct_start_event.attr(#label_name, &yaserde_inner)
|
||||||
let content = yaserde::ser::to_string_content(&self.#label)?;
|
}),
|
||||||
let struct_start_event =
|
)),
|
||||||
if self.#label != #default_function() {
|
Field::FieldVec { .. } => None,
|
||||||
struct_start_event.attr(#label_name, &content)
|
}
|
||||||
} else {
|
|
||||||
struct_start_event
|
|
||||||
};
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Some(quote! {
|
|
||||||
let content = yaserde::ser::to_string_content(&self.#label)?;
|
|
||||||
let struct_start_event = struct_start_event.attr(#label_name, &content);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.filter_map(|x| x)
|
.filter_map(|x| x)
|
||||||
.collect();
|
.collect();
|
||||||
@ -211,54 +113,48 @@ pub fn serialize(
|
|||||||
let struct_inspector: TokenStream = data_struct
|
let struct_inspector: 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_attrs.attribute {
|
if field.is_text_content() {
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let label = &field.ident;
|
|
||||||
if field_attrs.text {
|
|
||||||
return Some(quote!(
|
return Some(quote!(
|
||||||
let data_event = XmlEvent::characters(&self.#label);
|
let data_event = XmlEvent::characters(&self.#label);
|
||||||
writer.write(data_event).map_err(|e| e.to_string())?;
|
writer.write(data_event).map_err(|e| e.to_string())?;
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let label_name = build_label_name(
|
let label_name = field.renamed_label(root_attributes);
|
||||||
&label.as_ref().unwrap(),
|
let conditions = condition_generator(&label, &field);
|
||||||
&field_attrs,
|
|
||||||
&root_attributes.default_namespace,
|
|
||||||
);
|
|
||||||
let conditions = condition_generator(label, &field_attrs);
|
|
||||||
|
|
||||||
get_field_type(field).and_then(|f| match f {
|
match field.get_type() {
|
||||||
FieldType::FieldTypeString
|
Field::FieldString
|
||||||
| FieldType::FieldTypeBool
|
| Field::FieldBool
|
||||||
| FieldType::FieldTypeI8
|
| Field::FieldI8
|
||||||
| FieldType::FieldTypeU8
|
| Field::FieldU8
|
||||||
| FieldType::FieldTypeI16
|
| Field::FieldI16
|
||||||
| FieldType::FieldTypeU16
|
| Field::FieldU16
|
||||||
| FieldType::FieldTypeI32
|
| Field::FieldI32
|
||||||
| FieldType::FieldTypeU32
|
| Field::FieldU32
|
||||||
| FieldType::FieldTypeI64
|
| Field::FieldI64
|
||||||
| FieldType::FieldTypeU64
|
| Field::FieldU64
|
||||||
| FieldType::FieldTypeF32
|
| Field::FieldF32
|
||||||
| FieldType::FieldTypeF64 => serialize_element(label, label_name, &conditions),
|
| Field::FieldF64 => serialize_element(&label, label_name, &conditions),
|
||||||
FieldType::FieldTypeOption { data_type } => match *data_type {
|
|
||||||
FieldType::FieldTypeString
|
Field::FieldOption { data_type } => match *data_type {
|
||||||
| FieldType::FieldTypeBool
|
Field::FieldString
|
||||||
| FieldType::FieldTypeI8
|
| Field::FieldBool
|
||||||
| FieldType::FieldTypeU8
|
| Field::FieldI8
|
||||||
| FieldType::FieldTypeI16
|
| Field::FieldU8
|
||||||
| FieldType::FieldTypeU16
|
| Field::FieldI16
|
||||||
| FieldType::FieldTypeI32
|
| Field::FieldU16
|
||||||
| FieldType::FieldTypeU32
|
| Field::FieldI32
|
||||||
| FieldType::FieldTypeI64
|
| Field::FieldU32
|
||||||
| FieldType::FieldTypeU64
|
| Field::FieldI64
|
||||||
| FieldType::FieldTypeF32
|
| Field::FieldU64
|
||||||
| FieldType::FieldTypeF64 => {
|
| Field::FieldF32
|
||||||
let item_ident = Ident::new("yaserde_item", field.span());
|
| Field::FieldF64 => {
|
||||||
|
let item_ident = Ident::new("yaserde_item", field.get_span());
|
||||||
let inner = enclose_formatted_characters_for_value(&item_ident, label_name);
|
let inner = enclose_formatted_characters_for_value(&item_ident, label_name);
|
||||||
|
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
@ -269,8 +165,8 @@ pub fn serialize(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
FieldType::FieldTypeVec { .. } => {
|
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_for_value(&item_ident, label_name);
|
let inner = enclose_formatted_characters_for_value(&item_ident, label_name);
|
||||||
|
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
@ -283,7 +179,7 @@ pub fn serialize(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
FieldType::FieldTypeStruct { .. } => Some(if field_attrs.flatten {
|
Field::FieldStruct { .. } => Some(if field.is_flatten() {
|
||||||
quote! {
|
quote! {
|
||||||
if let Some(ref item) = &self.#label {
|
if let Some(ref item) = &self.#label {
|
||||||
writer.set_start_event_name(None);
|
writer.set_start_event_name(None);
|
||||||
@ -302,8 +198,8 @@ pub fn serialize(
|
|||||||
}),
|
}),
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
},
|
},
|
||||||
FieldType::FieldTypeStruct { .. } => {
|
Field::FieldStruct { .. } => {
|
||||||
let (start_event, skip_start) = if field_attrs.flatten {
|
let (start_event, skip_start) = if field.is_flatten() {
|
||||||
(quote!(None), true)
|
(quote!(None), true)
|
||||||
} else {
|
} else {
|
||||||
(quote!(Some(#label_name.to_string())), false)
|
(quote!(Some(#label_name.to_string())), false)
|
||||||
@ -315,9 +211,9 @@ pub fn serialize(
|
|||||||
self.#label.serialize(writer)?;
|
self.#label.serialize(writer)?;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
FieldType::FieldTypeVec { data_type } => match *data_type {
|
Field::FieldVec { data_type } => match *data_type {
|
||||||
FieldType::FieldTypeString => {
|
Field::FieldString => {
|
||||||
let item_ident = Ident::new("yaserde_item", field.span());
|
let item_ident = Ident::new("yaserde_item", field.get_span());
|
||||||
let inner = enclose_formatted_characters_for_value(&item_ident, label_name);
|
let inner = enclose_formatted_characters_for_value(&item_ident, label_name);
|
||||||
|
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
@ -326,18 +222,18 @@ pub fn serialize(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
FieldType::FieldTypeBool
|
Field::FieldBool
|
||||||
| FieldType::FieldTypeI8
|
| Field::FieldI8
|
||||||
| FieldType::FieldTypeU8
|
| Field::FieldU8
|
||||||
| FieldType::FieldTypeI16
|
| Field::FieldI16
|
||||||
| FieldType::FieldTypeU16
|
| Field::FieldU16
|
||||||
| FieldType::FieldTypeI32
|
| Field::FieldI32
|
||||||
| FieldType::FieldTypeU32
|
| Field::FieldU32
|
||||||
| FieldType::FieldTypeI64
|
| Field::FieldI64
|
||||||
| FieldType::FieldTypeU64
|
| Field::FieldU64
|
||||||
| FieldType::FieldTypeF32
|
| Field::FieldF32
|
||||||
| FieldType::FieldTypeF64 => {
|
| Field::FieldF64 => {
|
||||||
let item_ident = Ident::new("yaserde_item", field.span());
|
let item_ident = Ident::new("yaserde_item", field.get_span());
|
||||||
let inner = enclose_formatted_characters_for_value(&item_ident, label_name);
|
let inner = enclose_formatted_characters_for_value(&item_ident, label_name);
|
||||||
|
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
@ -346,7 +242,7 @@ pub fn serialize(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
FieldType::FieldTypeOption { .. } => Some(quote! {
|
Field::FieldOption { .. } => Some(quote! {
|
||||||
for item in &self.#label {
|
for item in &self.#label {
|
||||||
if let Some(value) = item {
|
if let Some(value) = item {
|
||||||
writer.set_start_event_name(None);
|
writer.set_start_event_name(None);
|
||||||
@ -355,18 +251,18 @@ pub fn serialize(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
FieldType::FieldTypeStruct { .. } => Some(quote! {
|
Field::FieldStruct { .. } => Some(quote! {
|
||||||
for item in &self.#label {
|
for item in &self.#label {
|
||||||
writer.set_start_event_name(None);
|
writer.set_start_event_name(None);
|
||||||
writer.set_skip_start_end(false);
|
writer.set_skip_start_end(false);
|
||||||
item.serialize(writer)?;
|
item.serialize(writer)?;
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
FieldType::FieldTypeVec { .. } => {
|
Field::FieldVec { .. } => {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
})
|
})
|
||||||
.filter_map(|x| x)
|
.filter_map(|x| x)
|
||||||
.collect();
|
.collect();
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use crate::attribute::YaSerdeAttribute;
|
use crate::common::YaSerdeAttribute;
|
||||||
use crate::ser::namespace::generate_namespaces_definition;
|
use crate::ser::namespace::generate_namespaces_definition;
|
||||||
use proc_macro2::Ident;
|
use proc_macro2::Ident;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use crate::attribute::YaSerdeAttribute;
|
use crate::common::YaSerdeAttribute;
|
||||||
use proc_macro2::Ident;
|
use proc_macro2::Ident;
|
||||||
|
|
||||||
pub fn build_label_name(
|
pub fn build_label_name(
|
||||||
|
|||||||
@ -5,7 +5,7 @@ pub mod implement_deserializer;
|
|||||||
pub mod label;
|
pub mod label;
|
||||||
pub mod namespace;
|
pub mod namespace;
|
||||||
|
|
||||||
use crate::attribute::YaSerdeAttribute;
|
use crate::common::YaSerdeAttribute;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use syn;
|
use syn;
|
||||||
use syn::Ident;
|
use syn::Ident;
|
||||||
@ -15,25 +15,30 @@ pub fn expand_derive_serialize(ast: &syn::DeriveInput) -> Result<TokenStream, St
|
|||||||
let attrs = &ast.attrs;
|
let attrs = &ast.attrs;
|
||||||
let data = &ast.data;
|
let data = &ast.data;
|
||||||
|
|
||||||
let root_attrs = YaSerdeAttribute::parse(attrs);
|
let root_attributes = YaSerdeAttribute::parse(attrs);
|
||||||
let root = root_attrs.clone().root.unwrap_or_else(|| name.to_string());
|
let root_name = root_attributes
|
||||||
|
.clone()
|
||||||
|
.rename
|
||||||
|
.unwrap_or_else(|| name.to_string());
|
||||||
|
|
||||||
let prefix = if root_attrs.default_namespace == root_attrs.prefix {
|
let prefix = if root_attributes.default_namespace == root_attributes.prefix {
|
||||||
"".to_string()
|
"".to_string()
|
||||||
} else {
|
} else {
|
||||||
root_attrs
|
root_attributes
|
||||||
.clone()
|
.clone()
|
||||||
.prefix
|
.prefix
|
||||||
.map_or("".to_string(), |prefix| prefix + ":")
|
.map_or("".to_string(), |prefix| prefix + ":")
|
||||||
};
|
};
|
||||||
|
|
||||||
let root = format!("{}{}", prefix, root);
|
let root_name = format!("{}{}", prefix, root_name);
|
||||||
|
|
||||||
let impl_block = match *data {
|
let impl_block = match *data {
|
||||||
syn::Data::Struct(ref data_struct) => {
|
syn::Data::Struct(ref data_struct) => {
|
||||||
expand_struct::serialize(data_struct, name, &root, &root_attrs)
|
expand_struct::serialize(data_struct, name, &root_name, &root_attributes)
|
||||||
|
}
|
||||||
|
syn::Data::Enum(ref data_enum) => {
|
||||||
|
expand_enum::serialize(data_enum, name, &root_name, &root_attributes)
|
||||||
}
|
}
|
||||||
syn::Data::Enum(ref data_enum) => expand_enum::serialize(data_enum, name, &root, &root_attrs),
|
|
||||||
syn::Data::Union(ref _data_union) => unimplemented!(),
|
syn::Data::Union(ref _data_union) => unimplemented!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use crate::attribute::YaSerdeAttribute;
|
use crate::common::YaSerdeAttribute;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
|
|
||||||
pub fn generate_namespaces_definition(attributes: &YaSerdeAttribute) -> TokenStream {
|
pub fn generate_namespaces_definition(attributes: &YaSerdeAttribute) -> TokenStream {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user