commit
efdab555e1
@ -325,7 +325,7 @@ macro_rules! serialize_and_validate {
|
|||||||
log::debug!("serialize_and_validate @ {}:{}", file!(), line!());
|
log::debug!("serialize_and_validate @ {}:{}", file!(), line!());
|
||||||
let data: Result<String, String> = yaserde::ser::to_string(&$model);
|
let data: Result<String, String> = yaserde::ser::to_string(&$model);
|
||||||
|
|
||||||
let content = format!(r#"<?xml version="1.0" encoding="utf-8"?>{}"#, $content);
|
let content = &format!(r#"<?xml version="1.0" encoding="utf-8"?>{}"#, $content);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
data,
|
data,
|
||||||
Ok(content.split("\n").map(|s| s.trim()).collect::<String>())
|
Ok(content.split("\n").map(|s| s.trim()).collect::<String>())
|
||||||
|
|||||||
@ -147,6 +147,85 @@ fn attribute_enum() {
|
|||||||
deserialize_and_validate!(content, model, XmlStruct);
|
deserialize_and_validate!(content, model, XmlStruct);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn attribute_enum2() {
|
||||||
|
#[derive(Debug, PartialEq, YaSerialize, YaDeserialize)]
|
||||||
|
#[yaserde(rename = "child1")]
|
||||||
|
struct Child1 {
|
||||||
|
#[yaserde(attribute, rename = "val")]
|
||||||
|
pub val: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Child1 {
|
||||||
|
fn default() -> Child1 {
|
||||||
|
Child1{val: "hello world".into()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, YaSerialize, YaDeserialize)]
|
||||||
|
#[yaserde(rename = "child2")]
|
||||||
|
struct Child2 {
|
||||||
|
#[yaserde(attribute)]
|
||||||
|
pub num: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Child2 {
|
||||||
|
fn default() -> Child2 {
|
||||||
|
Child2{num: 0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, YaSerialize, YaDeserialize)]
|
||||||
|
#[yaserde(flatten)]
|
||||||
|
enum Base {
|
||||||
|
#[yaserde(flatten, rename="child1")]
|
||||||
|
C1(Child1),
|
||||||
|
#[yaserde(flatten, rename="child2")]
|
||||||
|
C2(Child2),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Base {
|
||||||
|
fn default() -> Base {
|
||||||
|
Base::C1(Child1{val: "hello world".into()})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = r#"<child1 val="hello world" />"#;
|
||||||
|
let model = Base::C1(Child1 {
|
||||||
|
val: "hello world".into(),
|
||||||
|
});
|
||||||
|
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, Base);
|
||||||
|
|
||||||
|
let content = r#"<child2 num="7" />"#;
|
||||||
|
let model = Base::C2(Child2{ num: 7 });
|
||||||
|
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
deserialize_and_validate!(content, model, Base);
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, YaSerialize, YaDeserialize)]
|
||||||
|
#[yaserde(rename = "base")]
|
||||||
|
enum Base2 {
|
||||||
|
#[yaserde(flatten)]
|
||||||
|
C1(Child1),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Base2 {
|
||||||
|
fn default() -> Base2 {
|
||||||
|
Base2::C1(Child1{val: "hello world".into()})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = r#"<base><child1 val="hello world" /></base>"#;
|
||||||
|
let model = Base2::C1(Child1 {
|
||||||
|
val: "hello world".into(),
|
||||||
|
});
|
||||||
|
serialize_and_validate!(model, content);
|
||||||
|
println!("{:?}", yaserde::de::from_str::<Base2>(content));
|
||||||
|
deserialize_and_validate!(content, model, Base2);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn unnamed_enum() {
|
fn unnamed_enum() {
|
||||||
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
|
||||||
|
|||||||
@ -14,11 +14,81 @@ 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);
|
||||||
|
|
||||||
|
let get_id = |field: &YaSerdeField| {
|
||||||
|
field
|
||||||
|
.label()
|
||||||
|
.unwrap_or(field.get_type().get_simple_type_visitor())
|
||||||
|
};
|
||||||
|
|
||||||
|
let variant_matches: TokenStream = data_enum
|
||||||
|
.variants
|
||||||
|
.iter()
|
||||||
|
.map(|variant| -> TokenStream {
|
||||||
|
let _attrs = crate::common::YaSerdeAttribute::parse(&variant.attrs);
|
||||||
|
|
||||||
|
let all_fields = variant
|
||||||
|
.fields
|
||||||
|
.iter()
|
||||||
|
.map(|field| YaSerdeField::new(field.clone()));
|
||||||
|
|
||||||
|
let attribute_fields: Vec<_> = all_fields
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|field| {
|
||||||
|
field.is_attribute()
|
||||||
|
|| (field.is_flatten() && matches!(field.get_type(), Field::FieldStruct { .. }))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
attribute_fields
|
||||||
|
.iter()
|
||||||
|
.map(|field| {
|
||||||
|
let label = variant.ident.clone();
|
||||||
|
let var = get_id(field);
|
||||||
|
let name = name.clone();
|
||||||
|
|
||||||
|
let destructure = if field.get_value_label().is_some() {
|
||||||
|
quote! {{#var, ..}}
|
||||||
|
} else {
|
||||||
|
quote! {(#var, ..)}
|
||||||
|
};
|
||||||
|
|
||||||
|
if field.is_attribute() {
|
||||||
|
quote! { #name::#label { .. } => { }, }
|
||||||
|
} else {
|
||||||
|
match field.get_type() {
|
||||||
|
Field::FieldStruct { .. } => {
|
||||||
|
if root_attributes.flatten {
|
||||||
|
quote! {
|
||||||
|
match self {
|
||||||
|
#name::#label #destructure => {
|
||||||
|
let (attributes, namespace) = #var.serialize_attributes(
|
||||||
|
child_attributes,
|
||||||
|
child_attributes_namespace,
|
||||||
|
)?;
|
||||||
|
child_attributes_namespace.extend(&namespace);
|
||||||
|
child_attributes.extend(attributes);
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => quote! { #name::#label { .. } => { },},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
implement_serializer(
|
implement_serializer(
|
||||||
name,
|
name,
|
||||||
root,
|
root,
|
||||||
root_attributes,
|
root_attributes,
|
||||||
quote!(),
|
quote!(#variant_matches),
|
||||||
quote!(match self {
|
quote!(match self {
|
||||||
#inner_enum_inspector
|
#inner_enum_inspector
|
||||||
}),
|
}),
|
||||||
@ -38,7 +108,7 @@ fn inner_enum_inspector(
|
|||||||
|
|
||||||
let label = &variant.ident;
|
let label = &variant.ident;
|
||||||
let label_name = build_label_name(label, &variant_attrs, &root_attributes.default_namespace);
|
let label_name = build_label_name(label, &variant_attrs, &root_attributes.default_namespace);
|
||||||
|
|
||||||
match variant.fields {
|
match variant.fields {
|
||||||
Fields::Unit => quote! {
|
Fields::Unit => quote! {
|
||||||
&#name::#label => {
|
&#name::#label => {
|
||||||
@ -205,7 +275,13 @@ fn inner_enum_inspector(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Field::FieldStruct { .. } => write_element(&match_field(&serialize)),
|
Field::FieldStruct { .. } => {
|
||||||
|
if variant_attrs.flatten || field.is_flatten() {
|
||||||
|
match_field("e!{ ::yaserde::YaSerialize::serialize(item, writer)?})
|
||||||
|
} else {
|
||||||
|
write_element(&match_field(&serialize))
|
||||||
|
}
|
||||||
|
}
|
||||||
Field::FieldString => match_field(&write_element(&write_string_chars)),
|
Field::FieldString => match_field(&write_element(&write_string_chars)),
|
||||||
_simple_type => match_field(&write_simple_type),
|
_simple_type => match_field(&write_simple_type),
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user