aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/de/mod.rs22
-rw-r--r--src/error.rs6
-rw-r--r--src/lib.rs14
-rw-r--r--src/ser/map.rs124
-rw-r--r--src/ser/mod.rs412
-rw-r--r--src/ser/plain.rs196
-rw-r--r--src/ser/seq.rs37
-rw-r--r--src/ser/tuple.rs91
-rw-r--r--src/ser/var.rs103
9 files changed, 686 insertions, 319 deletions
diff --git a/src/de/mod.rs b/src/de/mod.rs
index 21240c5..486b38c 100644
--- a/src/de/mod.rs
+++ b/src/de/mod.rs
@@ -1,6 +1,6 @@
use std::{io::Read, marker::PhantomData};
-use log::debug;
+use log::trace;
use serde::de::{self, Unexpected};
use serde::forward_to_deserialize_any;
use xml::name::OwnedName;
@@ -21,10 +21,7 @@ mod var;
/// A convenience method for deserialize some object from a string.
///
/// ```rust
-/// # #[macro_use]
-/// # extern crate serde_derive;
-/// # extern crate serde;
-/// # extern crate serde_xml_rs;
+/// # use serde::{Deserialize, Serialize};
/// # use serde_xml_rs::from_str;
/// #[derive(Debug, Deserialize, PartialEq)]
/// struct Item {
@@ -44,10 +41,7 @@ pub fn from_str<'de, T: de::Deserialize<'de>>(s: &str) -> Result<T> {
/// A convenience method for deserialize some object from a reader.
///
/// ```rust
-/// # #[macro_use]
-/// # extern crate serde_derive;
-/// # extern crate serde;
-/// # extern crate serde_xml_rs;
+/// # use serde::Deserialize;
/// # use serde_xml_rs::from_reader;
/// #[derive(Debug, Deserialize, PartialEq)]
/// struct Item {
@@ -108,12 +102,8 @@ impl<'de, R: Read> RootDeserializer<R> {
/// default. Enabling this option may incur additional memory usage.
///
/// ```rust
- /// # #[macro_use]
- /// # extern crate serde_derive;
- /// # extern crate serde;
- /// # extern crate serde_xml_rs;
- /// # use serde_xml_rs::from_reader;
/// # use serde::Deserialize;
+ /// # use serde_xml_rs::from_reader;
/// #[derive(Debug, Deserialize, PartialEq)]
/// struct Foo {
/// bar: Vec<usize>,
@@ -164,7 +154,7 @@ impl<'de, R: Read, B: BufferedXmlReader<R>> Deserializer<R, B> {
fn peek(&mut self) -> Result<&XmlEvent> {
let peeked = self.buffered_reader.peek()?;
- debug!("Peeked {:?}", peeked);
+ trace!("Peeked {:?}", peeked);
Ok(peeked)
}
@@ -181,7 +171,7 @@ impl<'de, R: Read, B: BufferedXmlReader<R>> Deserializer<R, B> {
}
_ => {}
}
- debug!("Fetched {:?}", next);
+ trace!("Fetched {:?}", next);
Ok(next)
}
diff --git a/src/error.rs b/src/error.rs
index 5061b52..50a15c0 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -47,6 +47,12 @@ pub enum Error {
#[from]
source: ::xml::reader::Error,
},
+
+ #[error("Writer: {source}")]
+ Writer {
+ #[from]
+ source: ::xml::writer::Error,
+ },
}
pub type Result<T> = std::result::Result<T, Error>;
diff --git a/src/lib.rs b/src/lib.rs
index e1ef1df..41d9c82 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -49,8 +49,7 @@
//! ## Basic example
//!
//! ```rust
-//! use serde;
-//! use serde_derive::{Deserialize, Serialize};
+//! use serde::{Deserialize, Serialize};
//! use serde_xml_rs::{from_str, to_string};
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
@@ -60,7 +59,7 @@
//! }
//!
//! fn main() {
-//! let src = r#"<Item><name>Banana</name><source>Store</source></Item>"#;
+//! let src = r#"<?xml version="1.0" encoding="UTF-8"?><Item><name>Banana</name><source>Store</source></Item>"#;
//! let should_be = Item {
//! name: "Banana".to_string(),
//! source: "Store".to_string(),
@@ -77,8 +76,7 @@
//! ## Tag contents
//!
//! ```rust
-//! # use serde;
-//! # use serde_derive::{Deserialize, Serialize};
+//! # use serde::{Deserialize, Serialize};
//! # use serde_xml_rs::{from_str, to_string};
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
@@ -102,8 +100,7 @@
//! ## Repeated tags
//!
//! ```rust
-//! # use serde;
-//! # use serde_derive::{Deserialize, Serialize};
+//! # use serde::{Deserialize, Serialize};
//! # use serde_xml_rs::{from_str, to_string};
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
@@ -160,8 +157,7 @@
//! ## Custom EventReader
//!
//! ```rust
-//! use serde::Deserialize;
-//! use serde_derive::{Deserialize, Serialize};
+//! use serde::{Deserialize, Serialize};
//! use serde_xml_rs::{from_str, to_string, de::Deserializer};
//! use xml::reader::{EventReader, ParserConfig};
//!
diff --git a/src/ser/map.rs b/src/ser/map.rs
new file mode 100644
index 0000000..b0793e6
--- /dev/null
+++ b/src/ser/map.rs
@@ -0,0 +1,124 @@
+use super::{plain::to_plain_string, Serializer};
+use crate::error::{Error, Result};
+use log::debug;
+use serde::ser::Serialize;
+use std::io::Write;
+
+pub struct MapSerializer<'ser, W: 'ser + Write> {
+ ser: &'ser mut Serializer<W>,
+ must_close_tag: bool,
+}
+
+impl<'ser, W: 'ser + Write> MapSerializer<'ser, W> {
+ pub fn new(ser: &'ser mut Serializer<W>, must_close_tag: bool) -> Self {
+ MapSerializer {
+ ser,
+ must_close_tag,
+ }
+ }
+}
+
+impl<'ser, W: Write> serde::ser::SerializeMap for MapSerializer<'ser, W> {
+ type Ok = ();
+ type Error = Error;
+
+ fn serialize_key<T>(&mut self, key: &T) -> Result<()>
+ where
+ T: ?Sized + Serialize,
+ {
+ self.ser.open_tag(&to_plain_string(key)?)?;
+ Ok(())
+ }
+
+ fn serialize_value<T>(&mut self, value: &T) -> Result<()>
+ where
+ T: ?Sized + Serialize,
+ {
+ value.serialize(&mut *self.ser)?;
+ Ok(())
+ }
+
+ fn end(self) -> Result<()> {
+ if self.must_close_tag {
+ self.ser.end_tag()?;
+ }
+ Ok(())
+ }
+}
+
+pub struct StructSerializer<'ser, W: 'ser + Write> {
+ ser: &'ser mut Serializer<W>,
+ must_close_tag: bool,
+}
+
+impl<'ser, W: 'ser + Write> StructSerializer<'ser, W> {
+ pub fn new(ser: &'ser mut Serializer<W>, must_close_tag: bool) -> Self {
+ StructSerializer {
+ ser,
+ must_close_tag,
+ }
+ }
+
+ fn serialize_struct_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
+ where
+ T: ?Sized + Serialize,
+ {
+ if key.starts_with("@") {
+ debug!("attribute {}", key);
+ self.ser.add_attr(&key[1..], to_plain_string(value)?)
+ } else if key == "$value" {
+ self.ser.build_start_tag()?;
+ debug!("body");
+ value.serialize(&mut *self.ser)?;
+ Ok(())
+ } else {
+ self.ser.build_start_tag()?;
+ self.ser.open_tag(key)?;
+ debug!("field {}", key);
+ value.serialize(&mut *self.ser)?;
+ debug!("end field");
+ Ok(())
+ }
+ }
+
+ fn after_fields(self) -> Result<()> {
+ self.ser.build_start_tag()?;
+ self.ser.end_tag()?;
+ if self.must_close_tag {
+ self.ser.end_tag()?;
+ }
+ Ok(())
+ }
+}
+
+impl<'ser, W: 'ser + Write> serde::ser::SerializeStruct for StructSerializer<'ser, W> {
+ type Ok = ();
+ type Error = Error;
+
+ fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
+ where
+ T: ?Sized + Serialize,
+ {
+ self.serialize_struct_field(key, value)
+ }
+
+ fn end(self) -> Result<()> {
+ self.after_fields()
+ }
+}
+
+impl<'ser, W: 'ser + Write> serde::ser::SerializeStructVariant for StructSerializer<'ser, W> {
+ type Ok = ();
+ type Error = Error;
+
+ fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
+ where
+ T: ?Sized + Serialize,
+ {
+ self.serialize_struct_field(key, value)
+ }
+
+ fn end(self) -> Result<()> {
+ self.after_fields()
+ }
+}
diff --git a/src/ser/mod.rs b/src/ser/mod.rs
index a29ca6f..8130a8d 100644
--- a/src/ser/mod.rs
+++ b/src/ser/mod.rs
@@ -1,22 +1,25 @@
-use std::fmt::Display;
-use std::io::Write;
-
-use serde::ser::{self, Impossible, Serialize};
-
-use self::var::{Map, Struct};
+mod map;
+mod plain;
+mod seq;
+mod tuple;
+
+use self::{
+ map::{MapSerializer, StructSerializer},
+ seq::SeqSeralizer,
+ tuple::TupleSerializer,
+};
use crate::error::{Error, Result};
-
-mod var;
+use log::debug;
+use serde::ser::Serialize;
+use std::{collections::HashMap, io::Write};
+use xml::writer::{EmitterConfig, EventWriter, XmlEvent};
/// A convenience method for serializing some object to a buffer.
///
/// # Examples
///
/// ```rust
-/// # #[macro_use]
-/// # extern crate serde_derive;
-/// # extern crate serde;
-/// # extern crate serde_xml_rs;
+/// # use serde::Serialize;
/// # use serde_xml_rs::to_writer;
/// #[derive(Serialize)]
/// struct Person {
@@ -44,10 +47,7 @@ pub fn to_writer<W: Write, S: Serialize>(writer: W, value: &S) -> Result<()> {
/// # Examples
///
/// ```rust
-/// # #[macro_use]
-/// # extern crate serde_derive;
-/// # extern crate serde;
-/// # extern crate serde_xml_rs;
+/// # use serde::Serialize;
/// # use serde_xml_rs::to_string;
/// #[derive(Serialize)]
/// struct Person {
@@ -77,266 +77,329 @@ pub struct Serializer<W>
where
W: Write,
{
- writer: W,
+ writer: EventWriter<W>,
+ root: bool,
+ current_tag: String,
+ current_tag_attrs: Option<HashMap<&'static str, String>>,
}
impl<W> Serializer<W>
where
W: Write,
{
+ fn new_from_writer(writer: EventWriter<W>) -> Self {
+ Self {
+ writer,
+ root: true,
+ current_tag: "".into(),
+ current_tag_attrs: None,
+ }
+ }
+
pub fn new(writer: W) -> Self {
- Self { writer: writer }
+ Self::new_from_writer(EmitterConfig::new().create_writer(writer))
}
- fn write_primitive<P: Display>(&mut self, primitive: P) -> Result<()> {
- write!(self.writer, "{}", primitive)?;
+ fn next(&mut self, event: XmlEvent) -> Result<()> {
+ self.writer.write(event)?;
Ok(())
}
- fn write_wrapped<S: Serialize>(&mut self, tag: &str, value: S) -> Result<()> {
- write!(self.writer, "<{}>", tag)?;
- value.serialize(&mut *self)?;
- write!(self.writer, "</{}>", tag)?;
+ fn characters(&mut self, s: &str) -> Result<()> {
+ self.next(XmlEvent::characters(s))
+ }
+
+ fn start_document(&mut self) -> Result<()> {
+ self.next(XmlEvent::StartDocument {
+ encoding: Default::default(),
+ standalone: Default::default(),
+ version: xml::common::XmlVersion::Version10,
+ })
+ }
+
+ fn open_root_tag(&mut self, name: &'static str) -> Result<()> {
+ if self.root {
+ self.root = false;
+ self.start_document()?;
+ self.open_tag(name)?;
+ }
+ Ok(())
+ }
+
+ fn open_tag(&mut self, tag_name: &str) -> Result<()> {
+ self.current_tag = tag_name.into();
+ self.current_tag_attrs = Some(HashMap::new());
+ Ok(())
+ }
+
+ fn reopen_tag(&mut self) -> Result<()> {
+ self.current_tag_attrs = Some(HashMap::new());
Ok(())
}
+
+ fn abandon_tag(&mut self) -> Result<()> {
+ self.current_tag = "".into();
+ self.current_tag_attrs = None;
+ Ok(())
+ }
+
+ fn add_attr(&mut self, name: &'static str, value: String) -> Result<()> {
+ self.current_tag_attrs
+ .as_mut()
+ .ok_or(Error::Custom {
+ field: format!("Cannot add attribute {}", name),
+ })
+ .map(|attrs| {
+ attrs.insert(name, value);
+ })
+ }
+
+ fn build_start_tag(&mut self) -> Result<bool> {
+ if let Some(attrs) = self.current_tag_attrs.take() {
+ self.start_tag(&self.current_tag(), attrs)?;
+ Ok(true)
+ } else {
+ Ok(false)
+ }
+ }
+
+ fn start_tag(&mut self, tag_name: &str, attrs: HashMap<&str, String>) -> Result<()> {
+ let element = attrs
+ .iter()
+ .fold(XmlEvent::start_element(tag_name), |b, (&name, value)| {
+ b.attr(name, value)
+ });
+
+ self.next(element.into())
+ }
+
+ fn end_tag(&mut self) -> Result<()> {
+ self.next(XmlEvent::end_element().into())
+ }
+
+ fn current_tag(&self) -> String {
+ self.current_tag.clone()
+ }
}
-#[allow(unused_variables)]
-impl<'w, W> ser::Serializer for &'w mut Serializer<W>
-where
- W: Write,
-{
+impl<'ser, W: Write> serde::ser::Serializer for &'ser mut Serializer<W> {
type Ok = ();
type Error = Error;
- type SerializeSeq = Impossible<Self::Ok, Self::Error>;
- type SerializeTuple = Impossible<Self::Ok, Self::Error>;
- type SerializeTupleStruct = Impossible<Self::Ok, Self::Error>;
- type SerializeTupleVariant = Impossible<Self::Ok, Self::Error>;
- type SerializeMap = Map<'w, W>;
- type SerializeStruct = Struct<'w, W>;
- type SerializeStructVariant = Impossible<Self::Ok, Self::Error>;
+ type SerializeSeq = SeqSeralizer<'ser, W>;
+ type SerializeTuple = TupleSerializer<'ser, W>;
+ type SerializeTupleStruct = TupleSerializer<'ser, W>;
+ type SerializeTupleVariant = TupleSerializer<'ser, W>;
+ type SerializeMap = MapSerializer<'ser, W>;
+ type SerializeStruct = StructSerializer<'ser, W>;
+ type SerializeStructVariant = StructSerializer<'ser, W>;
fn serialize_bool(self, v: bool) -> Result<Self::Ok> {
- if v {
- write!(self.writer, "true")?;
- } else {
- write!(self.writer, "false")?;
- }
-
- Ok(())
+ self.serialize_str(&v.to_string())
}
fn serialize_i8(self, v: i8) -> Result<Self::Ok> {
- self.write_primitive(v)
+ self.serialize_i64(i64::from(v))
}
fn serialize_i16(self, v: i16) -> Result<Self::Ok> {
- self.write_primitive(v)
+ self.serialize_i64(i64::from(v))
}
fn serialize_i32(self, v: i32) -> Result<Self::Ok> {
- self.write_primitive(v)
+ self.serialize_i64(i64::from(v))
}
fn serialize_i64(self, v: i64) -> Result<Self::Ok> {
- self.write_primitive(v)
+ self.serialize_str(&v.to_string())
}
fn serialize_u8(self, v: u8) -> Result<Self::Ok> {
- self.write_primitive(v)
+ self.serialize_u64(u64::from(v))
}
fn serialize_u16(self, v: u16) -> Result<Self::Ok> {
- self.write_primitive(v)
+ self.serialize_u64(u64::from(v))
}
fn serialize_u32(self, v: u32) -> Result<Self::Ok> {
- self.write_primitive(v)
+ self.serialize_u64(u64::from(v))
}
fn serialize_u64(self, v: u64) -> Result<Self::Ok> {
- self.write_primitive(v)
+ let must_close_tag = self.build_start_tag()?;
+ self.characters(&v.to_string())?;
+ if must_close_tag {
+ self.end_tag()?;
+ }
+ Ok(())
}
fn serialize_f32(self, v: f32) -> Result<Self::Ok> {
- self.write_primitive(v)
+ self.serialize_f64(f64::from(v))
}
fn serialize_f64(self, v: f64) -> Result<Self::Ok> {
- self.write_primitive(v)
+ self.serialize_str(&v.to_string())
}
fn serialize_char(self, v: char) -> Result<Self::Ok> {
- self.write_primitive(v)
+ self.serialize_str(&v.to_string())
}
- fn serialize_str(self, value: &str) -> Result<Self::Ok> {
- self.write_primitive(value)
+ fn serialize_str(self, v: &str) -> Result<Self::Ok> {
+ let must_close_tag = self.build_start_tag()?;
+ self.characters(v)?;
+ if must_close_tag {
+ self.end_tag()?;
+ }
+ Ok(())
}
- fn serialize_bytes(self, value: &[u8]) -> Result<Self::Ok> {
- // TODO: I imagine you'd want to use base64 here.
- // Not sure how to roundtrip effectively though...
- Err(Error::UnsupportedOperation {
- operation: "serialize_bytes".to_string(),
- })
+ fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok> {
+ unimplemented!()
}
fn serialize_none(self) -> Result<Self::Ok> {
+ debug!("None");
+ let must_close_tag = self.build_start_tag()?;
+ if must_close_tag {
+ self.end_tag()?;
+ }
Ok(())
}
- fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Self::Ok> {
+ fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok>
+ where
+ T: Serialize,
+ {
+ debug!("Some");
value.serialize(self)
}
fn serialize_unit(self) -> Result<Self::Ok> {
- self.serialize_none()
+ debug!("Unit");
+ let must_close_tag = self.build_start_tag()?;
+ if must_close_tag {
+ self.end_tag()?;
+ }
+ Ok(())
}
fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok> {
- self.write_wrapped(name, ())
+ debug!("Unit struct {}", name);
+ self.serialize_unit()
}
fn serialize_unit_variant(
self,
name: &'static str,
- variant_index: u32,
+ _variant_index: u32,
variant: &'static str,
) -> Result<Self::Ok> {
- Err(Error::UnsupportedOperation {
- operation: "serialize_unit_variant".to_string(),
- })
+ debug!("Unit variant {}::{}", name, variant);
+ self.start_tag(variant, HashMap::new())?;
+ self.serialize_unit()?;
+ self.end_tag()?;
+ Ok(())
}
- fn serialize_newtype_struct<T: ?Sized + Serialize>(
- self,
- name: &'static str,
- value: &T,
- ) -> Result<Self::Ok> {
- Err(Error::UnsupportedOperation {
- operation: "serialize_newtype_struct".to_string(),
- })
+ fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) -> Result<Self::Ok>
+ where
+ T: Serialize,
+ {
+ debug!("Newtype struct {}", name);
+ value.serialize(self)
}
- fn serialize_newtype_variant<T: ?Sized + Serialize>(
+ fn serialize_newtype_variant<T: ?Sized>(
self,
name: &'static str,
- variant_index: u32,
+ _variant_index: u32,
variant: &'static str,
value: &T,
- ) -> Result<Self::Ok> {
- self.write_wrapped(variant, value)
+ ) -> Result<Self::Ok>
+ where
+ T: Serialize,
+ {
+ let must_close_tag = self.build_start_tag()?;
+
+ debug!("Newtype variant {}::{}", name, variant);
+ self.open_tag(variant)?;
+ value.serialize(&mut *self)?;
+
+ if must_close_tag {
+ self.end_tag()?;
+ }
+ Ok(())
}
- fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq> {
- // TODO: Figure out how to constrain the things written to only be composites
- Err(Error::UnsupportedOperation {
- operation: "serialize_seq".to_string(),
- })
+ fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
+ debug!("Sequence");
+ Ok(SeqSeralizer::new(self))
}
- fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
- Err(Error::UnsupportedOperation {
- operation: "serialize_tuple".to_string(),
- })
+ fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
+ debug!("Tuple");
+ let must_close_tag = self.build_start_tag()?;
+ Ok(TupleSerializer::new(self, must_close_tag))
}
fn serialize_tuple_struct(
self,
name: &'static str,
- len: usize,
+ _len: usize,
) -> Result<Self::SerializeTupleStruct> {
- Err(Error::UnsupportedOperation {
- operation: "serialize_tuple_struct".to_string(),
- })
+ debug!("Tuple struct {}", name);
+ let must_close_tag = self.build_start_tag()?;
+ Ok(TupleSerializer::new(self, must_close_tag))
}
fn serialize_tuple_variant(
self,
name: &'static str,
- variant_index: u32,
+ _variant_index: u32,
variant: &'static str,
- len: usize,
+ _len: usize,
) -> Result<Self::SerializeTupleVariant> {
- Err(Error::UnsupportedOperation {
- operation: "serialize_tuple_variant".to_string(),
- })
+ debug!("Tuple variant {}::{}", name, variant);
+ let must_close_tag = self.build_start_tag()?;
+ self.start_tag(variant, HashMap::new())?;
+ Ok(TupleSerializer::new(self, must_close_tag))
}
- fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap> {
- Ok(Map::new(self))
+ fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
+ let must_close_tag = self.build_start_tag()?;
+ Ok(MapSerializer::new(self, must_close_tag))
}
- fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
- write!(self.writer, "<{}>", name)?;
- Ok(Struct::new(self, name))
+ fn serialize_struct(self, name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
+ self.open_root_tag(name)?;
+
+ debug!("Struct {}", name);
+ Ok(StructSerializer::new(self, false))
}
fn serialize_struct_variant(
self,
name: &'static str,
- variant_index: u32,
+ _variant_index: u32,
variant: &'static str,
- len: usize,
+ _len: usize,
) -> Result<Self::SerializeStructVariant> {
- Err(Error::UnsupportedOperation {
- operation: "Result".to_string(),
- })
+ self.open_root_tag(name)?;
+
+ debug!("Struct variant {}", variant);
+ let must_close_tag = self.build_start_tag()?;
+ self.open_tag(variant)?;
+ Ok(StructSerializer::new(self, must_close_tag))
}
}
#[cfg(test)]
mod tests {
use super::*;
- use serde::ser::{SerializeMap, SerializeStruct};
- use serde::Serializer as SerSerializer;
- use serde_derive::Serialize;
-
- #[test]
- fn test_serialize_bool() {
- let inputs = vec![(true, "true"), (false, "false")];
-
- for (src, should_be) in inputs {
- let mut buffer = Vec::new();
-
- {
- let mut ser = Serializer::new(&mut buffer);
- ser.serialize_bool(src).unwrap();
- }
-
- let got = String::from_utf8(buffer).unwrap();
- assert_eq!(got, should_be);
- }
- }
-
- #[test]
- fn test_start_serialize_struct() {
- let mut buffer = Vec::new();
-
- {
- let mut ser = Serializer::new(&mut buffer);
- let _ = ser.serialize_struct("foo", 0).unwrap();
- }
-
- let got = String::from_utf8(buffer).unwrap();
- assert_eq!(got, "<foo>");
- }
-
- #[test]
- fn test_serialize_struct_field() {
- let mut buffer = Vec::new();
-
- {
- let mut ser = Serializer::new(&mut buffer);
- let mut struct_ser = Struct::new(&mut ser, "baz");
- struct_ser.serialize_field("foo", "bar").unwrap();
- }
-
- let got = String::from_utf8(buffer).unwrap();
- assert_eq!(got, "<foo>bar</foo>");
- }
+ use serde::Serialize;
#[test]
fn test_serialize_struct() {
@@ -350,7 +413,7 @@ mod tests {
name: "Bob".to_string(),
age: 42,
};
- let should_be = "<Person><name>Bob</name><age>42</age></Person>";
+ let should_be = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Person><name>Bob</name><age>42</age></Person>";
let mut buffer = Vec::new();
{
@@ -363,22 +426,6 @@ mod tests {
}
#[test]
- fn test_serialize_map_entries() {
- let should_be = "<name>Bob</name><age>5</age>";
- 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();
- }
-
- let got = String::from_utf8(buffer).unwrap();
- assert_eq!(got, should_be);
- }
-
- #[test]
fn test_serialize_enum() {
#[derive(Serialize)]
#[allow(dead_code)]
@@ -389,7 +436,7 @@ mod tests {
}
let mut buffer = Vec::new();
- let should_be = "<Boolean>true</Boolean>";
+ let should_be = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Boolean>true</Boolean>";
{
let mut ser = Serializer::new(&mut buffer);
@@ -400,21 +447,4 @@ mod tests {
let got = String::from_utf8(buffer).unwrap();
assert_eq!(got, should_be);
}
-
- #[test]
- #[ignore]
- fn serialize_a_list() {
- let inputs = vec![1, 2, 3, 4];
-
- let mut buffer = Vec::new();
-
- {
- let mut ser = Serializer::new(&mut buffer);
- inputs.serialize(&mut ser).unwrap();
- }
-
- let got = String::from_utf8(buffer).unwrap();
- println!("{}", got);
- panic!();
- }
}
diff --git a/src/ser/plain.rs b/src/ser/plain.rs
new file mode 100644
index 0000000..49e2964
--- /dev/null
+++ b/src/ser/plain.rs
@@ -0,0 +1,196 @@
+use std::io::Write;
+
+use serde::ser::{Impossible, Serialize};
+
+use crate::error::{Error, Result};
+
+pub fn to_plain_string<T>(value: &T) -> Result<String>
+where
+ T: ?Sized + Serialize,
+{
+ let mut writer = Vec::with_capacity(128);
+ value.serialize(&mut PlainStringSerializer::new(&mut writer))?;
+
+ let string = String::from_utf8(writer)?;
+ Ok(string)
+}
+
+struct PlainStringSerializer<W: Write> {
+ writer: W,
+}
+
+impl<W: Write> PlainStringSerializer<W> {
+ fn new(writer: W) -> Self {
+ PlainStringSerializer { writer }
+ }
+
+ fn characters(&mut self, s: &str) -> Result<()> {
+ write!(self.writer, "{}", s)?;
+ Ok(())
+ }
+}
+
+impl<'ser, W: 'ser + Write> serde::ser::Serializer for &'ser mut PlainStringSerializer<W> {
+ type Ok = ();
+ type Error = Error;
+
+ type SerializeSeq = Impossible<Self::Ok, Self::Error>;
+ type SerializeTuple = Impossible<Self::Ok, Self::Error>;
+ type SerializeTupleStruct = Impossible<Self::Ok, Self::Error>;
+ type SerializeTupleVariant = Impossible<Self::Ok, Self::Error>;
+ type SerializeMap = Impossible<Self::Ok, Self::Error>;
+ type SerializeStruct = Impossible<Self::Ok, Self::Error>;
+ type SerializeStructVariant = Impossible<Self::Ok, Self::Error>;
+
+ fn serialize_bool(self, v: bool) -> Result<Self::Ok> {
+ self.characters(&v.to_string())
+ }
+
+ fn serialize_i8(self, v: i8) -> Result<Self::Ok> {
+ self.serialize_i64(i64::from(v))
+ }
+
+ fn serialize_i16(self, v: i16) -> Result<Self::Ok> {
+ self.serialize_i64(i64::from(v))
+ }
+
+ fn serialize_i32(self, v: i32) -> Result<Self::Ok> {
+ self.serialize_i64(i64::from(v))
+ }
+
+ fn serialize_i64(self, v: i64) -> Result<Self::Ok> {
+ self.characters(&v.to_string())
+ }
+
+ fn serialize_u8(self, v: u8) -> Result<Self::Ok> {
+ self.serialize_u64(u64::from(v))
+ }
+
+ fn serialize_u16(self, v: u16) -> Result<Self::Ok> {
+ self.serialize_u64(u64::from(v))
+ }
+
+ fn serialize_u32(self, v: u32) -> Result<Self::Ok> {
+ self.serialize_u64(u64::from(v))
+ }
+
+ fn serialize_u64(self, v: u64) -> Result<Self::Ok> {
+ self.characters(&v.to_string())
+ }
+
+ fn serialize_f32(self, v: f32) -> Result<Self::Ok> {
+ self.serialize_f64(f64::from(v))
+ }
+
+ fn serialize_f64(self, v: f64) -> Result<Self::Ok> {
+ self.characters(&v.to_string())
+ }
+
+ fn serialize_char(self, v: char) -> Result<Self::Ok> {
+ self.characters(&v.to_string())
+ }
+
+ fn serialize_str(self, v: &str) -> Result<Self::Ok> {
+ self.characters(v)
+ }
+
+ fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok> {
+ unimplemented!()
+ }
+
+ fn serialize_none(self) -> Result<Self::Ok> {
+ unimplemented!()
+ }
+
+ fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<Self::Ok>
+ where
+ T: Serialize,
+ {
+ unimplemented!()
+ }
+
+ fn serialize_unit(self) -> Result<Self::Ok> {
+ unimplemented!()
+ }
+
+ fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok> {
+ unimplemented!()
+ }
+
+ fn serialize_unit_variant(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str,
+ ) -> Result<Self::Ok> {
+ unimplemented!()
+ }
+
+ fn serialize_newtype_struct<T: ?Sized>(
+ self,
+ _name: &'static str,
+ _value: &T,
+ ) -> Result<Self::Ok>
+ where
+ T: Serialize,
+ {
+ unimplemented!()
+ }
+
+ fn serialize_newtype_variant<T: ?Sized>(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str,
+ _value: &T,
+ ) -> Result<Self::Ok>
+ where
+ T: Serialize,
+ {
+ unimplemented!()
+ }
+
+ fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
+ unimplemented!()
+ }
+
+ fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
+ unimplemented!()
+ }
+
+ fn serialize_tuple_struct(
+ self,
+ _name: &'static str,
+ _len: usize,
+ ) -> Result<Self::SerializeTupleStruct> {
+ unimplemented!()
+ }
+
+ fn serialize_tuple_variant(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str,
+ _len: usize,
+ ) -> Result<Self::SerializeTupleVariant> {
+ unimplemented!()
+ }
+
+ fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
+ unimplemented!()
+ }
+
+ fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
+ unimplemented!()
+ }
+
+ fn serialize_struct_variant(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str,
+ _len: usize,
+ ) -> Result<Self::SerializeStructVariant> {
+ unimplemented!()
+ }
+}
diff --git a/src/ser/seq.rs b/src/ser/seq.rs
new file mode 100644
index 0000000..1681534
--- /dev/null
+++ b/src/ser/seq.rs
@@ -0,0 +1,37 @@
+use super::Serializer;
+use crate::error::{Error, Result};
+use serde::ser::Serialize;
+use std::io::Write;
+
+pub struct SeqSeralizer<'ser, W: 'ser + Write> {
+ ser: &'ser mut Serializer<W>,
+}
+
+impl<'ser, W: 'ser + Write> SeqSeralizer<'ser, W> {
+ pub fn new(ser: &'ser mut Serializer<W>) -> Self {
+ SeqSeralizer { ser }
+ }
+}
+
+impl<'ser, W: 'ser + Write> serde::ser::SerializeSeq for SeqSeralizer<'ser, W> {
+ type Ok = ();
+ type Error = Error;
+
+ fn serialize_element<T>(&mut self, value: &T) -> Result<()>
+ where
+ T: ?Sized + Serialize,
+ {
+ let must_close_tag = self.ser.build_start_tag()?;
+ value.serialize(&mut *self.ser)?;
+ if must_close_tag {
+ self.ser.end_tag()?;
+ self.ser.reopen_tag()?;
+ }
+ Ok(())
+ }
+
+ fn end(self) -> Result<()> {
+ self.ser.abandon_tag()?;
+ Ok(())
+ }
+}
diff --git a/src/ser/tuple.rs b/src/ser/tuple.rs
new file mode 100644
index 0000000..3d893f8
--- /dev/null
+++ b/src/ser/tuple.rs
@@ -0,0 +1,91 @@
+use std::io::Write;
+
+use serde::ser::Serialize;
+
+use super::Serializer;
+use crate::error::{Error, Result};
+
+pub struct TupleSerializer<'ser, W: 'ser + Write> {
+ ser: &'ser mut Serializer<W>,
+ must_close_tag: bool,
+ first: bool,
+}
+
+impl<'ser, W: 'ser + Write> TupleSerializer<'ser, W> {
+ pub fn new(ser: &'ser mut Serializer<W>, must_close_tag: bool) -> Self {
+ Self {
+ ser,
+ must_close_tag,
+ first: true,
+ }
+ }
+
+ fn serialize_item<T>(&mut self, value: &T) -> Result<()>
+ where
+ T: ?Sized + Serialize,
+ {
+ if self.first {
+ self.first = false;
+ } else {
+ self.ser.characters(" ")?;
+ }
+ value.serialize(&mut *self.ser)?;
+ Ok(())
+ }
+
+ fn after_items(self) -> Result<()> {
+ if self.must_close_tag {
+ self.ser.end_tag()?;
+ }
+ Ok(())
+ }
+}
+
+impl<'ser, W: 'ser + Write> serde::ser::SerializeTupleVariant for TupleSerializer<'ser, W> {
+ type Ok = ();
+ type Error = Error;
+
+ fn serialize_field<T>(&mut self, value: &T) -> Result<()>
+ where
+ T: ?Sized + Serialize,
+ {
+ self.serialize_item(value)
+ }
+
+ fn end(self) -> Result<()> {
+ self.ser.end_tag()?;
+ self.after_items()
+ }
+}
+
+impl<'ser, W: 'ser + Write> serde::ser::SerializeTupleStruct for TupleSerializer<'ser, W> {
+ type Ok = ();
+ type Error = Error;
+
+ fn serialize_field<T>(&mut self, value: &T) -> Result<()>
+ where
+ T: ?Sized + Serialize,
+ {
+ self.serialize_item(value)
+ }
+
+ fn end(self) -> Result<()> {
+ self.after_items()
+ }
+}
+
+impl<'ser, W: 'ser + Write> serde::ser::SerializeTuple for TupleSerializer<'ser, W> {
+ type Ok = ();
+ type Error = Error;
+
+ fn serialize_element<T>(&mut self, value: &T) -> Result<()>
+ where
+ T: ?Sized + Serialize,
+ {
+ self.serialize_item(value)
+ }
+
+ fn end(self) -> Result<()> {
+ self.after_items()
+ }
+}
diff --git a/src/ser/var.rs b/src/ser/var.rs
deleted file mode 100644
index e4ee0f0..0000000
--- a/src/ser/var.rs
+++ /dev/null
@@ -1,103 +0,0 @@
-use std::io::Write;
-
-use serde::ser::{self, Serialize};
-
-use crate::error::{Error, Result};
-use crate::ser::Serializer;
-
-/// An implementation of `SerializeMap` for serializing to XML.
-pub struct Map<'w, W>
-where
- W: Write,
-{
- parent: &'w mut Serializer<W>,
-}
-
-impl<'w, W> Map<'w, W>
-where
- W: 'w + Write,
-{
- pub fn new(parent: &'w mut Serializer<W>) -> Map<'w, W> {
- Map { parent }
- }
-}
-
-impl<'w, W> ser::SerializeMap for Map<'w, W>
-where
- W: 'w + Write,
-{
- type Ok = ();
- type Error = Error;
-
- fn serialize_key<T: ?Sized + Serialize>(&mut self, _: &T) -> Result<()> {
- panic!("impossible to serialize the key on its own, please use serialize_entry()")
- }
-
- fn serialize_value<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
- value.serialize(&mut *self.parent)
- }
-
- fn end(self) -> Result<Self::Ok> {
- Ok(())
- }
-
- fn serialize_entry<K: ?Sized + Serialize, V: ?Sized + Serialize>(
- &mut self,
- key: &K,
- value: &V,
- ) -> Result<()> {
- // TODO: Is it possible to ensure our key is never a composite type?
- // Anything which isn't a "primitive" would lead to malformed XML here...
- write!(self.parent.writer, "<")?;
- key.serialize(&mut *self.parent)?;
- write!(self.parent.writer, ">")?;
-
- value.serialize(&mut *self.parent)?;
-
- write!(self.parent.writer, "</")?;
- key.serialize(&mut *self.parent)?;
- write!(self.parent.writer, ">")?;
- Ok(())
- }
-}
-
-/// An implementation of `SerializeStruct` for serializing to XML.
-pub struct Struct<'w, W>
-where
- W: Write,
-{
- parent: &'w mut Serializer<W>,
- name: &'w str,
-}
-
-impl<'w, W> Struct<'w, W>
-where
- W: 'w + Write,
-{
- pub fn new(parent: &'w mut Serializer<W>, name: &'w str) -> Struct<'w, W> {
- Struct { parent, name }
- }
-}
-
-impl<'w, W> ser::SerializeStruct for Struct<'w, W>
-where
- W: 'w + Write,
-{
- type Ok = ();
- type Error = Error;
-
- fn serialize_field<T: ?Sized + Serialize>(
- &mut self,
- key: &'static str,
- value: &T,
- ) -> Result<()> {
- write!(self.parent.writer, "<{}>", key)?;
- value.serialize(&mut *self.parent)?;
- write!(self.parent.writer, "</{}>", key)?;
- Ok(())
- }
-
- fn end(self) -> Result<Self::Ok> {
- write!(self.parent.writer, "</{}>", self.name).map_err(|e| e.into())
- }
-}