Merge pull request #143 from TheSchemm/master

Fixes #142
This commit is contained in:
Marc-Antoine ARNAUD 2022-07-08 05:15:29 +02:00 committed by GitHub
commit efdab555e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 159 additions and 4 deletions

View File

@ -325,7 +325,7 @@ macro_rules! serialize_and_validate {
log::debug!("serialize_and_validate @ {}:{}", file!(), line!());
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!(
data,
Ok(content.split("\n").map(|s| s.trim()).collect::<String>())

View File

@ -147,6 +147,85 @@ fn attribute_enum() {
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]
fn unnamed_enum() {
#[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]

View File

@ -14,11 +14,81 @@ pub fn serialize(
) -> TokenStream {
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(
name,
root,
root_attributes,
quote!(),
quote!(#variant_matches),
quote!(match self {
#inner_enum_inspector
}),
@ -38,7 +108,7 @@ fn inner_enum_inspector(
let label = &variant.ident;
let label_name = build_label_name(label, &variant_attrs, &root_attributes.default_namespace);
match variant.fields {
Fields::Unit => quote! {
&#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(&quote!{ ::yaserde::YaSerialize::serialize(item, writer)?})
} else {
write_element(&match_field(&serialize))
}
}
Field::FieldString => match_field(&write_element(&write_string_chars)),
_simple_type => match_field(&write_simple_type),
}