From 7d241959d8daa7326005b41b33aa167f4e4b8f3d Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Wed, 7 Sep 2022 12:10:01 +0200 Subject: [PATCH] Centralize serializer prefix logic in one place --- instant-xml-macros/src/ser.rs | 18 +++++------------- instant-xml/src/ser.rs | 35 +++++++++++++++++++++++------------ 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/instant-xml-macros/src/ser.rs b/instant-xml-macros/src/ser.rs index d815089..bfd89f1 100644 --- a/instant-xml-macros/src/ser.rs +++ b/instant-xml-macros/src/ser.rs @@ -49,14 +49,14 @@ pub fn to_xml(input: &syn::DeriveInput) -> proc_macro2::TokenStream { serializer: &mut instant_xml::Serializer, ) -> Result<(), instant_xml::Error> { // Start tag - match serializer.default_ns() == #default_namespace { - true => serializer.write_start(None, #root_name, None)?, - false => serializer.write_start(None, #root_name, Some(#default_namespace))?, - } + let prefix = serializer.write_start(#root_name, #default_namespace, false)?; + debug_assert_eq!(prefix, None); + // Set up element context, this will also emit namespace declarations #context let old = serializer.push(new)?; + // Finalize start element #attributes serializer.end_start()?; @@ -110,15 +110,7 @@ fn process_named_field( self.#field_value.serialize(serializer)?; } ::instant_xml::Kind::Scalar => { - let (prefix, ns) = match serializer.default_ns() == #ns { - true => (None, None), - false => match serializer.prefix(#ns) { - Some(prefix) => (Some(prefix), None), - None => (None, Some(#ns)), - }, - }; - - serializer.write_start(prefix, #name, ns)?; + let prefix = serializer.write_start(#name, #ns, true)?; serializer.end_start()?; self.#field_value.serialize(serializer)?; serializer.write_close(prefix, #name)?; diff --git a/instant-xml/src/ser.rs b/instant-xml/src/ser.rs index e159f8f..fcd7231 100644 --- a/instant-xml/src/ser.rs +++ b/instant-xml/src/ser.rs @@ -30,26 +30,37 @@ impl<'xml, W: fmt::Write + ?Sized> Serializer<'xml, W> { pub fn write_start( &mut self, - prefix: Option<&str>, name: &str, - ns: Option<&str>, - ) -> Result<(), Error> { + ns: &str, + scalar: bool, + ) -> Result, Error> { if self.state != State::Element { return Err(Error::UnexpectedState); } - match prefix { - Some(prefix) => self.output.write_fmt(format_args!("<{prefix}:{name}"))?, - None => match ns { - Some(ns) => self - .output - .write_fmt(format_args!("<{name} xmlns=\"{ns}\""))?, - None => self.output.write_fmt(format_args!("<{name}"))?, + let prefix = match ns == self.default_ns { + true => { + self.output.write_fmt(format_args!("<{name}"))?; + None + } + // In the case of scalars, we can use the prefix instead of setting a + // default namespace (since there are no child elements that will + // expect the default namespace to be set). + false => match (scalar, self.prefixes.get(ns)) { + (false, _) | (true, None) => { + self.output + .write_fmt(format_args!("<{name} xmlns=\"{ns}\""))?; + None + } + (true, Some(&prefix)) => { + self.output.write_fmt(format_args!("<{prefix}:{name}"))?; + Some(prefix) + } }, - } + }; self.state = State::Attribute; - Ok(()) + Ok(prefix) } pub fn write_attr(&mut self, name: &str, value: &V) -> Result<(), Error> {