From 688ab0b1604df72d3c2cbb4e61aa30de72ccccd7 Mon Sep 17 00:00:00 2001 From: Dmitry Samoylov Date: Tue, 4 Feb 2020 15:18:09 +0700 Subject: [PATCH] Fix compilation errors when element name contains dots --- yaserde/tests/deserializer.rs | 22 ++++++++++- yaserde/tests/serializer.rs | 15 +++++++- yaserde_derive/src/de/expand_struct.rs | 51 +++++++++++++------------ yaserde_derive/src/ser/expand_struct.rs | 36 +++++++++-------- 4 files changed, 79 insertions(+), 45 deletions(-) diff --git a/yaserde/tests/deserializer.rs b/yaserde/tests/deserializer.rs index b250f44..42230ff 100644 --- a/yaserde/tests/deserializer.rs +++ b/yaserde/tests/deserializer.rs @@ -181,6 +181,8 @@ fn de_rename() { item: String, #[yaserde(rename = "sub")] sub_struct: SubStruct, + #[yaserde(rename = "maj.min.bug")] + with_dots: String, } #[derive(YaDeserialize, PartialEq, Debug)] @@ -198,7 +200,7 @@ fn de_rename() { } } - let content = ""; + let content = "2.0.1"; convert_and_validate!( content, XmlStruct, @@ -207,6 +209,7 @@ fn de_rename() { sub_struct: SubStruct { subitem: "sub_something".to_string(), }, + with_dots: "2.0.1".into() } ); } @@ -378,6 +381,8 @@ fn de_complex_enum() { Magenta(Vec), #[yaserde(rename = "NotSoCyan")] Cyan(Vec), + #[yaserde(rename = "renamed.with.dots")] + Dotted(u32), } impl Default for Color { @@ -551,6 +556,21 @@ fn de_complex_enum() { ]) } ); + + let content = r#" + + + 54 + + + "#; + convert_and_validate!( + content, + XmlStruct, + XmlStruct { + background: Color::Dotted(54) + } + ); } #[test] diff --git a/yaserde/tests/serializer.rs b/yaserde/tests/serializer.rs index c27e270..66480e0 100644 --- a/yaserde/tests/serializer.rs +++ b/yaserde/tests/serializer.rs @@ -125,6 +125,8 @@ fn ser_rename() { item: String, #[yaserde(rename = "sub")] sub_struct: SubStruct, + #[yaserde(rename = "maj.min.bug")] + version: String, } #[derive(YaSerialize, PartialEq, Debug)] @@ -154,9 +156,10 @@ fn ser_rename() { sub_struct: SubStruct { subitem: "sub_something".to_string(), }, + version: "2.0.2".into(), }; - let content = ""; + let content = "2.0.2"; convert_and_validate!(model, content); } @@ -326,6 +329,8 @@ fn ser_unnamed_enum() { Structs(Vec), #[yaserde(rename = "renamed")] ToRename(u32), + #[yaserde(rename = "renamed.with.dots")] + ToRenameDots(u32), } impl Default for Enum { @@ -422,6 +427,14 @@ fn ser_unnamed_enum() { let content = "87"; convert_and_validate!(model, content); + + let model = XmlStruct { + color: Enum::ToRenameDots(84), + }; + + let content = + "84"; + convert_and_validate!(model, content); } #[test] diff --git a/yaserde_derive/src/de/expand_struct.rs b/yaserde_derive/src/de/expand_struct.rs index 4f3fae2..37814e5 100644 --- a/yaserde_derive/src/de/expand_struct.rs +++ b/yaserde_derive/src/de/expand_struct.rs @@ -207,7 +207,7 @@ pub fn parse( .rename .unwrap_or_else(|| field.ident.as_ref().unwrap().to_string()); - let visitor_label = Ident::new(&format!("__Visitor{}", label_name), Span::call_site()); + let visitor_label = build_visitor_ident(&label_name, None); match get_field_type(field) { Some(FieldType::FieldTypeString) => { @@ -252,10 +252,7 @@ pub fn parse( .iter() .map(|s| s.ident.to_string()) .collect(); - let struct_ident = Ident::new( - &format!("__Visitor_{}_{}", label_name, struct_id), - Span::call_site(), - ); + let struct_ident = build_visitor_ident(&label_name, Some(&struct_id)); Some(quote! { #[allow(non_snake_case, non_camel_case_types)] @@ -405,11 +402,10 @@ pub fn parse( return None; } - let label_name = if let Some(ref value) = field_attrs.rename { - Ident::new(&value.to_string(), Span::call_site()).to_string() - } else { - field.ident.clone().unwrap().to_string() - }; + let label_name = field_attrs + .rename + .clone() + .unwrap_or_else(|| label.as_ref().unwrap().to_string()); match get_field_type(field) { Some(FieldType::FieldTypeString) => { @@ -899,7 +895,7 @@ pub fn parse( .rename .unwrap_or_else(|| field.ident.as_ref().unwrap().to_string()); - let visitor_label = Ident::new(&format!("__Visitor{}", label_name), Span::call_site()); + let visitor_label = build_visitor_ident(&label_name, None); match get_field_type(field) { Some(FieldType::FieldTypeString) => Some(quote! { @@ -1077,13 +1073,9 @@ pub fn parse( } } Some(FieldType::FieldTypeStruct { struct_name }) => { - let struct_ident = Ident::new( - &format!( - "__Visitor_{}_{}", - label_name, - struct_name.into_token_stream() - ), - Span::call_site(), + let struct_ident = build_visitor_ident( + &label_name, + Some(&struct_name.into_token_stream().to_string()), ); Some(quote! { @@ -1307,12 +1299,12 @@ fn build_call_visitor( // let label = &field.ident; let value_label = get_value_label(label); - let label_name = if let Some(ref value) = field_attrs.rename { - Ident::new(&value.to_string(), Span::call_site()).to_string() - } else { - label.clone().unwrap().to_string() - }; - let visitor_label = Ident::new(&format!("__Visitor{}", label_name), Span::call_site()); + let label_name = field_attrs + .rename + .clone() + .unwrap_or_else(|| label.as_ref().unwrap().to_string()); + + let visitor_label = build_visitor_ident(&label_name, None); let namespaces_matches: TokenStream = namespaces .iter() @@ -1410,3 +1402,14 @@ fn get_value_label(ident: &Option) -> Option { None => None, } } + +fn build_visitor_ident(label: &str, struct_id: Option<&str>) -> Ident { + Ident::new( + &format!( + "__Visitor_{}_{}", + label.replace(".", "_"), + struct_id.unwrap_or("") + ), + Span::call_site(), + ) +} diff --git a/yaserde_derive/src/ser/expand_struct.rs b/yaserde_derive/src/ser/expand_struct.rs index 4751439..d80f337 100644 --- a/yaserde_derive/src/ser/expand_struct.rs +++ b/yaserde_derive/src/ser/expand_struct.rs @@ -24,16 +24,9 @@ pub fn serialize( return None; } - let renamed_label = match field_attrs.rename { - Some(value) => Ident::new(&value, Span::call_site()), - None => field.ident.clone().unwrap(), - }; let label = &field.ident; - let label_name = if let Some(prefix) = field_attrs.prefix { - prefix + ":" + renamed_label.to_string().as_ref() - } else { - renamed_label.to_string() - }; + + let label_name = build_label_name(&field, &field_attrs); match get_field_type(field) { Some(FieldType::FieldTypeString) @@ -270,16 +263,7 @@ pub fn serialize( )); } - let renamed_label = match field_attrs.rename { - Some(value) => Ident::new(&value, Span::call_site()), - None => field.ident.clone().unwrap(), - }; - - let label_name = if let Some(prefix) = field_attrs.prefix { - format!("{}:{}", prefix, renamed_label) - } else { - renamed_label.to_string() - }; + let label_name = build_label_name(&field, &field_attrs); match get_field_type(field) { Some(FieldType::FieldTypeString) @@ -473,3 +457,17 @@ pub fn serialize( } } } + +fn build_label_name(field: &syn::Field, field_attrs: &YaSerdeAttribute) -> String { + format!( + "{}{}", + field_attrs + .prefix + .clone() + .map_or("".to_string(), |prefix| prefix + ":"), + field_attrs + .rename + .clone() + .unwrap_or_else(|| field.ident.as_ref().unwrap().to_string()) + ) +}