Snap for 10453563 from 565b261de703fafd39a79daf05d39926b3998e89 to mainline-ipsec-release

Change-Id: I7dadc35273eb84f6e022ec5d79457b10986d8d3b
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 61ebbbd..1c94bec 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
 {
   "git": {
-    "sha1": "2a13dbd3f6ae77e67d7d329e7fce0b66f2d16d05"
-  }
-}
+    "sha1": "920e54d059efe1dce4cef7f9728ef70e9d47b7b9"
+  },
+  "path_in_vcs": ""
+}
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 7d1bd7b..3a2d26c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -20,11 +20,10 @@
 
 rust_library {
     name: "libserde_xml_rs",
-    // has rustc warnings
     host_supported: true,
     crate_name: "serde_xml_rs",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.5.1",
+    cargo_pkg_version: "0.6.0",
     srcs: ["src/lib.rs"],
     edition: "2018",
     rustlibs: [
@@ -37,15 +36,16 @@
         "//apex_available:platform",
         "com.android.virt",
     ],
+    product_available: true,
+    vendor_available: true,
 }
 
 rust_test {
     name: "serde-xml-rs_test_src_lib",
-    // has rustc warnings
     host_supported: true,
     crate_name: "serde_xml_rs",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.5.1",
+    cargo_pkg_version: "0.6.0",
     srcs: ["src/lib.rs"],
     test_suites: ["general-tests"],
     auto_gen_config: true,
@@ -59,5 +59,4 @@
         "libthiserror",
         "libxml_rust",
     ],
-    proc_macros: ["libserde_derive"],
 }
diff --git a/Cargo.toml b/Cargo.toml
index 08bafe4..a642a06 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,11 +12,13 @@
 [package]
 edition = "2018"
 name = "serde-xml-rs"
-version = "0.5.1"
+version = "0.6.0"
 authors = ["Ingvar Stepanyan <me@rreverser.com>"]
 description = "xml-rs based deserializer for Serde (compatible with 0.9+)"
+readme = "README.md"
 license = "MIT"
 repository = "https://github.com/RReverser/serde-xml-rs"
+
 [dependencies.log]
 version = "0.4"
 
@@ -28,11 +30,16 @@
 
 [dependencies.xml-rs]
 version = "0.8"
+
 [dev-dependencies.docmatic]
 version = "0.1"
 
-[dev-dependencies.serde_derive]
+[dev-dependencies.rstest]
+version = "0.12"
+
+[dev-dependencies.serde]
 version = "1.0"
+features = ["derive"]
 
 [dev-dependencies.simple_logger]
-version = "1.0"
+version = "2.1"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 09ea859..1a4a29d 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -4,7 +4,7 @@
 license = "MIT"
 name = "serde-xml-rs"
 repository = "https://github.com/RReverser/serde-xml-rs"
-version = "0.5.1"
+version = "0.6.0"
 edition = "2018"
 
 [dependencies]
@@ -14,6 +14,7 @@
 thiserror = "1.0"
 
 [dev-dependencies]
-serde_derive = "1.0"
-simple_logger = "1.0"
+serde = { version = "1.0", features = ["derive"] }
+simple_logger = "2.1"
 docmatic = "0.1"
+rstest = "0.12"
diff --git a/METADATA b/METADATA
index 2a22775..b1016df 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,7 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update rust/crates/serde-xml-rs
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+
 name: "serde-xml-rs"
 description: "xml-rs based deserializer for Serde (compatible with 0.9+)"
 third_party {
@@ -7,13 +11,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/serde-xml-rs/serde-xml-rs-0.5.1.crate"
+    value: "https://static.crates.io/crates/serde-xml-rs/serde-xml-rs-0.6.0.crate"
   }
-  version: "0.5.1"
+  version: "0.6.0"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2021
-    month: 9
-    day: 28
+    year: 2022
+    month: 12
+    day: 19
   }
 }
diff --git a/README.md b/README.md
index ba23d1e..80ac31e 100644
--- a/README.md
+++ b/README.md
@@ -7,8 +7,7 @@
 ## Example usage
 
 ```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)]
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 019c527..1564ca8 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,19 +1,18 @@
 // Generated by update_crate_tests.py for tests that depend on this crate.
 {
+  "imports": [
+    {
+      "path": "packages/modules/Virtualization/virtualizationmanager"
+    }
+  ],
   "presubmit": [
     {
       "name": "serde-xml-rs_test_src_lib"
-    },
-    {
-      "name": "virtualizationservice_device_test"
     }
   ],
   "presubmit-rust": [
     {
       "name": "serde-xml-rs_test_src_lib"
-    },
-    {
-      "name": "virtualizationservice_device_test"
     }
   ]
 }
diff --git a/cargo2android.json b/cargo2android.json
index d735201..3223434 100644
--- a/cargo2android.json
+++ b/cargo2android.json
@@ -5,15 +5,17 @@
   ],
   "dependency-blocklist": [
     "docmatic",
+    "rstest",
     "simple_logger"
   ],
   "device": true,
   "run": true,
   "test-blocklist": [
+    "tests/datatypes.rs",
     "tests/failures.rs",
     "tests/migrated.rs",
     "tests/round_trip.rs",
     "tests/test.rs"
   ],
   "tests": true
-}
\ No newline at end of file
+}
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 @@
 /// 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 @@
 /// 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 @@
     /// 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 @@
     fn peek(&mut self) -> Result<&XmlEvent> {
         let peeked = self.buffered_reader.peek()?;
 
-        debug!("Peeked {:?}", peeked);
+        trace!("Peeked {:?}", peeked);
         Ok(peeked)
     }
 
@@ -181,7 +171,7 @@
             }
             _ => {}
         }
-        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 @@
         #[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;
+mod map;
+mod plain;
+mod seq;
+mod tuple;
 
-use serde::ser::{self, Impossible, Serialize};
-
-use self::var::{Map, Struct};
+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 @@
 /// # 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 @@
 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,
 {
-    pub fn new(writer: W) -> Self {
-        Self { writer: writer }
-    }
-
-    fn write_primitive<P: Display>(&mut self, primitive: P) -> Result<()> {
-        write!(self.writer, "{}", primitive)?;
-        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)?;
-        Ok(())
-    }
-}
-
-#[allow(unused_variables)]
-impl<'w, W> ser::Serializer for &'w mut Serializer<W>
-where
-    W: Write,
-{
-    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>;
-
-    fn serialize_bool(self, v: bool) -> Result<Self::Ok> {
-        if v {
-            write!(self.writer, "true")?;
-        } else {
-            write!(self.writer, "false")?;
+    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::new_from_writer(EmitterConfig::new().create_writer(writer))
+    }
+
+    fn next(&mut self, event: XmlEvent) -> Result<()> {
+        self.writer.write(event)?;
         Ok(())
     }
 
-    fn serialize_i8(self, v: i8) -> Result<Self::Ok> {
-        self.write_primitive(v)
+    fn characters(&mut self, s: &str) -> Result<()> {
+        self.next(XmlEvent::characters(s))
     }
 
-    fn serialize_i16(self, v: i16) -> Result<Self::Ok> {
-        self.write_primitive(v)
-    }
-
-    fn serialize_i32(self, v: i32) -> Result<Self::Ok> {
-        self.write_primitive(v)
-    }
-
-    fn serialize_i64(self, v: i64) -> Result<Self::Ok> {
-        self.write_primitive(v)
-    }
-
-    fn serialize_u8(self, v: u8) -> Result<Self::Ok> {
-        self.write_primitive(v)
-    }
-
-    fn serialize_u16(self, v: u16) -> Result<Self::Ok> {
-        self.write_primitive(v)
-    }
-
-    fn serialize_u32(self, v: u32) -> Result<Self::Ok> {
-        self.write_primitive(v)
-    }
-
-    fn serialize_u64(self, v: u64) -> Result<Self::Ok> {
-        self.write_primitive(v)
-    }
-
-    fn serialize_f32(self, v: f32) -> Result<Self::Ok> {
-        self.write_primitive(v)
-    }
-
-    fn serialize_f64(self, v: f64) -> Result<Self::Ok> {
-        self.write_primitive(v)
-    }
-
-    fn serialize_char(self, v: char) -> Result<Self::Ok> {
-        self.write_primitive(v)
-    }
-
-    fn serialize_str(self, value: &str) -> Result<Self::Ok> {
-        self.write_primitive(value)
-    }
-
-    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 start_document(&mut self) -> Result<()> {
+        self.next(XmlEvent::StartDocument {
+            encoding: Default::default(),
+            standalone: Default::default(),
+            version: xml::common::XmlVersion::Version10,
         })
     }
 
-    fn serialize_none(self) -> Result<Self::Ok> {
+    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 serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Self::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()
+    }
+}
+
+impl<'ser, W: Write> serde::ser::Serializer for &'ser mut Serializer<W> {
+    type Ok = ();
+    type Error = 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> {
+        self.serialize_str(&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.serialize_str(&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> {
+        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.serialize_f64(f64::from(v))
+    }
+
+    fn serialize_f64(self, v: f64) -> Result<Self::Ok> {
+        self.serialize_str(&v.to_string())
+    }
+
+    fn serialize_char(self, v: char) -> Result<Self::Ok> {
+        self.serialize_str(&v.to_string())
+    }
+
+    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, _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>(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 @@
             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 @@
     }
 
     #[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 @@
         }
 
         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 @@
         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())
-    }
-}
diff --git a/tests/common/mod.rs b/tests/common/mod.rs
new file mode 100644
index 0000000..26a82e4
--- /dev/null
+++ b/tests/common/mod.rs
@@ -0,0 +1,5 @@
+use simple_logger::SimpleLogger;
+
+pub fn init_logger() {
+    let _ = SimpleLogger::new().with_utc_timestamps().init();
+}
diff --git a/tests/datatypes.rs b/tests/datatypes.rs
new file mode 100644
index 0000000..60410c4
--- /dev/null
+++ b/tests/datatypes.rs
@@ -0,0 +1,149 @@
+pub use rstest::{fixture, rstest};
+use simple_logger::SimpleLogger;
+use std::fmt::Debug;
+
+#[fixture]
+fn logger() {
+    let _ = SimpleLogger::new().init();
+}
+
+mod de {
+    use super::*;
+    use serde::Deserialize;
+    use serde_xml_rs::from_str;
+
+    #[rstest]
+    #[case::string("<bla>This is a String</bla>", "This is a String".to_string())]
+    #[case::string("<bla></bla>", "".to_string())]
+    #[case::string("<bla>    </bla>", "".to_string())]
+    #[case::string("<bla>&lt;boom/&gt;</bla>", "<boom/>".to_string())]
+    #[case::string("<bla>&#9835;</bla>", "♫".to_string())]
+    #[case::string("<bla>&#x266B;</bla>", "♫".to_string())]
+    #[case::string("<bla>♫<![CDATA[<cookies/>]]>♫</bla>", "♫<cookies/>♫".to_string())]
+    #[case::i64("<bla>0</bla>", 0i64)]
+    #[case::i64("<bla>-2</bla>", -2i64)]
+    #[case::i64("<bla>-1234</bla>", -1234i64)]
+    #[case::i64("<bla> -1234 </bla>", -1234i64)]
+    #[case::u64("<bla>0</bla>", 0u64)]
+    #[case::u64("<bla>1234</bla>", 1234u64)]
+    #[case::u64("<bla> 1234 </bla>", 1234u64)]
+    #[case::bool("<bla>true</bla>", true)]
+    #[case::bool("<bla>false</bla>", false)]
+    #[case::unit("<bla/>", ())]
+    #[case::f64("<bla>3.0</bla>", 3.0f64)]
+    #[case::f64("<bla>3.1</bla>", 3.1f64)]
+    #[case::f64("<bla>-1.2</bla>", -1.2f64)]
+    #[case::f64("<bla>0.4</bla>", 0.4f64)]
+    #[case::f64("<bla>0.4e5</bla>", 0.4e5f64)]
+    #[case::f64("<bla>0.4e15</bla>", 0.4e15f64)]
+    #[case::f64_precision_troubles("<bla>0.4e-01</bla>", 0.4e-01f64)]
+    #[case::f64("<bla> 0.4e-01 </bla>", 0.4e-01f64)]
+    #[case::option("<bla/>", Some("".to_string()))]
+    #[case::option("<bla></bla>", Some("".to_string()))]
+    #[case::option("<bla> </bla>", Some("".to_string()))]
+    #[case::option("<bla>42</bla>", Some("42".to_string()))]
+    fn element_ok<T, 'de>(_logger: (), #[case] document: &str, #[case] expected: T)
+    where
+        T: Deserialize<'de> + Debug + PartialEq,
+    {
+        let actual: T = from_str(document).unwrap();
+        assert_eq!(actual, expected);
+    }
+
+    #[rstest]
+    #[case("<bla>verum</bla>", Some(true))]
+    fn element_ko<T, 'de>(_logger: (), #[case] document: &str, #[case] _type: Option<T>)
+    where
+        T: Deserialize<'de> + Debug + PartialEq,
+    {
+        let actual: Result<T, _> = from_str(document);
+        assert!(actual.is_err());
+    }
+
+    #[derive(PartialEq, Debug, Deserialize)]
+    struct DummyAttribute<T> {
+        foo: T,
+    }
+
+    #[rstest]
+    #[case(r#"<bla foo="true"/>"#, DummyAttribute { foo: true })]
+    #[case(r#"<bla foo="false"/>"#, DummyAttribute { foo: false })]
+    #[case(r#"<bla foo="1"/>"#, DummyAttribute { foo: true })]
+    #[case(r#"<bla foo="0"/>"#, DummyAttribute { foo: false })]
+    fn attribute_ok<T, 'de>(_logger: (), #[case] document: &str, #[case] expected: T)
+    where
+        T: Deserialize<'de> + Debug + PartialEq,
+    {
+        let actual: T = from_str(document).unwrap();
+        assert_eq!(actual, expected);
+    }
+}
+
+mod ser {
+    use super::*;
+    use serde::{self, Serialize};
+    use serde_xml_rs::to_string;
+
+    #[derive(Serialize, Debug)]
+    #[serde(rename = "bla")]
+    struct Dummy<T> {
+        #[serde(rename = "$value")]
+        value: T,
+    }
+
+    #[rstest]
+    #[case::string("<bla>This is a String</bla>", "This is a String".to_string())]
+    #[case::string("<bla></bla>", "".to_string())]
+    #[case::string("<bla>&lt;boom/></bla>", "<boom/>".to_string())]
+    #[case::string("<bla>♫</bla>", "♫".to_string())]
+    #[case::string("<bla>♫&lt;cookies/>♫</bla>", "♫<cookies/>♫".to_string())]
+    #[case::i64("<bla>0</bla>", 0i64)]
+    #[case::i64("<bla>-2</bla>", -2i64)]
+    #[case::i64("<bla>-1234</bla>", -1234i64)]
+    #[case::u64("<bla>0</bla>", 0u64)]
+    #[case::u64("<bla>1234</bla>", 1234u64)]
+    #[case::bool("<bla>true</bla>", true)]
+    #[case::bool("<bla>false</bla>", false)]
+    #[case::unit("<bla />", ())]
+    #[case::f64("<bla>3</bla>", 3.0f64)]
+    #[case::f64("<bla>3.1</bla>", 3.1f64)]
+    #[case::f64("<bla>-1.2</bla>", -1.2f64)]
+    #[case::f64("<bla>0.4</bla>", 0.4f64)]
+    #[case::f64("<bla>40000</bla>", 0.4e5f64)]
+    #[case::f64("<bla>400000000000000</bla>", 0.4e15f64)]
+    #[case::f64_precision_troubles("<bla>0.04</bla>", 0.4e-01f64)]
+    #[case::option("<bla></bla>", Some("".to_string()))]
+    #[case::option("<bla>42</bla>", Some("42".to_string()))]
+    fn element_ok<T>(_logger: (), #[case] expected: &str, #[case] value: T)
+    where
+        T: Serialize + Debug,
+    {
+        let actual = to_string(&Dummy { value }).unwrap();
+        assert_eq!(
+            actual,
+            format!(r#"<?xml version="1.0" encoding="UTF-8"?>{}"#, expected)
+        );
+    }
+
+    #[derive(Serialize, Debug)]
+    #[serde(rename = "bla")]
+    struct DummyAttribute<T> {
+        #[serde(rename = "@value")]
+        value: T,
+    }
+
+    #[rstest]
+    #[case::string(r#"<bla value="" />"#, "".to_string())]
+    #[case::bool(r#"<bla value="true" />"#, true)]
+    #[case::bool(r#"<bla value="false" />"#, false)]
+    fn attribute_ok<T>(_logger: (), #[case] expected: &str, #[case] value: T)
+    where
+        T: Serialize + Debug,
+    {
+        let actual = to_string(&DummyAttribute { value }).unwrap();
+        assert_eq!(
+            actual,
+            format!(r#"<?xml version="1.0" encoding="UTF-8"?>{}"#, expected)
+        );
+    }
+}
diff --git a/tests/failures.rs b/tests/failures.rs
index 7a55811..89ac200 100644
--- a/tests/failures.rs
+++ b/tests/failures.rs
@@ -1,11 +1,9 @@
-use log::info;
-use serde_derive::Deserialize;
-use serde_xml_rs::from_str;
-use simple_logger::SimpleLogger;
+mod common;
 
-fn init_logger() {
-    let _ = SimpleLogger::new().init();
-}
+use common::init_logger;
+use log::info;
+use serde::Deserialize;
+use serde_xml_rs::from_str;
 
 #[derive(Debug, Deserialize, PartialEq)]
 struct Item {
diff --git a/tests/migrated.rs b/tests/migrated.rs
index e01d750..c67712e 100644
--- a/tests/migrated.rs
+++ b/tests/migrated.rs
@@ -1,13 +1,9 @@
-use simple_logger::SimpleLogger;
-use std::fmt::Debug;
+mod common;
 
-use serde::{de, ser};
-use serde_derive::{Deserialize, Serialize};
+use common::init_logger;
+use serde::{de, ser, Deserialize, Serialize};
 use serde_xml_rs::{from_str, Error};
-
-fn init_logger() {
-    let _ = SimpleLogger::new().init();
-}
+use std::fmt::Debug;
 
 #[derive(PartialEq, Debug, Serialize, Deserialize)]
 enum Animal {
@@ -66,18 +62,6 @@
     }
 }
 
-fn test_parse_invalid<'de, 'a, T>(errors: &[&'a str])
-where
-    T: PartialEq + Debug + ser::Serialize + de::Deserialize<'de>,
-{
-    for &s in errors {
-        assert!(match from_str::<T>(s) {
-            Err(_) => true,
-            _ => false,
-        });
-    }
-}
-
 #[test]
 fn test_namespaces() {
     init_logger();
@@ -173,27 +157,6 @@
 }
 
 #[test]
-fn test_parse_string() {
-    init_logger();
-
-    test_parse_ok(&[
-        (
-            "<bla>This is a String</bla>",
-            "This is a String".to_string(),
-        ),
-        ("<bla></bla>", "".to_string()),
-        ("<bla>     </bla>", "".to_string()),
-        ("<bla>&lt;boom/&gt;</bla>", "<boom/>".to_string()),
-        ("<bla>&#9835;</bla>", "♫".to_string()),
-        ("<bla>&#x266B;</bla>", "♫".to_string()),
-        (
-            "<bla>♫<![CDATA[<cookies/>]]>♫</bla>",
-            "♫<cookies/>♫".to_string(),
-        ),
-    ]);
-}
-
-#[test]
 #[ignore] // FIXME
 fn test_parse_string_not_trim() {
     init_logger();
@@ -269,87 +232,6 @@
 }
 
 #[test]
-fn test_parse_i64() {
-    init_logger();
-    test_parse_ok(&[
-        ("<bla>0</bla>", 0),
-        ("<bla>-2</bla>", -2),
-        ("<bla>-1234</bla>", -1234),
-        ("<bla> -1234 </bla>", -1234),
-    ]);
-}
-
-#[test]
-fn test_parse_u64() {
-    init_logger();
-    test_parse_ok(&[
-        ("<bla>0</bla>", 0),
-        ("<bla>1234</bla>", 1234),
-        ("<bla> 1234 </bla>", 1234),
-    ]);
-}
-
-#[test]
-fn test_parse_bool_element() {
-    init_logger();
-    test_parse_ok(&[
-        ("<bla>true</bla>", true),
-        ("<bla>false</bla>", false),
-        ("<bla> true </bla>", true),
-        ("<bla> false </bla>", false),
-        ("<bla>1</bla>", true),
-        ("<bla>0</bla>", false),
-    ]);
-
-    test_parse_invalid::<bool>(&["<bla>verum</bla>"]);
-}
-
-#[test]
-fn test_parse_bool_attribute() {
-    #[derive(PartialEq, Debug, Deserialize, Serialize)]
-    struct Dummy {
-        foo: bool,
-    }
-
-    init_logger();
-    test_parse_ok(&[
-        ("<bla foo=\"true\"/>", Dummy { foo: true }),
-        ("<bla foo=\"false\"/>", Dummy { foo: false }),
-        ("<bla foo=\"1\"/>", Dummy { foo: true }),
-        ("<bla foo=\"0\"/>", Dummy { foo: false }),
-    ]);
-
-    test_parse_invalid::<Dummy>(&[
-        "<bla foo=\"bar\"/>",
-        "<bla foo=\" true \"/>",
-        "<bla foo=\"10\"/>",
-        "<bla foo=\"\"/>",
-        "<bla/>",
-    ]);
-}
-
-#[test]
-fn test_parse_unit() {
-    init_logger();
-    test_parse_ok(&[("<bla/>", ())]);
-}
-
-#[test]
-fn test_parse_f64() {
-    init_logger();
-    test_parse_ok(&[
-        ("<bla>3.0</bla>", 3.0f64),
-        ("<bla>3.1</bla>", 3.1),
-        ("<bla>-1.2</bla>", -1.2),
-        ("<bla>0.4</bla>", 0.4),
-        ("<bla>0.4e5</bla>", 0.4e5),
-        ("<bla>0.4e15</bla>", 0.4e15),
-        ("<bla>0.4e-01</bla>", 0.4e-01), // precision troubles
-        ("<bla> 0.4e-01 </bla>", 0.4e-01),
-    ]);
-}
-
-#[test]
 fn test_parse_struct() {
     init_logger();
 
@@ -397,17 +279,6 @@
 }
 
 #[test]
-fn test_option() {
-    init_logger();
-    test_parse_ok(&[
-        ("<a/>", Some("".to_string())),
-        ("<a></a>", Some("".to_string())),
-        ("<a> </a>", Some("".to_string())),
-        ("<a>42</a>", Some("42".to_string())),
-    ]);
-}
-
-#[test]
 #[ignore] // FIXME
 fn test_option_not_trim() {
     init_logger();
@@ -976,12 +847,12 @@
     #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)]
     struct Object {
         field: Option<Null>,
-    };
+    }
 
     #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)]
     struct Stuff {
         stuff_field: Option<Object>,
-    };
+    }
 
     test_parse_ok(&[
         (
diff --git a/tests/round_trip.rs b/tests/round_trip.rs
index 450a4b5..65c84ae 100644
--- a/tests/round_trip.rs
+++ b/tests/round_trip.rs
@@ -1,5 +1,4 @@
-use serde::Deserialize;
-use serde_derive::{Deserialize, Serialize};
+use serde::{Deserialize, Serialize};
 use serde_xml_rs::{self, from_str, to_string, EventReader, ParserConfig};
 
 #[derive(Debug, Serialize, Deserialize, PartialEq)]
@@ -23,7 +22,7 @@
 
 #[test]
 fn basic_struct() {
-    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(),
@@ -37,7 +36,6 @@
 }
 
 #[test]
-#[ignore]
 fn round_trip_list_of_enums() {
     // Construct some inputs
     let nodes = Nodes {
@@ -51,17 +49,7 @@
         ],
     };
 
-    let should_be = r#"
-    <Nodes>
-        <Boolean>
-            true
-        </Boolean>
-        <Identifier>
-            <value>foo</value>
-            <index>5</index>
-        </Identifier>
-        <EOF />
-    </Nodes>"#;
+    let should_be = r#"<?xml version="1.0" encoding="UTF-8"?><Nodes><Boolean>true</Boolean><Identifier><value>foo</value><index>5</index></Identifier><EOF /></Nodes>"#;
 
     let serialized_nodes = to_string(&nodes).unwrap();
     assert_eq!(serialized_nodes, should_be);
@@ -77,6 +65,7 @@
     // Test a configuration which does not clip whitespace from tags
 
     let src = r#"
+    <?xml version="1.0" encoding="UTF-8"?>
     <Item>
         <name>  space banana  </name>
         <source>   fantasy costco   </source>
@@ -97,7 +86,7 @@
 
     // Space outside values is not preserved.
     let serialized_should_be =
-        "<Item><name>  space banana  </name><source>   fantasy costco   </source></Item>";
+        "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Item><name>  space banana  </name><source>   fantasy costco   </source></Item>";
     let reserialized_item = to_string(&item).unwrap();
     assert_eq!(reserialized_item, serialized_should_be);
 }
diff --git a/tests/test.rs b/tests/test.rs
index 52075b1..aa93df6 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,11 +1,8 @@
-use serde::Deserialize;
-use serde_derive::Deserialize;
-use serde_xml_rs::{from_str, Deserializer};
-use simple_logger::SimpleLogger;
+mod common;
 
-fn init_logger() {
-    let _ = SimpleLogger::new().init();
-}
+use common::init_logger;
+use serde::Deserialize;
+use serde_xml_rs::{from_str, Deserializer};
 
 #[derive(Debug, Deserialize, PartialEq)]
 struct Item {