From fe5ed28bbae0635a0a56f6eab70e516f9bf26a53 Mon Sep 17 00:00:00 2001 From: Mingun Date: Tue, 30 Aug 2022 22:57:55 +0500 Subject: [PATCH] Switch to new serializer Fixes #252 - ok Fixes #280 - ok Fixes #287 - ok Fixes #343 - ok Fixes #346 - not ok Fixes #361 - ok Partially addresses #368 Fixes #429 - ok Fixes #430 - ok --- Changelog.md | 7 + README.md | 17 --- src/de/mod.rs | 1 - src/se/mod.rs | 332 +++++++++++++++++++-------------------------- src/se/var.rs | 335 ---------------------------------------------- tests/serde-se.rs | 39 ++---- 6 files changed, 159 insertions(+), 572 deletions(-) delete mode 100644 src/se/var.rs diff --git a/Changelog.md b/Changelog.md index 6485f828..2a0571dc 100644 --- a/Changelog.md +++ b/Changelog.md @@ -14,6 +14,11 @@ ### Bug Fixes +- [#490]: Ensure, that serialization of map keys always produces valid XML names. + In particular, that means that maps with numeric and numeric-like keys (for + example, `"42"`) no longer can be serialized because [XML name] cannot start + from a digit + ### Misc Changes - [#481]: Removed the uses of `const fn` added in version 0.24 in favor of a lower minimum @@ -28,10 +33,12 @@ (but text can represent a list as defined by `xs:list` type) - `#any` that is close to the previous `$value` behavior. Use it when you want to map field to any content of the field, text or markup +- [#490]: Removed `$primitive=` prefix [#481]: https://github.com/tafia/quick-xml/pull/481 [#489]: https://github.com/tafia/quick-xml/pull/489 [#490]: https://github.com/tafia/quick-xml/pull/490 +[XML name]: https://www.w3.org/TR/xml11/#NT-Name ## 0.25.0 -- 2022-09-10 diff --git a/README.md b/README.md index ed5cab00..99e46221 100644 --- a/README.md +++ b/README.md @@ -131,23 +131,6 @@ struct Foo { } ``` -### Serializing unit variants as primitives - -The `$primitive` prefix lets you serialize enum variants without associated values (internally referred to as _unit variants_) as primitive strings rather than self-closing tags. Consider the following definitions: - -```rust,ignore -enum Foo { - #[serde(rename = "$primitive=Bar")] - Bar -} - -struct Root { - foo: Foo -} -``` - -Serializing `Root { foo: Foo::Bar }` will then yield `` instead of ``. - ### Performance Note that despite not focusing on performance (there are several unnecessary copies), it remains about 10x faster than serde-xml-rs. diff --git a/src/de/mod.rs b/src/de/mod.rs index 0d722ca6..73d34738 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -208,7 +208,6 @@ use std::num::NonZeroUsize; pub(crate) const TEXT_KEY: &str = "#text"; /// Data represented by any XML markup inside pub(crate) const ANY_KEY: &str = "#any"; -pub(crate) const PRIMITIVE_PREFIX: &str = "$primitive="; /// Simplified event which contains only these variants that used by deserializer #[derive(Debug, PartialEq, Eq)] diff --git a/src/se/mod.rs b/src/se/mod.rs index 2a048d16..cff1c40f 100644 --- a/src/se/mod.rs +++ b/src/se/mod.rs @@ -77,31 +77,24 @@ mod content; mod element; mod key; pub(crate) mod simple_type; -mod var; - -use self::var::{Map, Seq, Struct, Tuple}; -use crate::{ - de::PRIMITIVE_PREFIX, - errors::serialize::DeError, - events::{BytesEnd, BytesStart, BytesText, Event}, - writer::{Indentation, Writer}, -}; + +use self::content::ContentSerializer; +use self::element::ElementSerializer; +use crate::errors::serialize::DeError; +use crate::writer::Indentation; use serde::ser::{self, Serialize}; use serde::serde_if_integer128; -use std::io::Write; +use std::fmt::Write; use std::str::from_utf8; /// Serialize struct into a `Write`r -pub fn to_writer(writer: W, value: &S) -> Result<(), DeError> { - let mut serializer = Serializer::new(writer); - value.serialize(&mut serializer) +pub fn to_writer(writer: W, value: &S) -> Result { + value.serialize(Serializer::new(writer)) } /// Serialize struct into a `String` pub fn to_string(value: &S) -> Result { - let mut writer = Vec::new(); - to_writer(&mut writer, value)?; - Ok(String::from_utf8(writer)?) + to_writer(String::new(), value) } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -109,7 +102,7 @@ pub fn to_string(value: &S) -> Result { /// Defines which characters would be quoted in [`Text`] events and attribute /// values. /// -/// [`Text`]: Event::Text +/// [`Text`]: crate::events::Event::Text #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum QuoteLevel { /// Performs quoting, escape all characters that could have special meaning @@ -154,6 +147,16 @@ pub enum QuoteLevel { //////////////////////////////////////////////////////////////////////////////////////////////////// +macro_rules! forward { + ($name:ident($ty:ty)) => { + fn $name(self, value: $ty) -> Result { + self.ser(&concat!("`", stringify!($ty), "`"))?.$name(value) + } + }; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + /// Almost all characters can form a name. Citation from : /// /// > The overall philosophy of names has changed since XML 1.0. Whereas XML 1.0 @@ -273,9 +276,9 @@ impl<'i> Indent<'i> { /// A Serializer pub struct Serializer<'r, W: Write> { - writer: Writer, + ser: ContentSerializer<'r, W>, /// Name of the root tag. If not specified, deduced from the structure name - root_tag: Option<&'r str>, + root_tag: Option>, } impl<'r, W: Write> Serializer<'r, W> { @@ -285,10 +288,19 @@ impl<'r, W: Write> Serializer<'r, W> { /// and newtype structs) will end up to an error. Use `with_root` to create /// serializer with explicitly defined root element name pub fn new(writer: W) -> Self { - Self::with_root(Writer::new(writer), None) + Self { + ser: ContentSerializer { + writer, + level: QuoteLevel::Full, + indent: Indent::None, + write_indent: false, + }, + root_tag: None, + } } - /// Creates a new `Serializer` that uses specified root tag name + /// Creates a new `Serializer` that uses specified root tag name. `name` should + /// be valid [XML name], otherwise error is returned. /// /// # Examples /// @@ -298,14 +310,13 @@ impl<'r, W: Write> Serializer<'r, W> { /// # use pretty_assertions::assert_eq; /// # use serde::Serialize; /// # use quick_xml::se::Serializer; - /// use quick_xml::writer::Writer; /// - /// let mut buffer = Vec::new(); - /// let mut writer = Writer::new_with_indent(&mut buffer, b' ', 2); - /// let mut ser = Serializer::with_root(writer, Some("root")); + /// let ser = Serializer::with_root(String::new(), Some("root")).unwrap(); /// - /// "node".serialize(&mut ser).unwrap(); - /// assert_eq!(String::from_utf8(buffer).unwrap(), "node"); + /// assert_eq!( + /// "node".serialize(ser).unwrap(), + /// "node" + /// ); /// ``` /// /// When serializing a struct, newtype struct, unit struct or tuple `root_tag` @@ -314,8 +325,7 @@ impl<'r, W: Write> Serializer<'r, W> { /// ``` /// # use pretty_assertions::assert_eq; /// # use serde::Serialize; - /// use quick_xml::se::Serializer; - /// use quick_xml::writer::Writer; + /// # use quick_xml::se::Serializer; /// /// #[derive(Debug, PartialEq, Serialize)] /// struct Struct { @@ -323,144 +333,102 @@ impl<'r, W: Write> Serializer<'r, W> { /// answer: u32, /// } /// - /// let mut buffer = Vec::new(); - /// let mut writer = Writer::new_with_indent(&mut buffer, b' ', 2); - /// let mut ser = Serializer::with_root(writer, Some("root")); + /// let ser = Serializer::with_root(String::new(), Some("root")).unwrap(); /// - /// Struct { + /// let data = Struct { /// question: "The Ultimate Question of Life, the Universe, and Everything".into(), /// answer: 42, - /// }.serialize(&mut ser).unwrap(); + /// }; + /// /// assert_eq!( - /// String::from_utf8(buffer.clone()).unwrap(), - /// r#""# + /// data.serialize(ser).unwrap(), + /// "\ + /// The Ultimate Question of Life, the Universe, and Everything\ + /// 42\ + /// " /// ); /// ``` - pub fn with_root(writer: Writer, root_tag: Option<&'r str>) -> Self { - Self { writer, root_tag } + /// + /// [XML name]: https://www.w3.org/TR/REC-xml/#NT-Name + pub fn with_root(writer: W, root_tag: Option<&'r str>) -> Result { + Ok(Self { + ser: ContentSerializer { + writer, + level: QuoteLevel::Full, + indent: Indent::None, + write_indent: false, + }, + root_tag: root_tag.map(|tag| XmlName::try_from(tag)).transpose()?, + }) } - fn write_primitive( - &mut self, - value: P, - escaped: bool, - ) -> Result<(), DeError> { - let value = value.to_string(); - let event = if escaped { - BytesText::from_escaped(&value) - } else { - BytesText::new(&value) - }; - self.writer.write_event(Event::Text(event))?; - Ok(()) + /// Configure indent for a serializer + pub fn indent(&mut self, indent_char: char, indent_size: usize) -> &mut Self { + self.ser.indent = Indent::Owned(Indentation::new(indent_char as u8, indent_size)); + self } - /// Writes self-closed tag `` into inner writer - fn write_self_closed(&mut self, tag_name: &str) -> Result<(), DeError> { - self.writer - .write_event(Event::Empty(BytesStart::new(tag_name)))?; - Ok(()) + fn ser(self, err: &str) -> Result, DeError> { + if let Some(key) = self.root_tag { + Ok(ElementSerializer { ser: self.ser, key }) + } else { + Err(DeError::Unsupported( + format!("cannot serialize {} without defined root tag", err).into(), + )) + } } - /// Writes a serialized `value` surrounded by `...` - fn write_paired( - &mut self, - tag_name: &str, - value: &T, - ) -> Result<(), DeError> { - self.writer - .write_event(Event::Start(BytesStart::new(tag_name)))?; - value.serialize(&mut *self)?; - self.writer - .write_event(Event::End(BytesEnd::new(tag_name)))?; - Ok(()) + fn ser_name(self, key: &'static str) -> Result, DeError> { + Ok(ElementSerializer { + ser: self.ser, + key: match self.root_tag { + Some(key) => key, + None => XmlName::try_from(key)?, + }, + }) } } -impl<'r, 'w, W: Write> ser::Serializer for &'w mut Serializer<'r, W> { - type Ok = (); +impl<'r, W: Write> ser::Serializer for Serializer<'r, W> { + type Ok = W; type Error = DeError; - type SerializeSeq = Seq<'r, 'w, W>; - type SerializeTuple = Tuple<'r, 'w, W>; - type SerializeTupleStruct = Tuple<'r, 'w, W>; - type SerializeTupleVariant = Tuple<'r, 'w, W>; - type SerializeMap = Map<'r, 'w, W>; - type SerializeStruct = Struct<'r, 'w, W>; - type SerializeStructVariant = Struct<'r, 'w, W>; - - fn serialize_bool(self, v: bool) -> Result { - self.write_primitive(if v { "true" } else { "false" }, true) - } - - fn serialize_i8(self, v: i8) -> Result { - self.write_primitive(v, true) - } - - fn serialize_i16(self, v: i16) -> Result { - self.write_primitive(v, true) - } - - fn serialize_i32(self, v: i32) -> Result { - self.write_primitive(v, true) - } - - fn serialize_i64(self, v: i64) -> Result { - self.write_primitive(v, true) - } + type SerializeSeq = as ser::Serializer>::SerializeSeq; + type SerializeTuple = as ser::Serializer>::SerializeTuple; + type SerializeTupleStruct = as ser::Serializer>::SerializeTupleStruct; + type SerializeTupleVariant = + as ser::Serializer>::SerializeTupleVariant; + type SerializeMap = as ser::Serializer>::SerializeMap; + type SerializeStruct = as ser::Serializer>::SerializeStruct; + type SerializeStructVariant = + as ser::Serializer>::SerializeStructVariant; - fn serialize_u8(self, v: u8) -> Result { - self.write_primitive(v, true) - } + forward!(serialize_bool(bool)); - fn serialize_u16(self, v: u16) -> Result { - self.write_primitive(v, true) - } + forward!(serialize_i8(i8)); + forward!(serialize_i16(i16)); + forward!(serialize_i32(i32)); + forward!(serialize_i64(i64)); - fn serialize_u32(self, v: u32) -> Result { - self.write_primitive(v, true) - } - - fn serialize_u64(self, v: u64) -> Result { - self.write_primitive(v, true) - } + forward!(serialize_u8(u8)); + forward!(serialize_u16(u16)); + forward!(serialize_u32(u32)); + forward!(serialize_u64(u64)); serde_if_integer128! { - fn serialize_i128(self, v: i128) -> Result { - self.write_primitive(v, true) - } - - fn serialize_u128(self, v: u128) -> Result { - self.write_primitive(v, true) - } - } - - fn serialize_f32(self, v: f32) -> Result { - self.write_primitive(v, true) + forward!(serialize_i128(i128)); + forward!(serialize_u128(u128)); } - fn serialize_f64(self, v: f64) -> Result { - self.write_primitive(v, true) - } - - fn serialize_char(self, v: char) -> Result { - self.write_primitive(v, false) - } - - fn serialize_str(self, value: &str) -> Result { - self.write_primitive(value, false) - } + forward!(serialize_f32(f32)); + forward!(serialize_f64(f64)); - fn serialize_bytes(self, _value: &[u8]) -> Result { - // TODO: I imagine you'd want to use base64 here. - // Not sure how to roundtrip effectively though... - Err(DeError::Unsupported( - "`serialize_bytes` not supported yet".into(), - )) - } + forward!(serialize_char(char)); + forward!(serialize_str(&str)); + forward!(serialize_bytes(&[u8])); fn serialize_none(self) -> Result { - Ok(()) + Ok(self.ser.writer) } fn serialize_some(self, value: &T) -> Result { @@ -468,25 +436,21 @@ impl<'r, 'w, W: Write> ser::Serializer for &'w mut Serializer<'r, W> { } fn serialize_unit(self) -> Result { - self.serialize_none() + self.ser("`()`")?.serialize_unit() } fn serialize_unit_struct(self, name: &'static str) -> Result { - self.write_self_closed(self.root_tag.unwrap_or(name)) + self.ser_name(name)?.serialize_unit_struct(name) } fn serialize_unit_variant( self, - _name: &'static str, - _variant_index: u32, + name: &'static str, + variant_index: u32, variant: &'static str, ) -> Result { - if variant.starts_with(PRIMITIVE_PREFIX) { - let variant = variant.split_at(PRIMITIVE_PREFIX.len()).1; - self.write_primitive(variant, false) - } else { - self.write_self_closed(variant) - } + self.ser_name(name)? + .serialize_unit_variant(name, variant_index, variant) } fn serialize_newtype_struct( @@ -494,85 +458,67 @@ impl<'r, 'w, W: Write> ser::Serializer for &'w mut Serializer<'r, W> { name: &'static str, value: &T, ) -> Result { - self.write_paired(self.root_tag.unwrap_or(name), value) + self.ser_name(name)?.serialize_newtype_struct(name, value) } fn serialize_newtype_variant( self, - _name: &'static str, - _variant_index: u32, + name: &'static str, + variant_index: u32, variant: &'static str, value: &T, ) -> Result { - // Flatten structs in enums are serialized as newtype struct variant + map. - // As serialize_map should write `root_tag` for ordinal maps (because it's - // only way for maps), and for enums this method already written a tag name - // (`variant`), we need to clear root tag before writing content and restore - // it after - let root = self.root_tag.take(); - let result = self.write_paired(variant, value); - self.root_tag = root; - result + self.ser_name(name)? + .serialize_newtype_variant(name, variant_index, variant, value) } - fn serialize_seq(self, _len: Option) -> Result { - Ok(Seq::new(self)) + fn serialize_seq(self, len: Option) -> Result { + self.ser("sequence")?.serialize_seq(len) } - fn serialize_tuple(self, _len: usize) -> Result { - let tag = match self.root_tag { - Some(tag) => tag, - None => { - return Err(DeError::Custom( - "cannot serialize unnamed tuple without defined root tag".into(), - )) - } - }; - Ok(Tuple::new(self, tag)) + fn serialize_tuple(self, len: usize) -> Result { + self.ser("unnamed tuple")?.serialize_tuple(len) } fn serialize_tuple_struct( self, name: &'static str, - _len: usize, + len: usize, ) -> Result { - Ok(Tuple::new(self, self.root_tag.unwrap_or(name))) + self.ser_name(name)?.serialize_tuple_struct(name, len) } fn serialize_tuple_variant( self, - _name: &'static str, - _variant_index: u32, + name: &'static str, + variant_index: u32, variant: &'static str, - _len: usize, + len: usize, ) -> Result { - Ok(Tuple::new(self, variant)) + self.ser_name(name)? + .serialize_tuple_variant(name, variant_index, variant, len) } - fn serialize_map(self, _len: Option) -> Result { - if let Some(tag) = self.root_tag { - // TODO: Write self-closed tag if map is empty - self.writer - .write_event(Event::Start(BytesStart::new(tag)))?; - } - Ok(Map::new(self)) + fn serialize_map(self, len: Option) -> Result { + self.ser("map")?.serialize_map(len) } fn serialize_struct( self, name: &'static str, - _len: usize, + len: usize, ) -> Result { - Ok(Struct::new(self, self.root_tag.unwrap_or(name))) + self.ser_name(name)?.serialize_struct(name, len) } fn serialize_struct_variant( self, - _name: &'static str, - _variant_index: u32, + name: &'static str, + variant_index: u32, variant: &'static str, - _len: usize, + len: usize, ) -> Result { - Ok(Struct::new(self, variant)) + self.ser_name(name)? + .serialize_struct_variant(name, variant_index, variant, len) } } diff --git a/src/se/var.rs b/src/se/var.rs deleted file mode 100644 index 7017a895..00000000 --- a/src/se/var.rs +++ /dev/null @@ -1,335 +0,0 @@ -use crate::{ - de::{ANY_KEY, TEXT_KEY}, - errors::{serialize::DeError, Error}, - events::{BytesEnd, BytesStart, Event}, - se::key::QNameSerializer, - se::Serializer, - writer::Writer, -}; -use serde::ser::{self, Serialize}; -use std::io::Write; - -/// An implementation of `SerializeMap` for serializing to XML. -pub struct Map<'r, 'w, W> -where - W: 'w + Write, -{ - parent: &'w mut Serializer<'r, W>, -} - -impl<'r, 'w, W> Map<'r, 'w, W> -where - W: 'w + Write, -{ - /// Create a new Map - pub fn new(parent: &'w mut Serializer<'r, W>) -> Self { - Map { parent } - } -} - -impl<'r, 'w, W> ser::SerializeMap for Map<'r, 'w, W> -where - W: 'w + Write, -{ - type Ok = (); - type Error = DeError; - - fn serialize_key(&mut self, key: &T) -> Result<(), DeError> { - /* - Err(DeError::Unsupported( - "impossible to serialize the key on its own, please use serialize_entry()", - )) - */ - write!(self.parent.writer.inner(), "").map_err(Error::Io)?; - Ok(()) - } - - fn serialize_value(&mut self, value: &T) -> Result<(), DeError> { - value.serialize(&mut *self.parent) - } - - fn end(self) -> Result { - if let Some(tag) = self.parent.root_tag { - self.parent - .writer - .write_event(Event::End(BytesEnd::new(tag)))?; - } - Ok(()) - } - - fn serialize_entry( - &mut self, - key: &K, - value: &V, - ) -> Result<(), DeError> { - let key = key.serialize(QNameSerializer { - writer: String::new(), - })?; - - let writer = self.parent.writer.inner(); - writer.write_all(b"<").map_err(Error::Io)?; - writer.write_all(key.as_bytes()).map_err(Error::Io)?; - writer.write_all(b">").map_err(Error::Io)?; - - value.serialize(&mut *self.parent)?; - - let writer = self.parent.writer.inner(); - writer.write_all(b"").map_err(Error::Io)?; - Ok(()) - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/// An implementation of `SerializeStruct` for serializing to XML. -pub struct Struct<'r, 'w, W> -where - W: 'w + Write, -{ - parent: &'w mut Serializer<'r, W>, - /// Buffer for holding fields, serialized as attributes. Doesn't allocate - /// if there are no fields represented as attributes - attrs: BytesStart<'w>, - /// Buffer for holding fields, serialized as elements - children: Vec, - /// Buffer for serializing one field. Cleared after serialize each field - buffer: Vec, -} - -impl<'r, 'w, W> Struct<'r, 'w, W> -where - W: 'w + Write, -{ - /// Create a new `Struct` - pub fn new(parent: &'w mut Serializer<'r, W>, name: &'r str) -> Self { - Struct { - parent, - attrs: BytesStart::new(name), - children: Vec::new(), - buffer: Vec::new(), - } - } -} - -impl<'r, 'w, W> ser::SerializeStruct for Struct<'r, 'w, W> -where - W: 'w + Write, -{ - type Ok = (); - type Error = DeError; - - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result<(), DeError> { - // TODO: Inherit indentation state from self.parent.writer - let writer = Writer::new(&mut self.buffer); - - let mut serializer = Serializer::with_root(writer, Some(key)); - value.serialize(&mut serializer)?; - - if !self.buffer.is_empty() { - if self.buffer[0] == b'<' || key == ANY_KEY || key == TEXT_KEY { - // Drains buffer, moves it to children - self.children.append(&mut self.buffer); - } else { - self.attrs - .push_attribute((key.as_bytes(), self.buffer.as_ref())); - self.buffer.clear(); - } - } - - Ok(()) - } - - fn end(self) -> Result { - if self.children.is_empty() { - self.parent.writer.write_event(Event::Empty(self.attrs))?; - } else { - self.parent - .writer - .write_event(Event::Start(self.attrs.borrow()))?; - self.parent.writer.write(&self.children)?; - self.parent - .writer - .write_event(Event::End(self.attrs.to_end()))?; - } - Ok(()) - } -} - -impl<'r, 'w, W> ser::SerializeStructVariant for Struct<'r, 'w, W> -where - W: 'w + Write, -{ - type Ok = (); - type Error = DeError; - - #[inline] - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result<(), Self::Error> { - ::serialize_field(self, key, value) - } - - #[inline] - fn end(self) -> Result { - ::end(self) - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/// An implementation of `SerializeSeq' for serializing to XML. -pub struct Seq<'r, 'w, W> -where - W: 'w + Write, -{ - parent: &'w mut Serializer<'r, W>, -} - -impl<'r, 'w, W> Seq<'r, 'w, W> -where - W: 'w + Write, -{ - /// Create a new `Seq` - pub fn new(parent: &'w mut Serializer<'r, W>) -> Self { - Seq { parent } - } -} - -impl<'r, 'w, W> ser::SerializeSeq for Seq<'r, 'w, W> -where - W: 'w + Write, -{ - type Ok = (); - type Error = DeError; - - fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> - where - T: Serialize, - { - value.serialize(&mut *self.parent)?; - Ok(()) - } - - fn end(self) -> Result { - Ok(()) - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/// An implementation of `SerializeTuple`, `SerializeTupleStruct` and -/// `SerializeTupleVariant` for serializing to XML. -pub struct Tuple<'r, 'w, W> -where - W: 'w + Write, -{ - parent: &'w mut Serializer<'r, W>, - /// Possible qualified name of XML tag surrounding each element - name: &'r str, -} - -impl<'r, 'w, W> Tuple<'r, 'w, W> -where - W: 'w + Write, -{ - /// Create a new `Tuple` - pub fn new(parent: &'w mut Serializer<'r, W>, name: &'r str) -> Self { - Tuple { parent, name } - } -} - -impl<'r, 'w, W> ser::SerializeTuple for Tuple<'r, 'w, W> -where - W: 'w + Write, -{ - type Ok = (); - type Error = DeError; - - fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> - where - T: Serialize, - { - write!(self.parent.writer.inner(), "<{}>", self.name).map_err(Error::Io)?; - value.serialize(&mut *self.parent)?; - write!(self.parent.writer.inner(), "", self.name).map_err(Error::Io)?; - Ok(()) - } - - #[inline] - fn end(self) -> Result { - Ok(()) - } -} - -impl<'r, 'w, W> ser::SerializeTupleStruct for Tuple<'r, 'w, W> -where - W: 'w + Write, -{ - type Ok = (); - type Error = DeError; - - #[inline] - fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> - where - T: Serialize, - { - ::serialize_element(self, value) - } - - #[inline] - fn end(self) -> Result { - ::end(self) - } -} - -impl<'r, 'w, W> ser::SerializeTupleVariant for Tuple<'r, 'w, W> -where - W: 'w + Write, -{ - type Ok = (); - type Error = DeError; - - #[inline] - fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> - where - T: Serialize, - { - ::serialize_element(self, value) - } - - #[inline] - fn end(self) -> Result { - ::end(self) - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -#[test] -fn test_serialize_map_entries() { - use serde::ser::SerializeMap; - - let mut buffer = Vec::new(); - - { - let mut ser = Serializer::new(&mut buffer); - let mut map = Map::new(&mut ser); - map.serialize_entry("name", "Bob").unwrap(); - map.serialize_entry("age", "5").unwrap(); - } - - assert_eq!( - String::from_utf8(buffer).unwrap(), - "Bob5" - ); -} diff --git a/tests/serde-se.rs b/tests/serde-se.rs index 33523fbe..ab830627 100644 --- a/tests/serde-se.rs +++ b/tests/serde-se.rs @@ -1,6 +1,5 @@ use quick_xml::se::Serializer; use quick_xml::utils::Bytes; -use quick_xml::writer::Writer; use quick_xml::DeError; use serde::{serde_if_integer128, Serialize}; @@ -52,8 +51,6 @@ struct Text { #[derive(Serialize)] enum ExternallyTagged { Unit, - #[serde(rename = "$primitive=PrimitiveUnit")] - PrimitiveUnit, Newtype(bool), Tuple(f64, &'static str), Struct { @@ -167,11 +164,9 @@ mod without_root { ($name:ident: $data:expr => $expected:literal) => { #[test] fn $name() { - let mut buffer = Vec::new(); - let mut ser = Serializer::new(&mut buffer); + let ser = Serializer::new(String::new()); - $data.serialize(&mut ser).unwrap(); - assert_eq!(String::from_utf8(buffer).unwrap(), $expected); + assert_eq!($data.serialize(ser).unwrap(), $expected); } }; } @@ -182,10 +177,10 @@ mod without_root { ($name:ident: $data:expr => $kind:ident($reason:literal)) => { #[test] fn $name() { - let mut buffer = Vec::new(); - let mut ser = Serializer::new(&mut buffer); + let mut buffer = String::new(); + let ser = Serializer::new(&mut buffer); - match $data.serialize(&mut ser) { + match $data.serialize(ser) { Err(DeError::$kind(e)) => assert_eq!(e, $reason), e => panic!( "Expected `{}({})`, found `{:?}`", @@ -194,7 +189,7 @@ mod without_root { e ), } - assert_eq!(String::from_utf8(buffer).unwrap(), ""); + assert_eq!(buffer, ""); } }; } @@ -233,7 +228,7 @@ mod without_root { err!(str_non_escaped: "non-escaped string" => Unsupported("cannot serialize `&str` without defined root tag")); err!(str_escaped: "<\"escaped & string'>" => Unsupported("cannot serialize `&str` without defined root tag")); - err!(bytes: Bytes(b"<\"escaped & bytes'>") => Unsupported("`serialize_bytes` not supported yet")); + err!(bytes: Bytes(b"<\"escaped & bytes'>") => Unsupported("cannot serialize `&[u8]` without defined root tag")); serialize_as!(option_none: Option::::None => ""); serialize_as!(option_some: Some(Unit) => ""); @@ -306,9 +301,6 @@ mod without_root { serialize_as!(unit: ExternallyTagged::Unit => ""); - serialize_as!(primitive_unit: - ExternallyTagged::PrimitiveUnit - => ""); serialize_as!(newtype: ExternallyTagged::Newtype(true) => "true"); @@ -565,11 +557,9 @@ mod with_root { ($name:ident: $data:expr => $expected:literal) => { #[test] fn $name() { - let mut buffer = Vec::new(); - let mut ser = Serializer::with_root(Writer::new(&mut buffer), Some("root")); + let ser = Serializer::with_root(String::new(), Some("root")).unwrap(); - $data.serialize(&mut ser).unwrap(); - assert_eq!(String::from_utf8(buffer).unwrap(), $expected); + assert_eq!($data.serialize(ser).unwrap(), $expected); } }; } @@ -580,10 +570,10 @@ mod with_root { ($name:ident: $data:expr => $kind:ident($reason:literal)) => { #[test] fn $name() { - let mut buffer = Vec::new(); - let mut ser = Serializer::with_root(Writer::new(&mut buffer), Some("root")); + let mut buffer = String::new(); + let ser = Serializer::with_root(&mut buffer, Some("root")).unwrap(); - match $data.serialize(&mut ser) { + match $data.serialize(ser) { Err(DeError::$kind(e)) => assert_eq!(e, $reason), e => panic!( "Expected `{}({})`, found `{:?}`", @@ -593,7 +583,7 @@ mod with_root { ), } // We can write something before fail - // assert_eq!(String::from_utf8(buffer).unwrap(), ""); + // assert_eq!(buffer, ""); } }; } @@ -721,9 +711,6 @@ mod with_root { serialize_as!(unit: ExternallyTagged::Unit => ""); - serialize_as!(primitive_unit: - ExternallyTagged::PrimitiveUnit - => ""); serialize_as!(newtype: ExternallyTagged::Newtype(true) => "true");