Merge pull request #97 from lumeohq/macro-refactor

Refactor macro code
This commit is contained in:
Marc-Antoine ARNAUD 2021-01-08 09:49:26 +01:00 committed by GitHub
commit 2ee3dcda42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 365 additions and 349 deletions

View File

@ -48,7 +48,7 @@ impl<'de, R: Read> Deserializer<R> {
if let Some(ref next) = self.peeked { if let Some(ref next) = self.peeked {
Ok(next) Ok(next)
} else { } else {
Err(String::from("unable to peek next item")) Err("unable to peek next item".into())
} }
} }

View File

@ -19,13 +19,12 @@ pub mod ser;
/// A **data structure** that can be deserialized from any data format supported by YaSerDe. /// A **data structure** that can be deserialized from any data format supported by YaSerDe.
pub trait YaDeserialize: Sized { pub trait YaDeserialize: Sized {
fn deserialize<R: Read>(reader: &mut de::Deserializer<R>) -> Result<Self, std::string::String>; fn deserialize<R: Read>(reader: &mut de::Deserializer<R>) -> Result<Self, String>;
} }
/// A **data structure** that can be serialized into any data format supported by YaSerDe. /// A **data structure** that can be serialized into any data format supported by YaSerDe.
pub trait YaSerialize: Sized { pub trait YaSerialize: Sized {
fn serialize<W: Write>(&self, writer: &mut ser::Serializer<W>) fn serialize<W: Write>(&self, writer: &mut ser::Serializer<W>) -> Result<(), String>;
-> Result<(), std::string::String>;
fn serialize_attributes( fn serialize_attributes(
&self, &self,
@ -36,7 +35,7 @@ pub trait YaSerialize: Sized {
Vec<xml::attribute::OwnedAttribute>, Vec<xml::attribute::OwnedAttribute>,
xml::namespace::Namespace, xml::namespace::Namespace,
), ),
std::string::String, String,
>; >;
} }
@ -45,51 +44,51 @@ pub trait Visitor<'de>: Sized {
/// The value produced by this visitor. /// The value produced by this visitor.
type Value; type Value;
fn visit_bool(self, v: &str) -> Result<Self::Value, std::string::String> { fn visit_bool(self, v: &str) -> Result<Self::Value, String> {
Err(format!("Unexpected bool {:?}", v)) Err(format!("Unexpected bool {:?}", v))
} }
fn visit_i8(self, v: &str) -> Result<Self::Value, std::string::String> { fn visit_i8(self, v: &str) -> Result<Self::Value, String> {
Err(format!("Unexpected i8 {:?}", v)) Err(format!("Unexpected i8 {:?}", v))
} }
fn visit_u8(self, v: &str) -> Result<Self::Value, std::string::String> { fn visit_u8(self, v: &str) -> Result<Self::Value, String> {
Err(format!("Unexpected u8 {:?}", v)) Err(format!("Unexpected u8 {:?}", v))
} }
fn visit_i16(self, v: &str) -> Result<Self::Value, std::string::String> { fn visit_i16(self, v: &str) -> Result<Self::Value, String> {
Err(format!("Unexpected i16 {:?}", v)) Err(format!("Unexpected i16 {:?}", v))
} }
fn visit_u16(self, v: &str) -> Result<Self::Value, std::string::String> { fn visit_u16(self, v: &str) -> Result<Self::Value, String> {
Err(format!("Unexpected u16 {:?}", v)) Err(format!("Unexpected u16 {:?}", v))
} }
fn visit_i32(self, v: &str) -> Result<Self::Value, std::string::String> { fn visit_i32(self, v: &str) -> Result<Self::Value, String> {
Err(format!("Unexpected i32 {:?}", v)) Err(format!("Unexpected i32 {:?}", v))
} }
fn visit_u32(self, v: &str) -> Result<Self::Value, std::string::String> { fn visit_u32(self, v: &str) -> Result<Self::Value, String> {
Err(format!("Unexpected u32 {:?}", v)) Err(format!("Unexpected u32 {:?}", v))
} }
fn visit_i64(self, v: &str) -> Result<Self::Value, std::string::String> { fn visit_i64(self, v: &str) -> Result<Self::Value, String> {
Err(format!("Unexpected i64 {:?}", v)) Err(format!("Unexpected i64 {:?}", v))
} }
fn visit_u64(self, v: &str) -> Result<Self::Value, std::string::String> { fn visit_u64(self, v: &str) -> Result<Self::Value, String> {
Err(format!("Unexpected u64 {:?}", v)) Err(format!("Unexpected u64 {:?}", v))
} }
fn visit_f32(self, v: &str) -> Result<Self::Value, std::string::String> { fn visit_f32(self, v: &str) -> Result<Self::Value, String> {
Err(format!("Unexpected f32 {:?}", v)) Err(format!("Unexpected f32 {:?}", v))
} }
fn visit_f64(self, v: &str) -> Result<Self::Value, std::string::String> { fn visit_f64(self, v: &str) -> Result<Self::Value, String> {
Err(format!("Unexpected f64 {:?}", v)) Err(format!("Unexpected f64 {:?}", v))
} }
fn visit_str(self, v: &str) -> Result<Self::Value, std::string::String> { fn visit_str(self, v: &str) -> Result<Self::Value, String> {
Err(format!("Unexpected str {:?}", v)) Err(format!("Unexpected str {:?}", v))
} }
} }
@ -97,10 +96,7 @@ pub trait Visitor<'de>: Sized {
macro_rules! serialize_type { macro_rules! serialize_type {
($type:ty) => { ($type:ty) => {
impl YaSerialize for $type { impl YaSerialize for $type {
fn serialize<W: Write>( fn serialize<W: Write>(&self, writer: &mut ser::Serializer<W>) -> Result<(), String> {
&self,
writer: &mut ser::Serializer<W>,
) -> Result<(), std::string::String> {
let content = format!("{}", self); let content = format!("{}", self);
let event = XmlEvent::characters(&content); let event = XmlEvent::characters(&content);
let _ret = writer.write(event); let _ret = writer.write(event);
@ -116,7 +112,7 @@ macro_rules! serialize_type {
Vec<xml::attribute::OwnedAttribute>, Vec<xml::attribute::OwnedAttribute>,
xml::namespace::Namespace, xml::namespace::Namespace,
), ),
std::string::String, String,
> { > {
Ok((attributes, namespace)) Ok((attributes, namespace))
} }
@ -182,9 +178,10 @@ mod testing {
let model = Data { item: $value }; let model = Data { item: $value };
let content = if let Some(str_value) = $content { let content = if let Some(str_value) = $content {
std::string::String::from("<data><item>") + str_value + "</item></data>" let str_value: &str = str_value;
format!("<data><item>{}</item></data>", str_value)
} else { } else {
std::string::String::from("<data />") "<data />".to_owned()
}; };
serialize_and_validate!(model, content); serialize_and_validate!(model, content);
@ -218,7 +215,7 @@ mod testing {
macro_rules! deserialize_and_validate { macro_rules! deserialize_and_validate {
($content: expr, $model: expr, $struct: tt) => { ($content: expr, $model: expr, $struct: tt) => {
log::debug!("deserialize_and_validate @ {}:{}", file!(), line!()); log::debug!("deserialize_and_validate @ {}:{}", file!(), line!());
let loaded: Result<$struct, std::string::String> = yaserde::de::from_str($content); let loaded: Result<$struct, String> = yaserde::de::from_str($content);
assert_eq!(loaded, Ok($model)); assert_eq!(loaded, Ok($model));
}; };
} }
@ -227,18 +224,12 @@ mod testing {
macro_rules! serialize_and_validate { macro_rules! serialize_and_validate {
($model: expr, $content: expr) => { ($model: expr, $content: expr) => {
log::debug!("serialize_and_validate @ {}:{}", file!(), line!()); log::debug!("serialize_and_validate @ {}:{}", file!(), line!());
let data: Result<std::string::String, std::string::String> = yaserde::ser::to_string(&$model); let data: Result<String, String> = yaserde::ser::to_string(&$model);
let content = let content = format!(r#"<?xml version="1.0" encoding="utf-8"?>{}"#, $content);
std::string::String::from(r#"<?xml version="1.0" encoding="utf-8"?>"#) + &$content;
assert_eq!( assert_eq!(
data, data,
Ok( Ok(content.split("\n").map(|s| s.trim()).collect::<String>())
std::string::String::from(content)
.split("\n")
.map(|s| s.trim())
.collect::<std::string::String>()
)
); );
}; };
} }

View File

@ -11,14 +11,14 @@ pub fn to_string<T: YaSerialize>(model: &T) -> Result<String, String> {
let buf = Cursor::new(Vec::new()); let buf = Cursor::new(Vec::new());
let cursor = serialize_with_writer(model, buf, &Config::default())?; let cursor = serialize_with_writer(model, buf, &Config::default())?;
let data = str::from_utf8(cursor.get_ref()).expect("Found invalid UTF-8"); let data = str::from_utf8(cursor.get_ref()).expect("Found invalid UTF-8");
Ok(std::string::String::from(data)) Ok(data.into())
} }
pub fn to_string_with_config<T: YaSerialize>(model: &T, config: &Config) -> Result<String, String> { pub fn to_string_with_config<T: YaSerialize>(model: &T, config: &Config) -> Result<String, String> {
let buf = Cursor::new(Vec::new()); let buf = Cursor::new(Vec::new());
let cursor = serialize_with_writer(model, buf, config)?; let cursor = serialize_with_writer(model, buf, config)?;
let data = str::from_utf8(cursor.get_ref()).expect("Found invalid UTF-8"); let data = str::from_utf8(cursor.get_ref()).expect("Found invalid UTF-8");
Ok(std::string::String::from(data)) Ok(data.into())
} }
pub fn serialize_with_writer<W: Write, T: YaSerialize>( pub fn serialize_with_writer<W: Write, T: YaSerialize>(
@ -37,7 +37,7 @@ pub fn to_string_content<T: YaSerialize>(model: &T) -> Result<String, String> {
let buf = Cursor::new(Vec::new()); let buf = Cursor::new(Vec::new());
let cursor = serialize_with_writer_content(model, buf)?; let cursor = serialize_with_writer_content(model, buf)?;
let data = str::from_utf8(cursor.get_ref()).expect("Found invalid UTF-8"); let data = str::from_utf8(cursor.get_ref()).expect("Found invalid UTF-8");
Ok(std::string::String::from(data)) Ok(data.into())
} }
pub fn serialize_with_writer_content<W: Write, T: YaSerialize>( pub fn serialize_with_writer_content<W: Write, T: YaSerialize>(

View File

@ -3,9 +3,6 @@ extern crate yaserde;
#[macro_use] #[macro_use]
extern crate yaserde_derive; extern crate yaserde_derive;
use std::io::{Read, Write};
use yaserde::{YaDeserialize, YaSerialize};
fn init() { fn init() {
let _ = env_logger::builder().is_test(true).try_init(); let _ = env_logger::builder().is_test(true).try_init();
} }
@ -128,8 +125,6 @@ fn module_inclusion() {
init(); init();
mod module { mod module {
use super::*;
#[derive(Debug, Default, PartialEq, YaDeserialize, YaSerialize)] #[derive(Debug, Default, PartialEq, YaDeserialize, YaSerialize)]
#[yaserde(rename = "module")] #[yaserde(rename = "module")]
pub struct Module { pub struct Module {

View File

@ -4,9 +4,9 @@ extern crate yaserde;
extern crate yaserde_derive; extern crate yaserde_derive;
use log::debug; use log::debug;
use std::io::{Read, Write}; use std::io::Read;
use yaserde::de::from_str; use yaserde::de::from_str;
use yaserde::{YaDeserialize, YaSerialize}; use yaserde::YaDeserialize;
fn init() { fn init() {
let _ = env_logger::builder().is_test(true).try_init(); let _ = env_logger::builder().is_test(true).try_init();
@ -15,7 +15,7 @@ fn init() {
macro_rules! convert_and_validate { macro_rules! convert_and_validate {
($content: expr, $struct: tt, $model: expr) => { ($content: expr, $struct: tt, $model: expr) => {
debug!("convert_and_validate @ {}:{}", file!(), line!()); debug!("convert_and_validate @ {}:{}", file!(), line!());
let loaded: Result<$struct, std::string::String> = from_str($content); let loaded: Result<$struct, String> = from_str($content);
assert_eq!(loaded, Ok($model)); assert_eq!(loaded, Ok($model));
}; };
} }
@ -37,8 +37,8 @@ fn de_basic() {
content, content,
Book, Book,
Book { Book {
author: String::from("Antoine de Saint-Exupéry"), author: "Antoine de Saint-Exupéry".to_owned(),
title: String::from("Little prince"), title: "Little prince".to_owned(),
} }
); );
@ -48,8 +48,8 @@ fn de_basic() {
content, content,
Book, Book,
Book { Book {
author: String::from("Antoine de Saint-Exupéry"), author: "Antoine de Saint-Exupéry".to_owned(),
title: String::from("Little prince"), title: "Little prince".to_owned(),
} }
); );
} }
@ -93,8 +93,8 @@ fn de_dash_param() {
content, content,
Book, Book,
Book { Book {
author: String::from("Antoine de Saint-Exupéry"), author: "Antoine de Saint-Exupéry".to_owned(),
title: String::from("Little prince"), title: "Little prince".to_owned(),
} }
); );
@ -104,8 +104,8 @@ fn de_dash_param() {
content, content,
Book, Book,
Book { Book {
author: String::from("Antoine de Saint-Exupéry"), author: "Antoine de Saint-Exupéry".to_owned(),
title: String::from("Little prince"), title: "Little prince".to_owned(),
} }
); );
} }
@ -115,21 +115,18 @@ fn de_multiple_segments() {
init(); init();
mod other_mod { mod other_mod {
use std::io::Read;
use yaserde::YaDeserialize;
#[derive(YaDeserialize, PartialEq, Debug, Default)] #[derive(YaDeserialize, PartialEq, Debug, Default)]
pub struct Page { pub struct Page {
pub number: i32, pub number: i32,
pub text: std::string::String, pub text: String,
} }
} }
#[derive(YaDeserialize, PartialEq, Debug)] #[derive(YaDeserialize, PartialEq, Debug)]
#[yaserde(root = "book")] #[yaserde(root = "book")]
pub struct Book { pub struct Book {
author: std::string::String, author: String,
title: std::string::String, title: String,
page: other_mod::Page, page: other_mod::Page,
} }
@ -148,11 +145,11 @@ fn de_multiple_segments() {
content, content,
Book, Book,
Book { Book {
author: String::from("Antoine de Saint-Exupéry"), author: "Antoine de Saint-Exupéry".to_owned(),
title: String::from("Little prince"), title: "Little prince".to_owned(),
page: other_mod::Page { page: other_mod::Page {
number: 40, number: 40,
text: String::from("The Earth is not just an ordinary planet!"), text: "The Earth is not just an ordinary planet!".to_owned(),
}, },
} }
); );
@ -173,7 +170,7 @@ fn de_list_of_items() {
content, content,
Library, Library,
Library { Library {
books: vec![String::from("Little Prince"), String::from("Harry Potter")], books: vec!["Little Prince".to_owned(), "Harry Potter".to_owned()],
} }
); );
@ -190,10 +187,10 @@ fn de_list_of_items() {
Libraries { Libraries {
library: vec![ library: vec![
Library { Library {
books: vec![String::from("Little Prince")], books: vec!["Little Prince".to_owned()],
}, },
Library { Library {
books: vec![String::from("Harry Potter")], books: vec!["Harry Potter".to_owned()],
}, },
], ],
} }
@ -280,7 +277,7 @@ fn de_attributes_custom_deserializer() {
#[derive(Default, YaDeserialize, PartialEq, Debug)] #[derive(Default, YaDeserialize, PartialEq, Debug)]
pub struct Struct { pub struct Struct {
#[yaserde(attribute)] #[yaserde(attribute)]
attr_option_string: Option<std::string::String>, attr_option_string: Option<String>,
#[yaserde(attribute)] #[yaserde(attribute)]
attr_option_struct: Option<other_mod::Attributes>, attr_option_struct: Option<other_mod::Attributes>,
} }
@ -311,8 +308,6 @@ fn de_attributes_complex() {
init(); init();
mod other_mod { mod other_mod {
use super::*;
#[derive(YaDeserialize, PartialEq, Debug)] #[derive(YaDeserialize, PartialEq, Debug)]
pub enum AttrEnum { pub enum AttrEnum {
#[yaserde(rename = "variant 1")] #[yaserde(rename = "variant 1")]
@ -331,7 +326,7 @@ fn de_attributes_complex() {
#[derive(Default, YaDeserialize, PartialEq, Debug)] #[derive(Default, YaDeserialize, PartialEq, Debug)]
pub struct Struct { pub struct Struct {
#[yaserde(attribute)] #[yaserde(attribute)]
attr_option_string: Option<std::string::String>, attr_option_string: Option<String>,
#[yaserde(attribute)] #[yaserde(attribute)]
attr_option_enum: Option<other_mod::AttrEnum>, attr_option_enum: Option<other_mod::AttrEnum>,
} }
@ -564,7 +559,7 @@ fn de_complex_enum() {
pub enum Color { pub enum Color {
White, White,
Black(String), Black(String),
Orange(std::string::String), Orange(String),
Red(i32), Red(i32),
Green(OtherStruct), Green(OtherStruct),
Yellow(Option<String>), Yellow(Option<String>),
@ -595,7 +590,7 @@ fn de_complex_enum() {
content, content,
XmlStruct, XmlStruct,
XmlStruct { XmlStruct {
background: Color::Black(String::from("text")), background: Color::Black("text".to_owned()),
} }
); );
@ -610,7 +605,7 @@ fn de_complex_enum() {
content, content,
XmlStruct, XmlStruct,
XmlStruct { XmlStruct {
background: Color::Orange(String::from("text")), background: Color::Orange("text".to_owned()),
} }
); );
@ -658,7 +653,7 @@ fn de_complex_enum() {
content, content,
XmlStruct, XmlStruct,
XmlStruct { XmlStruct {
background: Color::Yellow(Some(String::from("text"))), background: Color::Yellow(Some("text".to_owned())),
} }
); );
@ -692,7 +687,7 @@ fn de_complex_enum() {
content, content,
XmlStruct, XmlStruct,
XmlStruct { XmlStruct {
background: Color::Blue(vec![String::from("abc"), String::from("def")]), background: Color::Blue(vec!["abc".to_owned(), "def".to_owned()]),
} }
); );
@ -781,7 +776,7 @@ fn de_name_issue_21() {
content, content,
Book, Book,
Book { Book {
name: String::from("Little prince"), name: "Little prince".to_owned(),
} }
); );
} }
@ -806,13 +801,11 @@ fn de_custom() {
} }
impl YaDeserialize for Day { impl YaDeserialize for Day {
fn deserialize<R: Read>( fn deserialize<R: Read>(reader: &mut yaserde::de::Deserializer<R>) -> Result<Self, String> {
reader: &mut yaserde::de::Deserializer<R>,
) -> Result<Self, std::string::String> {
use std::str::FromStr; use std::str::FromStr;
if let xml::reader::XmlEvent::StartElement { name, .. } = reader.peek()?.to_owned() { if let xml::reader::XmlEvent::StartElement { name, .. } = reader.peek()?.to_owned() {
let expected_name = String::from("Day"); let expected_name = "Day".to_owned();
if name.local_name != expected_name { if name.local_name != expected_name {
return Err(format!( return Err(format!(
"Wrong StartElement name: {}, expected: {}", "Wrong StartElement name: {}, expected: {}",

View File

@ -3,9 +3,6 @@ extern crate yaserde;
#[macro_use] #[macro_use]
extern crate yaserde_derive; extern crate yaserde_derive;
use std::io::{Read, Write};
use yaserde::{YaDeserialize, YaSerialize};
#[test] #[test]
fn basic_enum() { fn basic_enum() {
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)] #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
@ -168,7 +165,7 @@ fn unnamed_enum() {
pub enum Enum { pub enum Enum {
Simple, Simple,
Field(String), Field(String),
FullPath(std::string::String), FullPath(String),
Integer(i32), Integer(i32),
UserStruct(OtherStruct), UserStruct(OtherStruct),
OptionString(Option<String>), OptionString(Option<String>),
@ -189,7 +186,7 @@ fn unnamed_enum() {
} }
let model = XmlStruct { let model = XmlStruct {
color: Enum::Field(String::from("some_text")), color: Enum::Field("some_text".to_owned()),
}; };
let content = "<base><color><Field>some_text</Field></color></base>"; let content = "<base><color><Field>some_text</Field></color></base>";
@ -197,7 +194,7 @@ fn unnamed_enum() {
deserialize_and_validate!(content, model, XmlStruct); deserialize_and_validate!(content, model, XmlStruct);
let model = XmlStruct { let model = XmlStruct {
color: Enum::FullPath(String::from("some_text")), color: Enum::FullPath("some_text".to_owned()),
}; };
let content = "<base><color><FullPath>some_text</FullPath></color></base>"; let content = "<base><color><FullPath>some_text</FullPath></color></base>";
@ -221,7 +218,7 @@ fn unnamed_enum() {
deserialize_and_validate!(content, model, XmlStruct); deserialize_and_validate!(content, model, XmlStruct);
let model = XmlStruct { let model = XmlStruct {
color: Enum::OptionString(Some(String::from("some_text"))), color: Enum::OptionString(Some("some_text".to_owned())),
}; };
let content = "<base><color><OptionString>some_text</OptionString></color></base>"; let content = "<base><color><OptionString>some_text</OptionString></color></base>";
@ -256,7 +253,7 @@ fn unnamed_enum() {
// deserialize_and_validate!(content, model, XmlStruct); // deserialize_and_validate!(content, model, XmlStruct);
let model = XmlStruct { let model = XmlStruct {
color: Enum::Strings(vec![String::from("abc"), String::from("def")]), color: Enum::Strings(vec!["abc".to_owned(), "def".to_owned()]),
}; };
let content = "<base><color><Strings>abc</Strings><Strings>def</Strings></color></base>"; let content = "<base><color><Strings>abc</Strings><Strings>def</Strings></color></base>";

View File

@ -1,9 +1,7 @@
#[macro_use] #[macro_use]
extern crate yaserde_derive; extern crate yaserde_derive;
use std::io::Read;
use yaserde::de::from_str; use yaserde::de::from_str;
use yaserde::YaDeserialize;
fn init() { fn init() {
let _ = env_logger::builder().is_test(true).try_init(); let _ = env_logger::builder().is_test(true).try_init();
@ -24,9 +22,7 @@ fn de_no_content() {
let loaded: Result<Book, String> = from_str(content); let loaded: Result<Book, String> = from_str(content);
assert_eq!( assert_eq!(
loaded, loaded,
Err(String::from( Err("Unexpected end of stream: no root element found".to_owned())
"Unexpected end of stream: no root element found"
))
); );
} }
@ -45,8 +41,6 @@ fn de_wrong_end_balise() {
let loaded: Result<Book, String> = from_str(content); let loaded: Result<Book, String> = from_str(content);
assert_eq!( assert_eq!(
loaded, loaded,
Err(String::from( Err("Unexpected closing tag: book, expected author".to_owned())
"Unexpected closing tag: book, expected author"
))
); );
} }

View File

@ -3,10 +3,6 @@ extern crate yaserde;
#[macro_use] #[macro_use]
extern crate yaserde_derive; extern crate yaserde_derive;
use std::io::{Read, Write};
use yaserde::{YaDeserialize, YaSerialize};
fn init() { fn init() {
let _ = env_logger::builder().is_test(true).try_init(); let _ = env_logger::builder().is_test(true).try_init();
} }

View File

@ -3,9 +3,6 @@ extern crate yaserde;
#[macro_use] #[macro_use]
extern crate yaserde_derive; extern crate yaserde_derive;
use std::io::{Read, Write};
use yaserde::{YaDeserialize, YaSerialize};
fn init() { fn init() {
let _ = env_logger::builder().is_test(true).try_init(); let _ = env_logger::builder().is_test(true).try_init();
} }
@ -35,8 +32,8 @@ fn struct_simple_namespace() {
"#; "#;
let model = Book { let model = Book {
author: String::from("Antoine de Saint-Exupéry"), author: "Antoine de Saint-Exupéry".to_owned(),
title: String::from("Little prince"), title: "Little prince".to_owned(),
}; };
serialize_and_validate!(model, content); serialize_and_validate!(model, content);
@ -69,8 +66,8 @@ fn struct_multiple_namespaces() {
"#; "#;
let model = Book { let model = Book {
author: String::from("Antoine de Saint-Exupéry"), author: "Antoine de Saint-Exupéry".to_owned(),
title: String::from("Little prince"), title: "Little prince".to_owned(),
}; };
serialize_and_validate!(model, content); serialize_and_validate!(model, content);
@ -101,8 +98,8 @@ fn struct_partial_namespace() {
"#; "#;
let model = Book { let model = Book {
author: String::from("Antoine de Saint-Exupéry"), author: "Antoine de Saint-Exupéry".to_owned(),
title: String::from("Little prince"), title: "Little prince".to_owned(),
}; };
serialize_and_validate!(model, content); serialize_and_validate!(model, content);
@ -135,8 +132,8 @@ fn struct_sub_namespace_definition() {
"#; "#;
let model = Book { let model = Book {
author: String::from("Antoine de Saint-Exupéry"), author: "Antoine de Saint-Exupéry".to_owned(),
title: String::from("Little prince"), title: "Little prince".to_owned(),
}; };
// TODO support namespace for attribute to specify local namespace // TODO support namespace for attribute to specify local namespace

View File

@ -3,9 +3,6 @@ extern crate yaserde;
#[macro_use] #[macro_use]
extern crate yaserde_derive; extern crate yaserde_derive;
use std::io::{Read, Write};
use yaserde::{YaDeserialize, YaSerialize};
fn init() { fn init() {
let _ = env_logger::builder().is_test(true).try_init(); let _ = env_logger::builder().is_test(true).try_init();
} }

View File

@ -177,8 +177,6 @@ fn ser_attributes() {
#[test] #[test]
fn ser_attributes_complex() { fn ser_attributes_complex() {
mod other_mod { mod other_mod {
use super::*;
#[derive(YaSerialize, PartialEq, Debug)] #[derive(YaSerialize, PartialEq, Debug)]
pub enum AttrEnum { pub enum AttrEnum {
#[yaserde(rename = "variant 1")] #[yaserde(rename = "variant 1")]
@ -197,7 +195,7 @@ fn ser_attributes_complex() {
#[derive(YaSerialize, PartialEq, Debug)] #[derive(YaSerialize, PartialEq, Debug)]
pub struct Struct { pub struct Struct {
#[yaserde(attribute)] #[yaserde(attribute)]
attr_option_string: Option<std::string::String>, attr_option_string: Option<String>,
#[yaserde(attribute)] #[yaserde(attribute)]
attr_option_enum: Option<other_mod::AttrEnum>, attr_option_enum: Option<other_mod::AttrEnum>,
} }

View File

@ -3,9 +3,6 @@ extern crate yaserde;
#[macro_use] #[macro_use]
extern crate yaserde_derive; extern crate yaserde_derive;
use std::io::Write;
use yaserde::YaSerialize;
fn init() { fn init() {
let _ = env_logger::builder().is_test(true).try_init(); let _ = env_logger::builder().is_test(true).try_init();
} }

View File

@ -3,9 +3,6 @@ extern crate yaserde;
#[macro_use] #[macro_use]
extern crate yaserde_derive; extern crate yaserde_derive;
use std::io::{Read, Write};
use yaserde::{YaDeserialize, YaSerialize};
fn init() { fn init() {
let _ = env_logger::builder().is_test(true).try_init(); let _ = env_logger::builder().is_test(true).try_init();
} }

View File

@ -18,7 +18,6 @@ proc-macro2 = "~1.0"
quote = "~1.0" quote = "~1.0"
[lib] [lib]
name = "yaserde_derive"
proc-macro = true proc-macro = true
[badges] [badges]

View File

@ -1,4 +1,5 @@
use proc_macro2::{token_stream::IntoIter, Delimiter, Ident, TokenStream, TokenTree}; use proc_macro2::{token_stream::IntoIter, Delimiter, Ident, TokenStream, TokenTree};
use quote::quote;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use syn::Attribute; use syn::Attribute;
@ -154,7 +155,8 @@ impl YaSerdeAttribute {
match namespace.as_str() { match namespace.as_str() {
#namespaces_matches #namespaces_matches
bad_namespace => { bad_namespace => {
let msg = format!("bad namespace for {}, found {}", #element_name, bad_namespace); let msg =
::std::format!("bad namespace for {}, found {}", #element_name, bad_namespace);
return Err(msg); return Err(msg);
} }
} }

View File

@ -2,6 +2,7 @@ use crate::common::attribute::YaSerdeAttribute;
use heck::CamelCase; use heck::CamelCase;
use proc_macro2::Span; use proc_macro2::Span;
use proc_macro2::{Ident, TokenStream}; use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, quote};
use std::fmt; use std::fmt;
use syn::ext::IdentExt; use syn::ext::IdentExt;
use syn::spanned::Spanned; use syn::spanned::Spanned;
@ -184,9 +185,8 @@ pub enum Field {
} }
impl Field { impl Field {
pub fn get_simple_type_visitor(&self) -> TokenStream { pub fn get_simple_type_visitor(&self) -> Ident {
let ident = format_ident!("visit_{}", self.to_string()); format_ident!("visit_{}", self.to_string())
quote! {#ident}
} }
} }
@ -255,25 +255,25 @@ impl From<&syn::PathSegment> for Field {
impl Into<proc_macro2::TokenStream> for Field { impl Into<proc_macro2::TokenStream> for Field {
fn into(self) -> proc_macro2::TokenStream { fn into(self) -> proc_macro2::TokenStream {
match self { match self {
Field::FieldString => quote! {std::string::String}, Field::FieldString => quote! { ::std::string::String },
Field::FieldBool => quote! {bool}, Field::FieldBool => quote! { bool },
Field::FieldI8 => quote! {i8}, Field::FieldI8 => quote! { i8 },
Field::FieldU8 => quote! {u8}, Field::FieldU8 => quote! { u8 },
Field::FieldI16 => quote! {i16}, Field::FieldI16 => quote! { i16 },
Field::FieldU16 => quote! {u16}, Field::FieldU16 => quote! { u16 },
Field::FieldI32 => quote! {i32}, Field::FieldI32 => quote! { i32 },
Field::FieldU32 => quote! {u32}, Field::FieldU32 => quote! { u32 },
Field::FieldI64 => quote! {i64}, Field::FieldI64 => quote! { i64 },
Field::FieldU64 => quote! {u64}, Field::FieldU64 => quote! { u64 },
Field::FieldF32 => quote! {f32}, Field::FieldF32 => quote! { f32 },
Field::FieldF64 => quote! {f64}, Field::FieldF64 => quote! { f64 },
_ => panic!("Not a simple type: {:?}", self), _ => panic!("Not a simple type: {:?}", self),
} }
} }
} }
impl Into<String> for &Field { impl Into<String> for &Field {
fn into(self) -> std::string::String { fn into(self) -> String {
match self { match self {
Field::FieldString => "str".to_string(), Field::FieldString => "str".to_string(),
Field::FieldBool => "bool".to_string(), Field::FieldBool => "bool".to_string(),
@ -294,7 +294,7 @@ impl Into<String> for &Field {
impl fmt::Display for Field { impl fmt::Display for Field {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let string_representation: std::string::String = self.into(); let string_representation: String = self.into();
write!(f, "{}", string_representation) write!(f, "{}", string_representation)
} }
} }

View File

@ -1,5 +1,6 @@
use crate::common::YaSerdeField; use crate::common::YaSerdeField;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::quote;
pub fn build_default_value( pub fn build_default_value(
field: &YaSerdeField, field: &YaSerdeField,

View File

@ -1,5 +1,6 @@
use crate::common::{Field, YaSerdeAttribute, YaSerdeField}; use crate::common::{Field, YaSerdeAttribute, YaSerdeField};
use proc_macro2::TokenStream; use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::{DataEnum, Fields, Ident}; use syn::{DataEnum, Fields, Ident};
pub fn parse( pub fn parse(
@ -25,35 +26,31 @@ pub fn parse(
let flatten = root_attributes.flatten; let flatten = root_attributes.flatten;
quote! { quote! {
use xml::reader::XmlEvent; impl ::yaserde::YaDeserialize for #name {
use yaserde::Visitor;
#[allow(unknown_lints, unused_imports)]
use std::str::FromStr;
use log::{debug, trace};
impl YaDeserialize for #name {
#[allow(unused_variables)] #[allow(unused_variables)]
fn deserialize<R: Read>(reader: &mut yaserde::de::Deserializer<R>) -> Result<Self, std::string::String> { fn deserialize<R: ::std::io::Read>(
reader: &mut ::yaserde::de::Deserializer<R>,
) -> ::std::result::Result<Self, ::std::string::String> {
let (named_element, enum_namespace) = let (named_element, enum_namespace) =
if let XmlEvent::StartElement{name, ..} = reader.peek()?.to_owned() { if let ::xml::reader::XmlEvent::StartElement{ name, .. } = reader.peek()?.to_owned() {
(name.local_name.to_owned(), name.namespace.clone()) (name.local_name.to_owned(), name.namespace.clone())
} else { } else {
(std::string::String::from(#root), None) (::std::string::String::from(#root), ::std::option::Option::None)
}; };
let start_depth = reader.depth(); let start_depth = reader.depth();
debug!("Enum {} @ {}: start to parse {:?}", stringify!(#name), start_depth, named_element); ::log::debug!("Enum {} @ {}: start to parse {:?}", stringify!(#name), start_depth, named_element);
#namespaces_matching #namespaces_matching
#[allow(unused_assignments, unused_mut)] #[allow(unused_assignments, unused_mut)]
let mut enum_value = None; let mut enum_value = ::std::option::Option::None;
loop { loop {
let event = reader.peek()?.to_owned(); let event = reader.peek()?.to_owned();
trace!("Enum {} @ {}: matching {:?}", stringify!(#name), start_depth, event); ::log::trace!("Enum {} @ {}: matching {:?}", stringify!(#name), start_depth, event);
match event { match event {
XmlEvent::StartElement{ref name, ref attributes, ..} => { ::xml::reader::XmlEvent::StartElement { ref name, ref attributes, .. } => {
match name.local_name.as_str() { match name.local_name.as_str() {
#match_to_enum #match_to_enum
_named_element => { _named_element => {
@ -61,40 +58,42 @@ pub fn parse(
} }
} }
if let XmlEvent::Characters(content) = reader.peek()?.to_owned() { if let ::xml::reader::XmlEvent::Characters(content) = reader.peek()?.to_owned() {
match content.as_str() { match content.as_str() {
#match_to_enum #match_to_enum
_ => {} _ => {}
} }
} }
} }
XmlEvent::EndElement{ref name} => { ::xml::reader::XmlEvent::EndElement { ref name } => {
if name.local_name == named_element { if name.local_name == named_element {
break; break;
} }
let _root = reader.next_event(); let _root = reader.next_event();
} }
XmlEvent::Characters(ref text_content) => { ::xml::reader::XmlEvent::Characters(ref text_content) => {
let _root = reader.next_event(); let _root = reader.next_event();
} }
XmlEvent::EndDocument => { ::xml::reader::XmlEvent::EndDocument => {
if #flatten { if #flatten {
break; break;
} }
return Err(format!("End of document, missing some content ?")) return ::std::result::Result::Err(
::std::format!("End of document, missing some content ?"),
);
} }
event => { event => {
return Err(format!("unknown event {:?}", event)) return ::std::result::Result::Err(::std::format!("unknown event {:?}", event))
} }
} }
} }
debug!("Enum {} @ {}: success", stringify!(#name), start_depth); ::log::debug!("Enum {} @ {}: success", stringify!(#name), start_depth);
match enum_value { match enum_value {
Some(value) => Ok(value), ::std::option::Option::Some(value) => ::std::result::Result::Ok(value),
None => { ::std::option::Option::None => {
Ok(#name::default()) ::std::result::Result::Ok(<#name as ::std::default::Default>::default())
}, },
} }
} }
@ -113,7 +112,7 @@ fn parse_variant(variant: &syn::Variant, name: &Ident) -> Option<TokenStream> {
match variant.fields { match variant.fields {
Fields::Unit => Some(quote! { Fields::Unit => Some(quote! {
#xml_element_name => { #xml_element_name => {
enum_value = Some(#variant_name); enum_value = ::std::option::Option::Some(#variant_name);
} }
}), }),
Fields::Unnamed(ref fields) => { Fields::Unnamed(ref fields) => {
@ -150,23 +149,25 @@ fn build_unnamed_field_visitors(fields: &syn::FieldsUnnamed) -> TokenStream {
.iter() .iter()
.map(|field| YaSerdeField::new(field.clone())) .map(|field| YaSerdeField::new(field.clone()))
.enumerate() .enumerate()
.map(|(idx, field)| { .filter_map(|(idx, field)| {
let visitor_label = Ident::new(&format!("__Visitor_{}", idx), field.get_span()); let visitor_label = Ident::new(&format!("__Visitor_{}", idx), field.get_span());
let make_visitor = let make_visitor = |visitor: &Ident, field_type: &TokenStream, fn_body: &TokenStream| {
|visitor: &TokenStream, field_type: &TokenStream, fn_body: &TokenStream| { quote! {
Some(quote! { #[allow(non_snake_case, non_camel_case_types)]
#[allow(non_snake_case, non_camel_case_types)] struct #visitor_label;
struct #visitor_label; impl<'de> ::yaserde::Visitor<'de> for #visitor_label {
impl<'de> Visitor<'de> for #visitor_label { type Value = #field_type;
type Value = #field_type;
fn #visitor(self, v: &str) -> Result<Self::Value, std::string::String> { fn #visitor(
#fn_body self,
} v: &str,
) -> ::std::result::Result<Self::Value, ::std::string::String> {
#fn_body
} }
}) }
}; }
};
let simple_type_visitor = |simple_type: Field| { let simple_type_visitor = |simple_type: Field| {
let visitor = simple_type.get_simple_type_visitor(); let visitor = simple_type.get_simple_type_visitor();
@ -175,36 +176,36 @@ fn build_unnamed_field_visitors(fields: &syn::FieldsUnnamed) -> TokenStream {
make_visitor( make_visitor(
&visitor, &visitor,
&field_type, &field_type,
&quote! { Ok(#field_type::from_str(v).unwrap()) }, &quote! { ::std::result::Result::Ok(#field_type::from_str(v).unwrap()) },
) )
}; };
match field.get_type() { match field.get_type() {
Field::FieldStruct { struct_name } => { Field::FieldStruct { struct_name } => {
let struct_id: std::string::String = struct_name let struct_id: String = struct_name
.segments .segments
.iter() .iter()
.map(|s| s.ident.to_string()) .map(|s| s.ident.to_string())
.collect(); .collect();
make_visitor( Some(make_visitor(
&quote! { visit_str }, &Ident::new("visit_str", Span::call_site()),
&quote! { #struct_name }, &quote! { #struct_name },
&quote! { &quote! {
let content = "<".to_string() + #struct_id + ">" + v + "</" + #struct_id + ">"; let content = "<".to_string() + #struct_id + ">" + v + "</" + #struct_id + ">";
let value : Result<#struct_name, std::string::String> = yaserde::de::from_str(&content); let value: ::std::result::Result<#struct_name, ::std::string::String> =
::yaserde::de::from_str(&content);
value value
}, },
) ))
} }
Field::FieldOption { data_type } | Field::FieldVec { data_type } => match *data_type { Field::FieldOption { data_type } | Field::FieldVec { data_type } => match *data_type {
Field::FieldStruct { .. } => None, Field::FieldStruct { .. } => None,
simple_type => simple_type_visitor(simple_type), simple_type => Some(simple_type_visitor(simple_type)),
}, },
simple_type => simple_type_visitor(simple_type), simple_type => Some(simple_type_visitor(simple_type)),
} }
}) })
.filter_map(|f| f)
.collect() .collect()
} }
@ -230,18 +231,22 @@ fn build_unnamed_visitor_calls(
let visitor = #visitor_label{}; let visitor = #visitor_label{};
let result = reader.read_inner_value::<#field_type, _>(|reader| { let result = reader.read_inner_value::<#field_type, _>(|reader| {
if let XmlEvent::EndElement { .. } = *reader.peek()? { if let ::xml::reader::XmlEvent::EndElement { .. } = *reader.peek()? {
return visitor.#visitor(""); return visitor.#visitor("");
} }
if let Ok(XmlEvent::Characters(s)) = reader.next_event() { if let ::std::result::Result::Ok(::xml::reader::XmlEvent::Characters(s))
= reader.next_event()
{
visitor.#visitor(&s) visitor.#visitor(&s)
} else { } else {
Err(format!("unable to parse content for {}", #label_name)) ::std::result::Result::Err(
::std::format!("unable to parse content for {}", #label_name),
)
} }
}); });
if let Ok(value) = result { if let ::std::result::Result::Ok(value) = result {
#action #action
} }
}) })
@ -261,16 +266,24 @@ fn build_unnamed_visitor_calls(
}) })
}; };
let set_val = quote! { enum_value = Some(#variant_name(value)) }; let set_val = quote! {
let set_opt = quote! { enum_value = Some(#variant_name(Some(value))) }; enum_value = ::std::option::Option::Some(#variant_name(value))
};
let set_opt = quote! {
enum_value = ::std::option::Option::Some(#variant_name(::std::option::Option::Some(value)))
};
let set_vec = quote! { let set_vec = quote! {
match enum_value { match enum_value {
Some(ref mut v) => match v { Some(ref mut v) => match v {
#variant_name(ref mut v) => v.push(value), #variant_name(ref mut v) => v.push(value),
_ => return Err(std::string::String::from("Got sequence of different types")) _ => {
return ::std::result::Result::Err(
::std::string::String::from("Got sequence of different types"),
);
}
} }
None => { None => {
enum_value = Some(#variant_name(vec![value])); enum_value = ::std::option::Option::Some(#variant_name(vec![value]));
} }
} }
}; };

View File

@ -2,6 +2,7 @@ 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 heck::CamelCase; use heck::CamelCase;
use proc_macro2::{Span, TokenStream}; use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::{DataStruct, Ident}; use syn::{DataStruct, Ident};
pub fn parse( pub fn parse(
@ -25,25 +26,33 @@ pub fn parse(
Field::FieldStruct { struct_name } => build_default_value( Field::FieldStruct { struct_name } => build_default_value(
&field, &field,
Some(quote!(#struct_name)), Some(quote!(#struct_name)),
quote!(#struct_name::default()), quote!(<#struct_name as ::std::default::Default>::default()),
), ),
Field::FieldOption { .. } => build_default_value(&field, None, quote!(None)), Field::FieldOption { .. } => {
build_default_value(&field, None, quote!(::std::option::Option::None))
}
Field::FieldVec { data_type } => match *data_type { Field::FieldVec { data_type } => match *data_type {
Field::FieldStruct { ref struct_name } => { Field::FieldStruct { ref struct_name } => build_default_value(
build_default_value(&field, Some(quote!(Vec<#struct_name>)), quote!(vec![])) &field,
} Some(quote!(::std::vec::Vec<#struct_name>)),
quote!(::std::vec![]),
),
Field::FieldOption { .. } | Field::FieldVec { .. } => { Field::FieldOption { .. } | Field::FieldVec { .. } => {
unimplemented!(); unimplemented!();
} }
simple_type => { simple_type => {
let type_token: TokenStream = simple_type.into(); let type_token: TokenStream = simple_type.into();
build_default_value(&field, Some(quote!(Vec<#type_token>)), quote!(vec![])) build_default_value(
&field,
Some(quote!(::std::vec::Vec<#type_token>)),
quote!(::std::vec![]),
)
} }
}, },
simple_type => { simple_type => {
let type_token: TokenStream = simple_type.into(); let type_token: TokenStream = simple_type.into();
let value_builder = quote!(#type_token::default()); let value_builder = quote!(<#type_token as ::std::default::Default>::default());
build_default_value(&field, Some(type_token), value_builder) build_default_value(&field, Some(type_token), value_builder)
} }
@ -57,7 +66,7 @@ pub fn parse(
.map(|field| YaSerdeField::new(field.clone())) .map(|field| YaSerdeField::new(field.clone()))
.map(|field| { .map(|field| {
let struct_visitor = |struct_name: syn::Path| { let struct_visitor = |struct_name: syn::Path| {
let struct_id: std::string::String = struct_name let struct_id: String = struct_name
.segments .segments
.iter() .iter()
.map(|s| s.ident.to_string()) .map(|s| s.ident.to_string())
@ -68,13 +77,15 @@ pub fn parse(
Some(quote! { Some(quote! {
#[allow(non_snake_case, non_camel_case_types)] #[allow(non_snake_case, non_camel_case_types)]
struct #visitor_label; struct #visitor_label;
impl<'de> Visitor<'de> for #visitor_label { impl<'de> ::yaserde::Visitor<'de> for #visitor_label {
type Value = #struct_name; type Value = #struct_name;
fn visit_str(self, v: &str) -> Result<Self::Value, std::string::String> { fn visit_str(
self,
v: &str,
) -> ::std::result::Result<Self::Value, ::std::string::String> {
let content = "<".to_string() + #struct_id + ">" + v + "</" + #struct_id + ">"; let content = "<".to_string() + #struct_id + ">" + v + "</" + #struct_id + ">";
let value : Result<#struct_name, std::string::String> = yaserde::de::from_str(&content); ::yaserde::de::from_str(&content)
value
} }
} }
}) })
@ -85,27 +96,27 @@ pub fn parse(
let visitor_label = field.get_visitor_ident(None); let visitor_label = field.get_visitor_ident(None);
let field_type: TokenStream = simple_type.into(); let field_type: TokenStream = simple_type.into();
let map_if_bool = let map_if_bool = if field_type.to_string() == "bool" {
if format!("{}", field_type) == "bool" { quote!(match v {
quote!( "1" => "true",
match v { "0" => "false",
"1" => "true", _ => v,
"0" => "false", })
_ => v, } else {
} quote!(v)
) };
} else {
quote!(v)
};
Some(quote! { Some(quote! {
#[allow(non_snake_case, non_camel_case_types)] #[allow(non_snake_case, non_camel_case_types)]
struct #visitor_label; struct #visitor_label;
impl<'de> Visitor<'de> for #visitor_label { impl<'de> ::yaserde::Visitor<'de> for #visitor_label {
type Value = #field_type; type Value = #field_type;
fn #visitor(self, v: &str) -> Result<Self::Value, std::string::String> { fn #visitor(
Ok(#field_type::from_str(#map_if_bool).unwrap()) self,
v: &str,
) -> ::std::result::Result<Self::Value, ::std::string::String> {
::std::result::Result::Ok(#field_type::from_str(#map_if_bool).unwrap())
} }
} }
}) })
@ -145,7 +156,7 @@ pub fn parse(
// Don't count current struct's StartElement as substruct's StartElement // Don't count current struct's StartElement as substruct's StartElement
let _root = reader.next_event(); let _root = reader.next_event();
} }
if let Ok(XmlEvent::StartElement { .. }) = reader.peek() { if let Ok(::xml::reader::XmlEvent::StartElement { .. }) = reader.peek() {
// If substruct's start element found then deserialize substruct // If substruct's start element found then deserialize substruct
let value = #struct_name::deserialize(reader)?; let value = #struct_name::deserialize(reader)?;
#value_label #action; #value_label #action;
@ -173,10 +184,12 @@ pub fn parse(
}; };
match field.get_type() { match field.get_type() {
Field::FieldStruct { struct_name } => visit_struct(struct_name, quote! {= value}), Field::FieldStruct { struct_name } => visit_struct(struct_name, quote! { = value }),
Field::FieldOption { data_type } => visit_sub(data_type, quote! {= Some(value)}), Field::FieldOption { data_type } => {
Field::FieldVec { data_type } => visit_sub(data_type, quote! {.push(value)}), visit_sub(data_type, quote! { = ::std::option::Option::Some(value) })
simple_type => visit_simple(simple_type, quote! {= value}), }
Field::FieldVec { data_type } => visit_sub(data_type, quote! { .push(value) }),
simple_type => visit_simple(simple_type, quote! { = value }),
} }
}) })
.filter_map(|x| x) .filter_map(|x| x)
@ -192,11 +205,11 @@ pub fn parse(
match field.get_type() { match field.get_type() {
Field::FieldStruct { .. } => Some(quote! { Field::FieldStruct { .. } => Some(quote! {
#value_label = yaserde::de::from_str(&unused_xml_elements)?; #value_label = ::yaserde::de::from_str(&unused_xml_elements)?;
}), }),
Field::FieldOption { data_type } => match *data_type { Field::FieldOption { data_type } => match *data_type {
Field::FieldStruct { .. } => 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!(r#""flatten" is not implemented for {:?}"#, field_type), field_type => unimplemented!(r#""flatten" is not implemented for {:?}"#, field_type),
}, },
@ -216,7 +229,7 @@ pub fn parse(
let label_name = field.renamed_label_without_namespace(); let label_name = field.renamed_label_without_namespace();
let visitor_label = build_visitor_ident(&label_name, field.get_span(), None); let visitor_label = build_visitor_ident(&label_name, field.get_span(), None);
let visit = |action: &TokenStream, visitor: &TokenStream, visitor_label: &Ident| { let visit = |action: &TokenStream, visitor: &Ident, visitor_label: &Ident| {
Some(quote! { Some(quote! {
for attr in attributes { for attr in attributes {
if attr.name.local_name == #label_name { if attr.name.local_name == #label_name {
@ -241,7 +254,7 @@ pub fn parse(
let visit_struct = |struct_name: syn::Path, action: TokenStream| { let visit_struct = |struct_name: syn::Path, action: TokenStream| {
visit( visit(
&action, &action,
&quote! {visit_str}, &Ident::new("visit_str", Span::call_site()),
&build_visitor_ident(&label_name, field.get_span(), Some(&struct_name)), &build_visitor_ident(&label_name, field.get_span(), Some(&struct_name)),
) )
}; };
@ -262,10 +275,12 @@ pub fn parse(
match field.get_type() { match field.get_type() {
Field::FieldString => visit_string(), Field::FieldString => visit_string(),
Field::FieldOption { data_type } => visit_sub(data_type, quote! {= Some(value)}), Field::FieldOption { data_type } => {
visit_sub(data_type, quote! { = ::std::option::Option::Some(value) })
}
Field::FieldVec { .. } => unimplemented!(), Field::FieldVec { .. } => unimplemented!(),
Field::FieldStruct { 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)
@ -280,18 +295,18 @@ pub fn parse(
let set_text = |action: &TokenStream| { let set_text = |action: &TokenStream| {
if field.is_text_content() { if field.is_text_content() {
Some(quote! {#label = #action;}) Some(quote! { #label = #action; })
} else { } else {
None None
} }
}; };
match field.get_type() { match field.get_type() {
Field::FieldString => set_text(&quote! {text_content.to_owned()}), Field::FieldString => set_text(&quote! { text_content.to_owned() }),
Field::FieldStruct { .. } | Field::FieldOption { .. } | Field::FieldVec { .. } => None, Field::FieldStruct { .. } | Field::FieldOption { .. } | Field::FieldVec { .. } => None,
simple_type => { simple_type => {
let type_token: TokenStream = simple_type.into(); let type_token: TokenStream = simple_type.into();
set_text(&quote! {#type_token::from_str(text_content).unwrap()}) set_text(&quote! { #type_token::from_str(text_content).unwrap() })
} }
} }
}) })
@ -319,24 +334,19 @@ pub fn parse(
let flatten = root_attributes.flatten; let flatten = root_attributes.flatten;
quote! { quote! {
use xml::reader::{XmlEvent, EventReader}; impl ::yaserde::YaDeserialize for #name {
use xml::writer::EventWriter;
use yaserde::Visitor;
#[allow(unknown_lints, unused_imports)]
use std::str::FromStr;
use log::{debug, trace};
impl YaDeserialize for #name {
#[allow(unused_variables)] #[allow(unused_variables)]
fn deserialize<R: Read>(reader: &mut yaserde::de::Deserializer<R>) -> Result<Self, std::string::String> { fn deserialize<R: ::std::io::Read>(
reader: &mut ::yaserde::de::Deserializer<R>,
) -> ::std::result::Result<Self, ::std::string::String> {
let (named_element, struct_namespace) = let (named_element, struct_namespace) =
if let XmlEvent::StartElement{name, ..} = reader.peek()?.to_owned() { if let ::xml::reader::XmlEvent::StartElement { name, .. } = reader.peek()?.to_owned() {
(name.local_name.to_owned(), name.namespace.clone()) (name.local_name.to_owned(), name.namespace.clone())
} else { } else {
(std::string::String::from(#root), None) (::std::string::String::from(#root), ::std::option::Option::None)
}; };
let start_depth = reader.depth(); let start_depth = reader.depth();
debug!("Struct {} @ {}: start to parse {:?}", stringify!(#name), start_depth, ::log::debug!("Struct {} @ {}: start to parse {:?}", stringify!(#name), start_depth,
named_element); named_element);
if reader.depth() == 0 { if reader.depth() == 0 {
@ -351,9 +361,12 @@ pub fn parse(
loop { loop {
let event = reader.peek()?.to_owned(); let event = reader.peek()?.to_owned();
trace!("Struct {} @ {}: matching {:?}", stringify!(#name), start_depth, event); ::log::trace!(
"Struct {} @ {}: matching {:?}",
stringify!(#name), start_depth, event,
);
match event { match event {
XmlEvent::StartElement{ref name, ref attributes, ..} => { ::xml::reader::XmlEvent::StartElement{ref name, ref attributes, ..} => {
match name.local_name.as_str() { match name.local_name.as_str() {
#call_visitors #call_visitors
_ => { _ => {
@ -372,7 +385,7 @@ pub fn parse(
} }
depth += 1; depth += 1;
} }
XmlEvent::EndElement{ref name} => { ::xml::reader::XmlEvent::EndElement { ref name } => {
if name.local_name == named_element { if name.local_name == named_element {
#write_unused #write_unused
break; break;
@ -381,26 +394,26 @@ pub fn parse(
#write_unused #write_unused
depth -= 1; depth -= 1;
} }
XmlEvent::EndDocument => { ::xml::reader::XmlEvent::EndDocument => {
if #flatten { if #flatten {
break; break;
} }
} }
XmlEvent::Characters(ref text_content) => { ::xml::reader::XmlEvent::Characters(ref text_content) => {
#set_text #set_text
let event = reader.next_event()?; let event = reader.next_event()?;
#write_unused #write_unused
} }
event => { event => {
return Err(format!("unknown event {:?}", event)) return ::std::result::Result::Err(::std::format!("unknown event {:?}", event));
} }
} }
} }
#visit_unused #visit_unused
debug!("Struct {} @ {}: success", stringify!(#name), start_depth); ::log::debug!("Struct {} @ {}: success", stringify!(#name), start_depth);
Ok(#name{#struct_builder}) ::std::result::Result::Ok(#name{#struct_builder})
} }
} }
} }
@ -408,7 +421,7 @@ pub fn parse(
fn build_call_visitor( fn build_call_visitor(
field_type: &TokenStream, field_type: &TokenStream,
visitor: &TokenStream, visitor: &Ident,
action: &TokenStream, action: &TokenStream,
field: &YaSerdeField, field: &YaSerdeField,
root_attributes: &YaSerdeAttribute, root_attributes: &YaSerdeAttribute,
@ -430,16 +443,16 @@ fn build_call_visitor(
#namespaces_matching #namespaces_matching
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 ::std::result::Result::Ok(::xml::reader::XmlEvent::Characters(s)) = reader.peek() {
let val = visitor.#visitor(&s); let val = visitor.#visitor(&s);
let _event = reader.next_event()?; let _event = reader.next_event()?;
val val
} else { } else {
Err(format!("unable to parse content for {}", #label_name)) ::std::result::Result::Err(::std::format!("unable to parse content for {}", #label_name))
} }
}); });
if let Ok(value) = result { if let ::std::result::Result::Ok(value) = result {
#value_label#action #value_label#action
} }
} }
@ -477,19 +490,19 @@ fn build_code_for_unused_xml_events(
) { ) {
( (
Some(quote! { Some(quote! {
let mut buf = Vec::new(); let mut buf = ::std::vec![];
let mut writer = Some(EventWriter::new(&mut buf)); let mut writer = ::std::option::Option::Some(::xml::writer::EventWriter::new(&mut buf));
}), }),
Some(quote! { Some(quote! {
if let Some(ref mut w) = writer { if let ::std::option::Option::Some(ref mut w) = writer {
if w.write(event.as_writer_event().unwrap()).is_err() { if w.write(event.as_writer_event().unwrap()).is_err() {
writer = None; writer = ::std::option::Option::None;
} }
} }
}), }),
Some(quote! { Some(quote! {
if writer.is_some() { if writer.is_some() {
let unused_xml_elements = std::string::String::from_utf8(buf).unwrap(); let unused_xml_elements = ::std::string::String::from_utf8(buf).unwrap();
#call_flatten_visitors #call_flatten_visitors
} }
}), }),

View File

@ -3,8 +3,8 @@ pub mod expand_enum;
pub mod expand_struct; pub mod expand_struct;
use crate::common::YaSerdeAttribute; use crate::common::YaSerdeAttribute;
use proc_macro2::TokenStream; use proc_macro2::{Ident, TokenStream};
use syn::Ident; use quote::quote;
pub fn expand_derive_deserialize(ast: &syn::DeriveInput) -> Result<TokenStream, String> { pub fn expand_derive_deserialize(ast: &syn::DeriveInput) -> Result<TokenStream, String> {
let name = &ast.ident; let name = &ast.ident;
@ -31,13 +31,13 @@ pub fn expand_derive_deserialize(ast: &syn::DeriveInput) -> Result<TokenStream,
let dummy_const = Ident::new(&format!("_IMPL_YA_DESERIALIZE_FOR_{}", name), name.span()); let dummy_const = Ident::new(&format!("_IMPL_YA_DESERIALIZE_FOR_{}", name), name.span());
let generated = quote! { Ok(quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = { const #dummy_const: () = {
extern crate yaserde as _yaserde; use ::std::str::FromStr as _;
use ::yaserde::Visitor as _;
#impl_block #impl_block
}; };
}; })
Ok(generated)
} }

View File

@ -1,10 +1,7 @@
#![recursion_limit = "256"] #![recursion_limit = "256"]
// Required for Rust < 1.42
extern crate proc_macro; extern crate proc_macro;
extern crate proc_macro2;
#[macro_use]
extern crate quote;
extern crate syn;
mod common; mod common;
mod de; mod de;

View File

@ -1,5 +1,6 @@
use crate::common::YaSerdeField; use crate::common::YaSerdeField;
use proc_macro2::{Ident, TokenStream}; use proc_macro2::{Ident, TokenStream};
use quote::quote;
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)))
@ -15,14 +16,14 @@ pub fn enclose_characters(label: &Option<Ident>, label_name: String) -> TokenStr
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 = ::xml::writer::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())?;
let yaserde_value = #yaserde_format; let yaserde_value = #yaserde_format;
let data_event = XmlEvent::characters(&yaserde_value); let data_event = ::xml::writer::XmlEvent::characters(&yaserde_value);
writer.write(data_event).map_err(|e| e.to_string())?; writer.write(data_event).map_err(|e| e.to_string())?;
let end_event = XmlEvent::end_element(); let end_event = ::xml::writer::XmlEvent::end_element();
writer.write(end_event).map_err(|e| e.to_string())?; writer.write(end_event).map_err(|e| e.to_string())?;
} }
} }

View File

@ -1,6 +1,7 @@
use crate::common::{Field, YaSerdeAttribute, YaSerdeField}; use crate::common::{Field, YaSerdeAttribute, YaSerdeField};
use crate::ser::{implement_serializer::implement_serializer, label::build_label_name}; use crate::ser::{implement_serializer::implement_serializer, label::build_label_name};
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::quote;
use syn::DataEnum; use syn::DataEnum;
use syn::Fields; use syn::Fields;
use syn::Ident; use syn::Ident;
@ -41,7 +42,7 @@ fn inner_enum_inspector(
match variant.fields { match variant.fields {
Fields::Unit => Some(quote! { Fields::Unit => Some(quote! {
&#name::#label => { &#name::#label => {
let data_event = XmlEvent::characters(#label_name); let data_event = ::xml::writer::XmlEvent::characters(#label_name);
writer.write(data_event).map_err(|e| e.to_string())?; writer.write(data_event).map_err(|e| e.to_string())?;
} }
}), }),
@ -56,7 +57,7 @@ fn inner_enum_inspector(
if field.is_text_content() { if field.is_text_content() {
return Some(quote!( return Some(quote!(
let data_event = XmlEvent::characters(&self.#field_label); let data_event = ::xml::writer::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())?;
)); ));
} }
@ -78,15 +79,16 @@ fn inner_enum_inspector(
| Field::FieldF64 => Some({ | Field::FieldF64 => Some({
quote! { quote! {
match self { match self {
&#name::#label{ref #field_label, ..} => { &#name::#label { ref #field_label, .. } => {
let struct_start_event = XmlEvent::start_element(#field_label_name); let struct_start_event =
::xml::writer::XmlEvent::start_element(#field_label_name);
writer.write(struct_start_event).map_err(|e| e.to_string())?; writer.write(struct_start_event).map_err(|e| e.to_string())?;
let string_value = #field_label.to_string(); let string_value = #field_label.to_string();
let data_event = XmlEvent::characters(&string_value); let data_event = ::xml::writer::XmlEvent::characters(&string_value);
writer.write(data_event).map_err(|e| e.to_string())?; writer.write(data_event).map_err(|e| e.to_string())?;
let struct_end_event = XmlEvent::end_element(); let struct_end_event = ::xml::writer::XmlEvent::end_element();
writer.write(struct_end_event).map_err(|e| e.to_string())?; writer.write(struct_end_event).map_err(|e| e.to_string())?;
}, },
_ => {}, _ => {},
@ -96,7 +98,9 @@ fn inner_enum_inspector(
Field::FieldStruct { .. } => 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(
::std::option::Option::Some(#field_label_name.to_string()),
);
writer.set_skip_start_end(false); writer.set_skip_start_end(false);
#field_label.serialize(writer)?; #field_label.serialize(writer)?;
}, },
@ -105,9 +109,11 @@ fn inner_enum_inspector(
}), }),
Field::FieldVec { .. } => 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 {
writer.set_start_event_name(Some(#field_label_name.to_string())); writer.set_start_event_name(
::std::option::Option::Some(#field_label_name.to_string()),
);
writer.set_skip_start_end(false); writer.set_skip_start_end(false);
item.serialize(writer)?; item.serialize(writer)?;
} }
@ -136,29 +142,29 @@ fn inner_enum_inspector(
.map(|field| { .map(|field| {
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 = ::xml::writer::XmlEvent::start_element(#label_name);
writer.write(struct_start_event).map_err(|e| e.to_string())?; writer.write(struct_start_event).map_err(|e| e.to_string())?;
#action #action
let struct_end_event = XmlEvent::end_element(); let struct_end_event = ::xml::writer::XmlEvent::end_element();
writer.write(struct_end_event).map_err(|e| e.to_string())?; writer.write(struct_end_event).map_err(|e| e.to_string())?;
} }
}; };
let write_string_chars = quote! { let write_string_chars = quote! {
let data_event = XmlEvent::characters(item); let data_event = ::xml::writer::XmlEvent::characters(item);
writer.write(data_event).map_err(|e| e.to_string())?; writer.write(data_event).map_err(|e| e.to_string())?;
}; };
let write_simple_type = write_element(&quote! { let write_simple_type = write_element(&quote! {
let s = item.to_string(); let s = item.to_string();
let data_event = XmlEvent::characters(&s); let data_event = ::xml::writer::XmlEvent::characters(&s);
writer.write(data_event).map_err(|e| e.to_string())?; writer.write(data_event).map_err(|e| e.to_string())?;
}); });
let serialize = quote! { let serialize = quote! {
writer.set_start_event_name(None); writer.set_start_event_name(::std::option::Option::None);
writer.set_skip_start_end(true); writer.set_skip_start_end(true);
item.serialize(writer)?; item.serialize(writer)?;
}; };
@ -186,7 +192,7 @@ fn inner_enum_inspector(
let write = write_sub_type(*data_type); let write = write_sub_type(*data_type);
Some(match_field(&quote! { Some(match_field(&quote! {
if let Some(item) = item { if let ::std::option::Option::Some(item) = item {
#write #write
} }
})) }))

View File

@ -2,6 +2,7 @@ use crate::common::{Field, YaSerdeAttribute, YaSerdeField};
use crate::ser::{element::*, implement_serializer::implement_serializer}; use crate::ser::{element::*, implement_serializer::implement_serializer};
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::quote;
use syn::DataStruct; use syn::DataStruct;
use syn::Ident; use syn::Ident;
@ -44,7 +45,7 @@ pub fn serialize(
Field::FieldString => field.ser_wrap_default_attribute( Field::FieldString => field.ser_wrap_default_attribute(
None, None,
quote!({ quote!({
if let Some(ref value) = self.#label { if let ::std::option::Option::Some(ref value) = self.#label {
struct_start_event.attr(#label_name, value) struct_start_event.attr(#label_name, value)
} else { } else {
struct_start_event struct_start_event
@ -62,9 +63,11 @@ pub fn serialize(
| Field::FieldU64 | Field::FieldU64
| Field::FieldF32 | Field::FieldF32
| Field::FieldF64 => field.ser_wrap_default_attribute( | Field::FieldF64 => field.ser_wrap_default_attribute(
Some(quote!(self.#label.map_or_else(|| std::string::String::new(), |v| v.to_string()))), Some(
quote!(self.#label.map_or_else(|| ::std::string::String::new(), |v| v.to_string())),
),
quote!({ quote!({
if let Some(ref value) = self.#label { if let ::std::option::Option::Some(ref value) = self.#label {
struct_start_event.attr(#label_name, &yaserde_inner) struct_start_event.attr(#label_name, &yaserde_inner)
} else { } else {
struct_start_event struct_start_event
@ -78,7 +81,7 @@ pub fn serialize(
field.ser_wrap_default_attribute( field.ser_wrap_default_attribute(
None, None,
quote!({ quote!({
if let Some(ref yaserde_list) = self.#label { if let ::std::option::Option::Some(ref yaserde_list) = self.#label {
for yaserde_item in yaserde_list.iter() { for yaserde_item in yaserde_list.iter() {
#inner #inner
} }
@ -87,11 +90,16 @@ pub fn serialize(
) )
} }
Field::FieldStruct { .. } => field.ser_wrap_default_attribute( Field::FieldStruct { .. } => field.ser_wrap_default_attribute(
Some(quote!(self.#label Some(quote! {
.as_ref() self.#label
.map_or_else(|| Ok(std::string::String::new()), |v| yaserde::ser::to_string_content(v))?)), .as_ref()
.map_or_else(
|| ::std::result::Result::Ok(::std::string::String::new()),
|v| ::yaserde::ser::to_string_content(v),
)?
}),
quote!({ quote!({
if let Some(ref yaserde_struct) = self.#label { if let ::std::option::Option::Some(ref yaserde_struct) = self.#label {
struct_start_event.attr(#label_name, &yaserde_inner) struct_start_event.attr(#label_name, &yaserde_inner)
} else { } else {
struct_start_event struct_start_event
@ -101,7 +109,7 @@ pub fn serialize(
Field::FieldOption { .. } => unimplemented!(), Field::FieldOption { .. } => unimplemented!(),
}, },
Field::FieldStruct { .. } => field.ser_wrap_default_attribute( Field::FieldStruct { .. } => field.ser_wrap_default_attribute(
Some(quote!(yaserde::ser::to_string_content(&self.#label)?)), Some(quote! { ::yaserde::ser::to_string_content(&self.#label)? }),
quote!({ quote!({
struct_start_event.attr(#label_name, &yaserde_inner) struct_start_event.attr(#label_name, &yaserde_inner)
}), }),
@ -115,12 +123,15 @@ pub fn serialize(
match field.get_type() { match field.get_type() {
Field::FieldStruct { .. } => { Field::FieldStruct { .. } => {
quote!( quote!(
let (attributes, namespace) = self.#label.serialize_attributes(vec![], xml::namespace::Namespace::empty())?; let (attributes, namespace) = self.#label.serialize_attributes(
::std::vec![],
::xml::namespace::Namespace::empty(),
)?;
child_attributes_namespace.extend(&namespace); child_attributes_namespace.extend(&namespace);
child_attributes.extend(attributes); child_attributes.extend(attributes);
) )
} }
_ => quote!() _ => quote!(),
} }
} }
}) })
@ -135,7 +146,7 @@ pub fn serialize(
let label = field.label(); let label = field.label();
if field.is_text_content() { if field.is_text_content() {
return Some(quote!( return Some(quote!(
let data_event = XmlEvent::characters(&self.#label); let data_event = ::xml::writer::XmlEvent::characters(&self.#label);
writer.write(data_event).map_err(|e| e.to_string())?; writer.write(data_event).map_err(|e| e.to_string())?;
)); ));
} }
@ -187,7 +198,7 @@ pub fn serialize(
Some(quote! { Some(quote! {
#conditions { #conditions {
if let Some(ref yaserde_items) = &self.#label { if let ::std::option::Option::Some(ref yaserde_items) = &self.#label {
for yaserde_item in yaserde_items.iter() { for yaserde_item in yaserde_items.iter() {
#inner #inner
} }
@ -197,16 +208,16 @@ pub fn serialize(
} }
Field::FieldStruct { .. } => Some(if field.is_flatten() { Field::FieldStruct { .. } => Some(if field.is_flatten() {
quote! { quote! {
if let Some(ref item) = &self.#label { if let ::std::option::Option::Some(ref item) = &self.#label {
writer.set_start_event_name(None); writer.set_start_event_name(::std::option::Option::None);
writer.set_skip_start_end(true); writer.set_skip_start_end(true);
item.serialize(writer)?; item.serialize(writer)?;
} }
} }
} else { } else {
quote! { quote! {
if let Some(ref item) = &self.#label { if let ::std::option::Option::Some(ref item) = &self.#label {
writer.set_start_event_name(Some(#label_name.to_string())); writer.set_start_event_name(::std::option::Option::Some(#label_name.to_string()));
writer.set_skip_start_end(false); writer.set_skip_start_end(false);
item.serialize(writer)?; item.serialize(writer)?;
} }
@ -216,9 +227,12 @@ pub fn serialize(
}, },
Field::FieldStruct { .. } => { Field::FieldStruct { .. } => {
let (start_event, skip_start) = if field.is_flatten() { let (start_event, skip_start) = if field.is_flatten() {
(quote!(None), true) (quote!(::std::option::Option::None), true)
} else { } else {
(quote!(Some(#label_name.to_string())), false) (
quote!(::std::option::Option::Some(#label_name.to_string())),
false,
)
}; };
Some(quote! { Some(quote! {
@ -271,7 +285,7 @@ pub fn serialize(
if field.is_flatten() { if field.is_flatten() {
Some(quote! { Some(quote! {
for item in &self.#label { for item in &self.#label {
writer.set_start_event_name(None); writer.set_start_event_name(::std::option::Option::None);
writer.set_skip_start_end(true); writer.set_skip_start_end(true);
item.serialize(writer)?; item.serialize(writer)?;
} }
@ -279,7 +293,7 @@ pub fn serialize(
} else { } else {
Some(quote! { Some(quote! {
for item in &self.#label { for item in &self.#label {
writer.set_start_event_name(Some(#label_name.to_string())); writer.set_start_event_name(::std::option::Option::Some(#label_name.to_string()));
writer.set_skip_start_end(false); writer.set_skip_start_end(false);
item.serialize(writer)?; item.serialize(writer)?;
} }

View File

@ -2,6 +2,7 @@ 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;
use quote::quote;
pub fn implement_serializer( pub fn implement_serializer(
name: &Ident, name: &Ident,
@ -14,26 +15,32 @@ pub fn implement_serializer(
let flatten = attributes.flatten; let flatten = attributes.flatten;
quote! { quote! {
use xml::writer::XmlEvent; impl ::yaserde::YaSerialize for #name {
impl YaSerialize for #name {
#[allow(unused_variables)] #[allow(unused_variables)]
fn serialize<W: Write>(&self, writer: &mut yaserde::ser::Serializer<W>) fn serialize<W: ::std::io::Write>(
-> Result<(), std::string::String> { &self,
writer: &mut ::yaserde::ser::Serializer<W>,
) -> ::std::result::Result<(), ::std::string::String> {
let skip = writer.skip_start_end(); let skip = writer.skip_start_end();
if !#flatten && !skip { if !#flatten && !skip {
let mut child_attributes = vec![]; let mut child_attributes = ::std::vec![];
let mut child_attributes_namespace = xml::namespace::Namespace::empty(); let mut child_attributes_namespace = ::xml::namespace::Namespace::empty();
let yaserde_label = writer.get_start_event_name().unwrap_or_else(|| #root.to_string()); let yaserde_label = writer.get_start_event_name().unwrap_or_else(|| #root.to_string());
let struct_start_event = XmlEvent::start_element(yaserde_label.as_ref())#namespaces_definition; let struct_start_event =
::xml::writer::XmlEvent::start_element(yaserde_label.as_ref()) #namespaces_definition;
#append_attributes #append_attributes
let event : xml::writer::events::XmlEvent = struct_start_event.into(); let event: ::xml::writer::events::XmlEvent = struct_start_event.into();
if let xml::writer::events::XmlEvent::StartElement{name, attributes, namespace} = event { if let ::xml::writer::events::XmlEvent::StartElement {
let mut attributes: Vec<xml::attribute::OwnedAttribute> = attributes.into_owned().to_vec().iter().map(|k| k.to_owned()).collect(); name,
attributes,
namespace,
} = event {
let mut attributes: ::std::vec::Vec<::xml::attribute::OwnedAttribute> =
attributes.into_owned().to_vec().iter().map(|k| k.to_owned()).collect();
attributes.extend(child_attributes); attributes.extend(child_attributes);
let all_attributes = attributes.iter().map(|ca| ca.borrow()).collect(); let all_attributes = attributes.iter().map(|ca| ca.borrow()).collect();
@ -41,10 +48,10 @@ pub fn implement_serializer(
let mut all_namespaces = namespace.into_owned(); let mut all_namespaces = namespace.into_owned();
all_namespaces.extend(&child_attributes_namespace); all_namespaces.extend(&child_attributes_namespace);
writer.write(xml::writer::events::XmlEvent::StartElement{ writer.write(::xml::writer::events::XmlEvent::StartElement{
name, name,
attributes: std::borrow::Cow::Owned(all_attributes), attributes: ::std::borrow::Cow::Owned(all_attributes),
namespace: std::borrow::Cow::Owned(all_namespaces) namespace: ::std::borrow::Cow::Owned(all_namespaces)
}).map_err(|e| e.to_string())?; }).map_err(|e| e.to_string())?;
} else { } else {
unreachable!() unreachable!()
@ -54,30 +61,41 @@ pub fn implement_serializer(
#inner_inspector #inner_inspector
if !#flatten && !skip { if !#flatten && !skip {
let struct_end_event = XmlEvent::end_element(); let struct_end_event = ::xml::writer::XmlEvent::end_element();
writer.write(struct_end_event).map_err(|e| e.to_string())?; writer.write(struct_end_event).map_err(|e| e.to_string())?;
} }
Ok(()) ::std::result::Result::Ok(())
} }
fn serialize_attributes(&self, mut source_attributes: Vec<xml::attribute::OwnedAttribute>, mut source_namespace: xml::namespace::Namespace) -> Result<(Vec<xml::attribute::OwnedAttribute>, xml::namespace::Namespace), std::string::String> { fn serialize_attributes(
let mut child_attributes : Vec<xml::attribute::OwnedAttribute> = vec![]; &self,
let mut child_attributes_namespace = xml::namespace::Namespace::empty(); mut source_attributes: ::std::vec::Vec<::xml::attribute::OwnedAttribute>,
mut source_namespace: ::xml::namespace::Namespace,
) -> ::std::result::Result<
(::std::vec::Vec<::xml::attribute::OwnedAttribute>, ::xml::namespace::Namespace),
::std::string::String
> {
let mut child_attributes = ::std::vec::Vec::<::xml::attribute::OwnedAttribute>::new();
let mut child_attributes_namespace = ::xml::namespace::Namespace::empty();
let struct_start_event =
::xml::writer::XmlEvent::start_element("temporary_element_to_generate_attributes")
#namespaces_definition;
let struct_start_event = XmlEvent::start_element("temporary_element_to_generate_attributes")#namespaces_definition;
#append_attributes #append_attributes
let event : xml::writer::events::XmlEvent = struct_start_event.into(); let event: ::xml::writer::events::XmlEvent = struct_start_event.into();
if let xml::writer::events::XmlEvent::StartElement{attributes, namespace, ..} = event { if let ::xml::writer::events::XmlEvent::StartElement { attributes, namespace, .. } = event {
source_namespace.extend(&namespace.into_owned()); source_namespace.extend(&namespace.into_owned());
source_namespace.extend(&child_attributes_namespace); source_namespace.extend(&child_attributes_namespace);
let a: Vec<xml::attribute::OwnedAttribute> = attributes.into_owned().to_vec().iter().map(|k| k.to_owned()).collect(); let a: ::std::vec::Vec<::xml::attribute::OwnedAttribute> =
attributes.into_owned().to_vec().iter().map(|k| k.to_owned()).collect();
source_attributes.extend(a); source_attributes.extend(a);
source_attributes.extend(child_attributes); source_attributes.extend(child_attributes);
Ok((source_attributes, source_namespace)) ::std::result::Result::Ok((source_attributes, source_namespace))
} else { } else {
unreachable!(); unreachable!();
} }

View File

@ -6,8 +6,8 @@ pub mod label;
pub mod namespace; pub mod namespace;
use crate::common::YaSerdeAttribute; use crate::common::YaSerdeAttribute;
use proc_macro2::TokenStream; use proc_macro2::{Ident, TokenStream};
use syn::Ident; use quote::quote;
pub fn expand_derive_serialize(ast: &syn::DeriveInput) -> Result<TokenStream, String> { pub fn expand_derive_serialize(ast: &syn::DeriveInput) -> Result<TokenStream, String> {
let name = &ast.ident; let name = &ast.ident;
@ -34,13 +34,12 @@ pub fn expand_derive_serialize(ast: &syn::DeriveInput) -> Result<TokenStream, St
let dummy_const = Ident::new(&format!("_IMPL_YA_SERIALIZE_FOR_{}", name), name.span()); let dummy_const = Ident::new(&format!("_IMPL_YA_SERIALIZE_FOR_{}", name), name.span());
let generated = quote! { Ok(quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = { const #dummy_const: () = {
extern crate yaserde as _yaserde; use ::std::str::FromStr as _;
#impl_block #impl_block
}; };
}; })
Ok(generated)
} }

View File

@ -1,5 +1,6 @@
use crate::common::YaSerdeAttribute; use crate::common::YaSerdeAttribute;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::quote;
pub fn generate_namespaces_definition(attributes: &YaSerdeAttribute) -> TokenStream { pub fn generate_namespaces_definition(attributes: &YaSerdeAttribute) -> TokenStream {
attributes attributes