Merge pull request #82 from media-io/flatten_attribute
support flatten attributes
This commit is contained in:
commit
23098184f2
@ -23,8 +23,20 @@ pub trait YaDeserialize: Sized {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 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<'a>: Sized {
|
||||||
fn serialize<W: Write>(&self, writer: &mut ser::Serializer<W>) -> Result<(), String>;
|
fn serialize<W: Write>(&self, writer: &mut ser::Serializer<W>) -> Result<(), String>;
|
||||||
|
|
||||||
|
fn serialize_attributes(
|
||||||
|
&self,
|
||||||
|
attributes: Vec<xml::attribute::OwnedAttribute>,
|
||||||
|
namespace: xml::namespace::Namespace,
|
||||||
|
) -> Result<
|
||||||
|
(
|
||||||
|
Vec<xml::attribute::OwnedAttribute>,
|
||||||
|
xml::namespace::Namespace,
|
||||||
|
),
|
||||||
|
String,
|
||||||
|
>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A **visitor** that can be implemented to retrieve information from source file.
|
/// A **visitor** that can be implemented to retrieve information from source file.
|
||||||
@ -83,13 +95,27 @@ pub trait Visitor<'de>: Sized {
|
|||||||
|
|
||||||
macro_rules! serialize_type {
|
macro_rules! serialize_type {
|
||||||
($type:ty) => {
|
($type:ty) => {
|
||||||
impl YaSerialize for $type {
|
impl<'a> YaSerialize<'a> for $type {
|
||||||
fn serialize<W: Write>(&self, writer: &mut ser::Serializer<W>) -> Result<(), String> {
|
fn serialize<W: Write>(&self, writer: &mut ser::Serializer<W>) -> Result<(), 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);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn serialize_attributes(
|
||||||
|
&self,
|
||||||
|
attributes: Vec<xml::attribute::OwnedAttribute>,
|
||||||
|
namespace: xml::namespace::Namespace,
|
||||||
|
) -> Result<
|
||||||
|
(
|
||||||
|
Vec<xml::attribute::OwnedAttribute>,
|
||||||
|
xml::namespace::Namespace,
|
||||||
|
),
|
||||||
|
String,
|
||||||
|
> {
|
||||||
|
Ok((attributes, namespace))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,21 +7,24 @@ use std::str;
|
|||||||
use xml::writer::XmlEvent;
|
use xml::writer::XmlEvent;
|
||||||
use xml::{EmitterConfig, EventWriter};
|
use xml::{EmitterConfig, EventWriter};
|
||||||
|
|
||||||
pub fn to_string<T: YaSerialize>(model: &T) -> Result<String, String> {
|
pub fn to_string<'a, T: YaSerialize<'a>>(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(String::from(data))
|
Ok(String::from(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_string_with_config<T: YaSerialize>(model: &T, config: &Config) -> Result<String, String> {
|
pub fn to_string_with_config<'a, T: YaSerialize<'a>>(
|
||||||
|
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(String::from(data))
|
Ok(String::from(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serialize_with_writer<W: Write, T: YaSerialize>(
|
pub fn serialize_with_writer<'a, W: Write, T: YaSerialize<'a>>(
|
||||||
model: &T,
|
model: &T,
|
||||||
writer: W,
|
writer: W,
|
||||||
_config: &Config,
|
_config: &Config,
|
||||||
@ -33,14 +36,14 @@ pub fn serialize_with_writer<W: Write, T: YaSerialize>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_string_content<T: YaSerialize>(model: &T) -> Result<String, String> {
|
pub fn to_string_content<'a, T: YaSerialize<'a>>(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(String::from(data))
|
Ok(String::from(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serialize_with_writer_content<W: Write, T: YaSerialize>(
|
pub fn serialize_with_writer_content<'a, W: Write, T: YaSerialize<'a>>(
|
||||||
model: &T,
|
model: &T,
|
||||||
writer: W,
|
writer: W,
|
||||||
) -> Result<W, String> {
|
) -> Result<W, String> {
|
||||||
|
|||||||
@ -144,3 +144,43 @@ fn root_flatten_enum() {
|
|||||||
let content = "<Data><string_data>string</string_data></Data>";
|
let content = "<Data><string_data>string</string_data></Data>";
|
||||||
serialize_and_validate!(model, content);
|
serialize_and_validate!(model, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn flatten_attribute() {
|
||||||
|
#[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)]
|
||||||
|
struct HtmlText {
|
||||||
|
#[yaserde(flatten)]
|
||||||
|
text_attributes: TextAttributes,
|
||||||
|
#[yaserde(attribute)]
|
||||||
|
display: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)]
|
||||||
|
struct TextAttributes {
|
||||||
|
#[yaserde(attribute)]
|
||||||
|
bold: bool,
|
||||||
|
#[yaserde(flatten)]
|
||||||
|
font: FontAttributes,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)]
|
||||||
|
#[yaserde(namespace = "ns: http://www.sample.com/ns/domain")]
|
||||||
|
pub struct FontAttributes {
|
||||||
|
#[yaserde(attribute, prefix = "ns")]
|
||||||
|
size: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
let model = HtmlText {
|
||||||
|
text_attributes: TextAttributes {
|
||||||
|
bold: true,
|
||||||
|
font: FontAttributes { size: 24 },
|
||||||
|
},
|
||||||
|
display: "block".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = r#"
|
||||||
|
<HtmlText xmlns:ns="http://www.sample.com/ns/domain" display="block" bold="true" ns:size="24" />"#;
|
||||||
|
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, HtmlText);
|
||||||
|
}
|
||||||
|
|||||||
@ -293,7 +293,7 @@ fn ser_custom() {
|
|||||||
value: i32,
|
value: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl YaSerialize for Day {
|
impl<'a> YaSerialize<'a> for Day {
|
||||||
fn serialize<W: Write>(&self, writer: &mut yaserde::ser::Serializer<W>) -> Result<(), String> {
|
fn serialize<W: Write>(&self, writer: &mut yaserde::ser::Serializer<W>) -> Result<(), String> {
|
||||||
let _ret = writer.write(xml::writer::XmlEvent::start_element("DoubleDay"));
|
let _ret = writer.write(xml::writer::XmlEvent::start_element("DoubleDay"));
|
||||||
let _ret = writer.write(xml::writer::XmlEvent::characters(
|
let _ret = writer.write(xml::writer::XmlEvent::characters(
|
||||||
@ -302,6 +302,20 @@ fn ser_custom() {
|
|||||||
let _ret = writer.write(xml::writer::XmlEvent::end_element());
|
let _ret = writer.write(xml::writer::XmlEvent::end_element());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn serialize_attributes(
|
||||||
|
&self,
|
||||||
|
attributes: Vec<xml::attribute::OwnedAttribute>,
|
||||||
|
namespace: xml::namespace::Namespace,
|
||||||
|
) -> Result<
|
||||||
|
(
|
||||||
|
Vec<xml::attribute::OwnedAttribute>,
|
||||||
|
xml::namespace::Namespace,
|
||||||
|
),
|
||||||
|
String,
|
||||||
|
> {
|
||||||
|
Ok((attributes, namespace))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let model = Date {
|
let model = Date {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use crate::common::{Field, YaSerdeAttribute, YaSerdeField};
|
use crate::common::{Field, YaSerdeAttribute, YaSerdeField};
|
||||||
use crate::ser::{implement_deserializer::implement_deserializer, label::build_label_name};
|
use crate::ser::{implement_serializer::implement_serializer, label::build_label_name};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use syn::DataEnum;
|
use syn::DataEnum;
|
||||||
use syn::Fields;
|
use syn::Fields;
|
||||||
@ -13,7 +13,7 @@ pub fn serialize(
|
|||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let inner_enum_inspector = inner_enum_inspector(data_enum, name, root_attributes);
|
let inner_enum_inspector = inner_enum_inspector(data_enum, name, root_attributes);
|
||||||
|
|
||||||
implement_deserializer(
|
implement_serializer(
|
||||||
name,
|
name,
|
||||||
root,
|
root,
|
||||||
root_attributes,
|
root_attributes,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::common::{Field, YaSerdeAttribute, YaSerdeField};
|
use crate::common::{Field, YaSerdeAttribute, YaSerdeField};
|
||||||
|
|
||||||
use crate::ser::{element::*, implement_deserializer::implement_deserializer};
|
use crate::ser::{element::*, implement_serializer::implement_serializer};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use syn::DataStruct;
|
use syn::DataStruct;
|
||||||
use syn::Ident;
|
use syn::Ident;
|
||||||
@ -11,45 +11,20 @@ pub fn serialize(
|
|||||||
root: &str,
|
root: &str,
|
||||||
root_attributes: &YaSerdeAttribute,
|
root_attributes: &YaSerdeAttribute,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let build_attributes: TokenStream = data_struct
|
let append_attributes: TokenStream = data_struct
|
||||||
.fields
|
.fields
|
||||||
.iter()
|
.iter()
|
||||||
.map(|field| YaSerdeField::new(field.clone()))
|
.map(|field| YaSerdeField::new(field.clone()))
|
||||||
.filter(|field| field.is_attribute())
|
.filter(|field| field.is_attribute() || field.is_flatten())
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
let label = field.label();
|
let label = field.label();
|
||||||
let label_name = field.renamed_label(root_attributes);
|
|
||||||
|
|
||||||
match field.get_type() {
|
if field.is_attribute() {
|
||||||
Field::FieldString
|
let label_name = field.renamed_label(root_attributes);
|
||||||
| Field::FieldBool
|
|
||||||
| Field::FieldI8
|
match field.get_type() {
|
||||||
| Field::FieldU8
|
Field::FieldString
|
||||||
| Field::FieldI16
|
| Field::FieldBool
|
||||||
| Field::FieldU16
|
|
||||||
| Field::FieldI32
|
|
||||||
| Field::FieldU32
|
|
||||||
| Field::FieldI64
|
|
||||||
| Field::FieldU64
|
|
||||||
| Field::FieldF32
|
|
||||||
| Field::FieldF64 => Some(field.ser_wrap_default_attribute(
|
|
||||||
Some(quote!(self.#label.to_string())),
|
|
||||||
quote!({
|
|
||||||
struct_start_event.attr(#label_name, &yaserde_inner)
|
|
||||||
}),
|
|
||||||
)),
|
|
||||||
Field::FieldOption { data_type } => match *data_type {
|
|
||||||
Field::FieldString => Some(field.ser_wrap_default_attribute(
|
|
||||||
None,
|
|
||||||
quote!({
|
|
||||||
if let Some(ref value) = self.#label {
|
|
||||||
struct_start_event.attr(#label_name, value)
|
|
||||||
} else {
|
|
||||||
struct_start_event
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
)),
|
|
||||||
Field::FieldBool
|
|
||||||
| Field::FieldI8
|
| Field::FieldI8
|
||||||
| Field::FieldU8
|
| Field::FieldU8
|
||||||
| Field::FieldI16
|
| Field::FieldI16
|
||||||
@ -59,55 +34,96 @@ pub fn serialize(
|
|||||||
| Field::FieldI64
|
| Field::FieldI64
|
||||||
| Field::FieldU64
|
| Field::FieldU64
|
||||||
| Field::FieldF32
|
| Field::FieldF32
|
||||||
| Field::FieldF64 => Some(field.ser_wrap_default_attribute(
|
| Field::FieldF64 => field.ser_wrap_default_attribute(
|
||||||
Some(quote!(self.#label.map_or_else(|| String::new(), |v| v.to_string()))),
|
Some(quote!(self.#label.to_string())),
|
||||||
quote!({
|
quote!({
|
||||||
if let Some(ref value) = self.#label {
|
struct_start_event.attr(#label_name, &yaserde_inner)
|
||||||
struct_start_event.attr(#label_name, &yaserde_inner)
|
|
||||||
} else {
|
|
||||||
struct_start_event
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
)),
|
),
|
||||||
Field::FieldVec { .. } => {
|
Field::FieldOption { data_type } => match *data_type {
|
||||||
let item_ident = Ident::new("yaserde_item", field.get_span());
|
Field::FieldString => field.ser_wrap_default_attribute(
|
||||||
let inner = enclose_formatted_characters(&item_ident, label_name);
|
|
||||||
|
|
||||||
Some(field.ser_wrap_default_attribute(
|
|
||||||
None,
|
None,
|
||||||
quote!({
|
quote!({
|
||||||
if let Some(ref yaserde_list) = self.#label {
|
if let Some(ref value) = self.#label {
|
||||||
for yaserde_item in yaserde_list.iter() {
|
struct_start_event.attr(#label_name, value)
|
||||||
#inner
|
} else {
|
||||||
}
|
struct_start_event
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
))
|
),
|
||||||
}
|
Field::FieldBool
|
||||||
Field::FieldStruct { .. } => Some(field.ser_wrap_default_attribute(
|
| Field::FieldI8
|
||||||
Some(quote!(self.#label
|
| Field::FieldU8
|
||||||
.as_ref()
|
| Field::FieldI16
|
||||||
.map_or_else(|| Ok(String::new()), |v| yaserde::ser::to_string_content(v))?)),
|
| Field::FieldU16
|
||||||
|
| Field::FieldI32
|
||||||
|
| Field::FieldU32
|
||||||
|
| Field::FieldI64
|
||||||
|
| Field::FieldU64
|
||||||
|
| Field::FieldF32
|
||||||
|
| Field::FieldF64 => field.ser_wrap_default_attribute(
|
||||||
|
Some(quote!(self.#label.map_or_else(|| String::new(), |v| v.to_string()))),
|
||||||
|
quote!({
|
||||||
|
if let Some(ref value) = self.#label {
|
||||||
|
struct_start_event.attr(#label_name, &yaserde_inner)
|
||||||
|
} else {
|
||||||
|
struct_start_event
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
Field::FieldVec { .. } => {
|
||||||
|
let item_ident = Ident::new("yaserde_item", field.get_span());
|
||||||
|
let inner = enclose_formatted_characters(&item_ident, label_name);
|
||||||
|
|
||||||
|
field.ser_wrap_default_attribute(
|
||||||
|
None,
|
||||||
|
quote!({
|
||||||
|
if let Some(ref yaserde_list) = self.#label {
|
||||||
|
for yaserde_item in yaserde_list.iter() {
|
||||||
|
#inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Field::FieldStruct { .. } => field.ser_wrap_default_attribute(
|
||||||
|
Some(quote!(self.#label
|
||||||
|
.as_ref()
|
||||||
|
.map_or_else(|| Ok(String::new()), |v| yaserde::ser::to_string_content(v))?)),
|
||||||
|
quote!({
|
||||||
|
if let Some(ref yaserde_struct) = self.#label {
|
||||||
|
struct_start_event.attr(#label_name, &yaserde_inner)
|
||||||
|
} else {
|
||||||
|
struct_start_event
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
Field::FieldOption { .. } => unimplemented!(),
|
||||||
|
},
|
||||||
|
Field::FieldStruct { .. } => field.ser_wrap_default_attribute(
|
||||||
|
Some(quote!(yaserde::ser::to_string_content(&self.#label)?)),
|
||||||
quote!({
|
quote!({
|
||||||
if let Some(ref yaserde_struct) = self.#label {
|
struct_start_event.attr(#label_name, &yaserde_inner)
|
||||||
struct_start_event.attr(#label_name, &yaserde_inner)
|
|
||||||
} else {
|
|
||||||
struct_start_event
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
)),
|
),
|
||||||
Field::FieldOption { .. } => unimplemented!(),
|
Field::FieldVec { .. } => {
|
||||||
},
|
// TODO
|
||||||
Field::FieldStruct { .. } => Some(field.ser_wrap_default_attribute(
|
quote!()
|
||||||
Some(quote!(yaserde::ser::to_string_content(&self.#label)?)),
|
}
|
||||||
quote!({
|
}
|
||||||
struct_start_event.attr(#label_name, &yaserde_inner)
|
} else {
|
||||||
}),
|
match field.get_type() {
|
||||||
)),
|
Field::FieldStruct { .. } => {
|
||||||
Field::FieldVec { .. } => None,
|
quote!(
|
||||||
|
let (attributes, namespace) = self.#label.serialize_attributes(vec![], xml::namespace::Namespace::empty())?;
|
||||||
|
child_attributes_namespace.extend(&namespace);
|
||||||
|
child_attributes.extend(attributes);
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => quote!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.filter_map(|x| x)
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let struct_inspector: TokenStream = data_struct
|
let struct_inspector: TokenStream = data_struct
|
||||||
@ -267,11 +283,11 @@ pub fn serialize(
|
|||||||
.filter_map(|x| x)
|
.filter_map(|x| x)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
implement_deserializer(
|
implement_serializer(
|
||||||
name,
|
name,
|
||||||
root,
|
root,
|
||||||
root_attributes,
|
root_attributes,
|
||||||
build_attributes,
|
append_attributes,
|
||||||
struct_inspector,
|
struct_inspector,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,43 +0,0 @@
|
|||||||
use crate::common::YaSerdeAttribute;
|
|
||||||
use crate::ser::namespace::generate_namespaces_definition;
|
|
||||||
use proc_macro2::Ident;
|
|
||||||
use proc_macro2::TokenStream;
|
|
||||||
|
|
||||||
pub fn implement_deserializer(
|
|
||||||
name: &Ident,
|
|
||||||
root: &str,
|
|
||||||
attributes: &YaSerdeAttribute,
|
|
||||||
attributes_inspector: TokenStream,
|
|
||||||
inner_inspector: TokenStream,
|
|
||||||
) -> TokenStream {
|
|
||||||
let namespaces_definition = generate_namespaces_definition(attributes);
|
|
||||||
let flatten = attributes.flatten;
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
use xml::writer::XmlEvent;
|
|
||||||
|
|
||||||
impl YaSerialize for #name {
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn serialize<W: Write>(&self, writer: &mut yaserde::ser::Serializer<W>)
|
|
||||||
-> Result<(), String> {
|
|
||||||
let skip = writer.skip_start_end();
|
|
||||||
|
|
||||||
if !#flatten && !skip {
|
|
||||||
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;
|
|
||||||
#attributes_inspector
|
|
||||||
writer.write(struct_start_event).map_err(|e| e.to_string())?;
|
|
||||||
}
|
|
||||||
|
|
||||||
#inner_inspector
|
|
||||||
|
|
||||||
if !#flatten && !skip {
|
|
||||||
let struct_end_event = XmlEvent::end_element();
|
|
||||||
writer.write(struct_end_event).map_err(|e| e.to_string())?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
87
yaserde_derive/src/ser/implement_serializer.rs
Normal file
87
yaserde_derive/src/ser/implement_serializer.rs
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
use crate::common::YaSerdeAttribute;
|
||||||
|
use crate::ser::namespace::generate_namespaces_definition;
|
||||||
|
use proc_macro2::Ident;
|
||||||
|
use proc_macro2::TokenStream;
|
||||||
|
|
||||||
|
pub fn implement_serializer(
|
||||||
|
name: &Ident,
|
||||||
|
root: &str,
|
||||||
|
attributes: &YaSerdeAttribute,
|
||||||
|
append_attributes: TokenStream,
|
||||||
|
inner_inspector: TokenStream,
|
||||||
|
) -> TokenStream {
|
||||||
|
let namespaces_definition = generate_namespaces_definition(attributes);
|
||||||
|
let flatten = attributes.flatten;
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
use xml::writer::XmlEvent;
|
||||||
|
|
||||||
|
impl<'a> YaSerialize<'a> for #name {
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn serialize<W: Write>(&self, writer: &mut yaserde::ser::Serializer<W>)
|
||||||
|
-> Result<(), 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 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;
|
||||||
|
#append_attributes
|
||||||
|
|
||||||
|
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();
|
||||||
|
attributes.extend(child_attributes);
|
||||||
|
|
||||||
|
let all_attributes = attributes.iter().map(|ca| ca.borrow()).collect();
|
||||||
|
|
||||||
|
let mut all_namespaces = namespace.into_owned();
|
||||||
|
all_namespaces.extend(&child_attributes_namespace);
|
||||||
|
|
||||||
|
writer.write(xml::writer::events::XmlEvent::StartElement{
|
||||||
|
name,
|
||||||
|
attributes: std::borrow::Cow::Owned(all_attributes),
|
||||||
|
namespace: std::borrow::Cow::Owned(all_namespaces)
|
||||||
|
}).map_err(|e| e.to_string())?;
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#inner_inspector
|
||||||
|
|
||||||
|
if !#flatten && !skip {
|
||||||
|
let struct_end_event = XmlEvent::end_element();
|
||||||
|
writer.write(struct_end_event).map_err(|e| e.to_string())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
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), String> {
|
||||||
|
let mut child_attributes : Vec<xml::attribute::OwnedAttribute> = vec![];
|
||||||
|
let mut child_attributes_namespace = xml::namespace::Namespace::empty();
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
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();
|
||||||
|
source_attributes.extend(a);
|
||||||
|
source_attributes.extend(child_attributes);
|
||||||
|
|
||||||
|
Ok((source_attributes, source_namespace))
|
||||||
|
} else {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
pub mod element;
|
pub mod element;
|
||||||
pub mod expand_enum;
|
pub mod expand_enum;
|
||||||
pub mod expand_struct;
|
pub mod expand_struct;
|
||||||
pub mod implement_deserializer;
|
pub mod implement_serializer;
|
||||||
pub mod label;
|
pub mod label;
|
||||||
pub mod namespace;
|
pub mod namespace;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user