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 {
Ok(next)
} 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.
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.
pub trait YaSerialize: Sized {
fn serialize<W: Write>(&self, writer: &mut ser::Serializer<W>)
-> Result<(), std::string::String>;
fn serialize<W: Write>(&self, writer: &mut ser::Serializer<W>) -> Result<(), String>;
fn serialize_attributes(
&self,
@ -36,7 +35,7 @@ pub trait YaSerialize: Sized {
Vec<xml::attribute::OwnedAttribute>,
xml::namespace::Namespace,
),
std::string::String,
String,
>;
}
@ -45,51 +44,51 @@ pub trait Visitor<'de>: Sized {
/// The value produced by this visitor.
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))
}
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))
}
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))
}
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))
}
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))
}
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))
}
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))
}
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))
}
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))
}
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))
}
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))
}
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))
}
}
@ -97,10 +96,7 @@ pub trait Visitor<'de>: Sized {
macro_rules! serialize_type {
($type:ty) => {
impl YaSerialize for $type {
fn serialize<W: Write>(
&self,
writer: &mut ser::Serializer<W>,
) -> Result<(), std::string::String> {
fn serialize<W: Write>(&self, writer: &mut ser::Serializer<W>) -> Result<(), String> {
let content = format!("{}", self);
let event = XmlEvent::characters(&content);
let _ret = writer.write(event);
@ -116,7 +112,7 @@ macro_rules! serialize_type {
Vec<xml::attribute::OwnedAttribute>,
xml::namespace::Namespace,
),
std::string::String,
String,
> {
Ok((attributes, namespace))
}
@ -182,9 +178,10 @@ mod testing {
let model = Data { item: $value };
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 {
std::string::String::from("<data />")
"<data />".to_owned()
};
serialize_and_validate!(model, content);
@ -218,7 +215,7 @@ mod testing {
macro_rules! deserialize_and_validate {
($content: expr, $model: expr, $struct: tt) => {
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));
};
}
@ -227,18 +224,12 @@ mod testing {
macro_rules! serialize_and_validate {
($model: expr, $content: expr) => {
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 =
std::string::String::from(r#"<?xml version="1.0" encoding="utf-8"?>"#) + &$content;
let content = format!(r#"<?xml version="1.0" encoding="utf-8"?>{}"#, $content);
assert_eq!(
data,
Ok(
std::string::String::from(content)
.split("\n")
.map(|s| s.trim())
.collect::<std::string::String>()
)
Ok(content.split("\n").map(|s| s.trim()).collect::<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 cursor = serialize_with_writer(model, buf, &Config::default())?;
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> {
let buf = Cursor::new(Vec::new());
let cursor = serialize_with_writer(model, buf, config)?;
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>(
@ -37,7 +37,7 @@ pub fn to_string_content<T: YaSerialize>(model: &T) -> Result<String, String> {
let buf = Cursor::new(Vec::new());
let cursor = serialize_with_writer_content(model, buf)?;
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>(

View File

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

View File

@ -4,9 +4,9 @@ extern crate yaserde;
extern crate yaserde_derive;
use log::debug;
use std::io::{Read, Write};
use std::io::Read;
use yaserde::de::from_str;
use yaserde::{YaDeserialize, YaSerialize};
use yaserde::YaDeserialize;
fn init() {
let _ = env_logger::builder().is_test(true).try_init();
@ -15,7 +15,7 @@ fn init() {
macro_rules! convert_and_validate {
($content: expr, $struct: tt, $model: expr) => {
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));
};
}
@ -37,8 +37,8 @@ fn de_basic() {
content,
Book,
Book {
author: String::from("Antoine de Saint-Exupéry"),
title: String::from("Little prince"),
author: "Antoine de Saint-Exupéry".to_owned(),
title: "Little prince".to_owned(),
}
);
@ -48,8 +48,8 @@ fn de_basic() {
content,
Book,
Book {
author: String::from("Antoine de Saint-Exupéry"),
title: String::from("Little prince"),
author: "Antoine de Saint-Exupéry".to_owned(),
title: "Little prince".to_owned(),
}
);
}
@ -93,8 +93,8 @@ fn de_dash_param() {
content,
Book,
Book {
author: String::from("Antoine de Saint-Exupéry"),
title: String::from("Little prince"),
author: "Antoine de Saint-Exupéry".to_owned(),
title: "Little prince".to_owned(),
}
);
@ -104,8 +104,8 @@ fn de_dash_param() {
content,
Book,
Book {
author: String::from("Antoine de Saint-Exupéry"),
title: String::from("Little prince"),
author: "Antoine de Saint-Exupéry".to_owned(),
title: "Little prince".to_owned(),
}
);
}
@ -115,21 +115,18 @@ fn de_multiple_segments() {
init();
mod other_mod {
use std::io::Read;
use yaserde::YaDeserialize;
#[derive(YaDeserialize, PartialEq, Debug, Default)]
pub struct Page {
pub number: i32,
pub text: std::string::String,
pub text: String,
}
}
#[derive(YaDeserialize, PartialEq, Debug)]
#[yaserde(root = "book")]
pub struct Book {
author: std::string::String,
title: std::string::String,
author: String,
title: String,
page: other_mod::Page,
}
@ -148,11 +145,11 @@ fn de_multiple_segments() {
content,
Book,
Book {
author: String::from("Antoine de Saint-Exupéry"),
title: String::from("Little prince"),
author: "Antoine de Saint-Exupéry".to_owned(),
title: "Little prince".to_owned(),
page: other_mod::Page {
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,
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 {
library: vec![
Library {
books: vec![String::from("Little Prince")],
books: vec!["Little Prince".to_owned()],
},
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)]
pub struct Struct {
#[yaserde(attribute)]
attr_option_string: Option<std::string::String>,
attr_option_string: Option<String>,
#[yaserde(attribute)]
attr_option_struct: Option<other_mod::Attributes>,
}
@ -311,8 +308,6 @@ fn de_attributes_complex() {
init();
mod other_mod {
use super::*;
#[derive(YaDeserialize, PartialEq, Debug)]
pub enum AttrEnum {
#[yaserde(rename = "variant 1")]
@ -331,7 +326,7 @@ fn de_attributes_complex() {
#[derive(Default, YaDeserialize, PartialEq, Debug)]
pub struct Struct {
#[yaserde(attribute)]
attr_option_string: Option<std::string::String>,
attr_option_string: Option<String>,
#[yaserde(attribute)]
attr_option_enum: Option<other_mod::AttrEnum>,
}
@ -564,7 +559,7 @@ fn de_complex_enum() {
pub enum Color {
White,
Black(String),
Orange(std::string::String),
Orange(String),
Red(i32),
Green(OtherStruct),
Yellow(Option<String>),
@ -595,7 +590,7 @@ fn de_complex_enum() {
content,
XmlStruct,
XmlStruct {
background: Color::Black(String::from("text")),
background: Color::Black("text".to_owned()),
}
);
@ -610,7 +605,7 @@ fn de_complex_enum() {
content,
XmlStruct,
XmlStruct {
background: Color::Orange(String::from("text")),
background: Color::Orange("text".to_owned()),
}
);
@ -658,7 +653,7 @@ fn de_complex_enum() {
content,
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,
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,
Book,
Book {
name: String::from("Little prince"),
name: "Little prince".to_owned(),
}
);
}
@ -806,13 +801,11 @@ fn de_custom() {
}
impl YaDeserialize for Day {
fn deserialize<R: Read>(
reader: &mut yaserde::de::Deserializer<R>,
) -> Result<Self, std::string::String> {
fn deserialize<R: Read>(reader: &mut yaserde::de::Deserializer<R>) -> Result<Self, String> {
use std::str::FromStr;
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 {
return Err(format!(
"Wrong StartElement name: {}, expected: {}",

View File

@ -3,9 +3,6 @@ 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)]
@ -168,7 +165,7 @@ fn unnamed_enum() {
pub enum Enum {
Simple,
Field(String),
FullPath(std::string::String),
FullPath(String),
Integer(i32),
UserStruct(OtherStruct),
OptionString(Option<String>),
@ -189,7 +186,7 @@ fn unnamed_enum() {
}
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>";
@ -197,7 +194,7 @@ fn unnamed_enum() {
deserialize_and_validate!(content, 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>";
@ -221,7 +218,7 @@ fn unnamed_enum() {
deserialize_and_validate!(content, 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>";
@ -256,7 +253,7 @@ fn unnamed_enum() {
// deserialize_and_validate!(content, 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>";

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,5 @@
use proc_macro2::{token_stream::IntoIter, Delimiter, Ident, TokenStream, TokenTree};
use quote::quote;
use std::collections::BTreeMap;
use syn::Attribute;
@ -154,7 +155,8 @@ impl YaSerdeAttribute {
match namespace.as_str() {
#namespaces_matches
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);
}
}

View File

@ -2,6 +2,7 @@ use crate::common::attribute::YaSerdeAttribute;
use heck::CamelCase;
use proc_macro2::Span;
use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, quote};
use std::fmt;
use syn::ext::IdentExt;
use syn::spanned::Spanned;
@ -184,9 +185,8 @@ pub enum Field {
}
impl Field {
pub fn get_simple_type_visitor(&self) -> TokenStream {
let ident = format_ident!("visit_{}", self.to_string());
quote! {#ident}
pub fn get_simple_type_visitor(&self) -> Ident {
format_ident!("visit_{}", self.to_string())
}
}
@ -255,25 +255,25 @@ impl From<&syn::PathSegment> for Field {
impl Into<proc_macro2::TokenStream> for Field {
fn into(self) -> proc_macro2::TokenStream {
match self {
Field::FieldString => quote! {std::string::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},
Field::FieldString => quote! { ::std::string::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) -> std::string::String {
fn into(self) -> String {
match self {
Field::FieldString => "str".to_string(),
Field::FieldBool => "bool".to_string(),
@ -294,7 +294,7 @@ impl Into<String> for &Field {
impl fmt::Display for Field {
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)
}
}

View File

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

View File

@ -1,5 +1,6 @@
use crate::common::{Field, YaSerdeAttribute, YaSerdeField};
use proc_macro2::TokenStream;
use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::{DataEnum, Fields, Ident};
pub fn parse(
@ -25,35 +26,31 @@ pub fn parse(
let flatten = root_attributes.flatten;
quote! {
use xml::reader::XmlEvent;
use yaserde::Visitor;
#[allow(unknown_lints, unused_imports)]
use std::str::FromStr;
use log::{debug, trace};
impl YaDeserialize for #name {
impl ::yaserde::YaDeserialize for #name {
#[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) =
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())
} else {
(std::string::String::from(#root), None)
(::std::string::String::from(#root), ::std::option::Option::None)
};
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
#[allow(unused_assignments, unused_mut)]
let mut enum_value = None;
let mut enum_value = ::std::option::Option::None;
loop {
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 {
XmlEvent::StartElement{ref name, ref attributes, ..} => {
::xml::reader::XmlEvent::StartElement { ref name, ref attributes, .. } => {
match name.local_name.as_str() {
#match_to_enum
_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_to_enum
_ => {}
}
}
}
XmlEvent::EndElement{ref name} => {
::xml::reader::XmlEvent::EndElement { ref name } => {
if name.local_name == named_element {
break;
}
let _root = reader.next_event();
}
XmlEvent::Characters(ref text_content) => {
::xml::reader::XmlEvent::Characters(ref text_content) => {
let _root = reader.next_event();
}
XmlEvent::EndDocument => {
::xml::reader::XmlEvent::EndDocument => {
if #flatten {
break;
}
return Err(format!("End of document, missing some content ?"))
return ::std::result::Result::Err(
::std::format!("End of document, missing some content ?"),
);
}
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 {
Some(value) => Ok(value),
None => {
Ok(#name::default())
::std::option::Option::Some(value) => ::std::result::Result::Ok(value),
::std::option::Option::None => {
::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 {
Fields::Unit => Some(quote! {
#xml_element_name => {
enum_value = Some(#variant_name);
enum_value = ::std::option::Option::Some(#variant_name);
}
}),
Fields::Unnamed(ref fields) => {
@ -150,22 +149,24 @@ fn build_unnamed_field_visitors(fields: &syn::FieldsUnnamed) -> TokenStream {
.iter()
.map(|field| YaSerdeField::new(field.clone()))
.enumerate()
.map(|(idx, field)| {
.filter_map(|(idx, field)| {
let visitor_label = Ident::new(&format!("__Visitor_{}", idx), field.get_span());
let make_visitor =
|visitor: &TokenStream, field_type: &TokenStream, fn_body: &TokenStream| {
Some(quote! {
let make_visitor = |visitor: &Ident, field_type: &TokenStream, fn_body: &TokenStream| {
quote! {
#[allow(non_snake_case, non_camel_case_types)]
struct #visitor_label;
impl<'de> Visitor<'de> for #visitor_label {
impl<'de> ::yaserde::Visitor<'de> for #visitor_label {
type Value = #field_type;
fn #visitor(self, v: &str) -> Result<Self::Value, std::string::String> {
fn #visitor(
self,
v: &str,
) -> ::std::result::Result<Self::Value, ::std::string::String> {
#fn_body
}
}
})
}
};
let simple_type_visitor = |simple_type: Field| {
@ -175,36 +176,36 @@ fn build_unnamed_field_visitors(fields: &syn::FieldsUnnamed) -> TokenStream {
make_visitor(
&visitor,
&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() {
Field::FieldStruct { struct_name } => {
let struct_id: std::string::String = struct_name
let struct_id: String = struct_name
.segments
.iter()
.map(|s| s.ident.to_string())
.collect();
make_visitor(
&quote! { visit_str },
Some(make_visitor(
&Ident::new("visit_str", Span::call_site()),
&quote! { #struct_name },
&quote! {
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
},
)
))
}
Field::FieldOption { data_type } | Field::FieldVec { data_type } => match *data_type {
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()
}
@ -230,18 +231,22 @@ fn build_unnamed_visitor_calls(
let visitor = #visitor_label{};
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("");
}
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)
} 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
}
})
@ -261,16 +266,24 @@ fn build_unnamed_visitor_calls(
})
};
let set_val = quote! { enum_value = Some(#variant_name(value)) };
let set_opt = quote! { enum_value = Some(#variant_name(Some(value))) };
let set_val = quote! {
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! {
match enum_value {
Some(ref mut v) => match v {
#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 => {
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 heck::CamelCase;
use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::{DataStruct, Ident};
pub fn parse(
@ -25,25 +26,33 @@ pub fn parse(
Field::FieldStruct { struct_name } => build_default_value(
&field,
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::FieldVec { data_type } => match *data_type {
Field::FieldStruct { ref struct_name } => {
build_default_value(&field, Some(quote!(Vec<#struct_name>)), quote!(vec![]))
Field::FieldOption { .. } => {
build_default_value(&field, None, quote!(::std::option::Option::None))
}
Field::FieldVec { data_type } => match *data_type {
Field::FieldStruct { ref struct_name } => build_default_value(
&field,
Some(quote!(::std::vec::Vec<#struct_name>)),
quote!(::std::vec![]),
),
Field::FieldOption { .. } | Field::FieldVec { .. } => {
unimplemented!();
}
simple_type => {
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 => {
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)
}
@ -57,7 +66,7 @@ pub fn parse(
.map(|field| YaSerdeField::new(field.clone()))
.map(|field| {
let struct_visitor = |struct_name: syn::Path| {
let struct_id: std::string::String = struct_name
let struct_id: String = struct_name
.segments
.iter()
.map(|s| s.ident.to_string())
@ -68,13 +77,15 @@ pub fn parse(
Some(quote! {
#[allow(non_snake_case, non_camel_case_types)]
struct #visitor_label;
impl<'de> Visitor<'de> for #visitor_label {
impl<'de> ::yaserde::Visitor<'de> for #visitor_label {
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 value : Result<#struct_name, std::string::String> = yaserde::de::from_str(&content);
value
::yaserde::de::from_str(&content)
}
}
})
@ -85,15 +96,12 @@ pub fn parse(
let visitor_label = field.get_visitor_ident(None);
let field_type: TokenStream = simple_type.into();
let map_if_bool =
if format!("{}", field_type) == "bool" {
quote!(
match v {
let map_if_bool = if field_type.to_string() == "bool" {
quote!(match v {
"1" => "true",
"0" => "false",
_ => v,
}
)
})
} else {
quote!(v)
};
@ -101,11 +109,14 @@ pub fn parse(
Some(quote! {
#[allow(non_snake_case, non_camel_case_types)]
struct #visitor_label;
impl<'de> Visitor<'de> for #visitor_label {
impl<'de> ::yaserde::Visitor<'de> for #visitor_label {
type Value = #field_type;
fn #visitor(self, v: &str) -> Result<Self::Value, std::string::String> {
Ok(#field_type::from_str(#map_if_bool).unwrap())
fn #visitor(
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
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
let value = #struct_name::deserialize(reader)?;
#value_label #action;
@ -173,10 +184,12 @@ pub fn parse(
};
match field.get_type() {
Field::FieldStruct { struct_name } => visit_struct(struct_name, quote! {= value}),
Field::FieldOption { data_type } => visit_sub(data_type, quote! {= Some(value)}),
Field::FieldVec { data_type } => visit_sub(data_type, quote! {.push(value)}),
simple_type => visit_simple(simple_type, quote! {= value}),
Field::FieldStruct { struct_name } => visit_struct(struct_name, quote! { = value }),
Field::FieldOption { data_type } => {
visit_sub(data_type, quote! { = ::std::option::Option::Some(value) })
}
Field::FieldVec { data_type } => visit_sub(data_type, quote! { .push(value) }),
simple_type => visit_simple(simple_type, quote! { = value }),
}
})
.filter_map(|x| x)
@ -192,11 +205,11 @@ pub fn parse(
match field.get_type() {
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::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),
},
@ -216,7 +229,7 @@ pub fn parse(
let label_name = field.renamed_label_without_namespace();
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! {
for attr in attributes {
if attr.name.local_name == #label_name {
@ -241,7 +254,7 @@ pub fn parse(
let visit_struct = |struct_name: syn::Path, action: TokenStream| {
visit(
&action,
&quote! {visit_str},
&Ident::new("visit_str", Span::call_site()),
&build_visitor_ident(&label_name, field.get_span(), Some(&struct_name)),
)
};
@ -262,10 +275,12 @@ pub fn parse(
match field.get_type() {
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::FieldStruct { struct_name } => visit_struct(struct_name, quote! {= value}),
simple_type => visit_simple(simple_type, quote! {= value}),
Field::FieldStruct { struct_name } => visit_struct(struct_name, quote! { = value }),
simple_type => visit_simple(simple_type, quote! { = value }),
}
})
.filter_map(|x| x)
@ -280,18 +295,18 @@ pub fn parse(
let set_text = |action: &TokenStream| {
if field.is_text_content() {
Some(quote! {#label = #action;})
Some(quote! { #label = #action; })
} else {
None
}
};
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,
simple_type => {
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;
quote! {
use xml::reader::{XmlEvent, EventReader};
use xml::writer::EventWriter;
use yaserde::Visitor;
#[allow(unknown_lints, unused_imports)]
use std::str::FromStr;
use log::{debug, trace};
impl YaDeserialize for #name {
impl ::yaserde::YaDeserialize for #name {
#[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) =
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())
} else {
(std::string::String::from(#root), None)
(::std::string::String::from(#root), ::std::option::Option::None)
};
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);
if reader.depth() == 0 {
@ -351,9 +361,12 @@ pub fn parse(
loop {
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 {
XmlEvent::StartElement{ref name, ref attributes, ..} => {
::xml::reader::XmlEvent::StartElement{ref name, ref attributes, ..} => {
match name.local_name.as_str() {
#call_visitors
_ => {
@ -372,7 +385,7 @@ pub fn parse(
}
depth += 1;
}
XmlEvent::EndElement{ref name} => {
::xml::reader::XmlEvent::EndElement { ref name } => {
if name.local_name == named_element {
#write_unused
break;
@ -381,26 +394,26 @@ pub fn parse(
#write_unused
depth -= 1;
}
XmlEvent::EndDocument => {
::xml::reader::XmlEvent::EndDocument => {
if #flatten {
break;
}
}
XmlEvent::Characters(ref text_content) => {
::xml::reader::XmlEvent::Characters(ref text_content) => {
#set_text
let event = reader.next_event()?;
#write_unused
}
event => {
return Err(format!("unknown event {:?}", event))
return ::std::result::Result::Err(::std::format!("unknown event {:?}", event));
}
}
}
#visit_unused
debug!("Struct {} @ {}: success", stringify!(#name), start_depth);
Ok(#name{#struct_builder})
::log::debug!("Struct {} @ {}: success", stringify!(#name), start_depth);
::std::result::Result::Ok(#name{#struct_builder})
}
}
}
@ -408,7 +421,7 @@ pub fn parse(
fn build_call_visitor(
field_type: &TokenStream,
visitor: &TokenStream,
visitor: &Ident,
action: &TokenStream,
field: &YaSerdeField,
root_attributes: &YaSerdeAttribute,
@ -430,16 +443,16 @@ fn build_call_visitor(
#namespaces_matching
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 _event = reader.next_event()?;
val
} 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
}
}
@ -477,19 +490,19 @@ fn build_code_for_unused_xml_events(
) {
(
Some(quote! {
let mut buf = Vec::new();
let mut writer = Some(EventWriter::new(&mut buf));
let mut buf = ::std::vec![];
let mut writer = ::std::option::Option::Some(::xml::writer::EventWriter::new(&mut buf));
}),
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() {
writer = None;
writer = ::std::option::Option::None;
}
}
}),
Some(quote! {
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
}
}),

View File

@ -3,8 +3,8 @@ pub mod expand_enum;
pub mod expand_struct;
use crate::common::YaSerdeAttribute;
use proc_macro2::TokenStream;
use syn::Ident;
use proc_macro2::{Ident, TokenStream};
use quote::quote;
pub fn expand_derive_deserialize(ast: &syn::DeriveInput) -> Result<TokenStream, String> {
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 generated = quote! {
Ok(quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
extern crate yaserde as _yaserde;
use ::std::str::FromStr as _;
use ::yaserde::Visitor as _;
#impl_block
};
};
Ok(generated)
})
}

View File

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

View File

@ -1,5 +1,6 @@
use crate::common::YaSerdeField;
use proc_macro2::{Ident, TokenStream};
use quote::quote;
pub fn enclose_formatted_characters(label: &Ident, label_name: String) -> TokenStream {
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 {
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())?;
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())?;
let end_event = XmlEvent::end_element();
let end_event = ::xml::writer::XmlEvent::end_element();
writer.write(end_event).map_err(|e| e.to_string())?;
}
}

View File

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

View File

@ -2,6 +2,7 @@ use crate::common::{Field, YaSerdeAttribute, YaSerdeField};
use crate::ser::{element::*, implement_serializer::implement_serializer};
use proc_macro2::TokenStream;
use quote::quote;
use syn::DataStruct;
use syn::Ident;
@ -44,7 +45,7 @@ pub fn serialize(
Field::FieldString => field.ser_wrap_default_attribute(
None,
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)
} else {
struct_start_event
@ -62,9 +63,11 @@ pub fn serialize(
| Field::FieldU64
| Field::FieldF32
| 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!({
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)
} else {
struct_start_event
@ -78,7 +81,7 @@ pub fn serialize(
field.ser_wrap_default_attribute(
None,
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() {
#inner
}
@ -87,11 +90,16 @@ pub fn serialize(
)
}
Field::FieldStruct { .. } => field.ser_wrap_default_attribute(
Some(quote!(self.#label
Some(quote! {
self.#label
.as_ref()
.map_or_else(|| Ok(std::string::String::new()), |v| yaserde::ser::to_string_content(v))?)),
.map_or_else(
|| ::std::result::Result::Ok(::std::string::String::new()),
|v| ::yaserde::ser::to_string_content(v),
)?
}),
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)
} else {
struct_start_event
@ -101,7 +109,7 @@ pub fn serialize(
Field::FieldOption { .. } => unimplemented!(),
},
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!({
struct_start_event.attr(#label_name, &yaserde_inner)
}),
@ -115,12 +123,15 @@ pub fn serialize(
match field.get_type() {
Field::FieldStruct { .. } => {
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.extend(attributes);
)
}
_ => quote!()
_ => quote!(),
}
}
})
@ -135,7 +146,7 @@ pub fn serialize(
let label = field.label();
if field.is_text_content() {
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())?;
));
}
@ -187,7 +198,7 @@ pub fn serialize(
Some(quote! {
#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() {
#inner
}
@ -197,16 +208,16 @@ pub fn serialize(
}
Field::FieldStruct { .. } => Some(if field.is_flatten() {
quote! {
if let Some(ref item) = &self.#label {
writer.set_start_event_name(None);
if let ::std::option::Option::Some(ref item) = &self.#label {
writer.set_start_event_name(::std::option::Option::None);
writer.set_skip_start_end(true);
item.serialize(writer)?;
}
}
} else {
quote! {
if let Some(ref item) = &self.#label {
writer.set_start_event_name(Some(#label_name.to_string()));
if let ::std::option::Option::Some(ref item) = &self.#label {
writer.set_start_event_name(::std::option::Option::Some(#label_name.to_string()));
writer.set_skip_start_end(false);
item.serialize(writer)?;
}
@ -216,9 +227,12 @@ pub fn serialize(
},
Field::FieldStruct { .. } => {
let (start_event, skip_start) = if field.is_flatten() {
(quote!(None), true)
(quote!(::std::option::Option::None), true)
} else {
(quote!(Some(#label_name.to_string())), false)
(
quote!(::std::option::Option::Some(#label_name.to_string())),
false,
)
};
Some(quote! {
@ -271,7 +285,7 @@ pub fn serialize(
if field.is_flatten() {
Some(quote! {
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);
item.serialize(writer)?;
}
@ -279,7 +293,7 @@ pub fn serialize(
} else {
Some(quote! {
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);
item.serialize(writer)?;
}

View File

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

View File

@ -6,8 +6,8 @@ pub mod label;
pub mod namespace;
use crate::common::YaSerdeAttribute;
use proc_macro2::TokenStream;
use syn::Ident;
use proc_macro2::{Ident, TokenStream};
use quote::quote;
pub fn expand_derive_serialize(ast: &syn::DeriveInput) -> Result<TokenStream, String> {
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 generated = quote! {
Ok(quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
extern crate yaserde as _yaserde;
use ::std::str::FromStr as _;
#impl_block
};
};
Ok(generated)
})
}

View File

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