Move serializer code into ser module
This commit is contained in:
parent
f7bbc00172
commit
9cfee92d03
|
@ -136,7 +136,7 @@ pub fn to_xml(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
|||
impl #generics ToXml for #ident #generics {
|
||||
fn serialize<W: std::fmt::Write>(&self, serializer: &mut instant_xml::Serializer<W>) -> Result<(), instant_xml::Error> {
|
||||
let _ = serializer.consume_field_context();
|
||||
let mut field_context = instant_xml::FieldContext {
|
||||
let mut field_context = instant_xml::ser::FieldContext {
|
||||
name: #root_name,
|
||||
attribute: None,
|
||||
};
|
||||
|
|
|
@ -81,7 +81,7 @@ impl<'a> Serializer {
|
|||
let field_value = field.ident.as_ref().unwrap();
|
||||
|
||||
let declaration = quote!(
|
||||
let mut field = instant_xml::FieldContext {
|
||||
let mut field = instant_xml::ser::FieldContext {
|
||||
name: #name,
|
||||
attribute: None,
|
||||
};
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::fmt::Write;
|
||||
|
||||
use thiserror::Error;
|
||||
pub use xmlparser;
|
||||
|
||||
pub use macros::{FromXml, ToXml};
|
||||
|
||||
mod impls;
|
||||
#[doc(hidden)]
|
||||
pub mod de;
|
||||
mod impls;
|
||||
pub use de::Deserializer;
|
||||
#[doc(hidden)]
|
||||
pub mod ser;
|
||||
pub use ser::Serializer;
|
||||
|
||||
pub trait ToXml {
|
||||
fn to_xml(&self) -> Result<String, Error> {
|
||||
|
@ -23,142 +23,12 @@ pub trait ToXml {
|
|||
fn serialize<W: fmt::Write>(&self, serializer: &mut Serializer<W>) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
pub struct Serializer<'xml, W: fmt::Write> {
|
||||
// For parent namespaces the key is the namespace and the value is the prefix. We are adding to map
|
||||
// only if the namespaces do not exist, if it does exist then we are using an already defined parent prefix.
|
||||
#[doc(hidden)]
|
||||
pub parent_namespaces: HashMap<&'xml str, &'xml str>,
|
||||
#[doc(hidden)]
|
||||
pub output: &'xml mut W,
|
||||
|
||||
parent_default_namespace: &'xml str,
|
||||
parent_default_namespace_to_revert: &'xml str,
|
||||
current_attributes: String,
|
||||
next_field_context: Option<FieldContext<'xml>>,
|
||||
}
|
||||
|
||||
impl<'xml, W: fmt::Write> Serializer<'xml, W> {
|
||||
pub fn new(output: &'xml mut W) -> Self {
|
||||
Self {
|
||||
parent_namespaces: HashMap::new(),
|
||||
output,
|
||||
parent_default_namespace: "",
|
||||
parent_default_namespace_to_revert: "",
|
||||
next_field_context: None,
|
||||
current_attributes: String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn consume_current_attributes(&mut self) -> Result<(), Error> {
|
||||
self.output.write_str(&self.current_attributes)?;
|
||||
self.current_attributes.clear();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_attribute_key(&mut self, attr_key: &impl fmt::Display) -> Result<(), Error> {
|
||||
self.current_attributes.push(' ');
|
||||
write!(self.current_attributes, "{}", attr_key)?;
|
||||
self.current_attributes.push('=');
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_attribute_value(&mut self, attr_value: &impl fmt::Display) -> Result<(), Error> {
|
||||
self.current_attributes.push('"');
|
||||
write!(self.current_attributes, "{}", attr_value)?;
|
||||
self.current_attributes.push('"');
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_field_context(&mut self, field_context: FieldContext<'xml>) -> Result<(), Error> {
|
||||
if self.next_field_context.is_some() {
|
||||
return Err(Error::UnexpectedState);
|
||||
};
|
||||
|
||||
self.next_field_context = Some(field_context);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn consume_field_context(&mut self) -> Option<FieldContext<'xml>> {
|
||||
self.next_field_context.take()
|
||||
}
|
||||
|
||||
pub fn set_parent_default_namespace(&mut self, namespace: &'xml str) -> Result<(), Error> {
|
||||
self.parent_default_namespace = namespace;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn parent_default_namespace(&self) -> &'xml str {
|
||||
self.parent_default_namespace
|
||||
}
|
||||
|
||||
pub fn update_parent_default_namespace(&mut self, namespace: &'xml str) {
|
||||
self.parent_default_namespace_to_revert = self.parent_default_namespace;
|
||||
self.parent_default_namespace = namespace;
|
||||
}
|
||||
|
||||
pub fn retrieve_parent_default_namespace(&mut self) {
|
||||
self.parent_default_namespace = self.parent_default_namespace_to_revert;
|
||||
}
|
||||
|
||||
fn add_open_tag(&mut self, field_context: &FieldContext) -> Result<(), Error> {
|
||||
match field_context.attribute {
|
||||
Some(FieldAttribute::Prefix(prefix)) => {
|
||||
self.output.write_char('<')?;
|
||||
self.output.write_str(prefix)?;
|
||||
self.output.write_char(':')?;
|
||||
self.output.write_str(field_context.name)?;
|
||||
self.output.write_char('>')?;
|
||||
}
|
||||
Some(FieldAttribute::Namespace(namespace))
|
||||
if self.parent_default_namespace != namespace =>
|
||||
{
|
||||
self.output.write_char('<')?;
|
||||
self.output.write_str(field_context.name)?;
|
||||
self.output.write_str(" xmlns=\"")?;
|
||||
self.output.write_str(namespace)?;
|
||||
self.output.write_str("\">")?;
|
||||
}
|
||||
_ => {
|
||||
self.output.write_char('<')?;
|
||||
self.output.write_str(field_context.name)?;
|
||||
self.output.write_char('>')?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_close_tag(&mut self, field_context: FieldContext) -> Result<(), Error> {
|
||||
match field_context.attribute {
|
||||
Some(FieldAttribute::Prefix(prefix)) => {
|
||||
self.output.write_str("</")?;
|
||||
self.output.write_str(prefix)?;
|
||||
self.output.write_char(':')?;
|
||||
self.output.write_str(field_context.name)?;
|
||||
self.output.write_char('>')?;
|
||||
}
|
||||
_ => {
|
||||
self.output.write_str("</")?;
|
||||
self.output.write_str(field_context.name)?;
|
||||
self.output.write_char('>')?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub enum FieldAttribute<'xml> {
|
||||
Prefix(&'xml str),
|
||||
Namespace(&'xml str),
|
||||
Attribute,
|
||||
}
|
||||
|
||||
pub struct FieldContext<'xml> {
|
||||
#[doc(hidden)]
|
||||
pub name: &'xml str,
|
||||
#[doc(hidden)]
|
||||
pub attribute: Option<FieldAttribute<'xml>>,
|
||||
}
|
||||
|
||||
pub enum TagName {
|
||||
FieldName,
|
||||
Custom(&'static str),
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
use std::collections::HashMap;
|
||||
use std::fmt::{self, Write};
|
||||
|
||||
use super::{Error, FieldAttribute};
|
||||
|
||||
pub struct Serializer<'xml, W: fmt::Write> {
|
||||
// For parent namespaces the key is the namespace and the value is the prefix. We are adding to map
|
||||
// only if the namespaces do not exist, if it does exist then we are using an already defined parent prefix.
|
||||
#[doc(hidden)]
|
||||
pub parent_namespaces: HashMap<&'xml str, &'xml str>,
|
||||
#[doc(hidden)]
|
||||
pub output: &'xml mut W,
|
||||
|
||||
parent_default_namespace: &'xml str,
|
||||
parent_default_namespace_to_revert: &'xml str,
|
||||
current_attributes: String,
|
||||
next_field_context: Option<FieldContext<'xml>>,
|
||||
}
|
||||
|
||||
impl<'xml, W: fmt::Write> Serializer<'xml, W> {
|
||||
pub fn new(output: &'xml mut W) -> Self {
|
||||
Self {
|
||||
parent_namespaces: HashMap::new(),
|
||||
output,
|
||||
parent_default_namespace: "",
|
||||
parent_default_namespace_to_revert: "",
|
||||
next_field_context: None,
|
||||
current_attributes: String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn consume_current_attributes(&mut self) -> Result<(), Error> {
|
||||
self.output.write_str(&self.current_attributes)?;
|
||||
self.current_attributes.clear();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_attribute_key(&mut self, attr_key: &impl fmt::Display) -> Result<(), Error> {
|
||||
self.current_attributes.push(' ');
|
||||
write!(self.current_attributes, "{}", attr_key)?;
|
||||
self.current_attributes.push('=');
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_attribute_value(&mut self, attr_value: &impl fmt::Display) -> Result<(), Error> {
|
||||
self.current_attributes.push('"');
|
||||
write!(self.current_attributes, "{}", attr_value)?;
|
||||
self.current_attributes.push('"');
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_field_context(&mut self, field_context: FieldContext<'xml>) -> Result<(), Error> {
|
||||
if self.next_field_context.is_some() {
|
||||
return Err(Error::UnexpectedState);
|
||||
};
|
||||
|
||||
self.next_field_context = Some(field_context);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn consume_field_context(&mut self) -> Option<FieldContext<'xml>> {
|
||||
self.next_field_context.take()
|
||||
}
|
||||
|
||||
pub fn set_parent_default_namespace(&mut self, namespace: &'xml str) -> Result<(), Error> {
|
||||
self.parent_default_namespace = namespace;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn parent_default_namespace(&self) -> &'xml str {
|
||||
self.parent_default_namespace
|
||||
}
|
||||
|
||||
pub fn update_parent_default_namespace(&mut self, namespace: &'xml str) {
|
||||
self.parent_default_namespace_to_revert = self.parent_default_namespace;
|
||||
self.parent_default_namespace = namespace;
|
||||
}
|
||||
|
||||
pub fn retrieve_parent_default_namespace(&mut self) {
|
||||
self.parent_default_namespace = self.parent_default_namespace_to_revert;
|
||||
}
|
||||
|
||||
pub fn add_open_tag(&mut self, field_context: &FieldContext) -> Result<(), Error> {
|
||||
match field_context.attribute {
|
||||
Some(FieldAttribute::Prefix(prefix)) => {
|
||||
self.output.write_char('<')?;
|
||||
self.output.write_str(prefix)?;
|
||||
self.output.write_char(':')?;
|
||||
self.output.write_str(field_context.name)?;
|
||||
self.output.write_char('>')?;
|
||||
}
|
||||
Some(FieldAttribute::Namespace(namespace))
|
||||
if self.parent_default_namespace != namespace =>
|
||||
{
|
||||
self.output.write_char('<')?;
|
||||
self.output.write_str(field_context.name)?;
|
||||
self.output.write_str(" xmlns=\"")?;
|
||||
self.output.write_str(namespace)?;
|
||||
self.output.write_str("\">")?;
|
||||
}
|
||||
_ => {
|
||||
self.output.write_char('<')?;
|
||||
self.output.write_str(field_context.name)?;
|
||||
self.output.write_char('>')?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_close_tag(&mut self, field_context: FieldContext) -> Result<(), Error> {
|
||||
match field_context.attribute {
|
||||
Some(FieldAttribute::Prefix(prefix)) => {
|
||||
self.output.write_str("</")?;
|
||||
self.output.write_str(prefix)?;
|
||||
self.output.write_char(':')?;
|
||||
self.output.write_str(field_context.name)?;
|
||||
self.output.write_char('>')?;
|
||||
}
|
||||
_ => {
|
||||
self.output.write_str("</")?;
|
||||
self.output.write_str(field_context.name)?;
|
||||
self.output.write_char('>')?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FieldContext<'xml> {
|
||||
#[doc(hidden)]
|
||||
pub name: &'xml str,
|
||||
#[doc(hidden)]
|
||||
pub attribute: Option<FieldAttribute<'xml>>,
|
||||
}
|
Loading…
Reference in New Issue