Centralize serializer prefix logic in one place

This commit is contained in:
Dirkjan Ochtman 2022-09-07 12:10:01 +02:00
parent 110605ba99
commit 7d241959d8
2 changed files with 28 additions and 25 deletions

View File

@ -49,14 +49,14 @@ pub fn to_xml(input: &syn::DeriveInput) -> proc_macro2::TokenStream {
serializer: &mut instant_xml::Serializer<W>, serializer: &mut instant_xml::Serializer<W>,
) -> Result<(), instant_xml::Error> { ) -> Result<(), instant_xml::Error> {
// Start tag // Start tag
match serializer.default_ns() == #default_namespace { let prefix = serializer.write_start(#root_name, #default_namespace, false)?;
true => serializer.write_start(None, #root_name, None)?, debug_assert_eq!(prefix, None);
false => serializer.write_start(None, #root_name, Some(#default_namespace))?,
}
// Set up element context, this will also emit namespace declarations
#context #context
let old = serializer.push(new)?; let old = serializer.push(new)?;
// Finalize start element
#attributes #attributes
serializer.end_start()?; serializer.end_start()?;
@ -110,15 +110,7 @@ fn process_named_field(
self.#field_value.serialize(serializer)?; self.#field_value.serialize(serializer)?;
} }
::instant_xml::Kind::Scalar => { ::instant_xml::Kind::Scalar => {
let (prefix, ns) = match serializer.default_ns() == #ns { let prefix = serializer.write_start(#name, #ns, true)?;
true => (None, None),
false => match serializer.prefix(#ns) {
Some(prefix) => (Some(prefix), None),
None => (None, Some(#ns)),
},
};
serializer.write_start(prefix, #name, ns)?;
serializer.end_start()?; serializer.end_start()?;
self.#field_value.serialize(serializer)?; self.#field_value.serialize(serializer)?;
serializer.write_close(prefix, #name)?; serializer.write_close(prefix, #name)?;

View File

@ -30,26 +30,37 @@ impl<'xml, W: fmt::Write + ?Sized> Serializer<'xml, W> {
pub fn write_start( pub fn write_start(
&mut self, &mut self,
prefix: Option<&str>,
name: &str, name: &str,
ns: Option<&str>, ns: &str,
) -> Result<(), Error> { scalar: bool,
) -> Result<Option<&'static str>, Error> {
if self.state != State::Element { if self.state != State::Element {
return Err(Error::UnexpectedState); return Err(Error::UnexpectedState);
} }
match prefix { let prefix = match ns == self.default_ns {
Some(prefix) => self.output.write_fmt(format_args!("<{prefix}:{name}"))?, true => {
None => match ns { self.output.write_fmt(format_args!("<{name}"))?;
Some(ns) => self None
.output
.write_fmt(format_args!("<{name} xmlns=\"{ns}\""))?,
None => self.output.write_fmt(format_args!("<{name}"))?,
},
} }
// 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; self.state = State::Attribute;
Ok(()) Ok(prefix)
} }
pub fn write_attr<V: ToXml + ?Sized>(&mut self, name: &str, value: &V) -> Result<(), Error> { pub fn write_attr<V: ToXml + ?Sized>(&mut self, name: &str, value: &V) -> Result<(), Error> {