337 lines
11 KiB
Rust
337 lines
11 KiB
Rust
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;
|
|
|
|
pub fn serialize(
|
|
data_struct: &DataStruct,
|
|
name: &Ident,
|
|
root: &str,
|
|
root_attributes: &YaSerdeAttribute,
|
|
) -> TokenStream {
|
|
let append_attributes: TokenStream = data_struct
|
|
.fields
|
|
.iter()
|
|
.map(|field| YaSerdeField::new(field.clone()))
|
|
.filter(|field| field.is_attribute() || field.is_flatten())
|
|
.map(|field| {
|
|
let label = field.label();
|
|
|
|
if field.is_attribute() {
|
|
let label_name = field.renamed_label(root_attributes);
|
|
|
|
match field.get_type() {
|
|
Field::FieldString
|
|
| Field::FieldBool
|
|
| Field::FieldI8
|
|
| Field::FieldU8
|
|
| Field::FieldI16
|
|
| Field::FieldU16
|
|
| Field::FieldI32
|
|
| Field::FieldU32
|
|
| Field::FieldI64
|
|
| Field::FieldU64
|
|
| Field::FieldF32
|
|
| Field::FieldF64 => 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 => field.ser_wrap_default_attribute(
|
|
None,
|
|
quote!({
|
|
if let ::std::option::Option::Some(ref value) = self.#label {
|
|
struct_start_event.attr(#label_name, value)
|
|
} else {
|
|
struct_start_event
|
|
}
|
|
}),
|
|
),
|
|
Field::FieldBool
|
|
| Field::FieldI8
|
|
| Field::FieldU8
|
|
| Field::FieldI16
|
|
| 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(|| ::std::string::String::new(), |v| v.to_string())),
|
|
),
|
|
quote!({
|
|
if let ::std::option::Option::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 ::std::option::Option::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(
|
|
|| ::std::result::Result::Ok(::std::string::String::new()),
|
|
|v| ::yaserde::ser::to_string_content(v),
|
|
)?
|
|
}),
|
|
quote!({
|
|
if let ::std::option::Option::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!({
|
|
struct_start_event.attr(#label_name, &yaserde_inner)
|
|
}),
|
|
),
|
|
Field::FieldVec { .. } => {
|
|
// TODO
|
|
quote!()
|
|
}
|
|
}
|
|
} else {
|
|
match field.get_type() {
|
|
Field::FieldStruct { .. } => {
|
|
quote!(
|
|
let (attributes, namespace) = self.#label.serialize_attributes(
|
|
::std::vec![],
|
|
::yaserde::__xml::namespace::Namespace::empty(),
|
|
)?;
|
|
child_attributes_namespace.extend(&namespace);
|
|
child_attributes.extend(attributes);
|
|
)
|
|
}
|
|
_ => quote!(),
|
|
}
|
|
}
|
|
})
|
|
.collect();
|
|
|
|
let struct_inspector: TokenStream = data_struct
|
|
.fields
|
|
.iter()
|
|
.map(|field| YaSerdeField::new(field.clone()))
|
|
.filter(|field| !field.is_attribute())
|
|
.filter_map(|field| {
|
|
let label = field.label();
|
|
if field.is_text_content() {
|
|
return match field.get_type() {
|
|
Field::FieldOption { .. } => Some(quote!(
|
|
let s = self.#label.as_deref().unwrap_or_default();
|
|
let data_event = ::yaserde::__xml::writer::XmlEvent::characters(s);
|
|
writer.write(data_event).map_err(|e| e.to_string())?;
|
|
)),
|
|
_ => Some(quote!(
|
|
let data_event = ::yaserde::__xml::writer::XmlEvent::characters(&self.#label);
|
|
writer.write(data_event).map_err(|e| e.to_string())?;
|
|
)),
|
|
};
|
|
}
|
|
|
|
let label_name = field.renamed_label(root_attributes);
|
|
let conditions = condition_generator(&label, &field);
|
|
|
|
match field.get_type() {
|
|
Field::FieldString
|
|
| Field::FieldBool
|
|
| Field::FieldI8
|
|
| Field::FieldU8
|
|
| Field::FieldI16
|
|
| Field::FieldU16
|
|
| Field::FieldI32
|
|
| Field::FieldU32
|
|
| Field::FieldI64
|
|
| Field::FieldU64
|
|
| Field::FieldF32
|
|
| Field::FieldF64 => serialize_element(&label, label_name, &conditions),
|
|
|
|
Field::FieldOption { data_type } => match *data_type {
|
|
Field::FieldString
|
|
| Field::FieldBool
|
|
| Field::FieldI8
|
|
| Field::FieldU8
|
|
| Field::FieldI16
|
|
| Field::FieldU16
|
|
| Field::FieldI32
|
|
| Field::FieldU32
|
|
| Field::FieldI64
|
|
| Field::FieldU64
|
|
| Field::FieldF32
|
|
| Field::FieldF64 => {
|
|
let item_ident = Ident::new("yaserde_item", field.get_span());
|
|
let inner = enclose_formatted_characters_for_value(&item_ident, label_name);
|
|
|
|
Some(quote! {
|
|
#conditions {
|
|
if let Some(ref yaserde_item) = self.#label {
|
|
#inner
|
|
}
|
|
}
|
|
})
|
|
}
|
|
Field::FieldVec { .. } => {
|
|
let item_ident = Ident::new("yaserde_item", field.get_span());
|
|
let inner = enclose_formatted_characters_for_value(&item_ident, label_name);
|
|
|
|
Some(quote! {
|
|
#conditions {
|
|
if let ::std::option::Option::Some(ref yaserde_items) = &self.#label {
|
|
for yaserde_item in yaserde_items.iter() {
|
|
#inner
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
Field::FieldStruct { .. } => Some(if field.is_flatten() {
|
|
quote! {
|
|
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);
|
|
::yaserde::YaSerialize::serialize(item, writer)?;
|
|
}
|
|
}
|
|
} else {
|
|
quote! {
|
|
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);
|
|
::yaserde::YaSerialize::serialize(item, writer)?;
|
|
}
|
|
}
|
|
}),
|
|
_ => unimplemented!(),
|
|
},
|
|
Field::FieldStruct { .. } => {
|
|
let (start_event, skip_start) = if field.is_flatten() {
|
|
(quote!(::std::option::Option::None), true)
|
|
} else {
|
|
(
|
|
quote!(::std::option::Option::Some(#label_name.to_string())),
|
|
false,
|
|
)
|
|
};
|
|
|
|
Some(quote! {
|
|
writer.set_start_event_name(#start_event);
|
|
writer.set_skip_start_end(#skip_start);
|
|
::yaserde::YaSerialize::serialize(&self.#label, writer)?;
|
|
})
|
|
}
|
|
Field::FieldVec { data_type } => match *data_type {
|
|
Field::FieldString => {
|
|
let item_ident = Ident::new("yaserde_item", field.get_span());
|
|
let inner = enclose_formatted_characters_for_value(&item_ident, label_name);
|
|
|
|
Some(quote! {
|
|
for yaserde_item in &self.#label {
|
|
#inner
|
|
}
|
|
})
|
|
}
|
|
Field::FieldBool
|
|
| Field::FieldI8
|
|
| Field::FieldU8
|
|
| Field::FieldI16
|
|
| Field::FieldU16
|
|
| Field::FieldI32
|
|
| Field::FieldU32
|
|
| Field::FieldI64
|
|
| Field::FieldU64
|
|
| Field::FieldF32
|
|
| Field::FieldF64 => {
|
|
let item_ident = Ident::new("yaserde_item", field.get_span());
|
|
let inner = enclose_formatted_characters_for_value(&item_ident, label_name);
|
|
|
|
Some(quote! {
|
|
for yaserde_item in &self.#label {
|
|
#inner
|
|
}
|
|
})
|
|
}
|
|
Field::FieldOption { .. } => Some(quote! {
|
|
for item in &self.#label {
|
|
if let Some(value) = item {
|
|
writer.set_start_event_name(None);
|
|
writer.set_skip_start_end(false);
|
|
::yaserde::YaSerialize::serialize(value, writer)?;
|
|
}
|
|
}
|
|
}),
|
|
Field::FieldStruct { .. } => {
|
|
if field.is_flatten() {
|
|
Some(quote! {
|
|
for item in &self.#label {
|
|
writer.set_start_event_name(::std::option::Option::None);
|
|
writer.set_skip_start_end(true);
|
|
::yaserde::YaSerialize::serialize(item, writer)?;
|
|
}
|
|
})
|
|
} else {
|
|
Some(quote! {
|
|
for item in &self.#label {
|
|
writer.set_start_event_name(::std::option::Option::Some(#label_name.to_string()));
|
|
writer.set_skip_start_end(false);
|
|
::yaserde::YaSerialize::serialize(item, writer)?;
|
|
}
|
|
})
|
|
}
|
|
/*let (start_event, skip_start) = if field.is_flatten() {
|
|
(quote!(None), true)
|
|
} else {
|
|
(quote!(Some(#label_name.to_string())), false)
|
|
};
|
|
|
|
Some(quote! {
|
|
writer.set_start_event_name(#start_event);
|
|
writer.set_skip_start_end(#skip_start);
|
|
::yaserde::YaSerialize::serialize(&self.#label, writer)?;
|
|
})*/
|
|
}
|
|
Field::FieldVec { .. } => {
|
|
unimplemented!();
|
|
}
|
|
},
|
|
}
|
|
})
|
|
.collect();
|
|
|
|
implement_serializer(
|
|
name,
|
|
root,
|
|
root_attributes,
|
|
append_attributes,
|
|
struct_inspector,
|
|
)
|
|
}
|