diff --git a/crates/xml/derive/src/de/attrs.rs b/crates/xml/derive/src/de/attrs.rs index 86f2147..931c90b 100644 --- a/crates/xml/derive/src/de/attrs.rs +++ b/crates/xml/derive/src/de/attrs.rs @@ -47,6 +47,8 @@ pub enum FieldType { Attr, Text, Untagged, + TagName, + Namespace, } #[derive(Default, FromField)] diff --git a/crates/xml/derive/src/de/de_struct.rs b/crates/xml/derive/src/de/de_struct.rs index 223b751..ce7a112 100644 --- a/crates/xml/derive/src/de/de_struct.rs +++ b/crates/xml/derive/src/de/de_struct.rs @@ -9,7 +9,7 @@ fn invalid_field_branch(allow: bool) -> proc_macro2::TokenStream { if allow { quote! {} } else { - quote! { return Err(XmlDeError::InvalidFieldName) } + quote! { return Err(XmlDeError::InvalidFieldName(format!("[{ns:?}]{tag:?}"))) } } } @@ -80,6 +80,7 @@ impl NamedStruct { } let text_field_branches = self.fields.iter().filter_map(Field::text_branch); let attr_field_branches = self.fields.iter().filter_map(Field::attr_branch); + let tagname_field_branches = self.fields.iter().filter_map(Field::tagname_branch); let builder_field_builds = self.fields.iter().map(Field::builder_field_build); @@ -106,11 +107,14 @@ impl NamedStruct { #(#builder_field_inits),* }; + let (ns, name) = reader.resolve_element(start.name()); + #(#tagname_field_branches);* + for attr in start.attributes() { let attr = attr?; match attr.key.as_ref() { #(#attr_field_branches),* - _ => { #invalid_field_branch } + _ => { /* ignore */ } } } @@ -129,7 +133,7 @@ impl NamedStruct { match (ns, name.as_ref()) { #(#named_field_branches),* #(#untagged_field_branches),* - _ => { #invalid_field_branch } + (ns, tag) => { #invalid_field_branch } } } Event::Text(bytes_text) => { diff --git a/crates/xml/derive/src/de/field.rs b/crates/xml/derive/src/de/field.rs index fbedfae..6eeacde 100644 --- a/crates/xml/derive/src/de/field.rs +++ b/crates/xml/derive/src/de/field.rs @@ -219,6 +219,24 @@ impl Field { }) } + pub fn tagname_branch(&self) -> Option { + if self.attrs.xml_ty != FieldType::TagName { + return None; + } + let field_ident = self.field_ident(); + + let value = wrap_option_if_no_default( + quote! { + rustical_xml::Value::deserialize(&String::from_utf8_lossy(name.as_ref()))? + }, + self.attrs.default.is_some(), + ); + + Some(quote! { + builder.#field_ident = #value; + }) + } + pub fn tag_writer(&self) -> Option { let field_ident = self.field_ident(); let field_name = self.xml_name(); @@ -235,6 +253,8 @@ impl Field { // TODO: untag! self.#field_ident.serialize(None, writer)?; }), + // TODO: Think about what to do here + FieldType::TagName | FieldType::Namespace => None, } } } diff --git a/crates/xml/src/de.rs b/crates/xml/src/de.rs index e5d2846..87e14ca 100644 --- a/crates/xml/src/de.rs +++ b/crates/xml/src/de.rs @@ -29,8 +29,8 @@ pub enum XmlDeError { Other(String), #[error("Invalid variant: {0}")] InvalidVariant(String), - #[error("Invalid field name: ")] - InvalidFieldName, + #[error("Invalid field name: {0}")] + InvalidFieldName(String), #[error(transparent)] InvalidValue(#[from] crate::value::ParseValueError), }