From 775bad82a47b29fa5b8a84a84093708cea95f6a8 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Fri, 24 May 2024 15:57:44 -0700 Subject: [PATCH] really fix scalar enum namespace handling It is actually important to consider the field name when provided, otherwise we can incorrectly match fields with different names! --- instant-xml-macros/src/de.rs | 10 +++++-- instant-xml/tests/scalar-enum.rs | 46 ++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/instant-xml-macros/src/de.rs b/instant-xml-macros/src/de.rs index 494ccfb..fb35b56 100644 --- a/instant-xml-macros/src/de.rs +++ b/instant-xml-macros/src/de.rs @@ -77,7 +77,13 @@ fn deserialize_scalar_enum( impl #impl_generics FromXml<'xml> for #ident #ty_generics #where_clause { #[inline] fn matches(id: ::instant_xml::Id<'_>, field: Option<::instant_xml::Id<'_>>) -> bool { - id == ::instant_xml::Id { ns: #default_namespace, name: id.name } + id == ::instant_xml::Id { + ns: #default_namespace, + name: match field { + Some(fid) => fid.name, + None => id.name, + }, + } } fn deserialize<'cx>( @@ -99,7 +105,7 @@ fn deserialize_scalar_enum( let value = match cow_str.as_ref() { #variants _ => return Err(Error::UnexpectedValue( - format!("enum variant not found for '{}'", cow_str), + format!("enum variant not found for '{}' in field {}", cow_str, field), )), }; diff --git a/instant-xml/tests/scalar-enum.rs b/instant-xml/tests/scalar-enum.rs index 237a93d..9ffc10a 100644 --- a/instant-xml/tests/scalar-enum.rs +++ b/instant-xml/tests/scalar-enum.rs @@ -42,3 +42,49 @@ fn scalar_enum_ns() { assert_eq!(xml, to_string(&v).unwrap()); assert_eq!(v, from_str(xml).unwrap()); } + +const DIDL: &str = "DIDL"; +const UPNP: &str = "UPNP"; +const DC: &str = "DC"; + +#[derive(Debug, FromXml, PartialEq, ToXml)] +#[xml(rename = "DIDL-Lite", ns(DIDL, dc = DC, upnp = UPNP))] +struct DidlLite { + item: Vec, +} + +#[derive(Debug, FromXml, PartialEq, ToXml)] +#[xml(rename = "item", ns(DIDL))] +struct UpnpItem { + class: Option, +} + +#[derive(Debug, Clone, PartialEq, FromXml, ToXml)] +#[xml(rename = "class", scalar, ns(UPNP, upnp = UPNP))] +enum ObjectClass { + #[xml(rename = "object.item.audioItem.musicTrack")] + MusicTrack, + #[xml(rename = "object.item.audioItem.audioBroadcast")] + AudioBroadcast, + #[xml(rename = "object.container.playlistContainer")] + PlayList, +} + +#[test] +fn scalar_enum_ns_match() { + let v = DidlLite { + item: vec![UpnpItem { + class: Some(ObjectClass::AudioBroadcast), + }], + }; + + // Keep the `upnp::mimeType` element after `upnp::class` to ensure that + // we tickle a `DuplicateValue` error if we don't match correctly. + let xml = r#" + + object.item.audioItem.audioBroadcast + audio/flac + + "#; + assert_eq!(v, from_str(xml).unwrap()); +}