Fix compilation errors when element name contains dots

This commit is contained in:
Dmitry Samoylov 2020-02-04 15:18:09 +07:00
parent 6bbb9676d0
commit 688ab0b160
4 changed files with 79 additions and 45 deletions

View File

@ -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 = "<base Item=\"something\"><sub sub_item=\"sub_something\"></sub></base>";
let content = "<base Item=\"something\"><sub sub_item=\"sub_something\"></sub><maj.min.bug>2.0.1</maj.min.bug></base>";
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<OtherStruct>),
#[yaserde(rename = "NotSoCyan")]
Cyan(Vec<OtherStruct>),
#[yaserde(rename = "renamed.with.dots")]
Dotted(u32),
}
impl Default for Color {
@ -551,6 +556,21 @@ fn de_complex_enum() {
])
}
);
let content = r#"<?xml version="1.0" encoding="utf-8"?>
<base xmlns:ns="http://www.sample.com/ns/domain">
<background>
<renamed.with.dots>54</renamed.with.dots>
</background>
</base>
"#;
convert_and_validate!(
content,
XmlStruct,
XmlStruct {
background: Color::Dotted(54)
}
);
}
#[test]

View File

@ -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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base Item=\"something\"><sub sub_item=\"sub_something\" /></base>";
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base Item=\"something\"><sub sub_item=\"sub_something\" /><maj.min.bug>2.0.2</maj.min.bug></base>";
convert_and_validate!(model, content);
}
@ -326,6 +329,8 @@ fn ser_unnamed_enum() {
Structs(Vec<OtherStruct>),
#[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 =
"<?xml version=\"1.0\" encoding=\"utf-8\"?><base><color><renamed>87</renamed></color></base>";
convert_and_validate!(model, content);
let model = XmlStruct {
color: Enum::ToRenameDots(84),
};
let content =
"<?xml version=\"1.0\" encoding=\"utf-8\"?><base><color><renamed.with.dots>84</renamed.with.dots></color></base>";
convert_and_validate!(model, content);
}
#[test]

View File

@ -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<syn::Ident>) -> Option<syn::Ident> {
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(),
)
}

View File

@ -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())
)
}