Upgrade rust/crates/serde-xml-rs to 0.5.1

Test: make
Change-Id: Ie318442be54fb52a5203d28496b2a0327f835201
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
new file mode 100644
index 0000000..61ebbbd
--- /dev/null
+++ b/.cargo_vcs_info.json
@@ -0,0 +1,5 @@
+{
+  "git": {
+    "sha1": "2a13dbd3f6ae77e67d7d329e7fce0b66f2d16d05"
+  }
+}
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
new file mode 100644
index 0000000..6f26d5c
--- /dev/null
+++ b/.github/workflows/lint.yml
@@ -0,0 +1,55 @@
+on:
+  push:
+    branches: [ master ]
+  pull_request:
+    branches: [ master ]
+
+
+name: Lint
+
+jobs:
+  check:
+    name: Check
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: actions-rs/toolchain@v1
+        with:
+          profile: minimal
+          toolchain: stable
+          override: true
+      - uses: actions-rs/cargo@v1
+        with:
+          command: check
+
+  fmt:
+    name: Format
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: actions-rs/toolchain@v1
+        with:
+          profile: minimal
+          toolchain: stable
+          override: true
+      - run: rustup component add rustfmt
+      - uses: actions-rs/cargo@v1
+        with:
+          command: fmt
+          args: --all -- --check
+
+  clippy:
+    name: Clippy
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: actions-rs/toolchain@v1
+        with:
+          toolchain: stable
+          components: clippy
+          override: true
+      - uses: actions-rs/clippy-check@v1
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          args: --all-features
+          name: Clippy Output
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
new file mode 100644
index 0000000..3c13d1b
--- /dev/null
+++ b/.github/workflows/rust.yml
@@ -0,0 +1,22 @@
+name: Rust
+
+on:
+  push:
+    branches: [ master ]
+  pull_request:
+    branches: [ master ]
+
+env:
+  CARGO_TERM_COLOR: always
+
+jobs:
+  build:
+
+    runs-on: ubuntu-latest
+
+    steps:
+    - uses: actions/checkout@v2
+    - name: Build
+      run: cargo build --verbose
+    - name: Run tests
+      run: cargo test --verbose
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a9d37c5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+target
+Cargo.lock
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..b866092
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,16 @@
+language: rust
+rust:
+  - stable
+  - beta
+  - nightly
+cache: cargo
+before_cache:
+  - cargo clean -p serde-xml-rs
+  - rm -rf target/
+env:
+  global:
+    - RUST_BACKTRACE=1
+matrix:
+  fast_finish: true
+  allow_failures:
+    - rust: nightly
diff --git a/Android.bp b/Android.bp
index 8816c03..770a90a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,8 +1,6 @@
 // This file is generated by cargo2android.py --config cargo2android.json.
 // Do not modify this file as changes will be overridden on upgrade.
 
-
-
 package {
     default_applicable_licenses: ["external_rust_crates_serde-xml-rs_license"],
 }
@@ -25,8 +23,10 @@
     // has rustc warnings
     host_supported: true,
     crate_name: "serde_xml_rs",
+    cargo_env_compat: true,
+    cargo_pkg_version: "0.5.1",
     srcs: ["src/lib.rs"],
-    edition: "2015",
+    edition: "2018",
     rustlibs: [
         "liblog_rust",
         "libserde",
@@ -44,9 +44,11 @@
     crate_name: "serde_xml_rs",
     // has rustc warnings
     srcs: ["src/lib.rs"],
+    cargo_env_compat: true,
+    cargo_pkg_version: "0.5.1",
     test_suites: ["general-tests"],
     auto_gen_config: true,
-    edition: "2015",
+    edition: "2018",
     rustlibs: [
         "liblog_rust",
         "libserde",
@@ -68,34 +70,3 @@
     name: "serde-xml-rs_device_test_src_lib",
     defaults: ["serde-xml-rs_test_defaults"],
 }
-
-rust_defaults {
-    name: "serde-xml-rs_test_defaults_serde_xml_rs",
-    crate_name: "serde_xml_rs",
-    // has rustc warnings
-    srcs: ["tests/round_trip.rs"],
-    test_suites: ["general-tests"],
-    auto_gen_config: true,
-    edition: "2015",
-    rustlibs: [
-        "liblog_rust",
-        "libserde",
-        "libserde_xml_rs",
-        "libthiserror",
-        "libxml_rust",
-    ],
-    proc_macros: ["libserde_derive"],
-}
-
-rust_test_host {
-    name: "serde-xml-rs_host_test_tests_round_trip",
-    defaults: ["serde-xml-rs_test_defaults_serde_xml_rs"],
-    test_options: {
-        unit_test: true,
-    },
-}
-
-rust_test {
-    name: "serde-xml-rs_device_test_tests_round_trip",
-    defaults: ["serde-xml-rs_test_defaults_serde_xml_rs"],
-}
diff --git a/Cargo.toml b/Cargo.toml
index fa4d9b9..08bafe4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,18 +1,38 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
 [package]
+edition = "2018"
+name = "serde-xml-rs"
+version = "0.5.1"
 authors = ["Ingvar Stepanyan <me@rreverser.com>"]
 description = "xml-rs based deserializer for Serde (compatible with 0.9+)"
 license = "MIT"
-name = "serde-xml-rs"
 repository = "https://github.com/RReverser/serde-xml-rs"
-version = "0.4.1"
+[dependencies.log]
+version = "0.4"
 
-[dependencies]
-log = "0.4"
-serde = "1.0"
-xml-rs = "0.8.0"
-thiserror = "1.0"
+[dependencies.serde]
+version = "1.0"
 
-[dev-dependencies]
-serde_derive = "1.0"
-simple_logger = "1.0.1"
-docmatic = "0.1.2"
+[dependencies.thiserror]
+version = "1.0"
+
+[dependencies.xml-rs]
+version = "0.8"
+[dev-dependencies.docmatic]
+version = "0.1"
+
+[dev-dependencies.serde_derive]
+version = "1.0"
+
+[dev-dependencies.simple_logger]
+version = "1.0"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
new file mode 100644
index 0000000..09ea859
--- /dev/null
+++ b/Cargo.toml.orig
@@ -0,0 +1,19 @@
+[package]
+authors = ["Ingvar Stepanyan <me@rreverser.com>"]
+description = "xml-rs based deserializer for Serde (compatible with 0.9+)"
+license = "MIT"
+name = "serde-xml-rs"
+repository = "https://github.com/RReverser/serde-xml-rs"
+version = "0.5.1"
+edition = "2018"
+
+[dependencies]
+log = "0.4"
+serde = "1.0"
+xml-rs = "0.8"
+thiserror = "1.0"
+
+[dev-dependencies]
+serde_derive = "1.0"
+simple_logger = "1.0"
+docmatic = "0.1"
diff --git a/METADATA b/METADATA
index a1b4d08..2a22775 100644
--- a/METADATA
+++ b/METADATA
@@ -1,17 +1,19 @@
 name: "serde-xml-rs"
-description:
-    "xml-rs based deserializer for Serde"
-
+description: "xml-rs based deserializer for Serde (compatible with 0.9+)"
 third_party {
   url {
     type: HOMEPAGE
     value: "https://crates.io/crates/serde_xml_rs"
   }
   url {
-    type: GIT
-    value: "https://github.com/RReverser/serde-xml-rs"
+    type: ARCHIVE
+    value: "https://static.crates.io/crates/serde-xml-rs/serde-xml-rs-0.5.1.crate"
   }
-  version: "0.4.1"
-  last_upgrade_date { year: 2021 month: 6 day: 21 }
+  version: "0.5.1"
   license_type: NOTICE
-}
\ No newline at end of file
+  last_upgrade_date {
+    year: 2021
+    month: 9
+    day: 28
+  }
+}
diff --git a/README.md b/README.md
index f2e530c..ba23d1e 100644
--- a/README.md
+++ b/README.md
@@ -2,61 +2,32 @@
 
 [![Build Status](https://travis-ci.org/RReverser/serde-xml-rs.svg?branch=master)](https://travis-ci.org/RReverser/serde-xml-rs)
 
-xml-rs based deserializer for Serde (compatible with 0.9+)
+`xml-rs` based deserializer for Serde (compatible with 1.0)
 
-## Usage
-
-Use `serde_xml_rs::from_reader(...)` on any type that implements [`std::io::Read`](https://doc.rust-lang.org/std/io/trait.Read.html) as following:
+## Example usage
 
 ```rust
-#[macro_use]
-extern crate serde_derive;
-extern crate serde;
-extern crate serde_xml_rs;
+use serde;
+use serde_derive::{Deserialize, Serialize};
+use serde_xml_rs::{from_str, to_string};
 
-use serde_xml_rs::from_reader;
-
-#[derive(Debug, Deserialize)]
+#[derive(Debug, Serialize, Deserialize, PartialEq)]
 struct Item {
-    pub name: String,
-    pub source: String
-}
-
-#[derive(Debug, Deserialize)]
-struct Project {
-    pub name: String,
-
-    #[serde(rename = "Item", default)]
-    pub items: Vec<Item>
+    name: String,
+    source: String,
 }
 
 fn main() {
-    let s = r##"
-        <Project name="my_project">
-            <Item name="hello" source="world.rs" />
-        </Project>
-    "##;
-    let project: Project = from_reader(s.as_bytes()).unwrap();
-    println!("{:#?}", project);
+    let src = r#"<Item><name>Banana</name><source>Store</source></Item>"#;
+    let should_be = Item {
+        name: "Banana".to_string(),
+        source: "Store".to_string(),
+    };
+
+    let item: Item = from_str(src).unwrap();
+    assert_eq!(item, should_be);
+
+    let reserialized_item = to_string(&item).unwrap();
+    assert_eq!(src, reserialized_item);
 }
 ```
-
-Alternatively, you can use `serde_xml_rs::Deserializer` to create a deserializer from a preconfigured [`xml_rs::EventReader`](https://netvl.github.io/xml-rs/xml/reader/struct.EventReader.html).
-
-## Parsing the "value" of a tag
-
-If you have an input of the form `<foo abc="xyz">bar</foo>`, and you want to get at the`bar`, you can use the special name `$value`:
-
-```rust,ignore
-struct Foo {
-    pub abc: String,
-    #[serde(rename = "$value")]
-    pub body: String,
-}
-```
-
-## Parsed representations
-
-Deserializer tries to be as intuitive as possible.
-
-However, there are some edge cases where you might get unexpected errors, so it's best to check out [`tests`](tests/test.rs) for expectations.
diff --git a/cargo2android.json b/cargo2android.json
index 7dc0a63..31f8835 100644
--- a/cargo2android.json
+++ b/cargo2android.json
@@ -11,9 +11,9 @@
   "test-blocklist": [
     "tests/failures.rs",
     "tests/migrated.rs",
-    "tests/readme.rs",
+    "tests/round_trip.rs",
     "tests/test.rs"
   ],
   "tests": true,
   "run": true
-}
\ No newline at end of file
+}
diff --git a/rustfmt.toml b/rustfmt.toml
index 8c795ae..e69de29 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -1 +0,0 @@
-match_block_trailing_comma = true
diff --git a/src/de/buffer.rs b/src/de/buffer.rs
new file mode 100644
index 0000000..2760acb
--- /dev/null
+++ b/src/de/buffer.rs
@@ -0,0 +1,169 @@
+use crate::debug_expect;
+use crate::error::Result;
+use std::{collections::VecDeque, io::Read};
+use xml::reader::{EventReader, XmlEvent};
+
+/// Retrieve XML events from an underlying reader.
+pub trait BufferedXmlReader<R: Read> {
+    /// Get and "consume" the next event.
+    fn next(&mut self) -> Result<XmlEvent>;
+
+    /// Get the next event without consuming.
+    fn peek(&mut self) -> Result<&XmlEvent>;
+
+    /// Spawn a child buffer whose cursor starts at the same position as this buffer.
+    fn child_buffer<'a>(&'a mut self) -> ChildXmlBuffer<'a, R>;
+}
+
+pub struct RootXmlBuffer<R: Read> {
+    reader: EventReader<R>,
+    buffer: VecDeque<CachedXmlEvent>,
+}
+
+impl<R: Read> RootXmlBuffer<R> {
+    pub fn new(reader: EventReader<R>) -> Self {
+        RootXmlBuffer {
+            reader,
+            buffer: VecDeque::new(),
+        }
+    }
+}
+
+impl<R: Read> BufferedXmlReader<R> for RootXmlBuffer<R> {
+    /// Consumed XML events in the root buffer are moved to the caller
+    fn next(&mut self) -> Result<XmlEvent> {
+        loop {
+            match self.buffer.pop_front() {
+                Some(CachedXmlEvent::Unused(ev)) => break Ok(ev),
+                Some(CachedXmlEvent::Used) => continue,
+                None => break next_significant_event(&mut self.reader),
+            }
+        }
+    }
+
+    fn peek(&mut self) -> Result<&XmlEvent> {
+        get_from_buffer_or_reader(&mut self.buffer, &mut self.reader, &mut 0)
+    }
+
+    fn child_buffer<'root>(&'root mut self) -> ChildXmlBuffer<'root, R> {
+        let RootXmlBuffer { reader, buffer } = self;
+        ChildXmlBuffer {
+            reader,
+            buffer,
+            cursor: 0,
+        }
+    }
+}
+
+pub struct ChildXmlBuffer<'parent, R: Read> {
+    reader: &'parent mut EventReader<R>,
+    buffer: &'parent mut VecDeque<CachedXmlEvent>,
+    cursor: usize,
+}
+
+impl<'parent, R: Read> ChildXmlBuffer<'parent, R> {
+    /// Advance the child buffer without marking an event as "used"
+    pub fn skip(&mut self) {
+        debug_assert!(
+            self.cursor < self.buffer.len(),
+            ".skip() only should be called after .peek()"
+        );
+
+        self.cursor += 1;
+    }
+}
+
+impl<'parent, R: Read> BufferedXmlReader<R> for ChildXmlBuffer<'parent, R> {
+    /// Consumed XML events in a child buffer are marked as "used"
+    fn next(&mut self) -> Result<XmlEvent> {
+        loop {
+            match self.buffer.get_mut(self.cursor) {
+                Some(entry @ CachedXmlEvent::Unused(_)) => {
+                    let taken = if self.cursor == 0 {
+                        self.buffer.pop_front().unwrap()
+                    } else {
+                        std::mem::replace(entry, CachedXmlEvent::Used)
+                    };
+
+                    return debug_expect!(taken, CachedXmlEvent::Unused(ev) => Ok(ev));
+                }
+                Some(CachedXmlEvent::Used) => {
+                    debug_assert!(
+                        self.cursor != 0,
+                        "Event buffer should not start with 'used' slot (should have been popped)"
+                    );
+                    self.cursor += 1;
+                    continue;
+                }
+                None => {
+                    debug_assert_eq!(self.buffer.len(), self.cursor);
+
+                    // Skip creation of buffer entry when consuming event straight away
+                    return next_significant_event(&mut self.reader);
+                }
+            }
+        }
+    }
+
+    fn peek(&mut self) -> Result<&XmlEvent> {
+        get_from_buffer_or_reader(self.buffer, self.reader, &mut self.cursor)
+    }
+
+    fn child_buffer<'a>(&'a mut self) -> ChildXmlBuffer<'a, R> {
+        let ChildXmlBuffer {
+            reader,
+            buffer,
+            cursor,
+        } = self;
+
+        ChildXmlBuffer {
+            reader,
+            buffer,
+            cursor: *cursor,
+        }
+    }
+}
+
+#[derive(Debug)]
+enum CachedXmlEvent {
+    Unused(XmlEvent),
+    Used,
+}
+
+fn get_from_buffer_or_reader<'buf>(
+    buffer: &'buf mut VecDeque<CachedXmlEvent>,
+    reader: &mut EventReader<impl Read>,
+    index: &mut usize,
+) -> Result<&'buf XmlEvent> {
+    // We should only be attempting to get an event already in the buffer, or the next event to place in the buffer
+    debug_assert!(*index <= buffer.len());
+
+    loop {
+        match buffer.get_mut(*index) {
+            Some(CachedXmlEvent::Unused(_)) => break,
+            Some(CachedXmlEvent::Used) => {
+                *index += 1;
+            }
+            None => {
+                let next = next_significant_event(reader)?;
+                buffer.push_back(CachedXmlEvent::Unused(next));
+            }
+        }
+    }
+
+    // Returning of borrowed data must be done after of loop/match due to current limitation of borrow checker
+    debug_expect!(buffer.get_mut(*index), Some(CachedXmlEvent::Unused(event)) => Ok(event))
+}
+
+/// Reads the next XML event from the underlying reader, skipping events we're not interested in.
+fn next_significant_event(reader: &mut EventReader<impl Read>) -> Result<XmlEvent> {
+    loop {
+        match reader.next()? {
+            XmlEvent::StartDocument { .. }
+            | XmlEvent::ProcessingInstruction { .. }
+            | XmlEvent::Whitespace { .. }
+            | XmlEvent::Comment(_) => { /* skip */ }
+            other => return Ok(other),
+        }
+    }
+}
diff --git a/src/de/map.rs b/src/de/map.rs
index ed1d0bb..0557d5e 100644
--- a/src/de/map.rs
+++ b/src/de/map.rs
@@ -1,57 +1,73 @@
 use std::io::Read;
 
 use serde::de::{self, IntoDeserializer, Unexpected};
+use serde::forward_to_deserialize_any;
 use xml::attribute::OwnedAttribute;
 use xml::reader::XmlEvent;
 
-use Deserializer;
-use error::{Error, Result};
+use crate::error::{Error, Result};
+use crate::Deserializer;
 
-pub struct MapAccess<'a, R: 'a + Read> {
+use super::buffer::BufferedXmlReader;
+
+pub struct MapAccess<'a, R: Read, B: BufferedXmlReader<R>> {
     attrs: ::std::vec::IntoIter<OwnedAttribute>,
-    next_value: Option<String>,
-    de: &'a mut Deserializer<R>,
+    /// Cache of attribute value, populated when visitor calls `next_key_seed`; should be read & emptied straight after
+    /// by visitor call to `next_value_seed`
+    next_attr_value: Option<String>,
+    de: &'a mut Deserializer<R, B>,
+    /// Whether this `MapAccess` is to deserialize all inner contents of an outer element.
     inner_value: bool,
 }
 
-impl<'a, R: 'a + Read> MapAccess<'a, R> {
-    pub fn new(de: &'a mut Deserializer<R>, attrs: Vec<OwnedAttribute>, inner_value: bool) -> Self {
+impl<'a, R: 'a + Read, B: BufferedXmlReader<R>> MapAccess<'a, R, B> {
+    pub fn new(
+        de: &'a mut Deserializer<R, B>,
+        attrs: Vec<OwnedAttribute>,
+        inner_value: bool,
+    ) -> Self {
         MapAccess {
             attrs: attrs.into_iter(),
-            next_value: None,
+            next_attr_value: None,
             de: de,
             inner_value: inner_value,
         }
     }
 }
 
-impl<'de, 'a, R: 'a + Read> de::MapAccess<'de> for MapAccess<'a, R> {
+impl<'de, 'a, R: 'a + Read, B: BufferedXmlReader<R>> de::MapAccess<'de> for MapAccess<'a, R, B> {
     type Error = Error;
 
     fn next_key_seed<K: de::DeserializeSeed<'de>>(&mut self, seed: K) -> Result<Option<K::Value>> {
-        debug_assert_eq!(self.next_value, None);
+        debug_assert_eq!(self.next_attr_value, None);
         match self.attrs.next() {
+            // Read all attributes first
             Some(OwnedAttribute { name, value }) => {
-                self.next_value = Some(value);
+                self.next_attr_value = Some(value);
                 seed.deserialize(name.local_name.into_deserializer())
                     .map(Some)
-            },
+            }
             None => match *self.de.peek()? {
-                XmlEvent::StartElement { ref name, .. } => seed.deserialize(
-                    if !self.inner_value {
-                        name.local_name.as_str()
-                    } else {
-                        "$value"
-                    }.into_deserializer(),
-                ).map(Some),
+                XmlEvent::StartElement { ref name, .. } => seed
+                    .deserialize(
+                        if !self.inner_value {
+                            name.local_name.as_str()
+                        } else {
+                            "$value"
+                        }
+                        .into_deserializer(),
+                    )
+                    .map(Some),
                 XmlEvent::Characters(_) => seed.deserialize("$value".into_deserializer()).map(Some),
+                // Any other event: assume end of map values (actual check for `EndElement` done by the originating
+                // `Deserializer`)
                 _ => Ok(None),
             },
         }
     }
 
     fn next_value_seed<V: de::DeserializeSeed<'de>>(&mut self, seed: V) -> Result<V::Value> {
-        match self.next_value.take() {
+        match self.next_attr_value.take() {
             Some(value) => seed.deserialize(AttrValueDeserializer(value)),
             None => {
                 if !self.inner_value {
@@ -61,7 +77,7 @@
                 }
                 let result = seed.deserialize(&mut *self.de)?;
                 Ok(result)
-            },
+            }
         }
     }
 
@@ -77,7 +93,7 @@
         fn $deserialize<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
             visitor.$visit(self.0.parse()?)
         }
-    }
+    };
 }
 
 impl<'de> de::Deserializer<'de> for AttrValueDeserializer {
@@ -115,7 +131,10 @@
         match self.0.as_str() {
             "true" | "1" => visitor.visit_bool(true),
             "false" | "0" => visitor.visit_bool(false),
-            _ => Err(de::Error::invalid_value(Unexpected::Str(&self.0), &"a boolean")),
+            _ => Err(de::Error::invalid_value(
+                Unexpected::Str(&self.0),
+                &"a boolean",
+            )),
         }
     }
 
diff --git a/src/de/mod.rs b/src/de/mod.rs
index 94077c5..21240c5 100644
--- a/src/de/mod.rs
+++ b/src/de/mod.rs
@@ -1,14 +1,19 @@
-use std::io::Read;
+use std::{io::Read, marker::PhantomData};
 
+use log::debug;
 use serde::de::{self, Unexpected};
+use serde::forward_to_deserialize_any;
 use xml::name::OwnedName;
 use xml::reader::{EventReader, ParserConfig, XmlEvent};
 
+use self::buffer::{BufferedXmlReader, ChildXmlBuffer, RootXmlBuffer};
 use self::map::MapAccess;
 use self::seq::SeqAccess;
 use self::var::EnumAccess;
-use error::{Error, Result};
+use crate::error::{Error, Result};
+use crate::{debug_expect, expect};
 
+mod buffer;
 mod map;
 mod seq;
 mod var;
@@ -59,20 +64,31 @@
     T::deserialize(&mut Deserializer::new_from_reader(reader))
 }
 
-pub struct Deserializer<R: Read> {
+type RootDeserializer<R> = Deserializer<R, RootXmlBuffer<R>>;
+type ChildDeserializer<'parent, R> = Deserializer<R, ChildXmlBuffer<'parent, R>>;
+
+pub struct Deserializer<
+    R: Read, // Kept as type param to avoid type signature breaking-change
+    B: BufferedXmlReader<R> = RootXmlBuffer<R>,
+> {
+    /// XML document nested element depth
     depth: usize,
-    reader: EventReader<R>,
-    peeked: Option<XmlEvent>,
+    buffered_reader: B,
     is_map_value: bool,
+    non_contiguous_seq_elements: bool,
+    marker: PhantomData<R>,
 }
 
-impl<'de, R: Read> Deserializer<R> {
+impl<'de, R: Read> RootDeserializer<R> {
     pub fn new(reader: EventReader<R>) -> Self {
+        let buffered_reader = RootXmlBuffer::new(reader);
+
         Deserializer {
+            buffered_reader,
             depth: 0,
-            reader: reader,
-            peeked: None,
             is_map_value: false,
+            non_contiguous_seq_elements: false,
+            marker: PhantomData,
         }
     }
 
@@ -87,34 +103,75 @@
         Self::new(EventReader::new_with_config(reader, config))
     }
 
+    /// Configures whether the deserializer should search all sibling elements when building a
+    /// sequence. Not required if all XML elements for sequences are adjacent. Disabled by
+    /// 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;
+    /// #[derive(Debug, Deserialize, PartialEq)]
+    /// struct Foo {
+    ///     bar: Vec<usize>,
+    ///     baz: String,
+    /// }
+    /// # fn main() {
+    /// let s = r##"
+    ///     <foo>
+    ///         <bar>1</bar>
+    ///         <bar>2</bar>
+    ///         <baz>Hello, world</baz>
+    ///         <bar>3</bar>
+    ///         <bar>4</bar>
+    ///     </foo>
+    /// "##;
+    /// let mut de = serde_xml_rs::Deserializer::new_from_reader(s.as_bytes())
+    ///     .non_contiguous_seq_elements(true);
+    /// let foo = Foo::deserialize(&mut de).unwrap();
+    /// assert_eq!(foo, Foo { bar: vec![1, 2, 3, 4], baz: "Hello, world".to_string()});
+    /// # }
+    /// ```
+    pub fn non_contiguous_seq_elements(mut self, set: bool) -> Self {
+        self.non_contiguous_seq_elements = set;
+        self
+    }
+}
+
+impl<'de, R: Read, B: BufferedXmlReader<R>> Deserializer<R, B> {
+    fn child<'a>(&'a mut self) -> Deserializer<R, ChildXmlBuffer<'a, R>> {
+        let Deserializer {
+            buffered_reader,
+            depth,
+            is_map_value,
+            non_contiguous_seq_elements,
+            ..
+        } = self;
+
+        Deserializer {
+            buffered_reader: buffered_reader.child_buffer(),
+            depth: *depth,
+            is_map_value: *is_map_value,
+            non_contiguous_seq_elements: *non_contiguous_seq_elements,
+            marker: PhantomData,
+        }
+    }
+
+    /// Gets the next XML event without advancing the cursor.
     fn peek(&mut self) -> Result<&XmlEvent> {
-        if self.peeked.is_none() {
-            self.peeked = Some(self.inner_next()?);
-        }
-        debug_expect!(self.peeked.as_ref(), Some(peeked) => {
-            debug!("Peeked {:?}", peeked);
-            Ok(peeked)
-        })
+        let peeked = self.buffered_reader.peek()?;
+
+        debug!("Peeked {:?}", peeked);
+        Ok(peeked)
     }
 
-    fn inner_next(&mut self) -> Result<XmlEvent> {
-        loop {
-            match self.reader.next()? {
-                XmlEvent::StartDocument { .. }
-                | XmlEvent::ProcessingInstruction { .. }
-                | XmlEvent::Whitespace { .. }
-                | XmlEvent::Comment(_) => { /* skip */ }
-                other => return Ok(other),
-            }
-        }
-    }
-
+    /// Gets the XML event at the cursor and advances the cursor.
     fn next(&mut self) -> Result<XmlEvent> {
-        let next = if let Some(peeked) = self.peeked.take() {
-            peeked
-        } else {
-            self.inner_next()?
-        };
+        let next = self.buffered_reader.next()?;
+
         match next {
             XmlEvent::StartElement { .. } => {
                 self.depth += 1;
@@ -136,6 +193,10 @@
         ::std::mem::replace(&mut self.is_map_value, false)
     }
 
+    /// If `self.is_map_value`: Performs the read operations specified by `f` on the inner content of an XML element.
+    /// `f` is expected to consume the entire inner contents of the element. The cursor will be moved to the end of the
+    /// element.
+    /// If `!self.is_map_value`: `f` will be performed without additional checks/advances for an outer XML element.
     fn read_inner_value<V: de::Visitor<'de>, T, F: FnOnce(&mut Self) -> Result<T>>(
         &mut self,
         f: F,
@@ -190,10 +251,12 @@
             let value = self.prepare_parse_type::<V>()?.parse()?;
             visitor.$visit(value)
         }
-    }
+    };
 }
 
-impl<'de, 'a, R: Read> de::Deserializer<'de> for &'a mut Deserializer<R> {
+impl<'de, 'a, R: Read, B: BufferedXmlReader<R>> de::Deserializer<'de>
+    for &'a mut Deserializer<R, B>
+{
     type Error = Error;
 
     forward_to_deserialize_any! {
@@ -299,7 +362,9 @@
     }
 
     fn deserialize_tuple<V: de::Visitor<'de>>(self, len: usize, visitor: V) -> Result<V::Value> {
-        visitor.visit_seq(SeqAccess::new(self, Some(len)))
+        let child_deserializer = self.child();
+
+        visitor.visit_seq(SeqAccess::new(child_deserializer, Some(len)))
     }
 
     fn deserialize_enum<V: de::Visitor<'de>>(
@@ -326,7 +391,9 @@
     }
 
     fn deserialize_seq<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
-        visitor.visit_seq(SeqAccess::new(self, None))
+        let child_deserializer = self.child();
+
+        visitor.visit_seq(SeqAccess::new(child_deserializer, None))
     }
 
     fn deserialize_map<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
diff --git a/src/de/seq.rs b/src/de/seq.rs
index 7e88d0c..56babe1 100644
--- a/src/de/seq.rs
+++ b/src/de/seq.rs
@@ -3,28 +3,42 @@
 use serde::de;
 use xml::reader::XmlEvent;
 
-use de::Deserializer;
-use error::{Error, Result};
+use crate::de::ChildDeserializer;
+use crate::debug_expect;
+use crate::error::{Error, Result};
 
-pub struct SeqAccess<'a, R: 'a + Read> {
-    de: &'a mut Deserializer<R>,
+pub struct SeqAccess<'a, R: Read> {
+    de: ChildDeserializer<'a, R>,
     max_size: Option<usize>,
-    expected_name: Option<String>,
+    seq_type: SeqType,
+}
+
+pub enum SeqType {
+    /// Sequence is of elements with the same name.
+    ByElementName {
+        expected_name: String,
+        search_non_contiguous: bool,
+    },
+    /// Sequence is of all elements/text at current depth.
+    AllMembers,
 }
 
 impl<'a, R: 'a + Read> SeqAccess<'a, R> {
-    pub fn new(de: &'a mut Deserializer<R>, max_size: Option<usize>) -> Self {
-        let expected_name = if de.unset_map_value() {
+    pub fn new(mut de: ChildDeserializer<'a, R>, max_size: Option<usize>) -> Self {
+        let seq_type = if de.unset_map_value() {
             debug_expect!(de.peek(), Ok(&XmlEvent::StartElement { ref name, .. }) => {
-                Some(name.local_name.clone())
+                SeqType::ByElementName {
+                    expected_name: name.local_name.clone(),
+                    search_non_contiguous: de.non_contiguous_seq_elements
+                }
             })
         } else {
-            None
+            SeqType::AllMembers
         };
         SeqAccess {
-            de: de,
-            max_size: max_size,
-            expected_name: expected_name,
+            de,
+            max_size,
+            seq_type,
         }
     }
 }
@@ -39,28 +53,65 @@
         match self.max_size.as_mut() {
             Some(&mut 0) => {
                 return Ok(None);
-            },
+            }
             Some(max_size) => {
                 *max_size -= 1;
-            },
-            None => {},
-        }
-        let more = match (self.de.peek()?, self.expected_name.as_ref()) {
-            (&XmlEvent::StartElement { ref name, .. }, Some(expected_name)) => {
-                &name.local_name == expected_name
-            },
-            (&XmlEvent::EndElement { .. }, None) |
-            (_, Some(_)) |
-            (&XmlEvent::EndDocument { .. }, _) => false,
-            (_, None) => true,
-        };
-        if more {
-            if self.expected_name.is_some() {
-                self.de.set_map_value();
             }
-            seed.deserialize(&mut *self.de).map(Some)
-        } else {
-            Ok(None)
+            None => {}
+        }
+
+        match &self.seq_type {
+            SeqType::ByElementName {
+                expected_name,
+                search_non_contiguous,
+            } => {
+                let mut local_depth = 0;
+
+                loop {
+                    let next_element = self.de.peek()?;
+
+                    match next_element {
+                        XmlEvent::StartElement { name, .. }
+                            if &name.local_name == expected_name && local_depth == 0 =>
+                        {
+                            self.de.set_map_value();
+                            return seed.deserialize(&mut self.de).map(Some);
+                        }
+                        XmlEvent::StartElement { .. } => {
+                            if *search_non_contiguous {
+                                self.de.buffered_reader.skip();
+                                local_depth += 1;
+                            } else {
+                                return Ok(None);
+                            }
+                        }
+                        XmlEvent::EndElement { .. } => {
+                            if local_depth == 0 {
+                                return Ok(None);
+                            } else {
+                                local_depth -= 1;
+                                self.de.buffered_reader.skip();
+                            }
+                        }
+                        XmlEvent::EndDocument => {
+                            return Ok(None);
+                        }
+                        _ => {
+                            self.de.buffered_reader.skip();
+                        }
+                    }
+                }
+            }
+            SeqType::AllMembers => {
+                let next_element = self.de.peek()?;
+
+                match next_element {
+                    XmlEvent::EndElement { .. } | XmlEvent::EndDocument => return Ok(None),
+                    _ => {
+                        return seed.deserialize(&mut self.de).map(Some);
+                    }
+                }
+            }
         }
     }
 
diff --git a/src/de/var.rs b/src/de/var.rs
index dbb400f..6c05153 100644
--- a/src/de/var.rs
+++ b/src/de/var.rs
@@ -4,27 +4,30 @@
 use xml::name::OwnedName;
 use xml::reader::XmlEvent;
 
-use de::Deserializer;
-use error::{Error, Result};
+use crate::de::Deserializer;
+use crate::error::{Error, Result};
+use crate::expect;
 
-pub struct EnumAccess<'a, R: 'a + Read> {
-    de: &'a mut Deserializer<R>,
+use super::buffer::BufferedXmlReader;
+
+pub struct EnumAccess<'a, R: Read, B: BufferedXmlReader<R>> {
+    de: &'a mut Deserializer<R, B>,
 }
 
-impl<'a, R: 'a + Read> EnumAccess<'a, R> {
-    pub fn new(de: &'a mut Deserializer<R>) -> Self {
+impl<'a, R: 'a + Read, B: BufferedXmlReader<R>> EnumAccess<'a, R, B> {
+    pub fn new(de: &'a mut Deserializer<R, B>) -> Self {
         EnumAccess { de: de }
     }
 }
 
-impl<'de, 'a, R: 'a + Read> de::EnumAccess<'de> for EnumAccess<'a, R> {
+impl<'de, 'a, R: 'a + Read, B: BufferedXmlReader<R>> de::EnumAccess<'de> for EnumAccess<'a, R, B> {
     type Error = Error;
-    type Variant = VariantAccess<'a, R>;
+    type Variant = VariantAccess<'a, R, B>;
 
     fn variant_seed<V: de::DeserializeSeed<'de>>(
         self,
         seed: V,
-    ) -> Result<(V::Value, VariantAccess<'a, R>)> {
+    ) -> Result<(V::Value, VariantAccess<'a, R, B>)> {
         let name = expect!(
             self.de.peek()?,
 
@@ -38,17 +41,19 @@
     }
 }
 
-pub struct VariantAccess<'a, R: 'a + Read> {
-    de: &'a mut Deserializer<R>,
+pub struct VariantAccess<'a, R: Read, B: BufferedXmlReader<R>> {
+    de: &'a mut Deserializer<R, B>,
 }
 
-impl<'a, R: 'a + Read> VariantAccess<'a, R> {
-    pub fn new(de: &'a mut Deserializer<R>) -> Self {
+impl<'a, R: 'a + Read, B: BufferedXmlReader<R>> VariantAccess<'a, R, B> {
+    pub fn new(de: &'a mut Deserializer<R, B>) -> Self {
         VariantAccess { de: de }
     }
 }
 
-impl<'de, 'a, R: 'a + Read> de::VariantAccess<'de> for VariantAccess<'a, R> {
+impl<'de, 'a, R: 'a + Read, B: BufferedXmlReader<R>> de::VariantAccess<'de>
+    for VariantAccess<'a, R, B>
+{
     type Error = Error;
 
     fn unit_variant(self) -> Result<()> {
@@ -56,11 +61,13 @@
         match self.de.next()? {
             XmlEvent::StartElement {
                 name, attributes, ..
-            } => if attributes.is_empty() {
-                self.de.expect_end_element(name)
-            } else {
-                Err(de::Error::invalid_length(attributes.len(), &"0"))
-            },
+            } => {
+                if attributes.is_empty() {
+                    self.de.expect_end_element(name)
+                } else {
+                    Err(de::Error::invalid_length(attributes.len(), &"0"))
+                }
+            }
             XmlEvent::Characters(_) => Ok(()),
             _ => unreachable!(),
         }
diff --git a/src/error.rs b/src/error.rs
index 8d6e4ad..5061b52 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -51,6 +51,7 @@
 
 pub type Result<T> = std::result::Result<T, Error>;
 
+#[macro_export]
 macro_rules! expect {
     ($actual: expr, $($expected: pat)|+ => $if_ok: expr) => {
         match $actual {
@@ -64,6 +65,7 @@
 }
 
 #[cfg(debug_assertions)]
+#[macro_export]
 macro_rules! debug_expect {
     ($actual: expr, $($expected: pat)|+ => $if_ok: expr) => {
         match $actual {
@@ -78,6 +80,7 @@
 }
 
 #[cfg(not(debug_assertions))]
+#[macro_export]
 macro_rules! debug_expect {
     ($actual: expr, $($expected: pat)|+ => $if_ok: expr) => {
         match $actual {
diff --git a/src/lib.rs b/src/lib.rs
index 1f93ed8..e1ef1df 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,14 +1,56 @@
+//! # Serde XML
 //!
+//! XML is a flexible markup language that is still used for sharing data between applications or
+//! for writing configuration files.
 //!
-//! # Examples
+//! Serde XML provides a way to convert between text and strongly-typed Rust data structures.
+//!
+//! ## Caveats
+//!
+//! The Serde framework was mainly designed with formats such as JSON or YAML in mind.
+//! As opposed to XML, these formats have the advantage of a stricter syntax which makes it
+//! possible to know what type a field is without relying on an accompanying schema,
+//! and disallows repeating the same tag multiple times in the same object.
+//!
+//! For example, encoding the following document in YAML is not trivial.
+//!
+//! ```xml
+//! <document>
+//!   <header>A header</header>
+//!   <section>First section</section>
+//!   <section>Second section</section>
+//!   <sidenote>A sidenote</sidenote>
+//!   <section>Third section</section>
+//!   <sidenote>Another sidenote</sidenote>
+//!   <section>Fourth section</section>
+//!   <footer>The footer</footer>
+//! </document>
+//! ```
+//!
+//! One possibility is the following YAML document.
+//!
+//! ```yaml
+//! - header: A header
+//! - section: First section
+//! - section: Second section
+//! - sidenote: A sidenote
+//! - section: Third section
+//! - sidenote: Another sidenote
+//! - section: Fourth section
+//! - footer: The footer
+//! ```
+//!
+//! Other notable differences:
+//! - XML requires a named root node.
+//! - XML has a namespace system.
+//! - XML distinguishes between attributes, child tags and contents.
+//! - In XML, the order of nodes is sometimes important.
+//!
+//! ## Basic example
 //!
 //! ```rust
-//! extern crate serde;
-//! extern crate serde_xml_rs;
-//!
-//! #[macro_use]
-//! extern crate serde_derive;
-//!
+//! use serde;
+//! use serde_derive::{Deserialize, Serialize};
 //! use serde_xml_rs::{from_str, to_string};
 //!
 //! #[derive(Debug, Serialize, Deserialize, PartialEq)]
@@ -31,25 +73,126 @@
 //!     assert_eq!(src, reserialized_item);
 //! }
 //! ```
+//!
+//! ## Tag contents
+//!
+//! ```rust
+//! # use serde;
+//! # use serde_derive::{Deserialize, Serialize};
+//! # use serde_xml_rs::{from_str, to_string};
+//!
+//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
+//! struct Document {
+//!     content: Content
+//! }
+//!
+//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
+//! struct Content {
+//!     #[serde(rename = "$value")]
+//!     value: String
+//! }
+//!
+//! fn main() {
+//!     let src = r#"<document><content>Lorem ipsum</content></document>"#;
+//!     let document: Document = from_str(src).unwrap();
+//!     assert_eq!(document.content.value, "Lorem ipsum");
+//! }
+//! ```
+//!
+//! ## Repeated tags
+//!
+//! ```rust
+//! # use serde;
+//! # use serde_derive::{Deserialize, Serialize};
+//! # use serde_xml_rs::{from_str, to_string};
+//!
+//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
+//! struct PlateAppearance {
+//!     #[serde(rename = "$value")]
+//!     events: Vec<Event>
+//! }
+//!
+//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
+//! #[serde(rename_all = "kebab-case")]
+//! enum Event {
+//!     Pitch(Pitch),
+//!     Runner(Runner),
+//! }
+//!
+//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
+//! struct Pitch {
+//!     speed: u32,
+//!     r#type: PitchType,
+//!     outcome: PitchOutcome,
+//! }
+//!
+//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
+//! enum PitchType { FourSeam, TwoSeam, Changeup, Cutter, Curve, Slider, Knuckle, Pitchout }
+//!
+//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
+//! enum PitchOutcome { Ball, Strike, Hit }
+//!
+//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
+//! struct Runner {
+//!     from: Base, to: Option<Base>, outcome: RunnerOutcome,
+//! }
+//!
+//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
+//! enum Base { First, Second, Third, Home }
+//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
+//! enum RunnerOutcome { Steal, Caught, PickOff }
+//!
+//! fn main() {
+//!     let document = r#"
+//!         <plate-appearance>
+//!           <pitch speed="95" type="FourSeam" outcome="Ball" />
+//!           <pitch speed="91" type="FourSeam" outcome="Strike" />
+//!           <pitch speed="85" type="Changeup" outcome="Ball" />
+//!           <runner from="First" to="Second" outcome="Steal" />
+//!           <pitch speed="89" type="Slider" outcome="Strike" />
+//!           <pitch speed="88" type="Curve" outcome="Hit" />
+//!         </plate-appearance>"#;
+//!     let plate_appearance: PlateAppearance = from_str(document).unwrap();
+//!     assert_eq!(plate_appearance.events[0], Event::Pitch(Pitch { speed: 95, r#type: PitchType::FourSeam, outcome: PitchOutcome::Ball }));
+//! }
+//! ```
+//!
+//! ## Custom EventReader
+//!
+//! ```rust
+//! use serde::Deserialize;
+//! use serde_derive::{Deserialize, Serialize};
+//! use serde_xml_rs::{from_str, to_string, de::Deserializer};
+//! use xml::reader::{EventReader, ParserConfig};
+//!
+//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
+//! struct Item {
+//!     name: String,
+//!     source: String,
+//! }
+//!
+//! fn main() {
+//!     let src = r#"<Item><name>  Banana  </name><source>Store</source></Item>"#;
+//!     let should_be = Item {
+//!         name: "  Banana  ".to_string(),
+//!         source: "Store".to_string(),
+//!     };
+//!
+//!     let config = ParserConfig::new()
+//!         .trim_whitespace(false)
+//!         .whitespace_to_characters(true);
+//!     let event_reader = EventReader::new_with_config(src.as_bytes(), config);
+//!     let item = Item::deserialize(&mut Deserializer::new(event_reader)).unwrap();
+//!     assert_eq!(item, should_be);
+//! }
+//! ```
+//!
 
-#[macro_use]
-extern crate log;
-#[macro_use]
-extern crate serde;
-extern crate xml;
-
-extern crate thiserror;
-
-#[cfg(test)]
-#[macro_use]
-extern crate serde_derive;
-
-#[macro_use]
-mod error;
 pub mod de;
+mod error;
 pub mod ser;
 
-pub use de::{from_reader, from_str, Deserializer};
-pub use error::Error;
-pub use ser::{to_string, to_writer, Serializer};
+pub use crate::de::{from_reader, from_str, Deserializer};
+pub use crate::error::Error;
+pub use crate::ser::{to_string, to_writer, Serializer};
 pub use xml::reader::{EventReader, ParserConfig};
diff --git a/src/ser/mod.rs b/src/ser/mod.rs
index bf97b1f..a29ca6f 100644
--- a/src/ser/mod.rs
+++ b/src/ser/mod.rs
@@ -4,7 +4,7 @@
 use serde::ser::{self, Impossible, Serialize};
 
 use self::var::{Map, Struct};
-use error::{Error, Result};
+use crate::error::{Error, Result};
 
 mod var;
 
@@ -292,6 +292,7 @@
     use super::*;
     use serde::ser::{SerializeMap, SerializeStruct};
     use serde::Serializer as SerSerializer;
+    use serde_derive::Serialize;
 
     #[test]
     fn test_serialize_bool() {
diff --git a/src/ser/var.rs b/src/ser/var.rs
index bb61472..e4ee0f0 100644
--- a/src/ser/var.rs
+++ b/src/ser/var.rs
@@ -2,13 +2,13 @@
 
 use serde::ser::{self, Serialize};
 
-use ser::Serializer;
-use error::{Error, Result};
+use crate::error::{Error, Result};
+use crate::ser::Serializer;
 
 /// An implementation of `SerializeMap` for serializing to XML.
 pub struct Map<'w, W>
 where
-    W: 'w + Write,
+    W: Write,
 {
     parent: &'w mut Serializer<W>,
 }
@@ -64,7 +64,7 @@
 /// An implementation of `SerializeStruct` for serializing to XML.
 pub struct Struct<'w, W>
 where
-    W: 'w + Write,
+    W: Write,
 {
     parent: &'w mut Serializer<W>,
     name: &'w str,
diff --git a/tests/failures.rs b/tests/failures.rs
index ca51f6b..7a55811 100644
--- a/tests/failures.rs
+++ b/tests/failures.rs
@@ -1,12 +1,11 @@
-#[macro_use]
-extern crate serde_derive;
-extern crate serde_xml_rs;
-
-#[macro_use]
-extern crate log;
-extern crate simple_logger;
-
+use log::info;
+use serde_derive::Deserialize;
 use serde_xml_rs::from_str;
+use simple_logger::SimpleLogger;
+
+fn init_logger() {
+    let _ = SimpleLogger::new().init();
+}
 
 #[derive(Debug, Deserialize, PartialEq)]
 struct Item {
@@ -16,7 +15,7 @@
 
 #[test]
 fn simple_struct_from_attributes_should_fail() {
-    let _ = simple_logger::init();
+    init_logger();
 
     let s = r##"
         <item name="hello" source="world.rs />
@@ -34,7 +33,7 @@
 
 #[test]
 fn multiple_roots_attributes_should_fail() {
-    let _ = simple_logger::init();
+    init_logger();
 
     let s = r##"
         <item name="hello" source="world.rs" />
diff --git a/tests/migrated.rs b/tests/migrated.rs
index 87d3e6a..e01d750 100644
--- a/tests/migrated.rs
+++ b/tests/migrated.rs
@@ -1,17 +1,14 @@
-#[macro_use]
-extern crate serde_derive;
-
-extern crate log;
-extern crate simple_logger;
-
-extern crate serde;
-extern crate serde_xml_rs;
-
+use simple_logger::SimpleLogger;
 use std::fmt::Debug;
 
 use serde::{de, ser};
+use serde_derive::{Deserialize, Serialize};
 use serde_xml_rs::{from_str, Error};
 
+fn init_logger() {
+    let _ = SimpleLogger::new().init();
+}
+
 #[derive(PartialEq, Debug, Serialize, Deserialize)]
 enum Animal {
     Dog,
@@ -83,7 +80,7 @@
 
 #[test]
 fn test_namespaces() {
-    let _ = simple_logger::init();
+    init_logger();
     #[derive(PartialEq, Serialize, Deserialize, Debug)]
     struct Envelope {
         subject: String,
@@ -102,9 +99,8 @@
 }
 
 #[test]
-#[ignore] // FIXME
 fn test_doctype() {
-    let _ = simple_logger::init();
+    init_logger();
     #[derive(PartialEq, Serialize, Deserialize, Debug)]
     struct Envelope {
         subject: String,
@@ -150,36 +146,6 @@
 }
 
 #[test]
-fn test_doctype_fail() {
-    let _ = simple_logger::init();
-    #[derive(PartialEq, Serialize, Deserialize, Debug)]
-    struct Envelope {
-        subject: String,
-    }
-
-    test_parse_err::<Envelope>(&[
-        r#"
-            <?xml version="1.0" encoding="UTF-8"?>
-            <!DOCTYPE Envelope [
-                <!ELEMENT subject (#PCDATA)>
-            >
-            <Envelope>
-            <subject>Reference rates</subject>
-            </Envelope>"#,
-        r#"
-            <?xml version="1.0" encoding="UTF-8"?>
-            <Envelope>
-            <subject>Reference rates</subject>
-
-            <!DOCTYPE Envelope [
-                <!ELEMENT subject (#PCDATA)>
-            ]>
-
-            </Envelope>"#,
-    ])
-}
-
-#[test]
 #[ignore] // FIXME
 fn test_forwarded_namespace() {
     #[derive(PartialEq, Serialize, Deserialize, Debug)]
@@ -208,7 +174,7 @@
 
 #[test]
 fn test_parse_string() {
-    let _ = simple_logger::init();
+    init_logger();
 
     test_parse_ok(&[
         (
@@ -230,7 +196,7 @@
 #[test]
 #[ignore] // FIXME
 fn test_parse_string_not_trim() {
-    let _ = simple_logger::init();
+    init_logger();
 
     test_parse_ok(&[("<bla>     </bla>", "     ".to_string())]);
 }
@@ -239,7 +205,7 @@
 #[ignore] // FIXME
 fn test_parse_enum() {
     use self::Animal::*;
-    let _ = simple_logger::init();
+    init_logger();
 
     test_parse_ok(&[
         ("<Animal xsi:type=\"Dog\"/>", Dog),
@@ -304,7 +270,7 @@
 
 #[test]
 fn test_parse_i64() {
-    let _ = simple_logger::init();
+    init_logger();
     test_parse_ok(&[
         ("<bla>0</bla>", 0),
         ("<bla>-2</bla>", -2),
@@ -315,7 +281,7 @@
 
 #[test]
 fn test_parse_u64() {
-    let _ = simple_logger::init();
+    init_logger();
     test_parse_ok(&[
         ("<bla>0</bla>", 0),
         ("<bla>1234</bla>", 1234),
@@ -325,7 +291,7 @@
 
 #[test]
 fn test_parse_bool_element() {
-    let _ = simple_logger::init();
+    init_logger();
     test_parse_ok(&[
         ("<bla>true</bla>", true),
         ("<bla>false</bla>", false),
@@ -345,7 +311,7 @@
         foo: bool,
     }
 
-    let _ = simple_logger::init();
+    init_logger();
     test_parse_ok(&[
         ("<bla foo=\"true\"/>", Dummy { foo: true }),
         ("<bla foo=\"false\"/>", Dummy { foo: false }),
@@ -364,13 +330,13 @@
 
 #[test]
 fn test_parse_unit() {
-    let _ = simple_logger::init();
+    init_logger();
     test_parse_ok(&[("<bla/>", ())]);
 }
 
 #[test]
 fn test_parse_f64() {
-    let _ = simple_logger::init();
+    init_logger();
     test_parse_ok(&[
         ("<bla>3.0</bla>", 3.0f64),
         ("<bla>3.1</bla>", 3.1),
@@ -385,7 +351,7 @@
 
 #[test]
 fn test_parse_struct() {
-    let _ = simple_logger::init();
+    init_logger();
 
     test_parse_ok(&[
         (
@@ -432,7 +398,7 @@
 
 #[test]
 fn test_option() {
-    let _ = simple_logger::init();
+    init_logger();
     test_parse_ok(&[
         ("<a/>", Some("".to_string())),
         ("<a></a>", Some("".to_string())),
@@ -444,13 +410,13 @@
 #[test]
 #[ignore] // FIXME
 fn test_option_not_trim() {
-    let _ = simple_logger::init();
+    init_logger();
     test_parse_ok(&[("<a> </a>", Some(" ".to_string()))]);
 }
 
 #[test]
 fn test_amoskvin() {
-    let _ = simple_logger::init();
+    init_logger();
     #[derive(Debug, Deserialize, PartialEq, Serialize)]
     struct Root {
         foo: Vec<Foo>,
@@ -490,7 +456,7 @@
 #[test]
 #[ignore] // FIXME
 fn test_nicolai86() {
-    let _ = simple_logger::init();
+    init_logger();
     #[derive(Serialize, Deserialize, PartialEq, Debug)]
     struct TheSender {
         name: String,
@@ -579,7 +545,7 @@
 
 #[test]
 fn test_hugo_duncan2() {
-    let _ = simple_logger::init();
+    init_logger();
     let s = r#"
     <?xml version="1.0" encoding="UTF-8"?>
     <DescribeVpcsResponse xmlns="http://ec2.amazonaws.com/doc/2014-10-01/">
@@ -634,7 +600,7 @@
 
 #[test]
 fn test_hugo_duncan() {
-    let _ = simple_logger::init();
+    init_logger();
     let s = "
         <?xml version=\"1.0\" encoding=\"UTF-8\"?>
         <DescribeInstancesResponse xmlns=\"http://ec2.amazonaws.com/doc/2014-10-01/\">
@@ -659,7 +625,7 @@
 
 #[test]
 fn test_parse_xml_value() {
-    let _ = simple_logger::init();
+    init_logger();
     #[derive(Eq, Debug, PartialEq, Deserialize, Serialize)]
     struct Test {
         #[serde(rename = "$value")]
@@ -676,7 +642,7 @@
 #[test]
 #[ignore] // FIXME
 fn test_parse_complexstruct() {
-    let _ = simple_logger::init();
+    init_logger();
 
     test_parse_ok(&[
         (
@@ -720,7 +686,7 @@
 
 #[test]
 fn test_parse_attributes() {
-    let _ = simple_logger::init();
+    init_logger();
 
     #[derive(PartialEq, Debug, Serialize, Deserialize)]
     struct A {
@@ -805,7 +771,7 @@
 #[test]
 #[ignore] // FIXME
 fn test_parse_hierarchies() {
-    let _ = simple_logger::init();
+    init_logger();
     #[derive(PartialEq, Debug, Serialize, Deserialize)]
     struct A {
         a1: String,
@@ -954,7 +920,7 @@
 
 #[test]
 fn futile() {
-    let _ = simple_logger::init();
+    init_logger();
     #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)]
     struct Object {
         id: u8,
@@ -1003,7 +969,7 @@
 
 #[test]
 fn futile2() {
-    let _ = simple_logger::init();
+    init_logger();
     #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)]
     struct Null;
 
diff --git a/tests/readme.rs b/tests/readme.rs
deleted file mode 100644
index 881d572..0000000
--- a/tests/readme.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-extern crate docmatic;
-
-#[test]
-fn test_readme() {
-    docmatic::assert_file("README.md");
-}
diff --git a/tests/round_trip.rs b/tests/round_trip.rs
index 54b3b53..450a4b5 100644
--- a/tests/round_trip.rs
+++ b/tests/round_trip.rs
@@ -1,10 +1,6 @@
-#[macro_use]
-extern crate serde_derive;
-extern crate serde;
-extern crate serde_xml_rs;
-
 use serde::Deserialize;
-use serde_xml_rs::{from_str, to_string, EventReader, ParserConfig};
+use serde_derive::{Deserialize, Serialize};
+use serde_xml_rs::{self, from_str, to_string, EventReader, ParserConfig};
 
 #[derive(Debug, Serialize, Deserialize, PartialEq)]
 struct Item {
@@ -12,7 +8,6 @@
     source: String,
 }
 
-
 #[derive(Debug, Serialize, Deserialize, PartialEq)]
 enum Node {
     Boolean(bool),
@@ -26,7 +21,6 @@
     items: Vec<Node>,
 }
 
-
 #[test]
 fn basic_struct() {
     let src = r#"<Item><name>Banana</name><source>Store</source></Item>"#;
@@ -42,7 +36,6 @@
     assert_eq!(src, reserialized_item);
 }
 
-
 #[test]
 #[ignore]
 fn round_trip_list_of_enums() {
diff --git a/tests/test.rs b/tests/test.rs
index 4b8ec86..52075b1 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,11 +1,11 @@
-#[macro_use]
-extern crate serde_derive;
-extern crate serde_xml_rs;
+use serde::Deserialize;
+use serde_derive::Deserialize;
+use serde_xml_rs::{from_str, Deserializer};
+use simple_logger::SimpleLogger;
 
-extern crate log;
-extern crate simple_logger;
-
-use serde_xml_rs::from_str;
+fn init_logger() {
+    let _ = SimpleLogger::new().init();
+}
 
 #[derive(Debug, Deserialize, PartialEq)]
 struct Item {
@@ -15,7 +15,7 @@
 
 #[test]
 fn simple_struct_from_attributes() {
-    let _ = simple_logger::init();
+    init_logger();
 
     let s = r##"
         <item name="hello" source="world.rs" />
@@ -34,7 +34,7 @@
 
 #[test]
 fn multiple_roots_attributes() {
-    let _ = simple_logger::init();
+    init_logger();
 
     let s = r##"
         <item name="hello" source="world.rs" />
@@ -60,7 +60,7 @@
 
 #[test]
 fn simple_struct_from_attribute_and_child() {
-    let _ = simple_logger::init();
+    init_logger();
 
     let s = r##"
         <item name="hello">
@@ -89,7 +89,7 @@
 
 #[test]
 fn nested_collection() {
-    let _ = simple_logger::init();
+    init_logger();
 
     let s = r##"
         <project name="my_project">
@@ -133,7 +133,7 @@
 
 #[test]
 fn collection_of_enums() {
-    let _ = simple_logger::init();
+    init_logger();
 
     let s = r##"
         <enums>
@@ -159,3 +159,225 @@
         }
     );
 }
+
+#[test]
+fn out_of_order_collection() {
+    #[derive(Debug, Deserialize, PartialEq)]
+    struct Collection {
+        a: Vec<A>,
+        b: Vec<B>,
+        c: C,
+    }
+
+    #[derive(Debug, Deserialize, PartialEq)]
+    struct A {
+        name: String,
+    }
+
+    #[derive(Debug, Deserialize, PartialEq)]
+    struct B {
+        name: String,
+    }
+
+    #[derive(Debug, Deserialize, PartialEq)]
+    struct C {
+        name: String,
+    }
+
+    init_logger();
+
+    let in_xml = r#"
+        <collection>
+            <a name="a1" />
+            <a name="a2" />
+            <b name="b1" />
+            <a name="a3" />
+            <c name="c" />
+            <b name="b2" />
+            <a name="a4" />
+        </collection>
+    "#;
+
+    let should_be = Collection {
+        a: vec![
+            A { name: "a1".into() },
+            A { name: "a2".into() },
+            A { name: "a3".into() },
+            A { name: "a4".into() },
+        ],
+        b: vec![B { name: "b1".into() }, B { name: "b2".into() }],
+        c: C { name: "c".into() },
+    };
+
+    let mut de = Deserializer::new_from_reader(in_xml.as_bytes()).non_contiguous_seq_elements(true);
+    let actual = Collection::deserialize(&mut de).unwrap();
+
+    assert_eq!(should_be, actual);
+}
+
+#[test]
+fn nested_out_of_order_collection() {
+    #[derive(Debug, Deserialize, PartialEq)]
+    struct OuterCollection {
+        a: A,
+        inner: Vec<InnerCollection>,
+    }
+
+    #[derive(Debug, Deserialize, PartialEq)]
+    struct InnerCollection {
+        b: Vec<B>,
+        c: Vec<C>,
+    }
+
+    #[derive(Debug, Deserialize, PartialEq)]
+    struct A {
+        name: String,
+    }
+
+    #[derive(Debug, Deserialize, PartialEq)]
+    struct B {
+        name: String,
+    }
+
+    #[derive(Debug, Deserialize, PartialEq)]
+    struct C {
+        name: String,
+    }
+
+    init_logger();
+
+    let in_xml = r#"
+        <collection>
+            <inner>
+                <b name="b1" />
+                <c name="c1" />
+                <b name="b2" />
+                <c name="c2" />
+            </inner>
+            <a name="a" />
+            <inner>
+                <c name="c3" />
+                <b name="b3" />
+                <c name="c4" />
+                <b name="b4" />
+            </inner>
+        </collection>
+    "#;
+
+    let should_be = OuterCollection {
+        a: A { name: "a".into() },
+        inner: vec![
+            InnerCollection {
+                b: vec![B { name: "b1".into() }, B { name: "b2".into() }],
+                c: vec![C { name: "c1".into() }, C { name: "c2".into() }],
+            },
+            InnerCollection {
+                b: vec![B { name: "b3".into() }, B { name: "b4".into() }],
+                c: vec![C { name: "c3".into() }, C { name: "c4".into() }],
+            },
+        ],
+    };
+
+    let mut de = Deserializer::new_from_reader(in_xml.as_bytes()).non_contiguous_seq_elements(true);
+    let actual = OuterCollection::deserialize(&mut de).unwrap();
+
+    assert_eq!(should_be, actual);
+}
+
+#[test]
+fn out_of_order_tuple() {
+    #[derive(Debug, Deserialize, PartialEq)]
+    struct Collection {
+        val: (A, B, C),
+        other: A,
+    }
+
+    #[derive(Debug, Deserialize, PartialEq)]
+    struct A {
+        name_a: String,
+    }
+
+    #[derive(Debug, Deserialize, PartialEq)]
+    struct B {
+        name_b: String,
+    }
+
+    #[derive(Debug, Deserialize, PartialEq)]
+    struct C {
+        name_c: String,
+    }
+
+    init_logger();
+
+    let in_xml = r#"
+        <collection>
+            <val name_a="a1" />
+            <val name_b="b" />
+            <other name_a="a2" />
+            <val name_c="c" />
+        </collection>
+    "#;
+
+    let should_be = Collection {
+        val: (
+            A {
+                name_a: "a1".into(),
+            },
+            B { name_b: "b".into() },
+            C { name_c: "c".into() },
+        ),
+        other: A {
+            name_a: "a2".into(),
+        },
+    };
+
+    let mut de = Deserializer::new_from_reader(in_xml.as_bytes()).non_contiguous_seq_elements(true);
+    let actual = Collection::deserialize(&mut de).unwrap();
+
+    assert_eq!(should_be, actual);
+}
+
+/// Ensure that identically-named elements at different depths are not deserialized as if they were
+/// at the same depth.
+#[test]
+fn nested_collection_repeated_elements() {
+    #[derive(Debug, Deserialize, PartialEq)]
+    struct OuterCollection {
+        a: Vec<A>,
+        inner: Inner,
+    }
+
+    #[derive(Debug, Deserialize, PartialEq)]
+    struct Inner {
+        a: A,
+    }
+
+    #[derive(Debug, Deserialize, PartialEq)]
+    struct A {
+        name: String,
+    }
+
+    init_logger();
+
+    let in_xml = r#"
+        <collection>
+            <a name="a1" />
+            <inner>
+                <a name="a2" />
+            </inner>
+            <a name="a3" />
+        </collection>
+    "#;
+
+    let should_be = OuterCollection {
+        a: vec![A { name: "a1".into() }, A { name: "a3".into() }],
+        inner: Inner {
+            a: A { name: "a2".into() },
+        },
+    };
+
+    let mut de = Deserializer::new_from_reader(in_xml.as_bytes()).non_contiguous_seq_elements(true);
+    let actual = OuterCollection::deserialize(&mut de).unwrap();
+
+    assert_eq!(should_be, actual);
+}