Initial import of serde_cbor-0.11.1 am: 2af68aa703 am: b90fe6f858 am: 0183f1f20c am: e8ee0a2ff2

Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/serde_cbor/+/1610053

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I3f74196962e316b4989dbcbf1d73adc376bfcbb8
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
new file mode 100644
index 0000000..efb3a6e
--- /dev/null
+++ b/.cargo_vcs_info.json
@@ -0,0 +1,5 @@
+{
+  "git": {
+    "sha1": "eddd181447c25722fa294dc2c1be8c1881b105eb"
+  }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4cc3f22
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+target
+Cargo.lock
+*.rs.bk
+tokamak.toml
+.idea
+*.iml
+examples/ferris.cbor
+.cargo/config
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..a3ce236
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,28 @@
+language: rust
+rust:
+  - 1.40.0
+  - stable
+  - beta
+  - nightly
+matrix:
+  allow_failures:
+    - rust: nightly
+sudo: false
+before_script:
+  - rustup component add rustfmt
+  - rustup target add thumbv7em-none-eabihf     # Any target that does not have a standard library will do
+script:
+  - cargo fmt --all -- --check
+  - (rustup component add clippy && cargo clippy --all -- -D clippy::all) || true
+  - cargo build
+  - cargo test
+  - >
+    [[ $TRAVIS_RUST_VERSION == "1.31.0" ]]
+    || cargo build --no-default-features --features alloc --target thumbv7em-none-eabihf
+    # Test we can build a platform that does not have std.
+  - cargo test --no-default-features --lib --tests # Run no_std tests
+  - >
+    [[ $TRAVIS_RUST_VERSION == "1.31.0" ]]
+    || cargo build --no-default-features --features alloc
+  - cargo build --features unsealed_read_write # The crate should still build when the unsealed_read_write feature is enabled.
+  - cargo build --no-default-features --features unsealed_read_write # The crate should still build when the unsealed_read_write feature is enabled and std disabled.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..1489ade
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,29 @@
+# Contributing to Serde CBOR
+Thanks for your interest!
+There are many ways to help:
+
+* write an issue about a problem you encountered
+* submit a pull request
+* add documentation and examples
+
+## Pull Requests
+
+Code should be easy to understand and documented.
+For new features and fixed bugs please add a test to one of the files in `test/`.
+The tests are run on Travis CI to catch regressions early.
+Format your code with `cargo fmt` before committing.
+Currently Serde CBOR does not contain `unsafe` code and I would like to keep it this way.
+
+## Making a Release
+
+* [ ] Make sure the crate compiles and all tests pass.
+* [ ] (Optional) Test that the fuzzer works and fuzz the crate for some time.
+* [ ] Write a list with all changes made since the last release
+* [ ] Increment the version number in `Cargo.toml` and the `README.md`. Bugfixes increase the patch version while new features or an increased minimum Rust version require a new minor version.
+* [ ] Check that the file `examples/readme.rs` and the example from the `README.md` match.
+* [ ] Commit the changes.
+* [ ] Add a git tag with the new version number:
+    `git tag "v42.0.2"`
+* [ ] Push the changes: `git push --tags`
+* [ ] Run `cargo publish`
+* [ ] Add a new release to GitHub with a list of changes.
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..3aa5f57
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,44 @@
+# 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 believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "serde_cbor"
+version = "0.11.1"
+authors = ["Pyfisch <[email protected]>", "Steven Fackler <[email protected]>"]
+description = "CBOR support for serde."
+readme = "README.md"
+keywords = ["serde", "cbor", "serialization", "no_std"]
+categories = ["encoding"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/pyfisch/cbor"
+[dependencies.half]
+version = "1.2.0"
+
+[dependencies.serde]
+version = "1.0.14"
+default-features = false
+[dev-dependencies.serde_derive]
+version = "1.0.14"
+default-features = false
+
+[features]
+alloc = ["serde/alloc"]
+default = ["std"]
+std = ["serde/std"]
+tags = []
+unsealed_read_write = []
+[badges.maintenance]
+status = "passively-maintained"
+
+[badges.travis-ci]
+repository = "pyfisch/cbor"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
new file mode 100644
index 0000000..8b5c14c
--- /dev/null
+++ b/Cargo.toml.orig
@@ -0,0 +1,33 @@
+[package]
+name = "serde_cbor"
+version = "0.11.1"
+authors = [
+    "Pyfisch <[email protected]>",
+    "Steven Fackler <[email protected]>"]
+repository = "https://github.com/pyfisch/cbor"
+readme = "README.md"
+license = "MIT/Apache-2.0"
+description = "CBOR support for serde."
+keywords = ["serde", "cbor", "serialization", "no_std"]
+categories = ["encoding"]
+edition = "2018"
+
+[badges]
+travis-ci = { repository = "pyfisch/cbor" }
+maintenance = { status = "passively-maintained" }
+
+[dependencies]
+half = "1.2.0"
+serde = { version = "1.0.14", default-features = false }
+
+[dev-dependencies]
+serde_derive = { version = "1.0.14", default-features = false }
+
+[features]
+default = ["std"]
+# Uses `alloc` library and adds support for vector functions with
+# `no_std`.
+alloc = ["serde/alloc"]
+std = ["serde/std" ]
+unsealed_read_write = []
+tags = []
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5624691
--- /dev/null
+++ b/README.md
@@ -0,0 +1,79 @@
+# Serde CBOR
+[![Build Status](https://travis-ci.org/pyfisch/cbor.svg?branch=master)](https://travis-ci.org/pyfisch/cbor)
+[![Crates.io](https://img.shields.io/crates/v/serde_cbor.svg)](https://crates.io/crates/serde_cbor)
+[![Documentation](https://docs.rs/serde_cbor/badge.svg)](https://docs.rs/serde_cbor)
+
+This crate implements the Concise Binary Object Representation from [RFC 7049].
+It builds on [Serde], the generic serialization framework for Rust.
+CBOR provides a binary encoding for a superset
+of the JSON data model that is small and very fast to parse.
+
+[RFC 7049]: https://tools.ietf.org/html/rfc7049
+[Serde]: https://github.com/serde-rs/serde
+
+## Usage
+
+Serde CBOR supports Rust 1.40 and up. Add this to your `Cargo.toml`:
+```toml
+[dependencies]
+serde_cbor = "0.11.1"
+```
+
+Storing and loading Rust types is easy and requires only
+minimal modifications to the program code.
+
+```rust
+use serde_derive::{Deserialize, Serialize};
+use std::error::Error;
+use std::fs::File;
+
+// Types annotated with `Serialize` can be stored as CBOR.
+// To be able to load them again add `Deserialize`.
+#[derive(Debug, Serialize, Deserialize)]
+struct Mascot {
+    name: String,
+    species: String,
+    year_of_birth: u32,
+}
+
+fn main() -> Result<(), Box<dyn Error>> {
+    let ferris = Mascot {
+        name: "Ferris".to_owned(),
+        species: "crab".to_owned(),
+        year_of_birth: 2015,
+    };
+
+    let ferris_file = File::create("examples/ferris.cbor")?;
+    // Write Ferris to the given file.
+    // Instead of a file you can use any type that implements `io::Write`
+    // like a HTTP body, database connection etc.
+    serde_cbor::to_writer(ferris_file, &ferris)?;
+
+    let tux_file = File::open("examples/tux.cbor")?;
+    // Load Tux from a file.
+    // Serde CBOR performs roundtrip serialization meaning that
+    // the data will not change in any way.
+    let tux: Mascot = serde_cbor::from_reader(tux_file)?;
+
+    println!("{:?}", tux);
+    // prints: Mascot { name: "Tux", species: "penguin", year_of_birth: 1996 }
+
+    Ok(())
+}
+```
+
+There are a lot of options available to customize the format.
+To operate on untyped CBOR values have a look at the `Value` type.
+
+## License
+Licensed under either of
+
+ * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
+ * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
+
+at your option.
+
+### Contribution
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
+additional terms or conditions.
diff --git a/examples/readme.rs b/examples/readme.rs
new file mode 100644
index 0000000..7689394
--- /dev/null
+++ b/examples/readme.rs
@@ -0,0 +1,39 @@
+// NOTE: This file should be kept in sync with README.md
+
+use serde_derive::{Deserialize, Serialize};
+use std::error::Error;
+use std::fs::File;
+
+// Types annotated with `Serialize` can be stored as CBOR.
+// To be able to load them again add `Deserialize`.
+#[derive(Debug, Serialize, Deserialize)]
+struct Mascot {
+    name: String,
+    species: String,
+    year_of_birth: u32,
+}
+
+fn main() -> Result<(), Box<dyn Error>> {
+    let ferris = Mascot {
+        name: "Ferris".to_owned(),
+        species: "crab".to_owned(),
+        year_of_birth: 2015,
+    };
+
+    let ferris_file = File::create("examples/ferris.cbor")?;
+    // Write Ferris to the given file.
+    // Instead of a file you can use any type that implements `io::Write`
+    // like a HTTP body, database connection etc.
+    serde_cbor::to_writer(ferris_file, &ferris)?;
+
+    let tux_file = File::open("examples/tux.cbor")?;
+    // Load Tux from a file.
+    // Serde CBOR performs roundtrip serialization meaning that
+    // the data will not change in any way.
+    let tux: Mascot = serde_cbor::from_reader(tux_file)?;
+
+    println!("{:?}", tux);
+    // prints: Mascot { name: "Tux", species: "penguin", year_of_birth: 1996 }
+
+    Ok(())
+}
diff --git a/examples/tags.rs b/examples/tags.rs
new file mode 100644
index 0000000..9281b9b
--- /dev/null
+++ b/examples/tags.rs
@@ -0,0 +1,84 @@
+use serde::de::{Deserialize, Deserializer};
+use serde::ser::{Serialize, Serializer};
+use serde_cbor::tags::Tagged;
+use serde_cbor::Value;
+use serde_derive::{Deserialize, Serialize};
+use std::error::Error;
+
+/// https://tools.ietf.org/html/rfc7049#section-2.4.1
+#[derive(Debug, PartialEq)]
+struct Date(String);
+
+impl Serialize for Date {
+    fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
+        Tagged::new(Some(0), &self.0).serialize(s)
+    }
+}
+
+impl<'de> Deserialize<'de> for Date {
+    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
+        let tagged = Tagged::<String>::deserialize(deserializer)?;
+        match tagged.tag {
+            Some(0) | None => Ok(Date(tagged.value)),
+            Some(_) => Err(serde::de::Error::custom("unexpected tag")),
+        }
+    }
+}
+
+/// https://tools.ietf.org/html/rfc7049#section-2.4.4.3
+#[derive(Debug, PartialEq)]
+struct Uri(String);
+
+impl Serialize for Uri {
+    fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
+        Tagged::new(Some(32), &self.0).serialize(s)
+    }
+}
+impl<'de> Deserialize<'de> for Uri {
+    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
+        let tagged = Tagged::<String>::deserialize(deserializer)?;
+        match tagged.tag {
+            // allow deserialization even if there is no tag. Allows roundtrip via other formats such as json
+            Some(0) | None => Ok(Uri(tagged.value)),
+            Some(_) => Err(serde::de::Error::custom("unexpected tag")),
+        }
+    }
+}
+
+#[derive(Debug, Serialize, Deserialize, PartialEq)]
+struct Bookmark {
+    title: String,
+    link: Uri,
+    created: Date,
+}
+
+fn main() -> Result<(), Box<dyn Error>> {
+    let bookmark = Bookmark {
+        title: "The Example Domain".into(),
+        link: Uri("http://example.org/".into()),
+        created: Date("2003-12-13T18:30:02Z".into()),
+    };
+
+    // serialize the struct to bytes
+    let bytes1 = serde_cbor::to_vec(&bookmark)?;
+    // deserialize to a serde_cbor::Value
+    let value1: Value = serde_cbor::from_slice(&bytes1)?;
+    println!("{:?}", value1);
+    // serialize the value to bytes
+    let bytes2 = serde_cbor::to_vec(&value1)?;
+    // deserialize to a serde_cbor::Value
+    let value2: Value = serde_cbor::from_slice(&bytes2)?;
+    println!("{:?}", value2);
+    // deserialize to a Bookmark
+    let result: Bookmark = serde_cbor::from_slice(&bytes2)?;
+
+    // check that the roundtrip was successful
+    assert_eq!(value1, value2);
+    assert_eq!(bookmark, result);
+
+    // check that going via a format that does not support tags does work
+    // let json = serde_json::to_vec(&bookmark)?;
+    // let result: Bookmark = serde_json::from_slice(&json)?;
+    // assert_eq!(bookmark, result);
+    Ok(())
+}
diff --git a/examples/tux.cbor b/examples/tux.cbor
new file mode 100644
index 0000000..c3331aa
--- /dev/null
+++ b/examples/tux.cbor
@@ -0,0 +1 @@
+£dnamecTuxgspeciesgpenguinmyear_of_birthÌ
\ No newline at end of file
diff --git a/src/de.rs b/src/de.rs
new file mode 100644
index 0000000..170e059
--- /dev/null
+++ b/src/de.rs
@@ -0,0 +1,1360 @@
+//! Deserialization.
+
+use core::f32;
+use core::marker::PhantomData;
+use core::result;
+use core::str;
+use half::f16;
+use serde::de;
+#[cfg(feature = "std")]
+use std::io;
+
+use crate::error::{Error, ErrorCode, Result};
+#[cfg(not(feature = "unsealed_read_write"))]
+use crate::read::EitherLifetime;
+#[cfg(feature = "unsealed_read_write")]
+pub use crate::read::EitherLifetime;
+#[cfg(feature = "std")]
+pub use crate::read::IoRead;
+use crate::read::Offset;
+#[cfg(any(feature = "std", feature = "alloc"))]
+pub use crate::read::SliceRead;
+pub use crate::read::{MutSliceRead, Read, SliceReadFixed};
+#[cfg(feature = "tags")]
+use crate::tags::set_tag;
+/// Decodes a value from CBOR data in a slice.
+///
+/// # Examples
+///
+/// Deserialize a `String`
+///
+/// ```
+/// # use serde_cbor::de;
+/// let v: Vec<u8> = vec![0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72];
+/// let value: String = de::from_slice(&v[..]).unwrap();
+/// assert_eq!(value, "foobar");
+/// ```
+///
+/// Deserialize a borrowed string with zero copies.
+///
+/// ```
+/// # use serde_cbor::de;
+/// let v: Vec<u8> = vec![0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72];
+/// let value: &str = de::from_slice(&v[..]).unwrap();
+/// assert_eq!(value, "foobar");
+/// ```
+#[cfg(any(feature = "std", feature = "alloc"))]
+pub fn from_slice<'a, T>(slice: &'a [u8]) -> Result<T>
+where
+    T: de::Deserialize<'a>,
+{
+    let mut deserializer = Deserializer::from_slice(slice);
+    let value = de::Deserialize::deserialize(&mut deserializer)?;
+    deserializer.end()?;
+    Ok(value)
+}
+
+// When the "std" feature is enabled there should be little to no need to ever use this function,
+// as `from_slice` covers all use cases (at the expense of being less efficient).
+/// Decode a value from CBOR data in a mutable slice.
+///
+/// This can be used in analogy to `from_slice`. Unlike `from_slice`, this will use the slice's
+/// mutability to rearrange data in it in order to resolve indefinite byte or text strings without
+/// resorting to allocations.
+pub fn from_mut_slice<'a, T>(slice: &'a mut [u8]) -> Result<T>
+where
+    T: de::Deserialize<'a>,
+{
+    let mut deserializer = Deserializer::from_mut_slice(slice);
+    let value = de::Deserialize::deserialize(&mut deserializer)?;
+    deserializer.end()?;
+    Ok(value)
+}
+
+// When the "std" feature is enabled there should be little to no need to ever use this function,
+// as `from_slice` covers all use cases and is much more reliable (at the expense of being less
+// efficient).
+/// Decode a value from CBOR data using a scratch buffer.
+///
+/// Users should generally prefer to use `from_slice` or `from_mut_slice` over this function,
+/// as decoding may fail when the scratch buffer turns out to be too small.
+///
+/// A realistic use case for this method would be decoding in a `no_std` environment from an
+/// immutable slice that is too large to copy.
+pub fn from_slice_with_scratch<'a, 'b, T>(slice: &'a [u8], scratch: &'b mut [u8]) -> Result<T>
+where
+    T: de::Deserialize<'a>,
+{
+    let mut deserializer = Deserializer::from_slice_with_scratch(slice, scratch);
+    let value = de::Deserialize::deserialize(&mut deserializer)?;
+    deserializer.end()?;
+    Ok(value)
+}
+
+/// Decodes a value from CBOR data in a reader.
+///
+/// # Examples
+///
+/// Deserialize a `String`
+///
+/// ```
+/// # use serde_cbor::de;
+/// let v: Vec<u8> = vec![0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72];
+/// let value: String = de::from_reader(&v[..]).unwrap();
+/// assert_eq!(value, "foobar");
+/// ```
+///
+/// Note that `from_reader` cannot borrow data:
+///
+/// ```compile_fail
+/// # use serde_cbor::de;
+/// let v: Vec<u8> = vec![0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72];
+/// let value: &str = de::from_reader(&v[..]).unwrap();
+/// assert_eq!(value, "foobar");
+/// ```
+#[cfg(feature = "std")]
+pub fn from_reader<T, R>(reader: R) -> Result<T>
+where
+    T: de::DeserializeOwned,
+    R: io::Read,
+{
+    let mut deserializer = Deserializer::from_reader(reader);
+    let value = de::Deserialize::deserialize(&mut deserializer)?;
+    deserializer.end()?;
+    Ok(value)
+}
+
+/// A Serde `Deserialize`r of CBOR data.
+#[derive(Debug)]
+pub struct Deserializer<R> {
+    read: R,
+    remaining_depth: u8,
+    accept_named: bool,
+    accept_packed: bool,
+    accept_standard_enums: bool,
+    accept_legacy_enums: bool,
+}
+
+#[cfg(feature = "std")]
+impl<R> Deserializer<IoRead<R>>
+where
+    R: io::Read,
+{
+    /// Constructs a `Deserializer` which reads from a `Read`er.
+    pub fn from_reader(reader: R) -> Deserializer<IoRead<R>> {
+        Deserializer::new(IoRead::new(reader))
+    }
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<'a> Deserializer<SliceRead<'a>> {
+    /// Constructs a `Deserializer` which reads from a slice.
+    ///
+    /// Borrowed strings and byte slices will be provided when possible.
+    pub fn from_slice(bytes: &'a [u8]) -> Deserializer<SliceRead<'a>> {
+        Deserializer::new(SliceRead::new(bytes))
+    }
+}
+
+impl<'a> Deserializer<MutSliceRead<'a>> {
+    /// Constructs a `Deserializer` which reads from a mutable slice that doubles as its own
+    /// scratch buffer.
+    ///
+    /// Borrowed strings and byte slices will be provided even for indefinite strings.
+    pub fn from_mut_slice(bytes: &'a mut [u8]) -> Deserializer<MutSliceRead<'a>> {
+        Deserializer::new(MutSliceRead::new(bytes))
+    }
+}
+
+impl<'a, 'b> Deserializer<SliceReadFixed<'a, 'b>> {
+    #[doc(hidden)]
+    pub fn from_slice_with_scratch(
+        bytes: &'a [u8],
+        scratch: &'b mut [u8],
+    ) -> Deserializer<SliceReadFixed<'a, 'b>> {
+        Deserializer::new(SliceReadFixed::new(bytes, scratch))
+    }
+}
+
+impl<'de, R> Deserializer<R>
+where
+    R: Read<'de>,
+{
+    /// Constructs a `Deserializer` from one of the possible serde_cbor input sources.
+    ///
+    /// `from_slice` and `from_reader` should normally be used instead of this method.
+    pub fn new(read: R) -> Self {
+        Deserializer {
+            read,
+            remaining_depth: 128,
+            accept_named: true,
+            accept_packed: true,
+            accept_standard_enums: true,
+            accept_legacy_enums: true,
+        }
+    }
+
+    /// Don't accept named variants and fields.
+    pub fn disable_named_format(mut self) -> Self {
+        self.accept_named = false;
+        self
+    }
+
+    /// Don't accept numbered variants and fields.
+    pub fn disable_packed_format(mut self) -> Self {
+        self.accept_packed = false;
+        self
+    }
+
+    /// Don't accept the new enum format used by `serde_cbor` versions >= v0.10.
+    pub fn disable_standard_enums(mut self) -> Self {
+        self.accept_standard_enums = false;
+        self
+    }
+
+    /// Don't accept the old enum format used by `serde_cbor` versions <= v0.9.
+    pub fn disable_legacy_enums(mut self) -> Self {
+        self.accept_legacy_enums = false;
+        self
+    }
+
+    /// This method should be called after a value has been deserialized to ensure there is no
+    /// trailing data in the input source.
+    pub fn end(&mut self) -> Result<()> {
+        match self.next()? {
+            Some(_) => Err(self.error(ErrorCode::TrailingData)),
+            None => Ok(()),
+        }
+    }
+
+    /// Turn a CBOR deserializer into an iterator over values of type T.
+    #[allow(clippy::should_implement_trait)] // Trait doesn't allow unconstrained T.
+    pub fn into_iter<T>(self) -> StreamDeserializer<'de, R, T>
+    where
+        T: de::Deserialize<'de>,
+    {
+        StreamDeserializer {
+            de: self,
+            output: PhantomData,
+            lifetime: PhantomData,
+        }
+    }
+
+    fn next(&mut self) -> Result<Option<u8>> {
+        self.read.next()
+    }
+
+    fn peek(&mut self) -> Result<Option<u8>> {
+        self.read.peek()
+    }
+
+    fn consume(&mut self) {
+        self.read.discard();
+    }
+
+    fn error(&self, reason: ErrorCode) -> Error {
+        let offset = self.read.offset();
+        Error::syntax(reason, offset)
+    }
+
+    fn parse_u8(&mut self) -> Result<u8> {
+        match self.next()? {
+            Some(byte) => Ok(byte),
+            None => Err(self.error(ErrorCode::EofWhileParsingValue)),
+        }
+    }
+
+    fn parse_u16(&mut self) -> Result<u16> {
+        let mut buf = [0; 2];
+        self.read
+            .read_into(&mut buf)
+            .map(|()| u16::from_be_bytes(buf))
+    }
+
+    fn parse_u32(&mut self) -> Result<u32> {
+        let mut buf = [0; 4];
+        self.read
+            .read_into(&mut buf)
+            .map(|()| u32::from_be_bytes(buf))
+    }
+
+    fn parse_u64(&mut self) -> Result<u64> {
+        let mut buf = [0; 8];
+        self.read
+            .read_into(&mut buf)
+            .map(|()| u64::from_be_bytes(buf))
+    }
+
+    fn parse_bytes<V>(&mut self, len: usize, visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        match self.read.read(len)? {
+            EitherLifetime::Long(buf) => visitor.visit_borrowed_bytes(buf),
+            EitherLifetime::Short(buf) => visitor.visit_bytes(buf),
+        }
+    }
+
+    fn parse_indefinite_bytes<V>(&mut self, visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        self.read.clear_buffer();
+        loop {
+            let byte = self.parse_u8()?;
+            let len = match byte {
+                0x40..=0x57 => byte as usize - 0x40,
+                0x58 => self.parse_u8()? as usize,
+                0x59 => self.parse_u16()? as usize,
+                0x5a => self.parse_u32()? as usize,
+                0x5b => {
+                    let len = self.parse_u64()?;
+                    if len > usize::max_value() as u64 {
+                        return Err(self.error(ErrorCode::LengthOutOfRange));
+                    }
+                    len as usize
+                }
+                0xff => break,
+                _ => return Err(self.error(ErrorCode::UnexpectedCode)),
+            };
+
+            self.read.read_to_buffer(len)?;
+        }
+
+        match self.read.take_buffer() {
+            EitherLifetime::Long(buf) => visitor.visit_borrowed_bytes(buf),
+            EitherLifetime::Short(buf) => visitor.visit_bytes(buf),
+        }
+    }
+
+    fn convert_str<'a>(buf: &'a [u8], buf_end_offset: u64) -> Result<&'a str> {
+        match str::from_utf8(buf) {
+            Ok(s) => Ok(s),
+            Err(e) => {
+                let shift = buf.len() - e.valid_up_to();
+                let offset = buf_end_offset - shift as u64;
+                Err(Error::syntax(ErrorCode::InvalidUtf8, offset))
+            }
+        }
+    }
+
+    fn parse_str<V>(&mut self, len: usize, visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        if let Some(offset) = self.read.offset().checked_add(len as u64) {
+            match self.read.read(len)? {
+                EitherLifetime::Long(buf) => {
+                    let s = Self::convert_str(buf, offset)?;
+                    visitor.visit_borrowed_str(s)
+                }
+                EitherLifetime::Short(buf) => {
+                    let s = Self::convert_str(buf, offset)?;
+                    visitor.visit_str(s)
+                }
+            }
+        } else {
+            // An overflow would have occured.
+            Err(Error::syntax(
+                ErrorCode::LengthOutOfRange,
+                self.read.offset(),
+            ))
+        }
+    }
+
+    fn parse_indefinite_str<V>(&mut self, visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        self.read.clear_buffer();
+        loop {
+            let byte = self.parse_u8()?;
+            let len = match byte {
+                0x60..=0x77 => byte as usize - 0x60,
+                0x78 => self.parse_u8()? as usize,
+                0x79 => self.parse_u16()? as usize,
+                0x7a => self.parse_u32()? as usize,
+                0x7b => {
+                    let len = self.parse_u64()?;
+                    if len > usize::max_value() as u64 {
+                        return Err(self.error(ErrorCode::LengthOutOfRange));
+                    }
+                    len as usize
+                }
+                0xff => break,
+                _ => return Err(self.error(ErrorCode::UnexpectedCode)),
+            };
+
+            self.read.read_to_buffer(len)?;
+        }
+
+        let offset = self.read.offset();
+        match self.read.take_buffer() {
+            EitherLifetime::Long(buf) => {
+                let s = Self::convert_str(buf, offset)?;
+                visitor.visit_borrowed_str(s)
+            }
+            EitherLifetime::Short(buf) => {
+                let s = Self::convert_str(buf, offset)?;
+                visitor.visit_str(s)
+            }
+        }
+    }
+
+    #[cfg(feature = "tags")]
+    fn handle_tagged_value<V>(&mut self, tag: u64, visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        self.recursion_checked(|d| {
+            set_tag(Some(tag));
+            let r = visitor.visit_newtype_struct(d);
+            set_tag(None);
+            r
+        })
+    }
+
+    #[cfg(not(feature = "tags"))]
+    fn handle_tagged_value<V>(&mut self, _tag: u64, visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        self.recursion_checked(|de| de.parse_value(visitor))
+    }
+
+    fn recursion_checked<F, T>(&mut self, f: F) -> Result<T>
+    where
+        F: FnOnce(&mut Deserializer<R>) -> Result<T>,
+    {
+        self.remaining_depth -= 1;
+        if self.remaining_depth == 0 {
+            return Err(self.error(ErrorCode::RecursionLimitExceeded));
+        }
+        let r = f(self);
+        self.remaining_depth += 1;
+        r
+    }
+
+    fn parse_array<V>(&mut self, mut len: usize, visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        self.recursion_checked(|de| {
+            let value = visitor.visit_seq(SeqAccess { de, len: &mut len })?;
+
+            if len != 0 {
+                Err(de.error(ErrorCode::TrailingData))
+            } else {
+                Ok(value)
+            }
+        })
+    }
+
+    fn parse_indefinite_array<V>(&mut self, visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        self.recursion_checked(|de| {
+            let value = visitor.visit_seq(IndefiniteSeqAccess { de })?;
+            match de.next()? {
+                Some(0xff) => Ok(value),
+                Some(_) => Err(de.error(ErrorCode::TrailingData)),
+                None => Err(de.error(ErrorCode::EofWhileParsingArray)),
+            }
+        })
+    }
+
+    fn parse_map<V>(&mut self, mut len: usize, visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        let accept_packed = self.accept_packed;
+        let accept_named = self.accept_named;
+        self.recursion_checked(|de| {
+            let value = visitor.visit_map(MapAccess {
+                de,
+                len: &mut len,
+                accept_named,
+                accept_packed,
+            })?;
+
+            if len != 0 {
+                Err(de.error(ErrorCode::TrailingData))
+            } else {
+                Ok(value)
+            }
+        })
+    }
+
+    fn parse_indefinite_map<V>(&mut self, visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        let accept_named = self.accept_named;
+        let accept_packed = self.accept_packed;
+        self.recursion_checked(|de| {
+            let value = visitor.visit_map(IndefiniteMapAccess {
+                de,
+                accept_packed,
+                accept_named,
+            })?;
+            match de.next()? {
+                Some(0xff) => Ok(value),
+                Some(_) => Err(de.error(ErrorCode::TrailingData)),
+                None => Err(de.error(ErrorCode::EofWhileParsingMap)),
+            }
+        })
+    }
+
+    fn parse_enum<V>(&mut self, mut len: usize, visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        self.recursion_checked(|de| {
+            let value = visitor.visit_enum(VariantAccess {
+                seq: SeqAccess { de, len: &mut len },
+            })?;
+
+            if len != 0 {
+                Err(de.error(ErrorCode::TrailingData))
+            } else {
+                Ok(value)
+            }
+        })
+    }
+
+    fn parse_enum_map<V>(&mut self, visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        let accept_named = self.accept_named;
+        let accept_packed = self.accept_packed;
+        self.recursion_checked(|de| {
+            let mut len = 1;
+            let value = visitor.visit_enum(VariantAccessMap {
+                map: MapAccess {
+                    de,
+                    len: &mut len,
+                    accept_packed,
+                    accept_named,
+                },
+            })?;
+
+            if len != 0 {
+                Err(de.error(ErrorCode::TrailingData))
+            } else {
+                Ok(value)
+            }
+        })
+    }
+
+    fn parse_indefinite_enum<V>(&mut self, visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        self.recursion_checked(|de| {
+            let value = visitor.visit_enum(VariantAccess {
+                seq: IndefiniteSeqAccess { de },
+            })?;
+            match de.next()? {
+                Some(0xff) => Ok(value),
+                Some(_) => Err(de.error(ErrorCode::TrailingData)),
+                None => Err(de.error(ErrorCode::EofWhileParsingArray)),
+            }
+        })
+    }
+
+    fn parse_f16(&mut self) -> Result<f32> {
+        Ok(f32::from(f16::from_bits(self.parse_u16()?)))
+    }
+
+    fn parse_f32(&mut self) -> Result<f32> {
+        self.parse_u32().map(|i| f32::from_bits(i))
+    }
+
+    fn parse_f64(&mut self) -> Result<f64> {
+        self.parse_u64().map(|i| f64::from_bits(i))
+    }
+
+    // Don't warn about the `unreachable!` in case
+    // exhaustive integer pattern matching is enabled.
+    #[allow(unreachable_patterns)]
+    fn parse_value<V>(&mut self, visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        let byte = self.parse_u8()?;
+        match byte {
+            // Major type 0: an unsigned integer
+            0x00..=0x17 => visitor.visit_u8(byte),
+            0x18 => {
+                let value = self.parse_u8()?;
+                visitor.visit_u8(value)
+            }
+            0x19 => {
+                let value = self.parse_u16()?;
+                visitor.visit_u16(value)
+            }
+            0x1a => {
+                let value = self.parse_u32()?;
+                visitor.visit_u32(value)
+            }
+            0x1b => {
+                let value = self.parse_u64()?;
+                visitor.visit_u64(value)
+            }
+            0x1c..=0x1f => Err(self.error(ErrorCode::UnassignedCode)),
+
+            // Major type 1: a negative integer
+            0x20..=0x37 => visitor.visit_i8(-1 - (byte - 0x20) as i8),
+            0x38 => {
+                let value = self.parse_u8()?;
+                visitor.visit_i16(-1 - i16::from(value))
+            }
+            0x39 => {
+                let value = self.parse_u16()?;
+                visitor.visit_i32(-1 - i32::from(value))
+            }
+            0x3a => {
+                let value = self.parse_u32()?;
+                visitor.visit_i64(-1 - i64::from(value))
+            }
+            0x3b => {
+                let value = self.parse_u64()?;
+                if value > i64::max_value() as u64 {
+                    return visitor.visit_i128(-1 - i128::from(value));
+                }
+                visitor.visit_i64(-1 - value as i64)
+            }
+            0x3c..=0x3f => Err(self.error(ErrorCode::UnassignedCode)),
+
+            // Major type 2: a byte string
+            0x40..=0x57 => self.parse_bytes(byte as usize - 0x40, visitor),
+            0x58 => {
+                let len = self.parse_u8()?;
+                self.parse_bytes(len as usize, visitor)
+            }
+            0x59 => {
+                let len = self.parse_u16()?;
+                self.parse_bytes(len as usize, visitor)
+            }
+            0x5a => {
+                let len = self.parse_u32()?;
+                self.parse_bytes(len as usize, visitor)
+            }
+            0x5b => {
+                let len = self.parse_u64()?;
+                if len > usize::max_value() as u64 {
+                    return Err(self.error(ErrorCode::LengthOutOfRange));
+                }
+                self.parse_bytes(len as usize, visitor)
+            }
+            0x5c..=0x5e => Err(self.error(ErrorCode::UnassignedCode)),
+            0x5f => self.parse_indefinite_bytes(visitor),
+
+            // Major type 3: a text string
+            0x60..=0x77 => self.parse_str(byte as usize - 0x60, visitor),
+            0x78 => {
+                let len = self.parse_u8()?;
+                self.parse_str(len as usize, visitor)
+            }
+            0x79 => {
+                let len = self.parse_u16()?;
+                self.parse_str(len as usize, visitor)
+            }
+            0x7a => {
+                let len = self.parse_u32()?;
+                self.parse_str(len as usize, visitor)
+            }
+            0x7b => {
+                let len = self.parse_u64()?;
+                if len > usize::max_value() as u64 {
+                    return Err(self.error(ErrorCode::LengthOutOfRange));
+                }
+                self.parse_str(len as usize, visitor)
+            }
+            0x7c..=0x7e => Err(self.error(ErrorCode::UnassignedCode)),
+            0x7f => self.parse_indefinite_str(visitor),
+
+            // Major type 4: an array of data items
+            0x80..=0x97 => self.parse_array(byte as usize - 0x80, visitor),
+            0x98 => {
+                let len = self.parse_u8()?;
+                self.parse_array(len as usize, visitor)
+            }
+            0x99 => {
+                let len = self.parse_u16()?;
+                self.parse_array(len as usize, visitor)
+            }
+            0x9a => {
+                let len = self.parse_u32()?;
+                self.parse_array(len as usize, visitor)
+            }
+            0x9b => {
+                let len = self.parse_u64()?;
+                if len > usize::max_value() as u64 {
+                    return Err(self.error(ErrorCode::LengthOutOfRange));
+                }
+                self.parse_array(len as usize, visitor)
+            }
+            0x9c..=0x9e => Err(self.error(ErrorCode::UnassignedCode)),
+            0x9f => self.parse_indefinite_array(visitor),
+
+            // Major type 5: a map of pairs of data items
+            0xa0..=0xb7 => self.parse_map(byte as usize - 0xa0, visitor),
+            0xb8 => {
+                let len = self.parse_u8()?;
+                self.parse_map(len as usize, visitor)
+            }
+            0xb9 => {
+                let len = self.parse_u16()?;
+                self.parse_map(len as usize, visitor)
+            }
+            0xba => {
+                let len = self.parse_u32()?;
+                self.parse_map(len as usize, visitor)
+            }
+            0xbb => {
+                let len = self.parse_u64()?;
+                if len > usize::max_value() as u64 {
+                    return Err(self.error(ErrorCode::LengthOutOfRange));
+                }
+                self.parse_map(len as usize, visitor)
+            }
+            0xbc..=0xbe => Err(self.error(ErrorCode::UnassignedCode)),
+            0xbf => self.parse_indefinite_map(visitor),
+
+            // Major type 6: optional semantic tagging of other major types
+            0xc0..=0xd7 => {
+                let tag = u64::from(byte) - 0xc0;
+                self.handle_tagged_value(tag, visitor)
+            }
+            0xd8 => {
+                let tag = self.parse_u8()?;
+                self.handle_tagged_value(tag.into(), visitor)
+            }
+            0xd9 => {
+                let tag = self.parse_u16()?;
+                self.handle_tagged_value(tag.into(), visitor)
+            }
+            0xda => {
+                let tag = self.parse_u32()?;
+                self.handle_tagged_value(tag.into(), visitor)
+            }
+            0xdb => {
+                let tag = self.parse_u64()?;
+                self.handle_tagged_value(tag, visitor)
+            }
+            0xdc..=0xdf => Err(self.error(ErrorCode::UnassignedCode)),
+
+            // Major type 7: floating-point numbers and other simple data types that need no content
+            0xe0..=0xf3 => Err(self.error(ErrorCode::UnassignedCode)),
+            0xf4 => visitor.visit_bool(false),
+            0xf5 => visitor.visit_bool(true),
+            0xf6 => visitor.visit_unit(),
+            0xf7 => visitor.visit_unit(),
+            0xf8 => Err(self.error(ErrorCode::UnassignedCode)),
+            0xf9 => {
+                let value = self.parse_f16()?;
+                visitor.visit_f32(value)
+            }
+            0xfa => {
+                let value = self.parse_f32()?;
+                visitor.visit_f32(value)
+            }
+            0xfb => {
+                let value = self.parse_f64()?;
+                visitor.visit_f64(value)
+            }
+            0xfc..=0xfe => Err(self.error(ErrorCode::UnassignedCode)),
+            0xff => Err(self.error(ErrorCode::UnexpectedCode)),
+
+            _ => unreachable!(),
+        }
+    }
+}
+
+impl<'de, 'a, R> de::Deserializer<'de> for &'a mut Deserializer<R>
+where
+    R: Read<'de>,
+{
+    type Error = Error;
+
+    #[inline]
+    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        self.parse_value(visitor)
+    }
+
+    #[inline]
+    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        match self.peek()? {
+            Some(0xf6) => {
+                self.consume();
+                visitor.visit_none()
+            }
+            _ => visitor.visit_some(self),
+        }
+    }
+
+    #[inline]
+    fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        visitor.visit_newtype_struct(self)
+    }
+
+    // Unit variants are encoded as just the variant identifier.
+    // Tuple variants are encoded as an array of the variant identifier followed by the fields.
+    // Struct variants are encoded as an array of the variant identifier followed by the struct.
+    #[inline]
+    fn deserialize_enum<V>(
+        self,
+        _name: &str,
+        _variants: &'static [&'static str],
+        visitor: V,
+    ) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        match self.peek()? {
+            Some(byte @ 0x80..=0x9f) => {
+                if !self.accept_legacy_enums {
+                    return Err(self.error(ErrorCode::WrongEnumFormat));
+                }
+                self.consume();
+                match byte {
+                    0x80..=0x97 => self.parse_enum(byte as usize - 0x80, visitor),
+                    0x98 => {
+                        let len = self.parse_u8()?;
+                        self.parse_enum(len as usize, visitor)
+                    }
+                    0x99 => {
+                        let len = self.parse_u16()?;
+                        self.parse_enum(len as usize, visitor)
+                    }
+                    0x9a => {
+                        let len = self.parse_u32()?;
+                        self.parse_enum(len as usize, visitor)
+                    }
+                    0x9b => {
+                        let len = self.parse_u64()?;
+                        if len > usize::max_value() as u64 {
+                            return Err(self.error(ErrorCode::LengthOutOfRange));
+                        }
+                        self.parse_enum(len as usize, visitor)
+                    }
+                    0x9c..=0x9e => Err(self.error(ErrorCode::UnassignedCode)),
+                    0x9f => self.parse_indefinite_enum(visitor),
+
+                    _ => unreachable!(),
+                }
+            }
+            Some(0xa1) => {
+                if !self.accept_standard_enums {
+                    return Err(self.error(ErrorCode::WrongEnumFormat));
+                }
+                self.consume();
+                self.parse_enum_map(visitor)
+            }
+            None => Err(self.error(ErrorCode::EofWhileParsingValue)),
+            _ => {
+                if !self.accept_standard_enums && !self.accept_legacy_enums {
+                    return Err(self.error(ErrorCode::WrongEnumFormat));
+                }
+                visitor.visit_enum(UnitVariantAccess { de: self })
+            }
+        }
+    }
+
+    #[inline]
+    fn is_human_readable(&self) -> bool {
+        false
+    }
+
+    serde::forward_to_deserialize_any! {
+        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string unit
+        unit_struct seq tuple tuple_struct map struct identifier ignored_any
+        bytes byte_buf
+    }
+}
+
+impl<R> Deserializer<R>
+where
+    R: Offset,
+{
+    /// Return the current offset in the reader
+    #[inline]
+    pub fn byte_offset(&self) -> usize {
+        self.read.byte_offset()
+    }
+}
+
+trait MakeError {
+    fn error(&self, code: ErrorCode) -> Error;
+}
+
+struct SeqAccess<'a, R> {
+    de: &'a mut Deserializer<R>,
+    len: &'a mut usize,
+}
+
+impl<'de, 'a, R> de::SeqAccess<'de> for SeqAccess<'a, R>
+where
+    R: Read<'de>,
+{
+    type Error = Error;
+
+    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
+    where
+        T: de::DeserializeSeed<'de>,
+    {
+        if *self.len == 0 {
+            return Ok(None);
+        }
+        *self.len -= 1;
+
+        let value = seed.deserialize(&mut *self.de)?;
+        Ok(Some(value))
+    }
+
+    fn size_hint(&self) -> Option<usize> {
+        Some(*self.len)
+    }
+}
+
+impl<'de, 'a, R> MakeError for SeqAccess<'a, R>
+where
+    R: Read<'de>,
+{
+    fn error(&self, code: ErrorCode) -> Error {
+        self.de.error(code)
+    }
+}
+
+struct IndefiniteSeqAccess<'a, R> {
+    de: &'a mut Deserializer<R>,
+}
+
+impl<'de, 'a, R> de::SeqAccess<'de> for IndefiniteSeqAccess<'a, R>
+where
+    R: Read<'de>,
+{
+    type Error = Error;
+
+    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
+    where
+        T: de::DeserializeSeed<'de>,
+    {
+        match self.de.peek()? {
+            Some(0xff) => return Ok(None),
+            Some(_) => {}
+            None => return Err(self.de.error(ErrorCode::EofWhileParsingArray)),
+        }
+
+        let value = seed.deserialize(&mut *self.de)?;
+        Ok(Some(value))
+    }
+}
+
+impl<'de, 'a, R> MakeError for IndefiniteSeqAccess<'a, R>
+where
+    R: Read<'de>,
+{
+    fn error(&self, code: ErrorCode) -> Error {
+        self.de.error(code)
+    }
+}
+
+struct MapAccess<'a, R> {
+    de: &'a mut Deserializer<R>,
+    len: &'a mut usize,
+    accept_named: bool,
+    accept_packed: bool,
+}
+
+impl<'de, 'a, R> de::MapAccess<'de> for MapAccess<'a, R>
+where
+    R: Read<'de>,
+{
+    type Error = Error;
+
+    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
+    where
+        K: de::DeserializeSeed<'de>,
+    {
+        if *self.len == 0 {
+            return Ok(None);
+        }
+        *self.len -= 1;
+
+        match self.de.peek()? {
+            Some(_byte @ 0x00..=0x1b) if !self.accept_packed => {
+                return Err(self.de.error(ErrorCode::WrongStructFormat));
+            }
+            Some(_byte @ 0x60..=0x7f) if !self.accept_named => {
+                return Err(self.de.error(ErrorCode::WrongStructFormat));
+            }
+            _ => {}
+        };
+
+        let value = seed.deserialize(&mut *self.de)?;
+        Ok(Some(value))
+    }
+
+    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
+    where
+        V: de::DeserializeSeed<'de>,
+    {
+        seed.deserialize(&mut *self.de)
+    }
+
+    fn size_hint(&self) -> Option<usize> {
+        Some(*self.len)
+    }
+}
+
+impl<'de, 'a, R> MakeError for MapAccess<'a, R>
+where
+    R: Read<'de>,
+{
+    fn error(&self, code: ErrorCode) -> Error {
+        self.de.error(code)
+    }
+}
+
+struct IndefiniteMapAccess<'a, R> {
+    de: &'a mut Deserializer<R>,
+    accept_packed: bool,
+    accept_named: bool,
+}
+
+impl<'de, 'a, R> de::MapAccess<'de> for IndefiniteMapAccess<'a, R>
+where
+    R: Read<'de>,
+{
+    type Error = Error;
+
+    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
+    where
+        K: de::DeserializeSeed<'de>,
+    {
+        match self.de.peek()? {
+            Some(_byte @ 0x00..=0x1b) if !self.accept_packed => {
+                return Err(self.de.error(ErrorCode::WrongStructFormat))
+            }
+            Some(_byte @ 0x60..=0x7f) if !self.accept_named => {
+                return Err(self.de.error(ErrorCode::WrongStructFormat))
+            }
+            Some(0xff) => return Ok(None),
+            Some(_) => {}
+            None => return Err(self.de.error(ErrorCode::EofWhileParsingMap)),
+        }
+
+        let value = seed.deserialize(&mut *self.de)?;
+        Ok(Some(value))
+    }
+
+    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
+    where
+        V: de::DeserializeSeed<'de>,
+    {
+        seed.deserialize(&mut *self.de)
+    }
+}
+
+struct UnitVariantAccess<'a, R> {
+    de: &'a mut Deserializer<R>,
+}
+
+impl<'de, 'a, R> de::EnumAccess<'de> for UnitVariantAccess<'a, R>
+where
+    R: Read<'de>,
+{
+    type Error = Error;
+    type Variant = UnitVariantAccess<'a, R>;
+
+    fn variant_seed<V>(self, seed: V) -> Result<(V::Value, UnitVariantAccess<'a, R>)>
+    where
+        V: de::DeserializeSeed<'de>,
+    {
+        let variant = seed.deserialize(&mut *self.de)?;
+        Ok((variant, self))
+    }
+}
+
+impl<'de, 'a, R> de::VariantAccess<'de> for UnitVariantAccess<'a, R>
+where
+    R: Read<'de>,
+{
+    type Error = Error;
+
+    fn unit_variant(self) -> Result<()> {
+        Ok(())
+    }
+
+    fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value>
+    where
+        T: de::DeserializeSeed<'de>,
+    {
+        Err(de::Error::invalid_type(
+            de::Unexpected::UnitVariant,
+            &"newtype variant",
+        ))
+    }
+
+    fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        Err(de::Error::invalid_type(
+            de::Unexpected::UnitVariant,
+            &"tuple variant",
+        ))
+    }
+
+    fn struct_variant<V>(self, _fields: &'static [&'static str], _visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        Err(de::Error::invalid_type(
+            de::Unexpected::UnitVariant,
+            &"struct variant",
+        ))
+    }
+}
+
+struct VariantAccess<T> {
+    seq: T,
+}
+
+impl<'de, T> de::EnumAccess<'de> for VariantAccess<T>
+where
+    T: de::SeqAccess<'de, Error = Error> + MakeError,
+{
+    type Error = Error;
+    type Variant = VariantAccess<T>;
+
+    fn variant_seed<V>(mut self, seed: V) -> Result<(V::Value, VariantAccess<T>)>
+    where
+        V: de::DeserializeSeed<'de>,
+    {
+        let variant = match self.seq.next_element_seed(seed) {
+            Ok(Some(variant)) => variant,
+            Ok(None) => return Err(self.seq.error(ErrorCode::ArrayTooShort)),
+            Err(e) => return Err(e),
+        };
+        Ok((variant, self))
+    }
+}
+
+impl<'de, T> de::VariantAccess<'de> for VariantAccess<T>
+where
+    T: de::SeqAccess<'de, Error = Error> + MakeError,
+{
+    type Error = Error;
+
+    fn unit_variant(mut self) -> Result<()> {
+        match self.seq.next_element() {
+            Ok(Some(())) => Ok(()),
+            Ok(None) => Err(self.seq.error(ErrorCode::ArrayTooLong)),
+            Err(e) => Err(e),
+        }
+    }
+
+    fn newtype_variant_seed<S>(mut self, seed: S) -> Result<S::Value>
+    where
+        S: de::DeserializeSeed<'de>,
+    {
+        match self.seq.next_element_seed(seed) {
+            Ok(Some(variant)) => Ok(variant),
+            Ok(None) => Err(self.seq.error(ErrorCode::ArrayTooShort)),
+            Err(e) => Err(e),
+        }
+    }
+
+    fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        visitor.visit_seq(self.seq)
+    }
+
+    fn struct_variant<V>(mut self, _fields: &'static [&'static str], visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        let seed = StructVariantSeed { visitor };
+        match self.seq.next_element_seed(seed) {
+            Ok(Some(variant)) => Ok(variant),
+            Ok(None) => Err(self.seq.error(ErrorCode::ArrayTooShort)),
+            Err(e) => Err(e),
+        }
+    }
+}
+
+struct StructVariantSeed<V> {
+    visitor: V,
+}
+
+impl<'de, V> de::DeserializeSeed<'de> for StructVariantSeed<V>
+where
+    V: de::Visitor<'de>,
+{
+    type Value = V::Value;
+
+    fn deserialize<D>(self, de: D) -> result::Result<V::Value, D::Error>
+    where
+        D: de::Deserializer<'de>,
+    {
+        de.deserialize_any(self.visitor)
+    }
+}
+
+/// Iterator that deserializes a stream into multiple CBOR values.
+///
+/// A stream deserializer can be created from any CBOR deserializer using the
+/// `Deserializer::into_iter` method.
+///
+/// ```
+/// # extern crate serde_cbor;
+/// use serde_cbor::de::Deserializer;
+/// use serde_cbor::value::Value;
+///
+/// # fn main() {
+/// let data: Vec<u8> = vec![
+///     0x01, 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72,
+/// ];
+/// let mut it = Deserializer::from_slice(&data[..]).into_iter::<Value>();
+/// assert_eq!(
+///     Value::Integer(1),
+///     it.next().unwrap().unwrap()
+/// );
+/// assert_eq!(
+///     Value::Text("foobar".to_string()),
+///     it.next().unwrap().unwrap()
+/// );
+/// # }
+/// ```
+#[derive(Debug)]
+pub struct StreamDeserializer<'de, R, T> {
+    de: Deserializer<R>,
+    output: PhantomData<T>,
+    lifetime: PhantomData<&'de ()>,
+}
+
+impl<'de, R, T> StreamDeserializer<'de, R, T>
+where
+    R: Read<'de>,
+    T: de::Deserialize<'de>,
+{
+    /// Create a new CBOR stream deserializer from one of the possible
+    /// serde_cbor input sources.
+    ///
+    /// Typically it is more convenient to use one of these methods instead:
+    ///
+    /// * `Deserializer::from_slice(...).into_iter()`
+    /// * `Deserializer::from_reader(...).into_iter()`
+    pub fn new(read: R) -> StreamDeserializer<'de, R, T> {
+        StreamDeserializer {
+            de: Deserializer::new(read),
+            output: PhantomData,
+            lifetime: PhantomData,
+        }
+    }
+}
+
+impl<'de, R, T> StreamDeserializer<'de, R, T>
+where
+    R: Offset,
+    T: de::Deserialize<'de>,
+{
+    /// Return the current offset in the reader
+    #[inline]
+    pub fn byte_offset(&self) -> usize {
+        self.de.byte_offset()
+    }
+}
+
+impl<'de, R, T> Iterator for StreamDeserializer<'de, R, T>
+where
+    R: Read<'de>,
+    T: de::Deserialize<'de>,
+{
+    type Item = Result<T>;
+
+    fn next(&mut self) -> Option<Result<T>> {
+        match self.de.peek() {
+            Ok(Some(_)) => Some(T::deserialize(&mut self.de)),
+            Ok(None) => None,
+            Err(e) => Some(Err(e)),
+        }
+    }
+}
+
+struct VariantAccessMap<T> {
+    map: T,
+}
+
+impl<'de, T> de::EnumAccess<'de> for VariantAccessMap<T>
+where
+    T: de::MapAccess<'de, Error = Error> + MakeError,
+{
+    type Error = Error;
+    type Variant = VariantAccessMap<T>;
+
+    fn variant_seed<V>(mut self, seed: V) -> Result<(V::Value, VariantAccessMap<T>)>
+    where
+        V: de::DeserializeSeed<'de>,
+    {
+        let variant = match self.map.next_key_seed(seed) {
+            Ok(Some(variant)) => variant,
+            Ok(None) => return Err(self.map.error(ErrorCode::ArrayTooShort)),
+            Err(e) => return Err(e),
+        };
+        Ok((variant, self))
+    }
+}
+
+impl<'de, T> de::VariantAccess<'de> for VariantAccessMap<T>
+where
+    T: de::MapAccess<'de, Error = Error> + MakeError,
+{
+    type Error = Error;
+
+    fn unit_variant(mut self) -> Result<()> {
+        match self.map.next_value() {
+            Ok(()) => Ok(()),
+            Err(e) => Err(e),
+        }
+    }
+
+    fn newtype_variant_seed<S>(mut self, seed: S) -> Result<S::Value>
+    where
+        S: de::DeserializeSeed<'de>,
+    {
+        self.map.next_value_seed(seed)
+    }
+
+    fn tuple_variant<V>(mut self, _len: usize, visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        let seed = StructVariantSeed { visitor };
+        self.map.next_value_seed(seed)
+    }
+
+    fn struct_variant<V>(mut self, _fields: &'static [&'static str], visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        let seed = StructVariantSeed { visitor };
+        self.map.next_value_seed(seed)
+    }
+}
diff --git a/src/error.rs b/src/error.rs
new file mode 100644
index 0000000..b1a6a45
--- /dev/null
+++ b/src/error.rs
@@ -0,0 +1,318 @@
+//! When serializing or deserializing CBOR goes wrong.
+use core::fmt;
+use core::result;
+use serde::de;
+use serde::ser;
+#[cfg(feature = "std")]
+use std::error;
+#[cfg(feature = "std")]
+use std::io;
+
+/// This type represents all possible errors that can occur when serializing or deserializing CBOR
+/// data.
+pub struct Error(ErrorImpl);
+
+/// Alias for a `Result` with the error type `serde_cbor::Error`.
+pub type Result<T> = result::Result<T, Error>;
+
+/// Categorizes the cause of a `serde_cbor::Error`.
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub enum Category {
+    /// The error was caused by a failure to read or write bytes on an IO stream.
+    Io,
+    /// The error was caused by input that was not syntactically valid CBOR.
+    Syntax,
+    /// The error was caused by input data that was semantically incorrect.
+    Data,
+    /// The error was caused by prematurely reaching the end of the input data.
+    Eof,
+}
+
+impl Error {
+    /// The byte offset at which the error occurred.
+    pub fn offset(&self) -> u64 {
+        self.0.offset
+    }
+
+    pub(crate) fn syntax(code: ErrorCode, offset: u64) -> Error {
+        Error(ErrorImpl { code, offset })
+    }
+
+    #[cfg(feature = "std")]
+    pub(crate) fn io(error: io::Error) -> Error {
+        Error(ErrorImpl {
+            code: ErrorCode::Io(error),
+            offset: 0,
+        })
+    }
+
+    #[cfg(all(not(feature = "std"), feature = "unsealed_read_write"))]
+    /// Creates an error signalling that the underlying `Read` encountered an I/O error.
+    pub fn io() -> Error {
+        Error(ErrorImpl {
+            code: ErrorCode::Io,
+            offset: 0,
+        })
+    }
+
+    #[cfg(feature = "unsealed_read_write")]
+    /// Creates an error signalling that the scratch buffer was too small to fit the data.
+    pub fn scratch_too_small(offset: u64) -> Error {
+        Error(ErrorImpl {
+            code: ErrorCode::ScratchTooSmall,
+            offset,
+        })
+    }
+
+    #[cfg(not(feature = "unsealed_read_write"))]
+    pub(crate) fn scratch_too_small(offset: u64) -> Error {
+        Error(ErrorImpl {
+            code: ErrorCode::ScratchTooSmall,
+            offset,
+        })
+    }
+
+    #[cfg(feature = "unsealed_read_write")]
+    /// Creates an error with a custom message.
+    ///
+    /// **Note**: When the "std" feature is disabled, the message will be discarded.
+    pub fn message<T: fmt::Display>(_msg: T) -> Error {
+        #[cfg(not(feature = "std"))]
+        {
+            Error(ErrorImpl {
+                code: ErrorCode::Message,
+                offset: 0,
+            })
+        }
+        #[cfg(feature = "std")]
+        {
+            Error(ErrorImpl {
+                code: ErrorCode::Message(_msg.to_string()),
+                offset: 0,
+            })
+        }
+    }
+
+    #[cfg(not(feature = "unsealed_read_write"))]
+    pub(crate) fn message<T: fmt::Display>(_msg: T) -> Error {
+        #[cfg(not(feature = "std"))]
+        {
+            Error(ErrorImpl {
+                code: ErrorCode::Message,
+                offset: 0,
+            })
+        }
+        #[cfg(feature = "std")]
+        {
+            Error(ErrorImpl {
+                code: ErrorCode::Message(_msg.to_string()),
+                offset: 0,
+            })
+        }
+    }
+
+    #[cfg(feature = "unsealed_read_write")]
+    /// Creates an error signalling that the underlying read
+    /// encountered an end of input.
+    pub fn eof(offset: u64) -> Error {
+        Error(ErrorImpl {
+            code: ErrorCode::EofWhileParsingValue,
+            offset,
+        })
+    }
+
+    /// Categorizes the cause of this error.
+    pub fn classify(&self) -> Category {
+        match self.0.code {
+            #[cfg(feature = "std")]
+            ErrorCode::Message(_) => Category::Data,
+            #[cfg(not(feature = "std"))]
+            ErrorCode::Message => Category::Data,
+            #[cfg(feature = "std")]
+            ErrorCode::Io(_) => Category::Io,
+            #[cfg(not(feature = "std"))]
+            ErrorCode::Io => Category::Io,
+            ErrorCode::ScratchTooSmall => Category::Io,
+            ErrorCode::EofWhileParsingValue
+            | ErrorCode::EofWhileParsingArray
+            | ErrorCode::EofWhileParsingMap => Category::Eof,
+            ErrorCode::LengthOutOfRange
+            | ErrorCode::InvalidUtf8
+            | ErrorCode::UnassignedCode
+            | ErrorCode::UnexpectedCode
+            | ErrorCode::TrailingData
+            | ErrorCode::ArrayTooShort
+            | ErrorCode::ArrayTooLong
+            | ErrorCode::RecursionLimitExceeded
+            | ErrorCode::WrongEnumFormat
+            | ErrorCode::WrongStructFormat => Category::Syntax,
+        }
+    }
+
+    /// Returns true if this error was caused by a failure to read or write bytes on an IO stream.
+    pub fn is_io(&self) -> bool {
+        match self.classify() {
+            Category::Io => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if this error was caused by input that was not syntactically valid CBOR.
+    pub fn is_syntax(&self) -> bool {
+        match self.classify() {
+            Category::Syntax => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if this error was caused by data that was semantically incorrect.
+    pub fn is_data(&self) -> bool {
+        match self.classify() {
+            Category::Data => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if this error was caused by prematurely reaching the end of the input data.
+    pub fn is_eof(&self) -> bool {
+        match self.classify() {
+            Category::Eof => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if this error was caused by the scratch buffer being too small.
+    ///
+    /// Note this being `true` implies that `is_io()` is also `true`.
+    pub fn is_scratch_too_small(&self) -> bool {
+        match self.0.code {
+            ErrorCode::ScratchTooSmall => true,
+            _ => false,
+        }
+    }
+}
+
+#[cfg(feature = "std")]
+impl error::Error for Error {
+    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
+        match self.0.code {
+            ErrorCode::Io(ref err) => Some(err),
+            _ => None,
+        }
+    }
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        if self.0.offset == 0 {
+            fmt::Display::fmt(&self.0.code, f)
+        } else {
+            write!(f, "{} at offset {}", self.0.code, self.0.offset)
+        }
+    }
+}
+
+impl fmt::Debug for Error {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&self.0, fmt)
+    }
+}
+
+impl de::Error for Error {
+    fn custom<T: fmt::Display>(msg: T) -> Error {
+        Error::message(msg)
+    }
+
+    fn invalid_type(unexp: de::Unexpected<'_>, exp: &dyn de::Expected) -> Error {
+        if let de::Unexpected::Unit = unexp {
+            Error::custom(format_args!("invalid type: null, expected {}", exp))
+        } else {
+            Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp))
+        }
+    }
+}
+
+impl ser::Error for Error {
+    fn custom<T: fmt::Display>(msg: T) -> Error {
+        Error::message(msg)
+    }
+}
+
+#[cfg(feature = "std")]
+impl From<io::Error> for Error {
+    fn from(e: io::Error) -> Error {
+        Error::io(e)
+    }
+}
+
+#[cfg(not(feature = "std"))]
+impl From<core::fmt::Error> for Error {
+    fn from(_: core::fmt::Error) -> Error {
+        Error(ErrorImpl {
+            code: ErrorCode::Message,
+            offset: 0,
+        })
+    }
+}
+
+#[derive(Debug)]
+struct ErrorImpl {
+    code: ErrorCode,
+    offset: u64,
+}
+
+#[derive(Debug)]
+pub(crate) enum ErrorCode {
+    #[cfg(feature = "std")]
+    Message(String),
+    #[cfg(not(feature = "std"))]
+    Message,
+    #[cfg(feature = "std")]
+    Io(io::Error),
+    #[allow(unused)]
+    #[cfg(not(feature = "std"))]
+    Io,
+    ScratchTooSmall,
+    EofWhileParsingValue,
+    EofWhileParsingArray,
+    EofWhileParsingMap,
+    LengthOutOfRange,
+    InvalidUtf8,
+    UnassignedCode,
+    UnexpectedCode,
+    TrailingData,
+    ArrayTooShort,
+    ArrayTooLong,
+    RecursionLimitExceeded,
+    WrongEnumFormat,
+    WrongStructFormat,
+}
+
+impl fmt::Display for ErrorCode {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            #[cfg(feature = "std")]
+            ErrorCode::Message(ref msg) => f.write_str(msg),
+            #[cfg(not(feature = "std"))]
+            ErrorCode::Message => f.write_str("Unknown error"),
+            #[cfg(feature = "std")]
+            ErrorCode::Io(ref err) => fmt::Display::fmt(err, f),
+            #[cfg(not(feature = "std"))]
+            ErrorCode::Io => f.write_str("Unknown I/O error"),
+            ErrorCode::ScratchTooSmall => f.write_str("Scratch buffer too small"),
+            ErrorCode::EofWhileParsingValue => f.write_str("EOF while parsing a value"),
+            ErrorCode::EofWhileParsingArray => f.write_str("EOF while parsing an array"),
+            ErrorCode::EofWhileParsingMap => f.write_str("EOF while parsing a map"),
+            ErrorCode::LengthOutOfRange => f.write_str("length out of range"),
+            ErrorCode::InvalidUtf8 => f.write_str("invalid UTF-8"),
+            ErrorCode::UnassignedCode => f.write_str("unassigned type"),
+            ErrorCode::UnexpectedCode => f.write_str("unexpected code"),
+            ErrorCode::TrailingData => f.write_str("trailing data"),
+            ErrorCode::ArrayTooShort => f.write_str("array too short"),
+            ErrorCode::ArrayTooLong => f.write_str("array too long"),
+            ErrorCode::RecursionLimitExceeded => f.write_str("recursion limit exceeded"),
+            ErrorCode::WrongEnumFormat => f.write_str("wrong enum format"),
+            ErrorCode::WrongStructFormat => f.write_str("wrong struct format"),
+        }
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..1736ce8
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,311 @@
+//! CBOR and serialization.
+//!
+//! # Usage
+//!
+//! Serde CBOR supports Rust 1.40 and up. Add this to your `Cargo.toml`:
+//! ```toml
+//! [dependencies]
+//! serde_cbor = "0.10"
+//! ```
+//!
+//! Storing and loading Rust types is easy and requires only
+//! minimal modifications to the program code.
+//!
+//! ```rust
+//! use serde_derive::{Deserialize, Serialize};
+//! use std::error::Error;
+//! use std::fs::File;
+//!
+//! // Types annotated with `Serialize` can be stored as CBOR.
+//! // To be able to load them again add `Deserialize`.
+//! #[derive(Debug, Serialize, Deserialize)]
+//! struct Mascot {
+//!     name: String,
+//!     species: String,
+//!     year_of_birth: u32,
+//! }
+//!
+//! fn main() -> Result<(), Box<dyn Error>> {
+//!     let ferris = Mascot {
+//!         name: "Ferris".to_owned(),
+//!         species: "crab".to_owned(),
+//!         year_of_birth: 2015,
+//!     };
+//!
+//!     let ferris_file = File::create("examples/ferris.cbor")?;
+//!     // Write Ferris to the given file.
+//!     // Instead of a file you can use any type that implements `io::Write`
+//!     // like a HTTP body, database connection etc.
+//!     serde_cbor::to_writer(ferris_file, &ferris)?;
+//!
+//!     let tux_file = File::open("examples/tux.cbor")?;
+//!     // Load Tux from a file.
+//!     // Serde CBOR performs roundtrip serialization meaning that
+//!     // the data will not change in any way.
+//!     let tux: Mascot = serde_cbor::from_reader(tux_file)?;
+//!
+//!     println!("{:?}", tux);
+//!     // prints: Mascot { name: "Tux", species: "penguin", year_of_birth: 1996 }
+//!
+//!     Ok(())
+//! }
+//! ```
+//!
+//! There are a lot of options available to customize the format.
+//! To operate on untyped CBOR values have a look at the `Value` type.
+//!
+//! # Type-based Serialization and Deserialization
+//! Serde provides a mechanism for low boilerplate serialization & deserialization of values to and
+//! from CBOR via the serialization API. To be able to serialize a piece of data, it must implement
+//! the `serde::Serialize` trait. To be able to deserialize a piece of data, it must implement the
+//! `serde::Deserialize` trait. Serde provides an annotation to automatically generate the
+//! code for these traits: `#[derive(Serialize, Deserialize)]`.
+//!
+//! The CBOR API also provides an enum `serde_cbor::Value`.
+//!
+//! # Packed Encoding
+//! When serializing structs or enums in CBOR the keys or enum variant names will be serialized
+//! as string keys to a map. Especially in embedded environments this can increase the file
+//! size too much. In packed encoding the keys and variants will be serialized as variable sized
+//! integers. The first 24 entries in any struct consume only a single byte!
+//! To serialize a document in this format use `Serializer::new(writer).packed_format()` or
+//! the shorthand `ser::to_vec_packed`. The deserialization works without any changes.
+//!
+//! # Self describing documents
+//! In some contexts different formats are used but there is no way to declare the format used
+//! out of band. For this reason CBOR has a magic number that may be added before any document.
+//! Self describing documents are created with `serializer.self_describe()`.
+//!
+//! # Examples
+//! Read a CBOR value that is known to be a map of string keys to string values and print it.
+//!
+//! ```rust
+//! use std::collections::BTreeMap;
+//! use serde_cbor::from_slice;
+//!
+//! let slice = b"\xa5aaaAabaBacaCadaDaeaE";
+//! let value: BTreeMap<String, String> = from_slice(slice).unwrap();
+//! println!("{:?}", value); // {"e": "E", "d": "D", "a": "A", "c": "C", "b": "B"}
+//! ```
+//!
+//! Read a general CBOR value with an unknown content.
+//!
+//! ```rust
+//! use serde_cbor::from_slice;
+//! use serde_cbor::value::Value;
+//!
+//! let slice = b"\x82\x01\xa1aaab";
+//! let value: Value = from_slice(slice).unwrap();
+//! println!("{:?}", value); // Array([U64(1), Object({String("a"): String("b")})])
+//! ```
+//!
+//! Serialize an object.
+//!
+//! ```rust
+//! use std::collections::BTreeMap;
+//! use serde_cbor::to_vec;
+//!
+//! let mut programming_languages = BTreeMap::new();
+//! programming_languages.insert("rust", vec!["safe", "concurrent", "fast"]);
+//! programming_languages.insert("python", vec!["powerful", "friendly", "open"]);
+//! programming_languages.insert("js", vec!["lightweight", "interpreted", "object-oriented"]);
+//! let encoded = to_vec(&programming_languages);
+//! assert_eq!(encoded.unwrap().len(), 103);
+//! ```
+//!
+//! Deserializing data in the middle of a slice
+//! ```
+//! # extern crate serde_cbor;
+//! use serde_cbor::Deserializer;
+//!
+//! # fn main() {
+//! let data: Vec<u8> = vec![
+//!     0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x66, 0x66, 0x6f, 0x6f, 0x62,
+//!     0x61, 0x72,
+//! ];
+//! let mut deserializer = Deserializer::from_slice(&data);
+//! let value: &str = serde::de::Deserialize::deserialize(&mut deserializer)
+//!     .unwrap();
+//! let rest = &data[deserializer.byte_offset()..];
+//! assert_eq!(value, "foobar");
+//! assert_eq!(rest, &[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]);
+//! # }
+//! ```
+//!
+//! # `no-std` support
+//!
+//! Serde CBOR supports building in a `no_std` context, use the following lines
+//! in your `Cargo.toml` dependencies:
+//! ``` toml
+//! [dependencies]
+//! serde = { version = "1.0", default-features = false }
+//! serde_cbor = { version = "0.10", default-features = false }
+//! ```
+//!
+//! Without the `std` feature the functions [from_reader], [from_slice], [to_vec], and [to_writer]
+//! are not exported. To export [from_slice] and [to_vec] enable the `alloc` feature. The `alloc`
+//! feature uses the [`alloc` library][alloc-lib] and requires at least version 1.36.0 of Rust.
+//!
+//! [alloc-lib]: https://doc.rust-lang.org/alloc/
+//!
+//! *Note*: to use derive macros in serde you will need to declare `serde`
+//! dependency like so:
+//! ``` toml
+//! serde = { version = "1.0", default-features = false, features = ["derive"] }
+//! ```
+//!
+//! Serialize an object with `no_std` and without `alloc`.
+//! ``` rust
+//! # #[macro_use] extern crate serde_derive;
+//! # fn main() -> Result<(), serde_cbor::Error> {
+//! use serde::Serialize;
+//! use serde_cbor::Serializer;
+//! use serde_cbor::ser::SliceWrite;
+//!
+//! #[derive(Serialize)]
+//! struct User {
+//!     user_id: u32,
+//!     password_hash: [u8; 4],
+//! }
+//!
+//! let mut buf = [0u8; 100];
+//! let writer = SliceWrite::new(&mut buf[..]);
+//! let mut ser = Serializer::new(writer);
+//! let user = User {
+//!     user_id: 42,
+//!     password_hash: [1, 2, 3, 4],
+//! };
+//! user.serialize(&mut ser)?;
+//! let writer = ser.into_inner();
+//! let size = writer.bytes_written();
+//! let expected = [
+//!     0xa2, 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x2a, 0x6d,
+//!     0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73,
+//!     0x68, 0x84, 0x1, 0x2, 0x3, 0x4
+//! ];
+//! assert_eq!(&buf[..size], expected);
+//! # Ok(())
+//! # }
+//! ```
+//!
+//! Deserialize an object.
+//! ``` rust
+//! # #[macro_use] extern crate serde_derive;
+//! # fn main() -> Result<(), serde_cbor::Error> {
+//! #[derive(Debug, PartialEq, Deserialize)]
+//! struct User {
+//!     user_id: u32,
+//!     password_hash: [u8; 4],
+//! }
+//!
+//! let value = [
+//!     0xa2, 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x2a, 0x6d,
+//!     0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73,
+//!     0x68, 0x84, 0x1, 0x2, 0x3, 0x4
+//! ];
+//!
+//! // from_slice_with_scratch will not alter input data, use it whenever you
+//! // borrow from somewhere else.
+//! // You will have to size your scratch according to the input data you
+//! // expect.
+//! use serde_cbor::de::from_slice_with_scratch;
+//! let mut scratch = [0u8; 32];
+//! let user: User = from_slice_with_scratch(&value[..], &mut scratch)?;
+//! assert_eq!(user, User {
+//!     user_id: 42,
+//!     password_hash: [1, 2, 3, 4],
+//! });
+//!
+//! let mut value = [
+//!     0xa2, 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x2a, 0x6d,
+//!     0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73,
+//!     0x68, 0x84, 0x1, 0x2, 0x3, 0x4
+//! ];
+//!
+//! // from_mut_slice will move data around the input slice, you may only use it
+//! // on data you may own or can modify.
+//! use serde_cbor::de::from_mut_slice;
+//! let user: User = from_mut_slice(&mut value[..])?;
+//! assert_eq!(user, User {
+//!     user_id: 42,
+//!     password_hash: [1, 2, 3, 4],
+//! });
+//! # Ok(())
+//! # }
+//! ```
+//!
+//! # Limitations
+//!
+//! While Serde CBOR strives to support all features of Serde and CBOR
+//! there are a few limitations.
+//!
+//! * [Tags] are ignored during deserialization and can't be emitted during
+//!     serialization. This is because Serde has no concept of tagged
+//!     values. See:&nbsp;[#3]
+//! * Unknown [simple values] cause an `UnassignedCode` error.
+//!     The simple values *False* and *True* are recognized and parsed as bool.
+//!     *Null* and *Undefined* are both deserialized as *unit*.
+//!     The *unit* type is serialized as *Null*. See:&nbsp;[#86]
+//! * [128-bit integers] can't be directly encoded in CBOR. If you need them
+//!     store them as a byte string. See:&nbsp;[#77]
+//!
+//! [Tags]: https://tools.ietf.org/html/rfc7049#section-2.4.4
+//! [#3]: https://github.com/pyfisch/cbor/issues/3
+//! [simple values]: https://tools.ietf.org/html/rfc7049#section-3.5
+//! [#86]: https://github.com/pyfisch/cbor/issues/86
+//! [128-bit integers]: https://doc.rust-lang.org/std/primitive.u128.html
+//! [#77]: https://github.com/pyfisch/cbor/issues/77
+
+#![deny(missing_docs)]
+#![cfg_attr(not(feature = "std"), no_std)]
+
+// When we are running tests in no_std mode we need to explicitly link std, because `cargo test`
+// will not work without it.
+#[cfg(all(not(feature = "std"), test))]
+extern crate std;
+
+#[cfg(feature = "alloc")]
+extern crate alloc;
+
+pub mod de;
+pub mod error;
+mod read;
+pub mod ser;
+pub mod tags;
+mod write;
+
+#[cfg(feature = "std")]
+pub mod value;
+
+// Re-export the [items recommended by serde](https://serde.rs/conventions.html).
+#[doc(inline)]
+pub use crate::de::{Deserializer, StreamDeserializer};
+
+#[doc(inline)]
+pub use crate::error::{Error, Result};
+
+#[doc(inline)]
+pub use crate::ser::Serializer;
+
+// Convenience functions for serialization and deserialization.
+// These functions are only available in `std` mode.
+#[cfg(feature = "std")]
+#[doc(inline)]
+pub use crate::de::from_reader;
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+#[doc(inline)]
+pub use crate::de::from_slice;
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+#[doc(inline)]
+pub use crate::ser::to_vec;
+
+#[cfg(feature = "std")]
+#[doc(inline)]
+pub use crate::ser::to_writer;
+
+// Re-export the value type like serde_json
+#[cfg(feature = "std")]
+#[doc(inline)]
+pub use crate::value::Value;
diff --git a/src/read.rs b/src/read.rs
new file mode 100644
index 0000000..1b53018
--- /dev/null
+++ b/src/read.rs
@@ -0,0 +1,637 @@
+#[cfg(feature = "alloc")]
+use alloc::{vec, vec::Vec};
+#[cfg(feature = "std")]
+use core::cmp;
+use core::mem;
+
+#[cfg(feature = "std")]
+use std::io::{self, Read as StdRead};
+
+use crate::error::{Error, ErrorCode, Result};
+
+#[cfg(not(feature = "unsealed_read_write"))]
+/// Trait used by the deserializer for iterating over input.
+///
+/// This trait is sealed by default, enabling the `unsealed_read_write` feature removes this bound
+/// to allow objects outside of this crate to implement this trait.
+pub trait Read<'de>: private::Sealed {
+    #[doc(hidden)]
+    /// Read n bytes from the input.
+    ///
+    /// Implementations that can are asked to return a slice with a Long lifetime that outlives the
+    /// decoder, but others (eg. ones that need to allocate the data into a temporary buffer) can
+    /// return it with a Short lifetime that just lives for the time of read's mutable borrow of
+    /// the reader.
+    ///
+    /// This may, as a side effect, clear the reader's scratch buffer (as the provided
+    /// implementation does).
+
+    // A more appropriate lifetime setup for this (that would allow the Deserializer::convert_str
+    // to stay a function) would be something like `fn read<'a, 'r: 'a>(&'a mut 'r immut self, ...) -> ...
+    // EitherLifetime<'r, 'de>>`, which borrows self mutably for the duration of the function and
+    // downgrates that reference to an immutable one that outlives the result (protecting the
+    // scratch buffer from changes), but alas, that can't be expressed (yet?).
+    fn read<'a>(&'a mut self, n: usize) -> Result<EitherLifetime<'a, 'de>> {
+        self.clear_buffer();
+        self.read_to_buffer(n)?;
+
+        Ok(self.take_buffer())
+    }
+
+    #[doc(hidden)]
+    fn next(&mut self) -> Result<Option<u8>>;
+
+    #[doc(hidden)]
+    fn peek(&mut self) -> Result<Option<u8>>;
+
+    #[doc(hidden)]
+    fn clear_buffer(&mut self);
+
+    #[doc(hidden)]
+    fn read_to_buffer(&mut self, n: usize) -> Result<()>;
+
+    #[doc(hidden)]
+    fn take_buffer<'a>(&'a mut self) -> EitherLifetime<'a, 'de>;
+
+    #[doc(hidden)]
+    fn read_into(&mut self, buf: &mut [u8]) -> Result<()>;
+
+    #[doc(hidden)]
+    fn discard(&mut self);
+
+    #[doc(hidden)]
+    fn offset(&self) -> u64;
+}
+
+#[cfg(feature = "unsealed_read_write")]
+/// Trait used by the deserializer for iterating over input.
+pub trait Read<'de> {
+    /// Read n bytes from the input.
+    ///
+    /// Implementations that can are asked to return a slice with a Long lifetime that outlives the
+    /// decoder, but others (eg. ones that need to allocate the data into a temporary buffer) can
+    /// return it with a Short lifetime that just lives for the time of read's mutable borrow of
+    /// the reader.
+    ///
+    /// This may, as a side effect, clear the reader's scratch buffer (as the provided
+    /// implementation does).
+
+    // A more appropriate lifetime setup for this (that would allow the Deserializer::convert_str
+    // to stay a function) would be something like `fn read<'a, 'r: 'a>(&'a mut 'r immut self, ...) -> ...
+    // EitherLifetime<'r, 'de>>`, which borrows self mutably for the duration of the function and
+    // downgrates that reference to an immutable one that outlives the result (protecting the
+    // scratch buffer from changes), but alas, that can't be expressed (yet?).
+    fn read<'a>(&'a mut self, n: usize) -> Result<EitherLifetime<'a, 'de>> {
+        self.clear_buffer();
+        self.read_to_buffer(n)?;
+
+        Ok(self.take_buffer())
+    }
+
+    /// Read the next byte from the input, if any.
+    fn next(&mut self) -> Result<Option<u8>>;
+
+    /// Peek at the next byte of the input, if any. This does not advance the reader, so the result
+    /// of this function will remain the same until a read or clear occurs.
+    fn peek(&mut self) -> Result<Option<u8>>;
+
+    /// Clear the underlying scratch buffer
+    fn clear_buffer(&mut self);
+
+    /// Append n bytes from the reader to the reader's scratch buffer (without clearing it)
+    fn read_to_buffer(&mut self, n: usize) -> Result<()>;
+
+    /// Read out everything accumulated in the reader's scratch buffer. This may, as a side effect,
+    /// clear it.
+    fn take_buffer<'a>(&'a mut self) -> EitherLifetime<'a, 'de>;
+
+    /// Read from the input until `buf` is full or end of input is encountered.
+    fn read_into(&mut self, buf: &mut [u8]) -> Result<()>;
+
+    /// Discard any data read by `peek`.
+    fn discard(&mut self);
+
+    /// Returns the offset from the start of the reader.
+    fn offset(&self) -> u64;
+}
+
+/// Represents a reader that can return its current position
+pub trait Offset {
+    fn byte_offset(&self) -> usize;
+}
+
+/// Represents a buffer with one of two lifetimes.
+pub enum EitherLifetime<'short, 'long> {
+    /// The short lifetime
+    Short(&'short [u8]),
+    /// The long lifetime
+    Long(&'long [u8]),
+}
+
+#[cfg(not(feature = "unsealed_read_write"))]
+mod private {
+    pub trait Sealed {}
+}
+
+/// CBOR input source that reads from a std::io input stream.
+#[cfg(feature = "std")]
+#[derive(Debug)]
+pub struct IoRead<R>
+where
+    R: io::Read,
+{
+    reader: OffsetReader<R>,
+    scratch: Vec<u8>,
+    ch: Option<u8>,
+}
+
+#[cfg(feature = "std")]
+impl<R> IoRead<R>
+where
+    R: io::Read,
+{
+    /// Creates a new CBOR input source to read from a std::io input stream.
+    pub fn new(reader: R) -> IoRead<R> {
+        IoRead {
+            reader: OffsetReader { reader, offset: 0 },
+            scratch: vec![],
+            ch: None,
+        }
+    }
+
+    #[inline]
+    fn next_inner(&mut self) -> Result<Option<u8>> {
+        let mut buf = [0; 1];
+        loop {
+            match self.reader.read(&mut buf) {
+                Ok(0) => return Ok(None),
+                Ok(_) => return Ok(Some(buf[0])),
+                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
+                Err(e) => return Err(Error::io(e)),
+            }
+        }
+    }
+}
+
+#[cfg(all(feature = "std", not(feature = "unsealed_read_write")))]
+impl<R> private::Sealed for IoRead<R> where R: io::Read {}
+
+#[cfg(feature = "std")]
+impl<'de, R> Read<'de> for IoRead<R>
+where
+    R: io::Read,
+{
+    #[inline]
+    fn next(&mut self) -> Result<Option<u8>> {
+        match self.ch.take() {
+            Some(ch) => Ok(Some(ch)),
+            None => self.next_inner(),
+        }
+    }
+
+    #[inline]
+    fn peek(&mut self) -> Result<Option<u8>> {
+        match self.ch {
+            Some(ch) => Ok(Some(ch)),
+            None => {
+                self.ch = self.next_inner()?;
+                Ok(self.ch)
+            }
+        }
+    }
+
+    fn read_to_buffer(&mut self, mut n: usize) -> Result<()> {
+        // defend against malicious input pretending to be huge strings by limiting growth
+        self.scratch.reserve(cmp::min(n, 16 * 1024));
+
+        if n == 0 {
+            return Ok(());
+        }
+
+        if let Some(ch) = self.ch.take() {
+            self.scratch.push(ch);
+            n -= 1;
+        }
+
+        // n == 0 is OK here and needs no further special treatment
+
+        let transfer_result = {
+            // Prepare for take() (which consumes its reader) by creating a reference adaptor
+            // that'll only live in this block
+            let reference = self.reader.by_ref();
+            // Append the first n bytes of the reader to the scratch vector (or up to
+            // an error or EOF indicated by a shorter read)
+            let mut taken = reference.take(n as u64);
+            taken.read_to_end(&mut self.scratch)
+        };
+
+        match transfer_result {
+            Ok(r) if r == n => Ok(()),
+            Ok(_) => Err(Error::syntax(
+                ErrorCode::EofWhileParsingValue,
+                self.offset(),
+            )),
+            Err(e) => Err(Error::io(e)),
+        }
+    }
+
+    fn clear_buffer(&mut self) {
+        self.scratch.clear();
+    }
+
+    fn take_buffer<'a>(&'a mut self) -> EitherLifetime<'a, 'de> {
+        EitherLifetime::Short(&self.scratch)
+    }
+
+    fn read_into(&mut self, buf: &mut [u8]) -> Result<()> {
+        self.reader.read_exact(buf).map_err(|e| {
+            if e.kind() == io::ErrorKind::UnexpectedEof {
+                Error::syntax(ErrorCode::EofWhileParsingValue, self.offset())
+            } else {
+                Error::io(e)
+            }
+        })
+    }
+
+    #[inline]
+    fn discard(&mut self) {
+        self.ch = None;
+    }
+
+    fn offset(&self) -> u64 {
+        self.reader.offset
+    }
+}
+
+#[cfg(feature = "std")]
+impl<R> Offset for IoRead<R>
+where
+    R: std::io::Read,
+{
+    fn byte_offset(&self) -> usize {
+        self.offset() as usize
+    }
+}
+
+#[cfg(feature = "std")]
+#[derive(Debug)]
+struct OffsetReader<R> {
+    reader: R,
+    offset: u64,
+}
+
+#[cfg(feature = "std")]
+impl<R> io::Read for OffsetReader<R>
+where
+    R: io::Read,
+{
+    #[inline]
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        let r = self.reader.read(buf);
+        if let Ok(count) = r {
+            self.offset += count as u64;
+        }
+        r
+    }
+}
+
+/// A CBOR input source that reads from a slice of bytes.
+#[cfg(any(feature = "std", feature = "alloc"))]
+#[derive(Debug)]
+pub struct SliceRead<'a> {
+    slice: &'a [u8],
+    scratch: Vec<u8>,
+    index: usize,
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<'a> SliceRead<'a> {
+    /// Creates a CBOR input source to read from a slice of bytes.
+    pub fn new(slice: &'a [u8]) -> SliceRead<'a> {
+        SliceRead {
+            slice,
+            scratch: vec![],
+            index: 0,
+        }
+    }
+
+    fn end(&self, n: usize) -> Result<usize> {
+        match self.index.checked_add(n) {
+            Some(end) if end <= self.slice.len() => Ok(end),
+            _ => Err(Error::syntax(
+                ErrorCode::EofWhileParsingValue,
+                self.slice.len() as u64,
+            )),
+        }
+    }
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<'a> Offset for SliceRead<'a> {
+    #[inline]
+    fn byte_offset(&self) -> usize {
+        self.index
+    }
+}
+
+#[cfg(all(
+    any(feature = "std", feature = "alloc"),
+    not(feature = "unsealed_read_write")
+))]
+impl<'a> private::Sealed for SliceRead<'a> {}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<'a> Read<'a> for SliceRead<'a> {
+    #[inline]
+    fn next(&mut self) -> Result<Option<u8>> {
+        Ok(if self.index < self.slice.len() {
+            let ch = self.slice[self.index];
+            self.index += 1;
+            Some(ch)
+        } else {
+            None
+        })
+    }
+
+    #[inline]
+    fn peek(&mut self) -> Result<Option<u8>> {
+        Ok(if self.index < self.slice.len() {
+            Some(self.slice[self.index])
+        } else {
+            None
+        })
+    }
+
+    fn clear_buffer(&mut self) {
+        self.scratch.clear();
+    }
+
+    fn read_to_buffer(&mut self, n: usize) -> Result<()> {
+        let end = self.end(n)?;
+        let slice = &self.slice[self.index..end];
+        self.scratch.extend_from_slice(slice);
+        self.index = end;
+
+        Ok(())
+    }
+
+    #[inline]
+    fn read<'b>(&'b mut self, n: usize) -> Result<EitherLifetime<'b, 'a>> {
+        let end = self.end(n)?;
+        let slice = &self.slice[self.index..end];
+        self.index = end;
+        Ok(EitherLifetime::Long(slice))
+    }
+
+    fn take_buffer<'b>(&'b mut self) -> EitherLifetime<'b, 'a> {
+        EitherLifetime::Short(&self.scratch)
+    }
+
+    #[inline]
+    fn read_into(&mut self, buf: &mut [u8]) -> Result<()> {
+        let end = self.end(buf.len())?;
+        buf.copy_from_slice(&self.slice[self.index..end]);
+        self.index = end;
+        Ok(())
+    }
+
+    #[inline]
+    fn discard(&mut self) {
+        self.index += 1;
+    }
+
+    fn offset(&self) -> u64 {
+        self.index as u64
+    }
+}
+
+/// A CBOR input source that reads from a slice of bytes using a fixed size scratch buffer.
+///
+/// [`SliceRead`](struct.SliceRead.html) and [`MutSliceRead`](struct.MutSliceRead.html) are usually
+/// preferred over this, as they can handle indefinite length items.
+#[derive(Debug)]
+pub struct SliceReadFixed<'a, 'b> {
+    slice: &'a [u8],
+    scratch: &'b mut [u8],
+    index: usize,
+    scratch_index: usize,
+}
+
+impl<'a, 'b> SliceReadFixed<'a, 'b> {
+    /// Creates a CBOR input source to read from a slice of bytes, backed by a scratch buffer.
+    pub fn new(slice: &'a [u8], scratch: &'b mut [u8]) -> SliceReadFixed<'a, 'b> {
+        SliceReadFixed {
+            slice,
+            scratch,
+            index: 0,
+            scratch_index: 0,
+        }
+    }
+
+    fn end(&self, n: usize) -> Result<usize> {
+        match self.index.checked_add(n) {
+            Some(end) if end <= self.slice.len() => Ok(end),
+            _ => Err(Error::syntax(
+                ErrorCode::EofWhileParsingValue,
+                self.slice.len() as u64,
+            )),
+        }
+    }
+
+    fn scratch_end(&self, n: usize) -> Result<usize> {
+        match self.scratch_index.checked_add(n) {
+            Some(end) if end <= self.scratch.len() => Ok(end),
+            _ => Err(Error::scratch_too_small(self.index as u64)),
+        }
+    }
+}
+
+#[cfg(not(feature = "unsealed_read_write"))]
+impl<'a, 'b> private::Sealed for SliceReadFixed<'a, 'b> {}
+
+impl<'a, 'b> Read<'a> for SliceReadFixed<'a, 'b> {
+    #[inline]
+    fn next(&mut self) -> Result<Option<u8>> {
+        Ok(if self.index < self.slice.len() {
+            let ch = self.slice[self.index];
+            self.index += 1;
+            Some(ch)
+        } else {
+            None
+        })
+    }
+
+    #[inline]
+    fn peek(&mut self) -> Result<Option<u8>> {
+        Ok(if self.index < self.slice.len() {
+            Some(self.slice[self.index])
+        } else {
+            None
+        })
+    }
+
+    fn clear_buffer(&mut self) {
+        self.scratch_index = 0;
+    }
+
+    fn read_to_buffer(&mut self, n: usize) -> Result<()> {
+        let end = self.end(n)?;
+        let scratch_end = self.scratch_end(n)?;
+        let slice = &self.slice[self.index..end];
+        self.scratch[self.scratch_index..scratch_end].copy_from_slice(&slice);
+        self.index = end;
+        self.scratch_index = scratch_end;
+
+        Ok(())
+    }
+
+    fn read<'c>(&'c mut self, n: usize) -> Result<EitherLifetime<'c, 'a>> {
+        let end = self.end(n)?;
+        let slice = &self.slice[self.index..end];
+        self.index = end;
+        Ok(EitherLifetime::Long(slice))
+    }
+
+    fn take_buffer<'c>(&'c mut self) -> EitherLifetime<'c, 'a> {
+        EitherLifetime::Short(&self.scratch[0..self.scratch_index])
+    }
+
+    #[inline]
+    fn read_into(&mut self, buf: &mut [u8]) -> Result<()> {
+        let end = self.end(buf.len())?;
+        buf.copy_from_slice(&self.slice[self.index..end]);
+        self.index = end;
+        Ok(())
+    }
+
+    #[inline]
+    fn discard(&mut self) {
+        self.index += 1;
+    }
+
+    fn offset(&self) -> u64 {
+        self.index as u64
+    }
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<'a, 'b> Offset for SliceReadFixed<'a, 'b> {
+    #[inline]
+    fn byte_offset(&self) -> usize {
+        self.index
+    }
+}
+
+/// A CBOR input source that reads from a slice of bytes, and can move data around internally to
+/// reassemble indefinite strings without the need of an allocated scratch buffer.
+#[derive(Debug)]
+pub struct MutSliceRead<'a> {
+    /// A complete view of the reader's data. It is promised that bytes before buffer_end are not
+    /// mutated any more.
+    slice: &'a mut [u8],
+    /// Read cursor position in slice
+    index: usize,
+    /// Number of bytes already discarded from the slice
+    before: usize,
+    /// End of the buffer area that contains all bytes read_into_buffer. This is always <= index.
+    buffer_end: usize,
+}
+
+impl<'a> MutSliceRead<'a> {
+    /// Creates a CBOR input source to read from a slice of bytes.
+    pub fn new(slice: &'a mut [u8]) -> MutSliceRead<'a> {
+        MutSliceRead {
+            slice,
+            index: 0,
+            before: 0,
+            buffer_end: 0,
+        }
+    }
+
+    fn end(&self, n: usize) -> Result<usize> {
+        match self.index.checked_add(n) {
+            Some(end) if end <= self.slice.len() => Ok(end),
+            _ => Err(Error::syntax(
+                ErrorCode::EofWhileParsingValue,
+                self.slice.len() as u64,
+            )),
+        }
+    }
+}
+
+#[cfg(not(feature = "unsealed_read_write"))]
+impl<'a> private::Sealed for MutSliceRead<'a> {}
+
+impl<'a> Read<'a> for MutSliceRead<'a> {
+    #[inline]
+    fn next(&mut self) -> Result<Option<u8>> {
+        // This is duplicated from SliceRead, can that be eased?
+        Ok(if self.index < self.slice.len() {
+            let ch = self.slice[self.index];
+            self.index += 1;
+            Some(ch)
+        } else {
+            None
+        })
+    }
+
+    #[inline]
+    fn peek(&mut self) -> Result<Option<u8>> {
+        // This is duplicated from SliceRead, can that be eased?
+        Ok(if self.index < self.slice.len() {
+            Some(self.slice[self.index])
+        } else {
+            None
+        })
+    }
+
+    fn clear_buffer(&mut self) {
+        self.slice = &mut mem::replace(&mut self.slice, &mut [])[self.index..];
+        self.before += self.index;
+        self.index = 0;
+        self.buffer_end = 0;
+    }
+
+    fn read_to_buffer(&mut self, n: usize) -> Result<()> {
+        let end = self.end(n)?;
+        debug_assert!(
+            self.buffer_end <= self.index,
+            "MutSliceRead invariant violated: scratch buffer exceeds index"
+        );
+        self.slice[self.buffer_end..end].rotate_left(self.index - self.buffer_end);
+        self.buffer_end += n;
+        self.index = end;
+
+        Ok(())
+    }
+
+    fn take_buffer<'b>(&'b mut self) -> EitherLifetime<'b, 'a> {
+        let (left, right) = mem::replace(&mut self.slice, &mut []).split_at_mut(self.index);
+        self.slice = right;
+        self.before += self.index;
+        self.index = 0;
+
+        let left = &left[..self.buffer_end];
+        self.buffer_end = 0;
+
+        EitherLifetime::Long(left)
+    }
+
+    #[inline]
+    fn read_into(&mut self, buf: &mut [u8]) -> Result<()> {
+        // This is duplicated from SliceRead, can that be eased?
+        let end = self.end(buf.len())?;
+        buf.copy_from_slice(&self.slice[self.index..end]);
+        self.index = end;
+        Ok(())
+    }
+
+    #[inline]
+    fn discard(&mut self) {
+        self.index += 1;
+    }
+
+    fn offset(&self) -> u64 {
+        (self.before + self.index) as u64
+    }
+}
diff --git a/src/ser.rs b/src/ser.rs
new file mode 100644
index 0000000..7016dc3
--- /dev/null
+++ b/src/ser.rs
@@ -0,0 +1,743 @@
+//! Serialize a Rust data structure to CBOR data.
+
+#[cfg(feature = "alloc")]
+use alloc::vec::Vec;
+
+#[cfg(feature = "std")]
+pub use crate::write::IoWrite;
+pub use crate::write::{SliceWrite, Write};
+
+use crate::error::{Error, Result};
+use half::f16;
+use serde::ser::{self, Serialize};
+#[cfg(feature = "std")]
+use std::io;
+
+use crate::tags::{get_tag, CBOR_NEWTYPE_NAME};
+
+/// Serializes a value to a vector.
+#[cfg(any(feature = "std", feature = "alloc"))]
+pub fn to_vec<T>(value: &T) -> Result<Vec<u8>>
+where
+    T: ser::Serialize,
+{
+    let mut vec = Vec::new();
+    value.serialize(&mut Serializer::new(&mut vec))?;
+    Ok(vec)
+}
+
+/// Serializes a value to a vector in packed format.
+#[cfg(feature = "std")]
+pub fn to_vec_packed<T>(value: &T) -> Result<Vec<u8>>
+where
+    T: ser::Serialize,
+{
+    let mut vec = Vec::new();
+    value.serialize(&mut Serializer::new(&mut IoWrite::new(&mut vec)).packed_format())?;
+    Ok(vec)
+}
+
+/// Serializes a value to a writer.
+#[cfg(feature = "std")]
+pub fn to_writer<W, T>(writer: W, value: &T) -> Result<()>
+where
+    W: io::Write,
+    T: ser::Serialize,
+{
+    value.serialize(&mut Serializer::new(&mut IoWrite::new(writer)))
+}
+
+/// A structure for serializing Rust values to CBOR.
+#[derive(Debug)]
+pub struct Serializer<W> {
+    writer: W,
+    packed: bool,
+    enum_as_map: bool,
+}
+
+impl<W> Serializer<W>
+where
+    W: Write,
+{
+    /// Creates a new CBOR serializer.
+    ///
+    /// `to_vec` and `to_writer` should normally be used instead of this method.
+    #[inline]
+    pub fn new(writer: W) -> Self {
+        Serializer {
+            writer,
+            packed: false,
+            enum_as_map: true,
+        }
+    }
+
+    /// Choose concise/packed format for serializer.
+    ///
+    /// In the packed format enum variant names and field names
+    /// are replaced with numeric indizes to conserve space.
+    pub fn packed_format(mut self) -> Self {
+        self.packed = true;
+        self
+    }
+
+    /// Enable old enum format used by `serde_cbor` versions <= v0.9.
+    ///
+    /// The `legacy_enums` option determines how enums are encoded.
+    ///
+    /// This makes no difference when encoding and decoding enums using
+    /// this crate, but it shows up when decoding to a `Value` or decoding
+    /// in other languages.
+    ///
+    /// # Examples
+    ///
+    /// Given the following enum
+    ///
+    /// ```rust
+    /// enum Enum {
+    ///     Unit,
+    ///     NewType(i32),
+    ///     Tuple(String, bool),
+    ///     Struct{ x: i32, y: i32 },
+    /// }
+    /// ```
+    /// we will give the `Value` with the same encoding for each case using
+    /// JSON notation.
+    ///
+    /// ## Default encodings
+    ///
+    /// * `Enum::Unit` encodes as `"Unit"`
+    /// * `Enum::NewType(10)` encodes as `{"NewType": 10}`
+    /// * `Enum::Tuple("x", true)` encodes as `{"Tuple": ["x", true]}`
+    ///
+    /// ## Legacy encodings
+    ///
+    /// * `Enum::Unit` encodes as `"Unit"`
+    /// * `Enum::NewType(10)` encodes as `["NewType", 10]`
+    /// * `Enum::Tuple("x", true)` encodes as `["Tuple", "x", true]`
+    /// * `Enum::Struct{ x: 5, y: -5 }` encodes as `["Struct", {"x": 5, "y": -5}]`
+    pub fn legacy_enums(mut self) -> Self {
+        self.enum_as_map = false;
+        self
+    }
+
+    /// Writes a CBOR self-describe tag to the stream.
+    ///
+    /// Tagging allows a decoder to distinguish different file formats based on their content
+    /// without further information.
+    #[inline]
+    pub fn self_describe(&mut self) -> Result<()> {
+        let mut buf = [6 << 5 | 25, 0, 0];
+        (&mut buf[1..]).copy_from_slice(&55799u16.to_be_bytes());
+        self.writer.write_all(&buf).map_err(|e| e.into())
+    }
+
+    /// Unwrap the `Writer` from the `Serializer`.
+    #[inline]
+    pub fn into_inner(self) -> W {
+        self.writer
+    }
+
+    #[inline]
+    fn write_u8(&mut self, major: u8, value: u8) -> Result<()> {
+        if value <= 0x17 {
+            self.writer.write_all(&[major << 5 | value])
+        } else {
+            let buf = [major << 5 | 24, value];
+            self.writer.write_all(&buf)
+        }
+        .map_err(|e| e.into())
+    }
+
+    #[inline]
+    fn write_u16(&mut self, major: u8, value: u16) -> Result<()> {
+        if value <= u16::from(u8::max_value()) {
+            self.write_u8(major, value as u8)
+        } else {
+            let mut buf = [major << 5 | 25, 0, 0];
+            (&mut buf[1..]).copy_from_slice(&value.to_be_bytes());
+            self.writer.write_all(&buf).map_err(|e| e.into())
+        }
+    }
+
+    #[inline]
+    fn write_u32(&mut self, major: u8, value: u32) -> Result<()> {
+        if value <= u32::from(u16::max_value()) {
+            self.write_u16(major, value as u16)
+        } else {
+            let mut buf = [major << 5 | 26, 0, 0, 0, 0];
+            (&mut buf[1..]).copy_from_slice(&value.to_be_bytes());
+            self.writer.write_all(&buf).map_err(|e| e.into())
+        }
+    }
+
+    #[inline]
+    fn write_u64(&mut self, major: u8, value: u64) -> Result<()> {
+        if value <= u64::from(u32::max_value()) {
+            self.write_u32(major, value as u32)
+        } else {
+            let mut buf = [major << 5 | 27, 0, 0, 0, 0, 0, 0, 0, 0];
+            (&mut buf[1..]).copy_from_slice(&value.to_be_bytes());
+            self.writer.write_all(&buf).map_err(|e| e.into())
+        }
+    }
+
+    #[inline]
+    fn serialize_collection<'a>(
+        &'a mut self,
+        major: u8,
+        len: Option<usize>,
+    ) -> Result<CollectionSerializer<'a, W>> {
+        let needs_eof = match len {
+            Some(len) => {
+                self.write_u64(major, len as u64)?;
+                false
+            }
+            None => {
+                self.writer
+                    .write_all(&[major << 5 | 31])
+                    .map_err(|e| e.into())?;
+                true
+            }
+        };
+
+        Ok(CollectionSerializer {
+            ser: self,
+            needs_eof,
+        })
+    }
+}
+
+impl<'a, W> ser::Serializer for &'a mut Serializer<W>
+where
+    W: Write,
+{
+    type Ok = ();
+    type Error = Error;
+
+    type SerializeSeq = CollectionSerializer<'a, W>;
+    type SerializeTuple = &'a mut Serializer<W>;
+    type SerializeTupleStruct = &'a mut Serializer<W>;
+    type SerializeTupleVariant = &'a mut Serializer<W>;
+    type SerializeMap = CollectionSerializer<'a, W>;
+    type SerializeStruct = StructSerializer<'a, W>;
+    type SerializeStructVariant = StructSerializer<'a, W>;
+
+    #[inline]
+    fn serialize_bool(self, value: bool) -> Result<()> {
+        let value = if value { 0xf5 } else { 0xf4 };
+        self.writer.write_all(&[value]).map_err(|e| e.into())
+    }
+
+    #[inline]
+    fn serialize_i8(self, value: i8) -> Result<()> {
+        if value < 0 {
+            self.write_u8(1, -(value + 1) as u8)
+        } else {
+            self.write_u8(0, value as u8)
+        }
+    }
+
+    #[inline]
+    fn serialize_i16(self, value: i16) -> Result<()> {
+        if value < 0 {
+            self.write_u16(1, -(value + 1) as u16)
+        } else {
+            self.write_u16(0, value as u16)
+        }
+    }
+
+    #[inline]
+    fn serialize_i32(self, value: i32) -> Result<()> {
+        if value < 0 {
+            self.write_u32(1, -(value + 1) as u32)
+        } else {
+            self.write_u32(0, value as u32)
+        }
+    }
+
+    #[inline]
+    fn serialize_i64(self, value: i64) -> Result<()> {
+        if value < 0 {
+            self.write_u64(1, -(value + 1) as u64)
+        } else {
+            self.write_u64(0, value as u64)
+        }
+    }
+
+    #[inline]
+    fn serialize_i128(self, value: i128) -> Result<()> {
+        if value < 0 {
+            if -(value + 1) > i128::from(u64::max_value()) {
+                return Err(Error::message("The number can't be stored in CBOR"));
+            }
+            self.write_u64(1, -(value + 1) as u64)
+        } else {
+            if value > i128::from(u64::max_value()) {
+                return Err(Error::message("The number can't be stored in CBOR"));
+            }
+            self.write_u64(0, value as u64)
+        }
+    }
+
+    #[inline]
+    fn serialize_u8(self, value: u8) -> Result<()> {
+        self.write_u8(0, value)
+    }
+
+    #[inline]
+    fn serialize_u16(self, value: u16) -> Result<()> {
+        self.write_u16(0, value)
+    }
+
+    #[inline]
+    fn serialize_u32(self, value: u32) -> Result<()> {
+        self.write_u32(0, value)
+    }
+
+    #[inline]
+    fn serialize_u64(self, value: u64) -> Result<()> {
+        self.write_u64(0, value)
+    }
+
+    #[inline]
+    fn serialize_u128(self, value: u128) -> Result<()> {
+        if value > u128::from(u64::max_value()) {
+            return Err(Error::message("The number can't be stored in CBOR"));
+        }
+        self.write_u64(0, value as u64)
+    }
+
+    #[inline]
+    #[allow(clippy::float_cmp)]
+    fn serialize_f32(self, value: f32) -> Result<()> {
+        if value.is_infinite() {
+            if value.is_sign_positive() {
+                self.writer.write_all(&[0xf9, 0x7c, 0x00])
+            } else {
+                self.writer.write_all(&[0xf9, 0xfc, 0x00])
+            }
+        } else if value.is_nan() {
+            self.writer.write_all(&[0xf9, 0x7e, 0x00])
+        } else if f32::from(f16::from_f32(value)) == value {
+            let mut buf = [0xf9, 0, 0];
+            (&mut buf[1..]).copy_from_slice(&f16::from_f32(value).to_bits().to_be_bytes());
+            self.writer.write_all(&buf)
+        } else {
+            let mut buf = [0xfa, 0, 0, 0, 0];
+            (&mut buf[1..]).copy_from_slice(&value.to_bits().to_be_bytes());
+            self.writer.write_all(&buf)
+        }
+        .map_err(|e| e.into())
+    }
+
+    #[inline]
+    #[allow(clippy::float_cmp)]
+    fn serialize_f64(self, value: f64) -> Result<()> {
+        if !value.is_finite() || f64::from(value as f32) == value {
+            self.serialize_f32(value as f32)
+        } else {
+            let mut buf = [0xfb, 0, 0, 0, 0, 0, 0, 0, 0];
+            (&mut buf[1..]).copy_from_slice(&value.to_bits().to_be_bytes());
+            self.writer.write_all(&buf).map_err(|e| e.into())
+        }
+    }
+
+    #[inline]
+    fn serialize_char(self, value: char) -> Result<()> {
+        // A char encoded as UTF-8 takes 4 bytes at most.
+        let mut buf = [0; 4];
+        self.serialize_str(value.encode_utf8(&mut buf))
+    }
+
+    #[inline]
+    fn serialize_str(self, value: &str) -> Result<()> {
+        self.write_u64(3, value.len() as u64)?;
+        self.writer
+            .write_all(value.as_bytes())
+            .map_err(|e| e.into())
+    }
+
+    #[inline]
+    fn serialize_bytes(self, value: &[u8]) -> Result<()> {
+        self.write_u64(2, value.len() as u64)?;
+        self.writer.write_all(value).map_err(|e| e.into())
+    }
+
+    #[inline]
+    fn serialize_unit(self) -> Result<()> {
+        self.serialize_none()
+    }
+
+    #[inline]
+    fn serialize_some<T>(self, value: &T) -> Result<()>
+    where
+        T: ?Sized + ser::Serialize,
+    {
+        value.serialize(self)
+    }
+
+    #[inline]
+    fn serialize_none(self) -> Result<()> {
+        self.writer.write_all(&[0xf6]).map_err(|e| e.into())
+    }
+
+    #[inline]
+    fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
+        self.serialize_unit()
+    }
+
+    #[inline]
+    fn serialize_unit_variant(
+        self,
+        _name: &'static str,
+        variant_index: u32,
+        variant: &'static str,
+    ) -> Result<()> {
+        if self.packed {
+            self.serialize_u32(variant_index)
+        } else {
+            self.serialize_str(variant)
+        }
+    }
+
+    #[inline]
+    fn serialize_newtype_struct<T>(self, name: &'static str, value: &T) -> Result<()>
+    where
+        T: ?Sized + ser::Serialize,
+    {
+        if name == CBOR_NEWTYPE_NAME {
+            for tag in get_tag().into_iter() {
+                self.write_u64(6, tag)?;
+            }
+        }
+        value.serialize(self)
+    }
+
+    #[inline]
+    fn serialize_newtype_variant<T>(
+        self,
+        name: &'static str,
+        variant_index: u32,
+        variant: &'static str,
+        value: &T,
+    ) -> Result<()>
+    where
+        T: ?Sized + ser::Serialize,
+    {
+        if self.enum_as_map {
+            self.write_u64(5, 1u64)?;
+            variant.serialize(&mut *self)?;
+        } else {
+            self.writer.write_all(&[4 << 5 | 2]).map_err(|e| e.into())?;
+            self.serialize_unit_variant(name, variant_index, variant)?;
+        }
+        value.serialize(self)
+    }
+
+    #[inline]
+    fn serialize_seq(self, len: Option<usize>) -> Result<CollectionSerializer<'a, W>> {
+        self.serialize_collection(4, len)
+    }
+
+    #[inline]
+    fn serialize_tuple(self, len: usize) -> Result<&'a mut Serializer<W>> {
+        self.write_u64(4, len as u64)?;
+        Ok(self)
+    }
+
+    #[inline]
+    fn serialize_tuple_struct(
+        self,
+        _name: &'static str,
+        len: usize,
+    ) -> Result<&'a mut Serializer<W>> {
+        self.serialize_tuple(len)
+    }
+
+    #[inline]
+    fn serialize_tuple_variant(
+        self,
+        name: &'static str,
+        variant_index: u32,
+        variant: &'static str,
+        len: usize,
+    ) -> Result<&'a mut Serializer<W>> {
+        if self.enum_as_map {
+            self.write_u64(5, 1u64)?;
+            variant.serialize(&mut *self)?;
+            self.serialize_tuple(len)
+        } else {
+            self.write_u64(4, (len + 1) as u64)?;
+            self.serialize_unit_variant(name, variant_index, variant)?;
+            Ok(self)
+        }
+    }
+
+    #[inline]
+    fn serialize_map(self, len: Option<usize>) -> Result<CollectionSerializer<'a, W>> {
+        self.serialize_collection(5, len)
+    }
+
+    #[cfg(not(feature = "std"))]
+    fn collect_str<T: ?Sized>(self, value: &T) -> Result<()>
+    where
+        T: core::fmt::Display,
+    {
+        use crate::write::FmtWrite;
+        use core::fmt::Write;
+
+        let mut w = FmtWrite::new(&mut self.writer);
+        write!(w, "{}", value)?;
+        Ok(())
+    }
+
+    #[inline]
+    fn serialize_struct(self, _name: &'static str, len: usize) -> Result<StructSerializer<'a, W>> {
+        self.write_u64(5, len as u64)?;
+        Ok(StructSerializer { ser: self, idx: 0 })
+    }
+
+    #[inline]
+    fn serialize_struct_variant(
+        self,
+        name: &'static str,
+        variant_index: u32,
+        variant: &'static str,
+        len: usize,
+    ) -> Result<StructSerializer<'a, W>> {
+        if self.enum_as_map {
+            self.write_u64(5, 1u64)?;
+        } else {
+            self.writer.write_all(&[4 << 5 | 2]).map_err(|e| e.into())?;
+        }
+        self.serialize_unit_variant(name, variant_index, variant)?;
+        self.serialize_struct(name, len)
+    }
+
+    #[inline]
+    fn is_human_readable(&self) -> bool {
+        false
+    }
+}
+
+impl<'a, W> ser::SerializeTuple for &'a mut Serializer<W>
+where
+    W: Write,
+{
+    type Ok = ();
+    type Error = Error;
+
+    #[inline]
+    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
+    where
+        T: ?Sized + ser::Serialize,
+    {
+        value.serialize(&mut **self)
+    }
+
+    #[inline]
+    fn end(self) -> Result<()> {
+        Ok(())
+    }
+}
+
+impl<'a, W> ser::SerializeTupleStruct for &'a mut Serializer<W>
+where
+    W: Write,
+{
+    type Ok = ();
+    type Error = Error;
+
+    #[inline]
+    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
+    where
+        T: ?Sized + ser::Serialize,
+    {
+        value.serialize(&mut **self)
+    }
+
+    #[inline]
+    fn end(self) -> Result<()> {
+        Ok(())
+    }
+}
+
+impl<'a, W> ser::SerializeTupleVariant for &'a mut Serializer<W>
+where
+    W: Write,
+{
+    type Ok = ();
+    type Error = Error;
+
+    #[inline]
+    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
+    where
+        T: ?Sized + ser::Serialize,
+    {
+        value.serialize(&mut **self)
+    }
+
+    #[inline]
+    fn end(self) -> Result<()> {
+        Ok(())
+    }
+}
+
+#[doc(hidden)]
+pub struct StructSerializer<'a, W> {
+    ser: &'a mut Serializer<W>,
+    idx: u32,
+}
+
+impl<'a, W> StructSerializer<'a, W>
+where
+    W: Write,
+{
+    #[inline]
+    fn serialize_field_inner<T>(&mut self, key: &'static str, value: &T) -> Result<()>
+    where
+        T: ?Sized + ser::Serialize,
+    {
+        if self.ser.packed {
+            self.idx.serialize(&mut *self.ser)?;
+        } else {
+            key.serialize(&mut *self.ser)?;
+        }
+        value.serialize(&mut *self.ser)?;
+        self.idx += 1;
+        Ok(())
+    }
+
+    #[inline]
+    fn skip_field_inner(&mut self, _: &'static str) -> Result<()> {
+        self.idx += 1;
+        Ok(())
+    }
+
+    #[inline]
+    fn end_inner(self) -> Result<()> {
+        Ok(())
+    }
+}
+
+impl<'a, W> ser::SerializeStruct for StructSerializer<'a, W>
+where
+    W: Write,
+{
+    type Ok = ();
+    type Error = Error;
+
+    #[inline]
+    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
+    where
+        T: ?Sized + ser::Serialize,
+    {
+        self.serialize_field_inner(key, value)
+    }
+
+    #[inline]
+    fn skip_field(&mut self, key: &'static str) -> Result<()> {
+        self.skip_field_inner(key)
+    }
+
+    #[inline]
+    fn end(self) -> Result<()> {
+        self.end_inner()
+    }
+}
+
+impl<'a, W> ser::SerializeStructVariant for StructSerializer<'a, W>
+where
+    W: Write,
+{
+    type Ok = ();
+    type Error = Error;
+
+    #[inline]
+    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
+    where
+        T: ?Sized + ser::Serialize,
+    {
+        self.serialize_field_inner(key, value)
+    }
+
+    #[inline]
+    fn skip_field(&mut self, key: &'static str) -> Result<()> {
+        self.skip_field_inner(key)
+    }
+
+    #[inline]
+    fn end(self) -> Result<()> {
+        self.end_inner()
+    }
+}
+
+#[doc(hidden)]
+pub struct CollectionSerializer<'a, W> {
+    ser: &'a mut Serializer<W>,
+    needs_eof: bool,
+}
+
+impl<'a, W> CollectionSerializer<'a, W>
+where
+    W: Write,
+{
+    #[inline]
+    fn end_inner(self) -> Result<()> {
+        if self.needs_eof {
+            self.ser.writer.write_all(&[0xff]).map_err(|e| e.into())
+        } else {
+            Ok(())
+        }
+    }
+}
+
+impl<'a, W> ser::SerializeSeq for CollectionSerializer<'a, W>
+where
+    W: Write,
+{
+    type Ok = ();
+    type Error = Error;
+
+    #[inline]
+    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
+    where
+        T: ?Sized + ser::Serialize,
+    {
+        value.serialize(&mut *self.ser)
+    }
+
+    #[inline]
+    fn end(self) -> Result<()> {
+        self.end_inner()
+    }
+}
+
+impl<'a, W> ser::SerializeMap for CollectionSerializer<'a, W>
+where
+    W: Write,
+{
+    type Ok = ();
+    type Error = Error;
+
+    #[inline]
+    fn serialize_key<T>(&mut self, key: &T) -> Result<()>
+    where
+        T: ?Sized + ser::Serialize,
+    {
+        key.serialize(&mut *self.ser)
+    }
+
+    #[inline]
+    fn serialize_value<T>(&mut self, value: &T) -> Result<()>
+    where
+        T: ?Sized + ser::Serialize,
+    {
+        value.serialize(&mut *self.ser)
+    }
+
+    #[inline]
+    fn end(self) -> Result<()> {
+        self.end_inner()
+    }
+}
diff --git a/src/tags.rs b/src/tags.rs
new file mode 100644
index 0000000..50e039e
--- /dev/null
+++ b/src/tags.rs
@@ -0,0 +1,221 @@
+//! Support for cbor tags
+use core::fmt;
+use core::marker::PhantomData;
+use serde::de::{
+    Deserialize, Deserializer, EnumAccess, IntoDeserializer, MapAccess, SeqAccess, Visitor,
+};
+use serde::forward_to_deserialize_any;
+use serde::ser::{Serialize, Serializer};
+
+/// signals that a newtype is from a CBOR tag
+pub(crate) const CBOR_NEWTYPE_NAME: &str = "\0cbor_tag";
+
+/// A value that is optionally tagged with a cbor tag
+///
+/// this only serves as an intermediate helper for tag serialization or deserialization
+pub struct Tagged<T> {
+    /// cbor tag
+    pub tag: Option<u64>,
+    /// value
+    pub value: T,
+}
+
+impl<T> Tagged<T> {
+    /// Create a new tagged value
+    pub fn new(tag: Option<u64>, value: T) -> Self {
+        Self { tag, value }
+    }
+}
+
+impl<T: Serialize> Serialize for Tagged<T> {
+    fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
+        set_tag(self.tag);
+        let r = s.serialize_newtype_struct(CBOR_NEWTYPE_NAME, &self.value);
+        set_tag(None);
+        r
+    }
+}
+
+fn untagged<T>(value: T) -> Tagged<T> {
+    Tagged::new(None, value)
+}
+
+macro_rules! delegate {
+    ($name: ident, $type: ty) => {
+        fn $name<E: serde::de::Error>(self, v: $type) -> Result<Self::Value, E>
+        {
+            T::deserialize(v.into_deserializer()).map(untagged)
+        }
+    };
+}
+
+struct EnumDeserializer<A>(A);
+
+impl<'de, A> Deserializer<'de> for EnumDeserializer<A>
+where
+    A: EnumAccess<'de>,
+{
+    type Error = A::Error;
+
+    fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
+        visitor.visit_enum(self.0)
+    }
+
+    forward_to_deserialize_any! {
+        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
+        bytes byte_buf option unit unit_struct newtype_struct seq tuple
+        tuple_struct map struct enum identifier ignored_any
+    }
+}
+
+struct NoneDeserializer<E>(PhantomData<E>);
+
+impl<'de, E> Deserializer<'de> for NoneDeserializer<E>
+where
+    E: serde::de::Error,
+{
+    type Error = E;
+
+    fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
+        visitor.visit_none()
+    }
+
+    forward_to_deserialize_any! {
+        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
+        bytes byte_buf option unit unit_struct newtype_struct seq tuple
+        tuple_struct map struct enum identifier ignored_any
+    }
+}
+
+struct BytesDeserializer<'a, E>(&'a [u8], PhantomData<E>);
+
+impl<'de, 'a, E> Deserializer<'de> for BytesDeserializer<'a, E>
+where
+    E: serde::de::Error,
+{
+    type Error = E;
+
+    fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
+        visitor.visit_bytes(self.0)
+    }
+
+    forward_to_deserialize_any! {
+        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
+        bytes byte_buf option unit unit_struct newtype_struct seq tuple
+        tuple_struct map struct enum identifier ignored_any
+    }
+}
+
+/// A visitor that intercepts *just* visit_newtype_struct and passes through everything else.
+struct MaybeTaggedVisitor<T>(PhantomData<T>);
+
+impl<'de, T: Deserialize<'de>> Visitor<'de> for MaybeTaggedVisitor<T> {
+    type Value = Tagged<T>;
+
+    fn expecting(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt.write_str("a cbor tag newtype")
+    }
+
+    delegate!(visit_bool, bool);
+
+    delegate!(visit_i8, i8);
+    delegate!(visit_i16, i16);
+    delegate!(visit_i32, i32);
+    delegate!(visit_i64, i64);
+
+    delegate!(visit_u8, u8);
+    delegate!(visit_u16, u16);
+    delegate!(visit_u32, u32);
+    delegate!(visit_u64, u64);
+
+    delegate!(visit_f32, f32);
+    delegate!(visit_f64, f64);
+
+    delegate!(visit_char, char);
+    delegate!(visit_str, &str);
+    delegate!(visit_borrowed_str, &'de str);
+
+    #[cfg(feature = "std")]
+    delegate!(visit_byte_buf, Vec<u8>);
+
+    #[cfg(feature = "std")]
+    delegate!(visit_string, String);
+
+    fn visit_bytes<E: serde::de::Error>(self, value: &[u8]) -> Result<Self::Value, E> {
+        T::deserialize(BytesDeserializer(value, PhantomData)).map(untagged)
+    }
+
+    fn visit_borrowed_bytes<E: serde::de::Error>(self, value: &'de [u8]) -> Result<Self::Value, E> {
+        T::deserialize(serde::de::value::BorrowedBytesDeserializer::new(value)).map(untagged)
+    }
+
+    fn visit_unit<E: serde::de::Error>(self) -> Result<Self::Value, E> {
+        T::deserialize(().into_deserializer()).map(untagged)
+    }
+
+    fn visit_none<E: serde::de::Error>(self) -> Result<Self::Value, E> {
+        T::deserialize(NoneDeserializer(PhantomData)).map(untagged)
+    }
+
+    fn visit_some<D: Deserializer<'de>>(self, deserializer: D) -> Result<Self::Value, D::Error> {
+        T::deserialize(deserializer).map(untagged)
+    }
+
+    fn visit_seq<A: SeqAccess<'de>>(self, seq: A) -> Result<Self::Value, A::Error> {
+        T::deserialize(serde::de::value::SeqAccessDeserializer::new(seq)).map(untagged)
+    }
+
+    fn visit_map<V: MapAccess<'de>>(self, map: V) -> Result<Self::Value, V::Error> {
+        T::deserialize(serde::de::value::MapAccessDeserializer::new(map)).map(untagged)
+    }
+
+    fn visit_enum<A: EnumAccess<'de>>(self, data: A) -> Result<Self::Value, A::Error> {
+        T::deserialize(EnumDeserializer(data)).map(untagged)
+    }
+
+    fn visit_newtype_struct<D: serde::Deserializer<'de>>(
+        self,
+        deserializer: D,
+    ) -> Result<Self::Value, D::Error> {
+        let t = get_tag();
+        T::deserialize(deserializer).map(|v| Tagged::new(t, v))
+    }
+}
+
+impl<'de, T: serde::de::Deserialize<'de>> serde::de::Deserialize<'de> for Tagged<T> {
+    fn deserialize<D: serde::de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
+        deserializer.deserialize_any(MaybeTaggedVisitor::<T>(PhantomData))
+    }
+}
+
+/// function to get the current cbor tag
+///
+/// The only place where it makes sense to call this function is within visit_newtype_struct of a serde visitor.
+/// This is a low level API. In most cases it is preferable to use Tagged
+pub fn current_cbor_tag() -> Option<u64> {
+    get_tag()
+}
+
+#[cfg(feature = "tags")]
+pub(crate) fn set_tag(value: Option<u64>) {
+    CBOR_TAG.with(|f| *f.borrow_mut() = value);
+}
+
+#[cfg(feature = "tags")]
+pub(crate) fn get_tag() -> Option<u64> {
+    CBOR_TAG.with(|f| *f.borrow())
+}
+
+#[cfg(not(feature = "tags"))]
+pub(crate) fn set_tag(_value: Option<u64>) {}
+
+#[cfg(not(feature = "tags"))]
+pub(crate) fn get_tag() -> Option<u64> {
+    None
+}
+
+#[cfg(feature = "tags")]
+use std::cell::RefCell;
+
+#[cfg(feature = "tags")]
+thread_local!(static CBOR_TAG: RefCell<Option<u64>> = RefCell::new(None));
diff --git a/src/value/de.rs b/src/value/de.rs
new file mode 100644
index 0000000..f5bdbb7
--- /dev/null
+++ b/src/value/de.rs
@@ -0,0 +1,166 @@
+use std::collections::BTreeMap;
+use std::fmt;
+
+use crate::value::Value;
+use serde::de;
+
+impl<'de> de::Deserialize<'de> for Value {
+    #[inline]
+    fn deserialize<D>(deserializer: D) -> Result<Value, D::Error>
+    where
+        D: de::Deserializer<'de>,
+    {
+        struct ValueVisitor;
+
+        impl<'de> de::Visitor<'de> for ValueVisitor {
+            type Value = Value;
+
+            fn expecting(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.write_str("any valid CBOR value")
+            }
+
+            #[inline]
+            fn visit_str<E>(self, value: &str) -> Result<Value, E>
+            where
+                E: de::Error,
+            {
+                self.visit_string(String::from(value))
+            }
+
+            #[inline]
+            fn visit_string<E>(self, value: String) -> Result<Value, E>
+            where
+                E: de::Error,
+            {
+                Ok(Value::Text(value))
+            }
+            #[inline]
+            fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
+            where
+                E: de::Error,
+            {
+                self.visit_byte_buf(v.to_owned())
+            }
+
+            #[inline]
+            fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
+            where
+                E: de::Error,
+            {
+                Ok(Value::Bytes(v))
+            }
+
+            #[inline]
+            fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
+            where
+                E: de::Error,
+            {
+                Ok(Value::Integer(v.into()))
+            }
+
+            #[inline]
+            fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
+            where
+                E: de::Error,
+            {
+                Ok(Value::Integer(v.into()))
+            }
+
+            #[inline]
+            fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
+            where
+                E: de::Error,
+            {
+                Ok(Value::Integer(v))
+            }
+
+            #[inline]
+            fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
+            where
+                E: de::Error,
+            {
+                Ok(Value::Bool(v))
+            }
+
+            #[inline]
+            fn visit_none<E>(self) -> Result<Self::Value, E>
+            where
+                E: de::Error,
+            {
+                self.visit_unit()
+            }
+
+            #[inline]
+            fn visit_unit<E>(self) -> Result<Self::Value, E>
+            where
+                E: de::Error,
+            {
+                Ok(Value::Null)
+            }
+
+            #[inline]
+            fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
+            where
+                V: de::SeqAccess<'de>,
+            {
+                let mut vec = Vec::new();
+
+                while let Some(elem) = visitor.next_element()? {
+                    vec.push(elem);
+                }
+
+                Ok(Value::Array(vec))
+            }
+
+            #[inline]
+            fn visit_map<V>(self, mut visitor: V) -> Result<Value, V::Error>
+            where
+                V: de::MapAccess<'de>,
+            {
+                let mut values = BTreeMap::new();
+
+                while let Some((key, value)) = visitor.next_entry()? {
+                    values.insert(key, value);
+                }
+
+                Ok(Value::Map(values))
+            }
+
+            #[inline]
+            fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
+            where
+                E: de::Error,
+            {
+                Ok(Value::Float(v))
+            }
+
+            fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+            where
+                D: serde::Deserializer<'de>,
+            {
+                let tag = crate::tags::get_tag();
+                let inner = deserializer.deserialize_any(self);
+                match tag {
+                    Some(tag) => inner.map(|v| Value::Tag(tag, Box::new(v))),
+                    None => inner,
+                }
+            }
+        }
+
+        deserializer.deserialize_any(ValueVisitor)
+    }
+}
+
+/// Convert a `serde_cbor::Value` into a type `T`
+#[allow(clippy::needless_pass_by_value)]
+pub fn from_value<T>(value: Value) -> Result<T, crate::error::Error>
+where
+    T: de::DeserializeOwned,
+{
+    // TODO implement in a way that doesn't require
+    // roundtrip through buffer (i.e. by implementing
+    // `serde::de::Deserializer` for `Value` and then doing
+    // `T::deserialize(value)`).
+    let buf = crate::to_vec(&value)?;
+    crate::from_slice(buf.as_slice())
+}
diff --git a/src/value/mod.rs b/src/value/mod.rs
new file mode 100644
index 0000000..7bd2255
--- /dev/null
+++ b/src/value/mod.rs
@@ -0,0 +1,156 @@
+//! CBOR values, keys and serialization routines.
+
+mod de;
+mod ser;
+
+use std::cmp::{Ord, Ordering, PartialOrd};
+use std::collections::BTreeMap;
+
+#[doc(inline)]
+pub use self::de::from_value;
+#[doc(inline)]
+pub use self::ser::to_value;
+
+/// The `Value` enum, a loosely typed way of representing any valid CBOR value.
+///
+/// Maps are sorted according to the canonical ordering
+/// described in [RFC 7049 bis].
+/// Therefore values are unambiguously serialized
+/// to a canonical form of CBOR from the same RFC.
+///
+/// [RFC 7049 bis]: https://tools.ietf.org/html/draft-ietf-cbor-7049bis-04#section-2
+#[derive(Clone, Debug)]
+pub enum Value {
+    /// Represents the absence of a value or the value undefined.
+    Null,
+    /// Represents a boolean value.
+    Bool(bool),
+    /// Integer CBOR numbers.
+    ///
+    /// The biggest value that can be represented is 2^64 - 1.
+    /// While the smallest value is -2^64.
+    /// Values outside this range can't be serialized
+    /// and will cause an error.
+    Integer(i128),
+    /// Represents a floating point value.
+    Float(f64),
+    /// Represents a byte string.
+    Bytes(Vec<u8>),
+    /// Represents an UTF-8 encoded string.
+    Text(String),
+    /// Represents an array of values.
+    Array(Vec<Value>),
+    /// Represents a map.
+    ///
+    /// Maps are also called tables, dictionaries, hashes, or objects (in JSON).
+    /// While any value can be used as a CBOR key
+    /// it is better to use only one type of key in a map
+    /// to avoid ambiguity.
+    /// If floating point values are used as keys they are compared bit-by-bit for equality.
+    /// If arrays or maps are used as keys the comparisons
+    /// to establish canonical order may be slow and therefore insertion
+    /// and retrieval of values will be slow too.
+    Map(BTreeMap<Value, Value>),
+    /// Represents a tagged value
+    Tag(u64, Box<Value>),
+    // The hidden variant allows the enum to be extended
+    // with variants for tags and simple values.
+    #[doc(hidden)]
+    __Hidden,
+}
+
+impl PartialEq for Value {
+    fn eq(&self, other: &Value) -> bool {
+        self.cmp(other) == Ordering::Equal
+    }
+}
+
+impl Eq for Value {}
+
+impl PartialOrd for Value {
+    fn partial_cmp(&self, other: &Value) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl Ord for Value {
+    fn cmp(&self, other: &Value) -> Ordering {
+        // Determine the canonical order of two values:
+        // 1. Smaller major type sorts first.
+        // 2. Shorter sequence sorts first.
+        // 3. Compare integers by magnitude.
+        // 4. Compare byte and text sequences lexically.
+        // 5. Compare the serializations of both types. (expensive)
+        use self::Value::*;
+        if self.major_type() != other.major_type() {
+            return self.major_type().cmp(&other.major_type());
+        }
+        match (self, other) {
+            (Integer(a), Integer(b)) => a.abs().cmp(&b.abs()),
+            (Bytes(a), Bytes(b)) if a.len() != b.len() => a.len().cmp(&b.len()),
+            (Text(a), Text(b)) if a.len() != b.len() => a.len().cmp(&b.len()),
+            (Array(a), Array(b)) if a.len() != b.len() => a.len().cmp(&b.len()),
+            (Map(a), Map(b)) if a.len() != b.len() => a.len().cmp(&b.len()),
+            (Bytes(a), Bytes(b)) => a.cmp(b),
+            (Text(a), Text(b)) => a.cmp(b),
+            (a, b) => {
+                let a = crate::to_vec(a).expect("self is serializable");
+                let b = crate::to_vec(b).expect("other is serializable");
+                a.cmp(&b)
+            }
+        }
+    }
+}
+
+macro_rules! impl_from {
+    ($variant:path, $for_type:ty) => {
+        impl From<$for_type> for Value {
+            fn from(v: $for_type) -> Value {
+                $variant(v.into())
+            }
+        }
+    };
+}
+
+impl_from!(Value::Bool, bool);
+impl_from!(Value::Integer, i8);
+impl_from!(Value::Integer, i16);
+impl_from!(Value::Integer, i32);
+impl_from!(Value::Integer, i64);
+// i128 omitted because not all numbers fit in CBOR serialization
+impl_from!(Value::Integer, u8);
+impl_from!(Value::Integer, u16);
+impl_from!(Value::Integer, u32);
+impl_from!(Value::Integer, u64);
+// u128 omitted because not all numbers fit in CBOR serialization
+impl_from!(Value::Float, f32);
+impl_from!(Value::Float, f64);
+impl_from!(Value::Bytes, Vec<u8>);
+impl_from!(Value::Text, String);
+// TODO: figure out if these impls should be more generic or removed.
+impl_from!(Value::Array, Vec<Value>);
+impl_from!(Value::Map, BTreeMap<Value, Value>);
+
+impl Value {
+    fn major_type(&self) -> u8 {
+        use self::Value::*;
+        match self {
+            Null => 7,
+            Bool(_) => 7,
+            Integer(v) => {
+                if *v >= 0 {
+                    0
+                } else {
+                    1
+                }
+            }
+            Tag(_, _) => 6,
+            Float(_) => 7,
+            Bytes(_) => 2,
+            Text(_) => 3,
+            Array(_) => 4,
+            Map(_) => 5,
+            __Hidden => unreachable!(),
+        }
+    }
+}
diff --git a/src/value/ser.rs b/src/value/ser.rs
new file mode 100644
index 0000000..347aae9
--- /dev/null
+++ b/src/value/ser.rs
@@ -0,0 +1,443 @@
+// Copyright 2017 Serde Developers
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::collections::BTreeMap;
+
+use crate::error::Error;
+use serde::{self, Serialize};
+
+use crate::tags::Tagged;
+use crate::value::Value;
+
+impl serde::Serialize for Value {
+    #[inline]
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: serde::Serializer,
+    {
+        match *self {
+            Value::Integer(v) => serializer.serialize_i128(v),
+            Value::Bytes(ref v) => serializer.serialize_bytes(&v),
+            Value::Text(ref v) => serializer.serialize_str(&v),
+            Value::Array(ref v) => v.serialize(serializer),
+            Value::Map(ref v) => v.serialize(serializer),
+            Value::Tag(tag, ref v) => Tagged::new(Some(tag), v).serialize(serializer),
+            Value::Float(v) => serializer.serialize_f64(v),
+            Value::Bool(v) => serializer.serialize_bool(v),
+            Value::Null => serializer.serialize_unit(),
+            Value::__Hidden => unreachable!(),
+        }
+    }
+}
+
+struct Serializer;
+
+impl serde::Serializer for Serializer {
+    type Ok = Value;
+    type Error = Error;
+
+    type SerializeSeq = SerializeVec;
+    type SerializeTuple = SerializeVec;
+    type SerializeTupleStruct = SerializeVec;
+    type SerializeTupleVariant = SerializeTupleVariant;
+    type SerializeMap = SerializeMap;
+    type SerializeStruct = SerializeMap;
+    type SerializeStructVariant = SerializeStructVariant;
+
+    #[inline]
+    fn serialize_bool(self, value: bool) -> Result<Value, Error> {
+        Ok(Value::Bool(value))
+    }
+
+    #[inline]
+    fn serialize_i8(self, value: i8) -> Result<Value, Error> {
+        self.serialize_i64(i64::from(value))
+    }
+
+    #[inline]
+    fn serialize_i16(self, value: i16) -> Result<Value, Error> {
+        self.serialize_i64(i64::from(value))
+    }
+
+    #[inline]
+    fn serialize_i32(self, value: i32) -> Result<Value, Error> {
+        self.serialize_i64(i64::from(value))
+    }
+
+    #[inline]
+    fn serialize_i64(self, value: i64) -> Result<Value, Error> {
+        self.serialize_i128(i128::from(value))
+    }
+
+    fn serialize_i128(self, value: i128) -> Result<Value, Error> {
+        Ok(Value::Integer(value))
+    }
+
+    #[inline]
+    fn serialize_u8(self, value: u8) -> Result<Value, Error> {
+        self.serialize_u64(u64::from(value))
+    }
+
+    #[inline]
+    fn serialize_u16(self, value: u16) -> Result<Value, Error> {
+        self.serialize_u64(u64::from(value))
+    }
+
+    #[inline]
+    fn serialize_u32(self, value: u32) -> Result<Value, Error> {
+        self.serialize_u64(u64::from(value))
+    }
+
+    #[inline]
+    fn serialize_u64(self, value: u64) -> Result<Value, Error> {
+        Ok(Value::Integer(value.into()))
+    }
+
+    #[inline]
+    fn serialize_f32(self, value: f32) -> Result<Value, Error> {
+        self.serialize_f64(f64::from(value))
+    }
+
+    #[inline]
+    fn serialize_f64(self, value: f64) -> Result<Value, Error> {
+        Ok(Value::Float(value))
+    }
+
+    #[inline]
+    fn serialize_char(self, value: char) -> Result<Value, Error> {
+        let mut s = String::new();
+        s.push(value);
+        self.serialize_str(&s)
+    }
+
+    #[inline]
+    fn serialize_str(self, value: &str) -> Result<Value, Error> {
+        Ok(Value::Text(value.to_owned()))
+    }
+
+    fn serialize_bytes(self, value: &[u8]) -> Result<Value, Error> {
+        Ok(Value::Bytes(value.to_vec()))
+    }
+
+    #[inline]
+    fn serialize_unit(self) -> Result<Value, Error> {
+        Ok(Value::Null)
+    }
+
+    #[inline]
+    fn serialize_unit_struct(self, _name: &'static str) -> Result<Value, Error> {
+        self.serialize_unit()
+    }
+
+    #[inline]
+    fn serialize_unit_variant(
+        self,
+        _name: &'static str,
+        _variant_index: u32,
+        variant: &'static str,
+    ) -> Result<Value, Error> {
+        self.serialize_str(variant)
+    }
+
+    #[inline]
+    fn serialize_newtype_struct<T: ?Sized>(
+        self,
+        _name: &'static str,
+        value: &T,
+    ) -> Result<Value, Error>
+    where
+        T: Serialize,
+    {
+        value.serialize(self)
+    }
+
+    fn serialize_newtype_variant<T: ?Sized>(
+        self,
+        _name: &'static str,
+        _variant_index: u32,
+        variant: &'static str,
+        value: &T,
+    ) -> Result<Value, Error>
+    where
+        T: Serialize,
+    {
+        let mut values = BTreeMap::new();
+        values.insert(Value::from(variant.to_owned()), to_value(&value)?);
+        Ok(Value::Map(values))
+    }
+
+    #[inline]
+    fn serialize_none(self) -> Result<Value, Error> {
+        self.serialize_unit()
+    }
+
+    #[inline]
+    fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Value, Error>
+    where
+        T: Serialize,
+    {
+        value.serialize(self)
+    }
+
+    fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Error> {
+        Ok(SerializeVec {
+            vec: Vec::with_capacity(len.unwrap_or(0)),
+        })
+    }
+
+    fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Error> {
+        self.serialize_seq(Some(len))
+    }
+
+    fn serialize_tuple_struct(
+        self,
+        _name: &'static str,
+        len: usize,
+    ) -> Result<Self::SerializeTupleStruct, Error> {
+        self.serialize_tuple(len)
+    }
+
+    fn serialize_tuple_variant(
+        self,
+        _name: &'static str,
+        _variant_index: u32,
+        variant: &'static str,
+        len: usize,
+    ) -> Result<Self::SerializeTupleVariant, Error> {
+        Ok(SerializeTupleVariant {
+            name: String::from(variant),
+            vec: Vec::with_capacity(len),
+        })
+    }
+
+    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Error> {
+        Ok(SerializeMap {
+            map: BTreeMap::new(),
+            next_key: None,
+        })
+    }
+
+    fn serialize_struct(
+        self,
+        _name: &'static str,
+        len: usize,
+    ) -> Result<Self::SerializeStruct, Error> {
+        self.serialize_map(Some(len))
+    }
+
+    fn serialize_struct_variant(
+        self,
+        _name: &'static str,
+        _variant_index: u32,
+        variant: &'static str,
+        _len: usize,
+    ) -> Result<Self::SerializeStructVariant, Error> {
+        Ok(SerializeStructVariant {
+            name: String::from(variant),
+            map: BTreeMap::new(),
+        })
+    }
+
+    #[inline]
+    fn is_human_readable(&self) -> bool {
+        false
+    }
+}
+
+pub struct SerializeVec {
+    vec: Vec<Value>,
+}
+
+pub struct SerializeTupleVariant {
+    name: String,
+    vec: Vec<Value>,
+}
+
+pub struct SerializeMap {
+    map: BTreeMap<Value, Value>,
+    next_key: Option<Value>,
+}
+
+pub struct SerializeStructVariant {
+    name: String,
+    map: BTreeMap<Value, Value>,
+}
+
+impl serde::ser::SerializeSeq for SerializeVec {
+    type Ok = Value;
+    type Error = Error;
+
+    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+    where
+        T: Serialize,
+    {
+        self.vec.push(to_value(&value)?);
+        Ok(())
+    }
+
+    fn end(self) -> Result<Value, Error> {
+        Ok(Value::Array(self.vec))
+    }
+}
+
+impl serde::ser::SerializeTuple for SerializeVec {
+    type Ok = Value;
+    type Error = Error;
+
+    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+    where
+        T: Serialize,
+    {
+        serde::ser::SerializeSeq::serialize_element(self, value)
+    }
+
+    fn end(self) -> Result<Value, Error> {
+        serde::ser::SerializeSeq::end(self)
+    }
+}
+
+impl serde::ser::SerializeTupleStruct for SerializeVec {
+    type Ok = Value;
+    type Error = Error;
+
+    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+    where
+        T: Serialize,
+    {
+        serde::ser::SerializeSeq::serialize_element(self, value)
+    }
+
+    fn end(self) -> Result<Value, Error> {
+        serde::ser::SerializeSeq::end(self)
+    }
+}
+
+impl serde::ser::SerializeTupleVariant for SerializeTupleVariant {
+    type Ok = Value;
+    type Error = Error;
+
+    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+    where
+        T: Serialize,
+    {
+        self.vec.push(to_value(&value)?);
+        Ok(())
+    }
+
+    fn end(self) -> Result<Value, Error> {
+        let mut object = BTreeMap::new();
+
+        object.insert(Value::from(self.name), Value::Array(self.vec));
+
+        Ok(Value::Map(object))
+    }
+}
+
+impl serde::ser::SerializeMap for SerializeMap {
+    type Ok = Value;
+    type Error = Error;
+
+    fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Error>
+    where
+        T: Serialize,
+    {
+        self.next_key = Some(to_value(&key)?);
+        Ok(())
+    }
+
+    fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+    where
+        T: Serialize,
+    {
+        let key = self.next_key.take();
+        // Panic because this indicates a bug in the program rather than an
+        // expected failure.
+        let key = key.expect("serialize_value called before serialize_key");
+        self.map.insert(key, to_value(&value)?);
+        Ok(())
+    }
+
+    fn end(self) -> Result<Value, Error> {
+        Ok(Value::Map(self.map))
+    }
+}
+
+impl serde::ser::SerializeStruct for SerializeMap {
+    type Ok = Value;
+    type Error = Error;
+
+    fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
+    where
+        T: Serialize,
+    {
+        serde::ser::SerializeMap::serialize_key(self, key)?;
+        serde::ser::SerializeMap::serialize_value(self, value)
+    }
+
+    fn end(self) -> Result<Value, Error> {
+        serde::ser::SerializeMap::end(self)
+    }
+}
+
+impl serde::ser::SerializeStructVariant for SerializeStructVariant {
+    type Ok = Value;
+    type Error = Error;
+
+    fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
+    where
+        T: Serialize,
+    {
+        self.map
+            .insert(Value::from(String::from(key)), to_value(&value)?);
+        Ok(())
+    }
+
+    fn end(self) -> Result<Value, Error> {
+        let mut object = BTreeMap::new();
+
+        object.insert(Value::from(self.name), Value::Map(self.map));
+
+        Ok(Value::Map(object))
+    }
+}
+
+/// Convert a `T` into `serde_cbor::Value` which is an enum that can represent
+/// any valid CBOR data.
+///
+/// ```rust
+/// extern crate serde;
+///
+/// #[macro_use]
+/// extern crate serde_derive;
+/// extern crate serde_cbor;
+///
+/// use std::error::Error;
+///
+/// #[derive(Serialize)]
+/// struct User {
+///     fingerprint: String,
+///     location: String,
+/// }
+///
+/// fn main() {
+///     let u = User {
+///         fingerprint: "0xF9BA143B95FF6D82".to_owned(),
+///         location: "Menlo Park, CA".to_owned(),
+///     };
+///
+///     let v = serde_cbor::value::to_value(u).unwrap();
+/// }
+/// ```
+#[allow(clippy::needless_pass_by_value)]
+// Taking by value is more friendly to iterator adapters, option and result
+pub fn to_value<T>(value: T) -> Result<Value, Error>
+where
+    T: Serialize,
+{
+    value.serialize(Serializer)
+}
diff --git a/src/write.rs b/src/write.rs
new file mode 100644
index 0000000..94c326e
--- /dev/null
+++ b/src/write.rs
@@ -0,0 +1,175 @@
+#[cfg(feature = "alloc")]
+use alloc::vec::Vec;
+#[cfg(not(feature = "std"))]
+use core::fmt;
+#[cfg(feature = "std")]
+use std::io;
+
+use crate::error;
+
+#[cfg(not(feature = "unsealed_read_write"))]
+/// A sink for serialized CBOR.
+///
+/// This trait is similar to the [`Write`]() trait in the standard library,
+/// but has a smaller and more general API.
+///
+/// Any object implementing `std::io::Write`
+/// can be wrapped in an [`IoWrite`](../write/struct.IoWrite.html) that implements
+/// this trait for the underlying object.
+pub trait Write: private::Sealed {
+    /// The type of error returned when a write operation fails.
+    #[doc(hidden)]
+    type Error: Into<error::Error>;
+
+    /// Attempts to write an entire buffer into this write.
+    #[doc(hidden)]
+    fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>;
+}
+
+#[cfg(feature = "unsealed_read_write")]
+/// A sink for serialized CBOR.
+///
+/// This trait is similar to the [`Write`]() trait in the standard library,
+/// but has a smaller and more general API.
+///
+/// Any object implementing `std::io::Write`
+/// can be wrapped in an [`IoWrite`](../write/struct.IoWrite.html) that implements
+/// this trait for the underlying object.
+///
+/// This trait is sealed by default, enabling the `unsealed_read_write` feature removes this bound
+/// to allow objects outside of this crate to implement this trait.
+pub trait Write {
+    /// The type of error returned when a write operation fails.
+    type Error: Into<error::Error>;
+
+    /// Attempts to write an entire buffer into this write.
+    fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>;
+}
+
+#[cfg(not(feature = "unsealed_read_write"))]
+mod private {
+    pub trait Sealed {}
+}
+
+impl<W> Write for &mut W
+where
+    W: Write,
+{
+    type Error = W::Error;
+
+    fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
+        (*self).write_all(buf)
+    }
+}
+
+#[cfg(not(feature = "unsealed_read_write"))]
+impl<W> private::Sealed for &mut W where W: Write {}
+
+#[cfg(feature = "std")]
+/// A wrapper for types that implement
+/// [`std::io::Write`](https://doc.rust-lang.org/std/io/trait.Write.html) to implement the local
+/// [`Write`](trait.Write.html) trait.
+#[derive(Debug)]
+pub struct IoWrite<W>(W);
+
+#[cfg(feature = "std")]
+impl<W: io::Write> IoWrite<W> {
+    /// Wraps an `io::Write` writer to make it compatible with [`Write`](trait.Write.html)
+    pub fn new(w: W) -> IoWrite<W> {
+        IoWrite(w)
+    }
+}
+
+#[cfg(feature = "std")]
+impl<W: io::Write> Write for IoWrite<W> {
+    type Error = io::Error;
+
+    fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
+        self.0.write_all(buf)
+    }
+}
+
+#[cfg(all(feature = "std", not(feature = "unsealed_read_write")))]
+impl<W> private::Sealed for IoWrite<W> where W: io::Write {}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl Write for Vec<u8> {
+    type Error = error::Error;
+
+    fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
+        self.extend_from_slice(buf);
+        Ok(())
+    }
+}
+
+#[cfg(all(
+    any(feature = "std", feature = "alloc"),
+    not(feature = "unsealed_read_write")
+))]
+impl private::Sealed for Vec<u8> {}
+
+#[cfg(not(feature = "std"))]
+#[derive(Debug)]
+pub struct FmtWrite<'a, W: Write>(&'a mut W);
+
+#[cfg(not(feature = "std"))]
+impl<'a, W: Write> FmtWrite<'a, W> {
+    /// Wraps an `fmt::Write` writer to make it compatible with [`Write`](trait.Write.html)
+    pub fn new(w: &'a mut W) -> FmtWrite<'a, W> {
+        FmtWrite(w)
+    }
+}
+
+#[cfg(not(feature = "std"))]
+impl<'a, W: Write> fmt::Write for FmtWrite<'a, W> {
+    fn write_str(&mut self, s: &str) -> fmt::Result {
+        self.0.write_all(s.as_bytes()).map_err(|_| fmt::Error)
+    }
+}
+
+#[cfg(all(not(feature = "std"), not(feature = "unsealed_read_write")))]
+impl<'a, W> private::Sealed for FmtWrite<'a, W> where W: Write {}
+
+/// Implements [`Write`](trait.Write.html) for mutable byte slices (`&mut [u8]`).
+///
+/// Returns an error if the value to serialize is too large to fit in the slice.
+#[derive(Debug)]
+pub struct SliceWrite<'a> {
+    slice: &'a mut [u8],
+    index: usize,
+}
+
+impl<'a> SliceWrite<'a> {
+    /// Wraps a mutable slice so it can be used as a `Write`.
+    pub fn new(slice: &'a mut [u8]) -> SliceWrite<'a> {
+        SliceWrite { slice, index: 0 }
+    }
+
+    /// Returns the number of bytes written to the underlying slice.
+    pub fn bytes_written(&self) -> usize {
+        self.index
+    }
+
+    /// Returns the underlying slice.
+    pub fn into_inner(self) -> &'a mut [u8] {
+        self.slice
+    }
+}
+
+impl<'a> Write for SliceWrite<'a> {
+    type Error = error::Error;
+
+    fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
+        if self.slice.len() - self.index < buf.len() {
+            // This buffer will not fit in our slice
+            return Err(error::Error::scratch_too_small(self.index as u64));
+        }
+        let end = self.index + buf.len();
+        self.slice[self.index..end].copy_from_slice(buf);
+        self.index = end;
+        Ok(())
+    }
+}
+
+#[cfg(not(feature = "unsealed_read_write"))]
+impl<'a> private::Sealed for SliceWrite<'a> {}
diff --git a/tests/bennofs.rs b/tests/bennofs.rs
new file mode 100644
index 0000000..1b289f4
--- /dev/null
+++ b/tests/bennofs.rs
@@ -0,0 +1,60 @@
+#[macro_use]
+extern crate serde_derive;
+
+use serde::Serialize;
+use serde_cbor::ser::SliceWrite;
+use serde_cbor::{self, Serializer};
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+struct Example {
+    foo: Foo,
+    payload: u8,
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+struct Foo {
+    x: u8,
+    color: Color,
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+enum Color {
+    Red,
+    Blue,
+    Yellow(u8),
+}
+
+const EXAMPLE: Example = Example {
+    foo: Foo {
+        x: 0xAA,
+        color: Color::Yellow(40),
+    },
+    payload: 0xCC,
+};
+
+#[cfg(feature = "std")]
+mod std_tests {
+    use super::*;
+
+    #[test]
+    fn test() {
+        let serialized = serde_cbor::ser::to_vec_packed(&EXAMPLE).expect("bennofs 1");
+        println!("{:?}", serialized);
+        let deserialized: Example = serde_cbor::from_slice(&serialized).expect("bennofs 2");
+        assert_eq!(EXAMPLE, deserialized);
+    }
+}
+
+#[test]
+fn test() {
+    let mut slice = [0u8; 64];
+    let writer = SliceWrite::new(&mut slice);
+    let mut serializer = Serializer::new(writer).packed_format();
+    EXAMPLE.serialize(&mut serializer).unwrap();
+    let writer = serializer.into_inner();
+    let end = writer.bytes_written();
+    let slice = writer.into_inner();
+    let deserialized: Example =
+        serde_cbor::de::from_slice_with_scratch(&slice[..end], &mut []).unwrap();
+    assert_eq!(EXAMPLE, deserialized);
+}
diff --git a/tests/canonical.rs b/tests/canonical.rs
new file mode 100644
index 0000000..438e29e
--- /dev/null
+++ b/tests/canonical.rs
@@ -0,0 +1,104 @@
+#[cfg(feature = "std")]
+mod std_tests {
+    use serde_cbor::value::Value;
+
+    #[test]
+    fn integer_canonical_sort_order() {
+        let expected = [
+            0,
+            23,
+            24,
+            255,
+            256,
+            65535,
+            65536,
+            4294967295,
+            -1,
+            -24,
+            -25,
+            -256,
+            -257,
+            -65536,
+            -65537,
+            -4294967296,
+        ]
+        .iter()
+        .map(|i| Value::Integer(*i))
+        .collect::<Vec<_>>();
+
+        let mut sorted = expected.clone();
+        sorted.sort();
+
+        assert_eq!(expected, sorted);
+    }
+
+    #[test]
+    fn string_canonical_sort_order() {
+        let expected = ["", "a", "b", "aa"]
+            .iter()
+            .map(|s| Value::Text(s.to_string()))
+            .collect::<Vec<_>>();
+
+        let mut sorted = expected.clone();
+        sorted.sort();
+
+        assert_eq!(expected, sorted);
+    }
+
+    #[test]
+    fn bytes_canonical_sort_order() {
+        let expected = vec![vec![], vec![0u8], vec![1u8], vec![0u8, 0u8]]
+            .into_iter()
+            .map(|v| Value::Bytes(v))
+            .collect::<Vec<_>>();
+
+        let mut sorted = expected.clone();
+        sorted.sort();
+
+        assert_eq!(expected, sorted);
+    }
+
+    #[test]
+    fn simple_data_canonical_sort_order() {
+        let expected = vec![Value::Bool(false), Value::Bool(true), Value::Null];
+
+        let mut sorted = expected.clone();
+        sorted.sort();
+
+        assert_eq!(expected, sorted);
+    }
+
+    #[test]
+    fn major_type_canonical_sort_order() {
+        let expected = vec![
+            Value::Integer(0),
+            Value::Integer(-1),
+            Value::Bytes(vec![]),
+            Value::Text("".to_string()),
+            Value::Null,
+        ];
+
+        let mut sorted = expected.clone();
+        sorted.sort();
+
+        assert_eq!(expected, sorted);
+    }
+
+    #[test]
+    fn test_rfc_example() {
+        // See: https://tools.ietf.org/html/draft-ietf-cbor-7049bis-04#section-4.10
+        let expected = vec![
+            Value::Integer(10),
+            Value::Integer(100),
+            Value::Integer(-1),
+            Value::Text("z".to_owned()),
+            Value::Text("aa".to_owned()),
+            Value::Array(vec![Value::Integer(100)]),
+            Value::Array(vec![Value::Integer(-1)]),
+            Value::Bool(false),
+        ];
+        let mut sorted = expected.clone();
+        sorted.sort();
+        assert_eq!(expected, sorted);
+    }
+}
diff --git a/tests/crash.cbor b/tests/crash.cbor
new file mode 100644
index 0000000..a3bc785
--- /dev/null
+++ b/tests/crash.cbor
Binary files differ
diff --git a/tests/de.rs b/tests/de.rs
new file mode 100644
index 0000000..01d7914
--- /dev/null
+++ b/tests/de.rs
@@ -0,0 +1,747 @@
+#[macro_use]
+extern crate serde_derive;
+
+use serde_cbor;
+use serde_cbor::de;
+
+#[test]
+fn test_str() {
+    let s: &str =
+        de::from_slice_with_scratch(&[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72], &mut []).unwrap();
+    assert_eq!(s, "foobar");
+}
+
+#[test]
+fn test_bytes() {
+    let s: &[u8] =
+        de::from_slice_with_scratch(&[0x46, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72], &mut []).unwrap();
+    assert_eq!(s, b"foobar");
+}
+
+#[test]
+fn test_int() {
+    let num: i64 = de::from_slice_with_scratch(&[0x39, 0x07, 0xde], &mut []).unwrap();
+    assert_eq!(num, -2015);
+}
+
+#[test]
+fn test_float() {
+    let float: f64 = de::from_slice_with_scratch(b"\xfa\x47\xc3\x50\x00", &mut []).unwrap();
+    assert_eq!(float, 100000.0);
+}
+
+#[test]
+fn test_indefinite_object() {
+    #[derive(Debug, Deserialize, PartialEq)]
+    struct Foo {
+        a: u64,
+        b: [u64; 2],
+    }
+    let expected = Foo { a: 1, b: [2, 3] };
+    let actual: Foo =
+        de::from_slice_with_scratch(b"\xbfaa\x01ab\x9f\x02\x03\xff\xff", &mut []).unwrap();
+    assert_eq!(expected, actual);
+}
+
+#[cfg(feature = "std")]
+mod std_tests {
+    use std::collections::BTreeMap;
+
+    use serde::de as serde_de;
+    use serde_cbor::value::Value;
+    use serde_cbor::{de, error, to_vec, Deserializer};
+
+    #[test]
+    fn test_string1() {
+        let value: error::Result<Value> =
+            de::from_slice(&[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]);
+        assert_eq!(value.unwrap(), Value::Text("foobar".to_owned()));
+    }
+
+    #[test]
+    fn test_string2() {
+        let value: error::Result<Value> = de::from_slice(&[
+            0x71, 0x49, 0x20, 0x6d, 0x65, 0x74, 0x20, 0x61, 0x20, 0x74, 0x72, 0x61, 0x76, 0x65,
+            0x6c, 0x6c, 0x65, 0x72,
+        ]);
+        assert_eq!(value.unwrap(), Value::Text("I met a traveller".to_owned()));
+    }
+
+    #[test]
+    fn test_string3() {
+        let slice = b"\x78\x2fI met a traveller from an antique land who said";
+        let value: error::Result<Value> = de::from_slice(slice);
+        assert_eq!(
+            value.unwrap(),
+            Value::Text("I met a traveller from an antique land who said".to_owned())
+        );
+    }
+
+    #[test]
+    fn test_byte_string() {
+        let value: error::Result<Value> =
+            de::from_slice(&[0x46, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]);
+        assert_eq!(value.unwrap(), Value::Bytes(b"foobar".to_vec()));
+    }
+
+    #[test]
+    fn test_numbers1() {
+        let value: error::Result<Value> = de::from_slice(&[0x00]);
+        assert_eq!(value.unwrap(), Value::Integer(0));
+    }
+
+    #[test]
+    fn test_numbers2() {
+        let value: error::Result<Value> = de::from_slice(&[0x1a, 0x00, 0xbc, 0x61, 0x4e]);
+        assert_eq!(value.unwrap(), Value::Integer(12345678));
+    }
+
+    #[test]
+    fn test_numbers3() {
+        let value: error::Result<Value> = de::from_slice(&[0x39, 0x07, 0xde]);
+        assert_eq!(value.unwrap(), Value::Integer(-2015));
+    }
+
+    #[test]
+    fn test_bool() {
+        let value: error::Result<Value> = de::from_slice(b"\xf4");
+        assert_eq!(value.unwrap(), Value::Bool(false));
+    }
+
+    #[test]
+    fn test_trailing_bytes() {
+        let value: error::Result<Value> = de::from_slice(b"\xf4trailing");
+        assert!(value.is_err());
+    }
+
+    #[test]
+    fn test_list1() {
+        let value: error::Result<Value> = de::from_slice(b"\x83\x01\x02\x03");
+        assert_eq!(
+            value.unwrap(),
+            Value::Array(vec![
+                Value::Integer(1),
+                Value::Integer(2),
+                Value::Integer(3)
+            ])
+        );
+    }
+
+    #[test]
+    fn test_list2() {
+        let value: error::Result<Value> = de::from_slice(b"\x82\x01\x82\x02\x81\x03");
+        assert_eq!(
+            value.unwrap(),
+            Value::Array(vec![
+                Value::Integer(1),
+                Value::Array(vec![
+                    Value::Integer(2),
+                    Value::Array(vec![Value::Integer(3)])
+                ])
+            ])
+        );
+    }
+
+    #[test]
+    fn test_object() {
+        let value: error::Result<Value> = de::from_slice(b"\xa5aaaAabaBacaCadaDaeaE");
+        let mut object = BTreeMap::new();
+        object.insert(Value::Text("a".to_owned()), Value::Text("A".to_owned()));
+        object.insert(Value::Text("b".to_owned()), Value::Text("B".to_owned()));
+        object.insert(Value::Text("c".to_owned()), Value::Text("C".to_owned()));
+        object.insert(Value::Text("d".to_owned()), Value::Text("D".to_owned()));
+        object.insert(Value::Text("e".to_owned()), Value::Text("E".to_owned()));
+        assert_eq!(value.unwrap(), Value::Map(object));
+    }
+
+    #[test]
+    fn test_indefinite_object() {
+        let value: error::Result<Value> = de::from_slice(b"\xbfaa\x01ab\x9f\x02\x03\xff\xff");
+        let mut object = BTreeMap::new();
+        object.insert(Value::Text("a".to_owned()), Value::Integer(1));
+        object.insert(
+            Value::Text("b".to_owned()),
+            Value::Array(vec![Value::Integer(2), Value::Integer(3)]),
+        );
+        assert_eq!(value.unwrap(), Value::Map(object));
+    }
+
+    #[test]
+    fn test_indefinite_list() {
+        let value: error::Result<Value> = de::from_slice(b"\x9f\x01\x02\x03\xff");
+        assert_eq!(
+            value.unwrap(),
+            Value::Array(vec![
+                Value::Integer(1),
+                Value::Integer(2),
+                Value::Integer(3)
+            ])
+        );
+    }
+
+    #[test]
+    fn test_indefinite_string() {
+        let value: error::Result<Value> =
+            de::from_slice(b"\x7f\x65Mary \x64Had \x62a \x67Little \x60\x64Lamb\xff");
+        assert_eq!(
+            value.unwrap(),
+            Value::Text("Mary Had a Little Lamb".to_owned())
+        );
+    }
+
+    #[test]
+    fn test_indefinite_byte_string() {
+        let value: error::Result<Value> = de::from_slice(b"\x5f\x42\x01\x23\x42\x45\x67\xff");
+        assert_eq!(value.unwrap(), Value::Bytes(b"\x01#Eg".to_vec()));
+    }
+
+    #[test]
+    fn test_multiple_indefinite_strings() {
+        let input = b"\x82\x7f\x65Mary \x64Had \x62a \x67Little \x60\x64Lamb\xff\x5f\x42\x01\x23\x42\x45\x67\xff";
+        _test_multiple_indefinite_strings(de::from_slice(input));
+        _test_multiple_indefinite_strings(de::from_mut_slice(input.to_vec().as_mut()));
+        let mut buf = [0u8; 64];
+        _test_multiple_indefinite_strings(de::from_slice_with_scratch(input, &mut buf));
+    }
+    fn _test_multiple_indefinite_strings(value: error::Result<Value>) {
+        // This assures that buffer rewinding in infinite buffers works as intended.
+        assert_eq!(
+            value.unwrap(),
+            Value::Array(vec![
+                Value::Text("Mary Had a Little Lamb".to_owned()),
+                Value::Bytes(b"\x01#Eg".to_vec())
+            ])
+        );
+    }
+
+    #[test]
+    fn test_float() {
+        let value: error::Result<Value> = de::from_slice(b"\xfa\x47\xc3\x50\x00");
+        assert_eq!(value.unwrap(), Value::Float(100000.0));
+    }
+
+    #[test]
+    fn test_self_describing() {
+        let value: error::Result<Value> =
+            de::from_slice(&[0xd9, 0xd9, 0xf7, 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]);
+        let expected = Value::Text("foobar".to_owned());
+        let strip_tags = |x: Value| {
+            if let Value::Tag(_, inner) = x {
+                *inner
+            } else {
+                x
+            }
+        };
+        assert_eq!(strip_tags(value.unwrap()), expected);
+    }
+
+    #[test]
+    fn test_f16() {
+        let mut x: Value = de::from_slice(&[0xf9, 0x41, 0x00]).unwrap();
+        assert_eq!(x, Value::Float(2.5));
+        x = de::from_slice(&[0xf9, 0x41, 0x90]).unwrap();
+        assert_eq!(x, Value::Float(2.78125));
+        x = de::from_slice(&[0xf9, 0x50, 0x90]).unwrap();
+        assert_eq!(x, Value::Float(36.5));
+        x = de::from_slice(&[0xf9, 0xd0, 0x90]).unwrap();
+        assert_eq!(x, Value::Float(-36.5));
+    }
+
+    #[test]
+    fn test_crazy_list() {
+        let slice = b"\x88\x1b\x00\x00\x00\x1c\xbe\x99\x1d\xc7\x3b\x00\x7a\xcf\x51\xdc\x51\x70\xdb\x3a\x1b\x3a\x06\xdd\xf5\xf6\xf7\xfb\x41\x76\x5e\xb1\xf8\x00\x00\x00\xf9\x7c\x00";
+        let value: Vec<Value> = de::from_slice(slice).unwrap();
+        assert_eq!(
+            value,
+            vec![
+                Value::Integer(123456789959),
+                Value::Integer(-34567897654325468),
+                Value::Integer(-456787678),
+                Value::Bool(true),
+                Value::Null,
+                Value::Null,
+                Value::Float(23456543.5),
+                Value::Float(::std::f64::INFINITY)
+            ]
+        );
+    }
+
+    #[test]
+    fn test_nan() {
+        let value: f64 = de::from_slice(b"\xf9\x7e\x00").unwrap();
+        assert!(value.is_nan());
+    }
+
+    #[test]
+    fn test_32f16() {
+        let value: f32 = de::from_slice(b"\xf9\x50\x00").unwrap();
+        assert_eq!(value, 32.0f32);
+    }
+
+    #[test]
+    // The file was reported as not working by user kie0tauB
+    // but it parses to a cbor value.
+    fn test_kietaub_file() {
+        let file = include_bytes!("kietaub.cbor");
+        let value_result: error::Result<Value> = de::from_slice(file);
+        value_result.unwrap();
+    }
+
+    #[test]
+    fn test_option_roundtrip() {
+        let obj1 = Some(10u32);
+
+        let v = to_vec(&obj1).unwrap();
+        let obj2: Result<Option<u32>, _> = serde_cbor::de::from_reader(&v[..]);
+        println!("{:?}", obj2);
+
+        assert_eq!(obj1, obj2.unwrap());
+    }
+
+    #[test]
+    fn test_option_none_roundtrip() {
+        let obj1 = None;
+
+        let v = to_vec(&obj1).unwrap();
+        println!("{:?}", v);
+        let obj2: Result<Option<u32>, _> = serde_cbor::de::from_reader(&v[..]);
+
+        assert_eq!(obj1, obj2.unwrap());
+    }
+
+    #[test]
+    fn test_variable_length_map() {
+        let slice = b"\xbf\x67\x6d\x65\x73\x73\x61\x67\x65\x64\x70\x6f\x6e\x67\xff";
+        let value: Value = de::from_slice(slice).unwrap();
+        let mut map = BTreeMap::new();
+        map.insert(
+            Value::Text("message".to_string()),
+            Value::Text("pong".to_string()),
+        );
+        assert_eq!(value, Value::Map(map))
+    }
+
+    #[test]
+    fn test_object_determinism_roundtrip() {
+        let expected = b"\xa2aa\x01ab\x82\x02\x03";
+
+        // 0.1% chance of not catching failure
+        for _ in 0..10 {
+            assert_eq!(
+                &to_vec(&de::from_slice::<Value>(expected).unwrap()).unwrap(),
+                expected
+            );
+        }
+    }
+
+    #[test]
+    fn stream_deserializer() {
+        let slice = b"\x01\x66foobar";
+        let mut it = Deserializer::from_slice(slice).into_iter::<Value>();
+        assert_eq!(Value::Integer(1), it.next().unwrap().unwrap());
+        assert_eq!(
+            Value::Text("foobar".to_string()),
+            it.next().unwrap().unwrap()
+        );
+        assert!(it.next().is_none());
+    }
+
+    #[test]
+    fn stream_deserializer_eof() {
+        let slice = b"\x01\x66foob";
+        let mut it = Deserializer::from_slice(slice).into_iter::<Value>();
+        assert_eq!(Value::Integer(1), it.next().unwrap().unwrap());
+        assert!(it.next().unwrap().unwrap_err().is_eof());
+    }
+
+    #[test]
+    fn stream_deserializer_eof_in_indefinite() {
+        let slice = b"\x7f\x65Mary \x64Had \x62a \x60\x67Little \x60\x64Lamb\xff";
+        let indices: &[usize] = &[
+            2,  // announcement but no data
+            10, // mid-buffer EOF
+            12, // neither new element nor end marker
+        ];
+        for end_of_slice in indices {
+            let mut it = Deserializer::from_slice(&slice[..*end_of_slice]).into_iter::<Value>();
+            assert!(it.next().unwrap().unwrap_err().is_eof());
+
+            let mut mutcopy = slice[..*end_of_slice].to_vec();
+            let mut it = Deserializer::from_mut_slice(mutcopy.as_mut()).into_iter::<Value>();
+            assert!(it.next().unwrap().unwrap_err().is_eof());
+
+            let mut buf = [0u8; 64];
+            let mut it = Deserializer::from_slice_with_scratch(&slice[..*end_of_slice], &mut buf)
+                .into_iter::<Value>();
+            assert!(it.next().unwrap().unwrap_err().is_eof());
+        }
+    }
+
+    #[test]
+    fn crash() {
+        let file = include_bytes!("crash.cbor");
+        let value_result: error::Result<Value> = de::from_slice(file);
+        assert_eq!(
+            value_result.unwrap_err().classify(),
+            serde_cbor::error::Category::Syntax
+        );
+    }
+
+    fn from_slice_stream<'a, T>(slice: &'a [u8]) -> error::Result<(&'a [u8], T)>
+    where
+        T: serde_de::Deserialize<'a>,
+    {
+        let mut deserializer = Deserializer::from_slice(slice);
+        let value = serde_de::Deserialize::deserialize(&mut deserializer)?;
+        let rest = &slice[deserializer.byte_offset()..];
+
+        Ok((rest, value))
+    }
+
+    #[test]
+    fn test_slice_offset() {
+        let v: Vec<u8> = vec![
+            0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72,
+        ];
+        let (rest, value): (&[u8], String) = from_slice_stream(&v[..]).unwrap();
+        assert_eq!(value, "foobar");
+        assert_eq!(rest, &[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]);
+        let (rest, value): (&[u8], String) = from_slice_stream(rest).unwrap();
+        assert_eq!(value, "foobar");
+        assert_eq!(rest, &[]);
+    }
+
+    #[derive(Debug, Copy, Clone)]
+    struct Options {
+        standard: bool,
+        legacy: bool,
+        packed: bool,
+        named: bool,
+    }
+
+    impl Default for Options {
+        fn default() -> Self {
+            Options {
+                standard: true,
+                legacy: true,
+                packed: true,
+                named: true,
+            }
+        }
+    }
+
+    impl Options {
+        fn no_standard(self) -> Self {
+            Options {
+                standard: false,
+                ..self
+            }
+        }
+
+        fn no_legacy(self) -> Self {
+            Options {
+                legacy: false,
+                ..self
+            }
+        }
+
+        fn no_packed(self) -> Self {
+            Options {
+                packed: false,
+                ..self
+            }
+        }
+
+        fn no_named(self) -> Self {
+            Options {
+                named: false,
+                ..self
+            }
+        }
+    }
+
+    fn from_slice_stream_options<'a, T>(
+        slice: &'a [u8],
+        options: Options,
+    ) -> error::Result<(&'a [u8], T)>
+    where
+        T: serde_de::Deserialize<'a>,
+    {
+        let deserializer = Deserializer::from_slice(slice);
+        let deserializer = if !options.packed {
+            deserializer.disable_packed_format()
+        } else {
+            deserializer
+        };
+        let deserializer = if !options.named {
+            deserializer.disable_named_format()
+        } else {
+            deserializer
+        };
+        let deserializer = if !options.standard {
+            deserializer.disable_standard_enums()
+        } else {
+            deserializer
+        };
+        let mut deserializer = if !options.legacy {
+            deserializer.disable_legacy_enums()
+        } else {
+            deserializer
+        };
+        let value = serde_de::Deserialize::deserialize(&mut deserializer)?;
+        let rest = &slice[deserializer.byte_offset()..];
+
+        Ok((rest, value))
+    }
+
+    #[test]
+    fn test_deserializer_enums() {
+        #[derive(Debug, PartialEq, Deserialize)]
+        enum Enum {
+            Unit,
+            NewType(i32),
+            Tuple(String, bool),
+            Struct { x: i32, y: i32 },
+        }
+
+        // This is the format used in serde >= 0.10
+        //
+        // Serialization of Enum::NewType(10)
+        let v: Vec<u8> = vec![
+            0xa1, // map 1pair
+            0x67, 0x4e, 0x65, 0x77, 0x54, 0x79, 0x70, 0x65, // utf8 string: NewType
+            0x1a, // u32
+            0x00, 0x00, 0x00, 0x0a, // 10 (dec)
+        ];
+        let (_rest, value): (&[u8], Enum) = from_slice_stream(&v[..]).unwrap();
+        assert_eq!(value, Enum::NewType(10));
+        let (_rest, value): (&[u8], Enum) =
+            from_slice_stream_options(&v[..], Options::default().no_legacy()).unwrap();
+        assert_eq!(value, Enum::NewType(10));
+        let value: error::Result<(&[u8], Enum)> =
+            from_slice_stream_options(&v[..], Options::default().no_standard());
+        assert_eq!(
+            value.unwrap_err().classify(),
+            serde_cbor::error::Category::Syntax
+        );
+        let value: error::Result<(&[u8], Enum)> =
+            from_slice_stream_options(&v[..], Options::default().no_standard().no_legacy());
+        assert_eq!(
+            value.unwrap_err().classify(),
+            serde_cbor::error::Category::Syntax
+        );
+        // Serialization of Enum::Unit
+        let v: Vec<u8> = vec![
+            0x64, 0x55, 0x6e, 0x69, 0x74, // utf8 string: Unit
+        ];
+        let (_rest, value): (&[u8], Enum) = from_slice_stream(&v[..]).unwrap();
+        assert_eq!(value, Enum::Unit);
+        let (_rest, value): (&[u8], Enum) =
+            from_slice_stream_options(&v[..], Options::default().no_legacy()).unwrap();
+        assert_eq!(value, Enum::Unit);
+        let (_rest, value): (&[u8], Enum) =
+            from_slice_stream_options(&v[..], Options::default().no_standard()).unwrap();
+        assert_eq!(value, Enum::Unit);
+        let value: error::Result<(&[u8], Enum)> =
+            from_slice_stream_options(&v[..], Options::default().no_legacy().no_standard());
+        assert_eq!(
+            value.unwrap_err().classify(),
+            serde_cbor::error::Category::Syntax
+        );
+
+        // This is the format used in serde <= 0.9
+        let v: Vec<u8> = vec![
+            0x82, // array 2 items
+            0x67, 0x4e, 0x65, 0x77, 0x54, 0x79, 0x70, 0x65, // utf8 string: NewType
+            0x1a, // u32
+            0x00, 0x00, 0x00, 0x0a, // 10 (dec)
+        ];
+        let (_rest, value): (&[u8], Enum) = from_slice_stream(&v[..]).unwrap();
+        assert_eq!(value, Enum::NewType(10));
+        let value: error::Result<(&[u8], Enum)> =
+            from_slice_stream_options(&v[..], Options::default().no_legacy());
+        assert_eq!(
+            value.unwrap_err().classify(),
+            serde_cbor::error::Category::Syntax
+        );
+        let value: error::Result<(&[u8], Enum)> =
+            from_slice_stream_options(&v[..], Options::default().no_standard());
+        assert_eq!(value.unwrap().1, Enum::NewType(10));
+        let value: error::Result<(&[u8], Enum)> =
+            from_slice_stream_options(&v[..], Options::default().no_standard().no_legacy());
+        assert_eq!(
+            value.unwrap_err().classify(),
+            serde_cbor::error::Category::Syntax
+        );
+    }
+
+    #[test]
+    fn test_packed_deserialization() {
+        #[derive(Debug, PartialEq, Deserialize)]
+        struct User {
+            user_id: u32,
+            password_hash: [u8; 4],
+        }
+
+        // unpacked
+        let v: Vec<u8> = vec![
+            0xa2, // map 2pair
+            0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, // utf8 string: user_id
+            0x0a, // integer: 10
+            // utf8 string: password_hash
+            0x6d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68,
+            0x84, 0x01, 0x02, 0x03, 0x04, // 4 byte array [1, 2, 3, 4]
+        ];
+
+        let (_rest, value): (&[u8], User) = from_slice_stream(&v[..]).unwrap();
+        assert_eq!(
+            value,
+            User {
+                user_id: 10,
+                password_hash: [1, 2, 3, 4],
+            }
+        );
+        let (_rest, value): (&[u8], User) =
+            from_slice_stream_options(&v[..], Options::default().no_packed()).unwrap();
+        assert_eq!(
+            value,
+            User {
+                user_id: 10,
+                password_hash: [1, 2, 3, 4],
+            }
+        );
+        let value: error::Result<(&[u8], User)> =
+            from_slice_stream_options(&v[..], Options::default().no_named());
+        assert_eq!(
+            value.unwrap_err().classify(),
+            serde_cbor::error::Category::Syntax
+        );
+
+        // unpacked - indefinite length
+        let v: Vec<u8> = vec![
+            0xbf, // map to be followed by a break
+            0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, // utf8 string: user_id
+            0x0a, // integer: 10
+            // utf8 string: password_hash
+            0x6d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68,
+            0x84, 0x01, 0x02, 0x03, 0x04, // 4 byte array [1, 2, 3, 4]
+            0xff, // break
+        ];
+
+        let (_rest, value): (&[u8], User) = from_slice_stream(&v[..]).unwrap();
+        assert_eq!(
+            value,
+            User {
+                user_id: 10,
+                password_hash: [1, 2, 3, 4],
+            }
+        );
+        let (_rest, value): (&[u8], User) =
+            from_slice_stream_options(&v[..], Options::default().no_packed()).unwrap();
+        assert_eq!(
+            value,
+            User {
+                user_id: 10,
+                password_hash: [1, 2, 3, 4],
+            }
+        );
+        let value: error::Result<(&[u8], User)> =
+            from_slice_stream_options(&v[..], Options::default().no_named());
+        assert_eq!(
+            value.unwrap_err().classify(),
+            serde_cbor::error::Category::Syntax
+        );
+
+        // packed
+        let v: Vec<u8> = vec![
+            0xa2, // map 2pair
+            0x00, // index 0
+            0x0a, // integer: 10
+            0x01, // index 1
+            0x84, 0x01, 0x02, 0x03, 0x04, // 4 byte array [1, 2, 3, 4]
+        ];
+
+        let (_rest, value): (&[u8], User) = from_slice_stream(&v[..]).unwrap();
+        assert_eq!(
+            value,
+            User {
+                user_id: 10,
+                password_hash: [1, 2, 3, 4],
+            }
+        );
+        let (_rest, value): (&[u8], User) =
+            from_slice_stream_options(&v[..], Options::default().no_named()).unwrap();
+        assert_eq!(
+            value,
+            User {
+                user_id: 10,
+                password_hash: [1, 2, 3, 4],
+            }
+        );
+        let value: error::Result<(&[u8], User)> =
+            from_slice_stream_options(&v[..], Options::default().no_packed());
+        assert_eq!(
+            value.unwrap_err().classify(),
+            serde_cbor::error::Category::Syntax
+        );
+
+        // packed - indefinite length
+        let v: Vec<u8> = vec![
+            0xbf, // map, to be followed by a break
+            0x00, // index 0
+            0x0a, // integer: 10
+            0x01, // index 1
+            0x84, 0x01, 0x02, 0x03, 0x04, // 4 byte array [1, 2, 3, 4]
+            0xff, // break
+        ];
+
+        let (_rest, value): (&[u8], User) = from_slice_stream(&v[..]).unwrap();
+        assert_eq!(
+            value,
+            User {
+                user_id: 10,
+                password_hash: [1, 2, 3, 4],
+            }
+        );
+        let (_rest, value): (&[u8], User) =
+            from_slice_stream_options(&v[..], Options::default().no_named()).unwrap();
+        assert_eq!(
+            value,
+            User {
+                user_id: 10,
+                password_hash: [1, 2, 3, 4],
+            }
+        );
+        let value: error::Result<(&[u8], User)> =
+            from_slice_stream_options(&v[..], Options::default().no_packed());
+        assert_eq!(
+            value.unwrap_err().classify(),
+            serde_cbor::error::Category::Syntax
+        );
+    }
+
+    use serde_cbor::{de::from_slice, ser::to_vec_packed};
+    use std::net::{IpAddr, Ipv4Addr};
+    #[test]
+    fn test_ipaddr_deserialization() {
+        let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
+        let buf = to_vec_packed(&ip).unwrap();
+        let deserialized_ip = from_slice::<IpAddr>(&buf).unwrap();
+        assert_eq!(ip, deserialized_ip);
+
+        let buf = to_vec(&ip).unwrap();
+        let deserialized_ip = from_slice::<IpAddr>(&buf).unwrap();
+        assert_eq!(ip, deserialized_ip);
+    }
+
+    #[test]
+    fn attempt_stack_overflow() {
+        // Create a tag 17, followed by 999 more tag 17:
+        // 17(17(17(17(17(17(17(17(17(17(17(17(17(17(17(17(17(17(...
+        // This causes deep recursion in the decoder and may
+        // exhaust the stack and therfore result in a stack overflow.
+        let input = vec![0xd1; 1000];
+        let err = serde_cbor::from_slice::<serde_cbor::Value>(&input).expect_err("recursion limit");
+        assert!(err.is_syntax());
+    }
+}
diff --git a/tests/enum.rs b/tests/enum.rs
new file mode 100644
index 0000000..630500d
--- /dev/null
+++ b/tests/enum.rs
@@ -0,0 +1,236 @@
+use serde::Serialize;
+use serde_cbor;
+use serde_cbor::ser::{Serializer, SliceWrite};
+
+#[macro_use]
+extern crate serde_derive;
+
+#[test]
+fn test_simple_data_enum_roundtrip() {
+    #[derive(Debug, Serialize, Deserialize, PartialEq)]
+    enum DataEnum {
+        A(u32),
+        B(f32),
+    }
+
+    let a = DataEnum::A(42);
+
+    let mut slice = [0u8; 64];
+    let writer = SliceWrite::new(&mut slice);
+    let mut serializer = Serializer::new(writer);
+    a.serialize(&mut serializer).unwrap();
+    let writer = serializer.into_inner();
+    let end = writer.bytes_written();
+    let slice = writer.into_inner();
+    let deserialized: DataEnum =
+        serde_cbor::de::from_slice_with_scratch(&slice[..end], &mut []).unwrap();
+    assert_eq!(a, deserialized);
+}
+
+#[cfg(feature = "std")]
+mod std_tests {
+    use std::collections::BTreeMap;
+
+    use serde_cbor::ser::{IoWrite, Serializer};
+    use serde_cbor::value::Value;
+    use serde_cbor::{from_slice, to_vec};
+
+    pub fn to_vec_legacy<T>(value: &T) -> serde_cbor::Result<Vec<u8>>
+    where
+        T: serde::ser::Serialize,
+    {
+        let mut vec = Vec::new();
+        value.serialize(&mut Serializer::new(&mut IoWrite::new(&mut vec)).legacy_enums())?;
+        Ok(vec)
+    }
+
+    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
+    enum Enum {
+        A,
+        B,
+    }
+
+    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
+    struct EnumStruct {
+        e: Enum,
+    }
+
+    #[test]
+    fn test_enum() {
+        let enum_struct = EnumStruct { e: Enum::B };
+        let raw = &to_vec(&enum_struct).unwrap();
+        println!("raw enum {:?}", raw);
+        let re: EnumStruct = from_slice(raw).unwrap();
+        assert_eq!(enum_struct, re);
+    }
+
+    #[repr(u16)]
+    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
+    enum ReprEnum {
+        A,
+        B,
+    }
+
+    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
+    struct ReprEnumStruct {
+        e: ReprEnum,
+    }
+
+    #[test]
+    fn test_repr_enum() {
+        let repr_enum_struct = ReprEnumStruct { e: ReprEnum::B };
+        let re: ReprEnumStruct = from_slice(&to_vec(&repr_enum_struct).unwrap()).unwrap();
+        assert_eq!(repr_enum_struct, re);
+    }
+
+    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
+    enum DataEnum {
+        A(u32),
+        B(bool, u8),
+        C { x: u8, y: String },
+    }
+
+    #[test]
+    fn test_data_enum() {
+        let data_enum_a = DataEnum::A(4);
+        let re_a: DataEnum = from_slice(&to_vec(&data_enum_a).unwrap()).unwrap();
+        assert_eq!(data_enum_a, re_a);
+        let data_enum_b = DataEnum::B(true, 42);
+        let re_b: DataEnum = from_slice(&to_vec(&data_enum_b).unwrap()).unwrap();
+        assert_eq!(data_enum_b, re_b);
+        let data_enum_c = DataEnum::C {
+            x: 3,
+            y: "foo".to_owned(),
+        };
+        println!("{:?}", &to_vec(&data_enum_c).unwrap());
+        let re_c: DataEnum = from_slice(&to_vec(&data_enum_c).unwrap()).unwrap();
+        assert_eq!(data_enum_c, re_c);
+    }
+
+    #[test]
+    fn test_serialize() {
+        assert_eq!(to_vec_legacy(&Enum::A).unwrap(), &[97, 65]);
+        assert_eq!(to_vec_legacy(&Enum::B).unwrap(), &[97, 66]);
+        assert_eq!(
+            to_vec_legacy(&DataEnum::A(42)).unwrap(),
+            &[130, 97, 65, 24, 42]
+        );
+        assert_eq!(
+            to_vec_legacy(&DataEnum::B(true, 9)).unwrap(),
+            &[131, 97, 66, 245, 9]
+        );
+    }
+
+    #[test]
+    fn test_newtype_struct() {
+        #[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
+        pub struct Newtype(u8);
+        assert_eq!(to_vec(&142u8).unwrap(), to_vec(&Newtype(142u8)).unwrap());
+        assert_eq!(from_slice::<Newtype>(&[24, 142]).unwrap(), Newtype(142));
+    }
+
+    #[derive(Deserialize, PartialEq, Debug)]
+    enum Foo {
+        #[serde(rename = "require")]
+        Require,
+    }
+
+    #[test]
+    fn test_variable_length_array() {
+        let slice = b"\x9F\x67\x72\x65\x71\x75\x69\x72\x65\xFF";
+        let value: Vec<Foo> = from_slice(slice).unwrap();
+        assert_eq!(value, [Foo::Require]);
+    }
+
+    #[derive(Serialize, Deserialize, PartialEq, Debug)]
+    enum Bar {
+        Empty,
+        Number(i32),
+        Flag(String, bool),
+        Point { x: i32, y: i32 },
+    }
+
+    #[test]
+    fn test_enum_as_map() {
+        // unit variants serialize like bare strings
+        let empty_s = to_vec_legacy(&Bar::Empty).unwrap();
+        let empty_str_s = to_vec_legacy(&"Empty").unwrap();
+        assert_eq!(empty_s, empty_str_s);
+
+        // tuple-variants serialize like ["<variant>", values..]
+        let number_s = to_vec_legacy(&Bar::Number(42)).unwrap();
+        let number_vec = vec![Value::Text("Number".to_string()), Value::Integer(42)];
+        let number_vec_s = to_vec_legacy(&number_vec).unwrap();
+        assert_eq!(number_s, number_vec_s);
+
+        let flag_s = to_vec_legacy(&Bar::Flag("foo".to_string(), true)).unwrap();
+        let flag_vec = vec![
+            Value::Text("Flag".to_string()),
+            Value::Text("foo".to_string()),
+            Value::Bool(true),
+        ];
+        let flag_vec_s = to_vec_legacy(&flag_vec).unwrap();
+        assert_eq!(flag_s, flag_vec_s);
+
+        // struct-variants serialize like ["<variant>", {struct..}]
+        let point_s = to_vec_legacy(&Bar::Point { x: 5, y: -5 }).unwrap();
+        let mut struct_map = BTreeMap::new();
+        struct_map.insert(Value::Text("x".to_string()), Value::Integer(5));
+        struct_map.insert(Value::Text("y".to_string()), Value::Integer(-5));
+        let point_vec = vec![
+            Value::Text("Point".to_string()),
+            Value::Map(struct_map.clone()),
+        ];
+        let point_vec_s = to_vec_legacy(&point_vec).unwrap();
+        assert_eq!(point_s, point_vec_s);
+
+        // enum_as_map matches serde_json's default serialization for enums.
+
+        // unit variants still serialize like bare strings
+        let empty_s = to_vec(&Bar::Empty).unwrap();
+        assert_eq!(empty_s, empty_str_s);
+
+        // 1-element tuple variants serialize like {"<variant>": value}
+        let number_s = to_vec(&Bar::Number(42)).unwrap();
+        let mut number_map = BTreeMap::new();
+        number_map.insert("Number", 42);
+        let number_map_s = to_vec(&number_map).unwrap();
+        assert_eq!(number_s, number_map_s);
+
+        // multi-element tuple variants serialize like {"<variant>": [values..]}
+        let flag_s = to_vec(&Bar::Flag("foo".to_string(), true)).unwrap();
+        let mut flag_map = BTreeMap::new();
+        flag_map.insert(
+            "Flag",
+            vec![Value::Text("foo".to_string()), Value::Bool(true)],
+        );
+        let flag_map_s = to_vec(&flag_map).unwrap();
+        assert_eq!(flag_s, flag_map_s);
+
+        // struct-variants serialize like {"<variant>", {struct..}}
+        let point_s = to_vec(&Bar::Point { x: 5, y: -5 }).unwrap();
+        let mut point_map = BTreeMap::new();
+        point_map.insert("Point", Value::Map(struct_map));
+        let point_map_s = to_vec(&point_map).unwrap();
+        assert_eq!(point_s, point_map_s);
+
+        // deserialization of all encodings should just work
+        let empty_str_ds = from_slice(&empty_str_s).unwrap();
+        assert_eq!(Bar::Empty, empty_str_ds);
+
+        let number_vec_ds = from_slice(&number_vec_s).unwrap();
+        assert_eq!(Bar::Number(42), number_vec_ds);
+        let number_map_ds = from_slice(&number_map_s).unwrap();
+        assert_eq!(Bar::Number(42), number_map_ds);
+
+        let flag_vec_ds = from_slice(&flag_vec_s).unwrap();
+        assert_eq!(Bar::Flag("foo".to_string(), true), flag_vec_ds);
+        let flag_map_ds = from_slice(&flag_map_s).unwrap();
+        assert_eq!(Bar::Flag("foo".to_string(), true), flag_map_ds);
+
+        let point_vec_ds = from_slice(&point_vec_s).unwrap();
+        assert_eq!(Bar::Point { x: 5, y: -5 }, point_vec_ds);
+        let point_map_ds = from_slice(&point_map_s).unwrap();
+        assert_eq!(Bar::Point { x: 5, y: -5 }, point_map_ds);
+    }
+}
diff --git a/tests/kietaub.cbor b/tests/kietaub.cbor
new file mode 100644
index 0000000..866a093
--- /dev/null
+++ b/tests/kietaub.cbor
Binary files differ
diff --git a/tests/ser.rs b/tests/ser.rs
new file mode 100644
index 0000000..d374ce2
--- /dev/null
+++ b/tests/ser.rs
@@ -0,0 +1,254 @@
+use serde::Serialize;
+use serde_cbor::ser::{Serializer, SliceWrite};
+
+#[test]
+fn test_str() {
+    serialize_and_compare("foobar", b"ffoobar");
+}
+
+#[test]
+fn test_list() {
+    serialize_and_compare(&[1, 2, 3], b"\x83\x01\x02\x03");
+}
+
+#[test]
+fn test_float() {
+    serialize_and_compare(12.3f64, b"\xfb@(\x99\x99\x99\x99\x99\x9a");
+}
+
+#[test]
+fn test_integer() {
+    // u8
+    serialize_and_compare(24, b"\x18\x18");
+    // i8
+    serialize_and_compare(-5, b"\x24");
+    // i16
+    serialize_and_compare(-300, b"\x39\x01\x2b");
+    // i32
+    serialize_and_compare(-23567997, b"\x3a\x01\x67\x9e\x7c");
+    // u64
+    serialize_and_compare(::core::u64::MAX, b"\x1b\xff\xff\xff\xff\xff\xff\xff\xff");
+}
+
+fn serialize_and_compare<T: Serialize>(value: T, expected: &[u8]) {
+    let mut slice = [0u8; 64];
+    let writer = SliceWrite::new(&mut slice);
+    let mut serializer = Serializer::new(writer);
+    value.serialize(&mut serializer).unwrap();
+    let writer = serializer.into_inner();
+    let end = writer.bytes_written();
+    let slice = writer.into_inner();
+    assert_eq!(&slice[..end], expected);
+}
+
+#[cfg(feature = "std")]
+mod std_tests {
+    use serde::Serializer;
+    use serde_cbor::ser;
+    use serde_cbor::{from_slice, to_vec};
+    use std::collections::BTreeMap;
+
+    #[test]
+    fn test_string() {
+        let value = "foobar".to_owned();
+        assert_eq!(&to_vec(&value).unwrap()[..], b"ffoobar");
+    }
+
+    #[test]
+    fn test_list() {
+        let value = vec![1, 2, 3];
+        assert_eq!(&to_vec(&value).unwrap()[..], b"\x83\x01\x02\x03");
+    }
+
+    #[test]
+    fn test_object() {
+        let mut object = BTreeMap::new();
+        object.insert("a".to_owned(), "A".to_owned());
+        object.insert("b".to_owned(), "B".to_owned());
+        object.insert("c".to_owned(), "C".to_owned());
+        object.insert("d".to_owned(), "D".to_owned());
+        object.insert("e".to_owned(), "E".to_owned());
+        let vec = to_vec(&object).unwrap();
+        let test_object = from_slice(&vec[..]).unwrap();
+        assert_eq!(object, test_object);
+    }
+
+    #[test]
+    fn test_object_list_keys() {
+        let mut object = BTreeMap::new();
+        object.insert(vec![0i64], ());
+        object.insert(vec![100i64], ());
+        object.insert(vec![-1i64], ());
+        object.insert(vec![-2i64], ());
+        object.insert(vec![0i64, 0i64], ());
+        object.insert(vec![0i64, -1i64], ());
+        let vec = to_vec(&serde_cbor::value::to_value(object.clone()).unwrap()).unwrap();
+        assert_eq!(
+            vec![
+                166, 129, 0, 246, 129, 24, 100, 246, 129, 32, 246, 129, 33, 246, 130, 0, 0, 246,
+                130, 0, 32, 246
+            ],
+            vec
+        );
+        let test_object = from_slice(&vec[..]).unwrap();
+        assert_eq!(object, test_object);
+    }
+
+    #[test]
+    fn test_object_object_keys() {
+        use std::iter::FromIterator;
+        let mut object = BTreeMap::new();
+        let keys = vec![
+            vec!["a"],
+            vec!["b"],
+            vec!["c"],
+            vec!["d"],
+            vec!["aa"],
+            vec!["a", "aa"],
+        ]
+        .into_iter()
+        .map(|v| BTreeMap::from_iter(v.into_iter().map(|s| (s.to_owned(), ()))));
+
+        for key in keys {
+            object.insert(key, ());
+        }
+        let vec = to_vec(&serde_cbor::value::to_value(object.clone()).unwrap()).unwrap();
+        assert_eq!(
+            vec![
+                166, 161, 97, 97, 246, 246, 161, 97, 98, 246, 246, 161, 97, 99, 246, 246, 161, 97,
+                100, 246, 246, 161, 98, 97, 97, 246, 246, 162, 97, 97, 246, 98, 97, 97, 246, 246
+            ],
+            vec
+        );
+        let test_object = from_slice(&vec[..]).unwrap();
+        assert_eq!(object, test_object);
+    }
+
+    #[test]
+    fn test_float() {
+        let vec = to_vec(&12.3f64).unwrap();
+        assert_eq!(vec, b"\xfb@(\x99\x99\x99\x99\x99\x9a");
+    }
+
+    #[test]
+    fn test_f32() {
+        let vec = to_vec(&4000.5f32).unwrap();
+        assert_eq!(vec, b"\xfa\x45\x7a\x08\x00");
+    }
+
+    #[test]
+    fn test_infinity() {
+        let vec = to_vec(&::std::f64::INFINITY).unwrap();
+        assert_eq!(vec, b"\xf9|\x00");
+    }
+
+    #[test]
+    fn test_neg_infinity() {
+        let vec = to_vec(&::std::f64::NEG_INFINITY).unwrap();
+        assert_eq!(vec, b"\xf9\xfc\x00");
+    }
+
+    #[test]
+    fn test_nan() {
+        let vec = to_vec(&::std::f32::NAN).unwrap();
+        assert_eq!(vec, b"\xf9\x7e\x00");
+    }
+
+    #[test]
+    fn test_integer() {
+        // u8
+        let vec = to_vec(&24).unwrap();
+        assert_eq!(vec, b"\x18\x18");
+        // i8
+        let vec = to_vec(&-5).unwrap();
+        assert_eq!(vec, b"\x24");
+        // i16
+        let vec = to_vec(&-300).unwrap();
+        assert_eq!(vec, b"\x39\x01\x2b");
+        // i32
+        let vec = to_vec(&-23567997).unwrap();
+        assert_eq!(vec, b"\x3a\x01\x67\x9e\x7c");
+        // u64
+        let vec = to_vec(&::std::u64::MAX).unwrap();
+        assert_eq!(vec, b"\x1b\xff\xff\xff\xff\xff\xff\xff\xff");
+    }
+
+    #[test]
+    fn test_self_describing() {
+        let mut vec = Vec::new();
+        {
+            let mut serializer = ser::Serializer::new(&mut vec);
+            serializer.self_describe().unwrap();
+            serializer.serialize_u64(9).unwrap();
+        }
+        assert_eq!(vec, b"\xd9\xd9\xf7\x09");
+    }
+
+    #[test]
+    fn test_ip_addr() {
+        use std::net::Ipv4Addr;
+
+        let addr = Ipv4Addr::new(8, 8, 8, 8);
+        let vec = to_vec(&addr).unwrap();
+        println!("{:?}", vec);
+        assert_eq!(vec.len(), 5);
+        let test_addr: Ipv4Addr = from_slice(&vec).unwrap();
+        assert_eq!(addr, test_addr);
+    }
+
+    /// Test all of CBOR's fixed-length byte string types
+    #[test]
+    fn test_byte_string() {
+        // Very short byte strings have 1-byte headers
+        let short = vec![0, 1, 2, 255];
+        let mut short_s = Vec::new();
+        serde_cbor::Serializer::new(&mut short_s)
+            .serialize_bytes(&short)
+            .unwrap();
+        assert_eq!(&short_s[..], [0x44, 0, 1, 2, 255]);
+
+        // byte strings > 23 bytes have 2-byte headers
+        let medium = vec![
+            0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 255,
+        ];
+        let mut medium_s = Vec::new();
+        serde_cbor::Serializer::new(&mut medium_s)
+            .serialize_bytes(&medium)
+            .unwrap();
+        assert_eq!(
+            &medium_s[..],
+            [
+                0x58, 24, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+                21, 22, 255
+            ]
+        );
+
+        // byte strings > 256 bytes have 3-byte headers
+        let long_vec = (0..256).map(|i| (i & 0xFF) as u8).collect::<Vec<_>>();
+        let mut long_s = Vec::new();
+        serde_cbor::Serializer::new(&mut long_s)
+            .serialize_bytes(&long_vec)
+            .unwrap();
+        assert_eq!(&long_s[0..3], [0x59, 1, 0]);
+        assert_eq!(&long_s[3..], &long_vec[..]);
+
+        // byte strings > 2^16 bytes have 5-byte headers
+        let very_long_vec = (0..65536).map(|i| (i & 0xFF) as u8).collect::<Vec<_>>();
+        let mut very_long_s = Vec::new();
+        serde_cbor::Serializer::new(&mut very_long_s)
+            .serialize_bytes(&very_long_vec)
+            .unwrap();
+        assert_eq!(&very_long_s[0..5], [0x5a, 0, 1, 0, 0]);
+        assert_eq!(&very_long_s[5..], &very_long_vec[..]);
+
+        // byte strings > 2^32 bytes have 9-byte headers, but they take too much RAM
+        // to test in Travis.
+    }
+
+    #[test]
+    fn test_half() {
+        let vec = to_vec(&42.5f32).unwrap();
+        assert_eq!(vec, b"\xF9\x51\x50");
+        assert_eq!(from_slice::<f32>(&vec[..]).unwrap(), 42.5f32);
+    }
+}
diff --git a/tests/std_types.rs b/tests/std_types.rs
new file mode 100644
index 0000000..7a7ded4
--- /dev/null
+++ b/tests/std_types.rs
@@ -0,0 +1,186 @@
+#[macro_use]
+extern crate serde_derive;
+
+#[cfg(feature = "std")]
+mod std_tests {
+    use std::u8;
+
+    use serde_cbor::de::from_mut_slice;
+    use serde_cbor::ser::{to_vec, to_vec_packed};
+    use serde_cbor::{from_reader, from_slice};
+
+    fn to_binary(s: &'static str) -> Vec<u8> {
+        assert!(s.len() % 2 == 0);
+        let mut b = Vec::with_capacity(s.len() / 2);
+        for i in 0..s.len() / 2 {
+            b.push(u8::from_str_radix(&s[i * 2..(i + 1) * 2], 16).unwrap());
+        }
+        b
+    }
+
+    macro_rules! testcase {
+        ($name:ident, f64, $expr:expr, $s:expr) => {
+            #[test]
+            fn $name() {
+                let expr: f64 = $expr;
+                let mut serialized = to_binary($s);
+                assert_eq!(to_vec(&expr).unwrap(), serialized);
+                let parsed: f64 = from_slice(&serialized[..]).unwrap();
+                if !expr.is_nan() {
+                    assert_eq!(expr, parsed);
+                } else {
+                    assert!(parsed.is_nan())
+                }
+
+                let parsed: f64 = from_reader(&mut &serialized[..]).unwrap();
+                if !expr.is_nan() {
+                    assert_eq!(expr, parsed);
+                } else {
+                    assert!(parsed.is_nan())
+                }
+
+                let parsed: f64 = from_mut_slice(&mut serialized[..]).unwrap();
+                if !expr.is_nan() {
+                    assert_eq!(expr, parsed);
+                } else {
+                    assert!(parsed.is_nan())
+                }
+            }
+        };
+        ($name:ident, $ty:ty, $expr:expr, $s:expr) => {
+            #[test]
+            fn $name() {
+                let expr: $ty = $expr;
+                let mut serialized = to_binary($s);
+                assert_eq!(
+                    to_vec(&expr).expect("ser1 works"),
+                    serialized,
+                    "serialization differs"
+                );
+                let parsed: $ty = from_slice(&serialized[..]).expect("de1 works");
+                assert_eq!(parsed, expr, "parsed result differs");
+                let packed = &to_vec_packed(&expr).expect("serializing packed")[..];
+                let parsed_from_packed: $ty = from_slice(packed).expect("parsing packed");
+                assert_eq!(parsed_from_packed, expr, "packed roundtrip fail");
+
+                let parsed: $ty = from_reader(&mut &serialized[..]).unwrap();
+                assert_eq!(parsed, expr, "parsed result differs");
+                let mut packed = to_vec_packed(&expr).expect("serializing packed");
+                let parsed_from_packed: $ty =
+                    from_reader(&mut &packed[..]).expect("parsing packed");
+                assert_eq!(parsed_from_packed, expr, "packed roundtrip fail");
+
+                let parsed: $ty = from_mut_slice(&mut serialized[..]).unwrap();
+                assert_eq!(parsed, expr, "parsed result differs");
+                let parsed_from_packed: $ty =
+                    from_mut_slice(&mut packed[..]).expect("parsing packed");
+                assert_eq!(parsed_from_packed, expr, "packed roundtrip fail");
+            }
+        };
+    }
+
+    testcase!(test_bool_false, bool, false, "f4");
+    testcase!(test_bool_true, bool, true, "f5");
+    testcase!(test_isize_neg_256, isize, -256, "38ff");
+    testcase!(test_isize_neg_257, isize, -257, "390100");
+    testcase!(test_isize_255, isize, 255, "18ff");
+    testcase!(test_i8_5, i8, 5, "05");
+    testcase!(test_i8_23, i8, 23, "17");
+    testcase!(test_i8_24, i8, 24, "1818");
+    testcase!(test_i8_neg_128, i8, -128, "387f");
+    testcase!(test_u32_98745874, u32, 98745874, "1a05e2be12");
+    testcase!(test_f32_1234_point_5, f32, 1234.5, "fa449a5000");
+    testcase!(test_f64_12345_point_6, f64, 12345.6, "fb40c81ccccccccccd");
+    testcase!(test_f64_nan, f64, ::std::f64::NAN, "f97e00");
+    testcase!(test_f64_infinity, f64, ::std::f64::INFINITY, "f97c00");
+    testcase!(test_f64_neg_infinity, f64, -::std::f64::INFINITY, "f9fc00");
+    testcase!(test_char_null, char, '\x00', "6100");
+    testcase!(test_char_broken_heart, char, '💔', "64f09f9294");
+    testcase!(
+        test_str_pangram_de,
+        String,
+        "aâø↓é".to_owned(),
+        "6a61c3a2c3b8e28693c3a9"
+    );
+    testcase!(test_unit, (), (), "f6");
+
+    #[derive(Debug, PartialEq, Deserialize, Serialize)]
+    struct UnitStruct;
+    testcase!(test_unit_struct, UnitStruct, UnitStruct, "f6");
+
+    #[derive(Debug, PartialEq, Deserialize, Serialize)]
+    struct NewtypeStruct(bool);
+    testcase!(
+        test_newtype_struct,
+        NewtypeStruct,
+        NewtypeStruct(true),
+        "f5"
+    );
+
+    testcase!(test_option_none, Option<u8>, None, "f6");
+    testcase!(test_option_some, Option<u8>, Some(42), "182a");
+
+    #[derive(Debug, PartialEq, Deserialize, Serialize)]
+    struct Person {
+        name: String,
+        year_of_birth: u16,
+        profession: Option<String>,
+    }
+
+    testcase!(test_person_struct,
+    Person,
+    Person {
+        name: "Grace Hopper".to_string(),
+        year_of_birth: 1906,
+        profession: Some("computer scientist".to_string()),
+    },
+    "a3646e616d656c477261636520486f707065726d796561725f6f665f62697274681907726a70726f66657373696f6e72636f6d707574657220736369656e74697374");
+
+    #[derive(Debug, PartialEq, Deserialize, Serialize)]
+    struct OptionalPerson {
+        name: String,
+        #[serde(skip_serializing_if = "Option::is_none")]
+        year_of_birth: Option<u16>,
+        profession: Option<String>,
+    }
+
+    testcase!(test_optional_person_struct,
+    OptionalPerson,
+    OptionalPerson {
+        name: "Grace Hopper".to_string(),
+        year_of_birth: None,
+        profession: Some("computer scientist".to_string()),
+    },
+    "a2646e616d656c477261636520486f707065726a70726f66657373696f6e72636f6d707574657220736369656e74697374");
+
+    #[derive(Debug, PartialEq, Deserialize, Serialize)]
+    enum Color {
+        Red,
+        Blue,
+        Yellow,
+        Other(u64),
+        Alpha(u64, u8),
+    }
+
+    testcase!(test_color_enum, Color, Color::Blue, "64426c7565");
+    testcase!(
+        test_color_enum_transparent,
+        Color,
+        Color::Other(42),
+        "a1654f74686572182a"
+    );
+    testcase!(
+        test_color_enum_with_alpha,
+        Color,
+        Color::Alpha(234567, 60),
+        "a165416c706861821a00039447183c"
+    );
+    testcase!(test_i128_a, i128, -1i128, "20");
+    testcase!(
+        test_i128_b,
+        i128,
+        -18446744073709551616i128,
+        "3BFFFFFFFFFFFFFFFF"
+    );
+    testcase!(test_u128, u128, 17, "11");
+}
diff --git a/tests/tags.rs b/tests/tags.rs
new file mode 100644
index 0000000..92534c0
--- /dev/null
+++ b/tests/tags.rs
@@ -0,0 +1,48 @@
+#[cfg(feature = "tags")]
+mod tagtests {
+    use serde_cbor::value::Value;
+    use serde_cbor::{from_slice, to_vec};
+
+    fn decode_hex(s: &str) -> std::result::Result<Vec<u8>, std::num::ParseIntError> {
+        (0..s.len())
+            .step_by(2)
+            .map(|i| u8::from_str_radix(&s[i..i + 2], 16))
+            .collect()
+    }
+
+    // get bytes from http://cbor.me/ trees
+    fn parse_cbor_me(example: &str) -> std::result::Result<Vec<u8>, std::num::ParseIntError> {
+        let hex = example
+            .split("\n")
+            .flat_map(|line| line.split("#").take(1))
+            .collect::<Vec<&str>>()
+            .join("")
+            .replace(" ", "");
+        decode_hex(&hex)
+    }
+
+    #[test]
+    fn tagged_cbor_roundtrip() {
+        let data = r#"
+C1                   # tag(1)
+   82                # array(2)
+      C2             # tag(2)
+         63          # text(3)
+            666F6F   # "foo"
+      C3             # tag(3)
+         A1          # map(1)
+            C4       # tag(4)
+               61    # text(1)
+                  61 # "a"
+            C5       # tag(5)
+               61    # text(1)
+                  62 # "b"
+            "#;
+        let bytes1 = parse_cbor_me(&data).unwrap();
+        let value1: Value = from_slice(&bytes1).unwrap();
+        let bytes2 = to_vec(&value1).unwrap();
+        let value2: Value = from_slice(&bytes2).unwrap();
+        assert_eq!(bytes1, bytes2);
+        assert_eq!(value1, value2);
+    }
+}
diff --git a/tests/value.rs b/tests/value.rs
new file mode 100644
index 0000000..554d742
--- /dev/null
+++ b/tests/value.rs
@@ -0,0 +1,100 @@
+#[macro_use]
+extern crate serde_derive;
+
+#[cfg(feature = "std")]
+mod std_tests {
+    use serde_cbor;
+
+    use std::collections::BTreeMap;
+
+    #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
+    struct TupleStruct(String, i32, u64);
+
+    #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
+    struct UnitStruct;
+
+    #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
+    struct Struct<'a> {
+        tuple_struct: TupleStruct,
+        tuple: (String, f32, f64),
+        map: BTreeMap<String, String>,
+        bytes: &'a [u8],
+        array: Vec<String>,
+        unit_array: Vec<UnitStruct>,
+    }
+
+    use serde_cbor::value::Value;
+    use std::iter::FromIterator;
+
+    #[test]
+    fn serde() {
+        let tuple_struct = TupleStruct(format!("test"), -60, 3000);
+
+        let tuple = (format!("hello"), -50.0040957, -12.094635556478);
+
+        let map = BTreeMap::from_iter(
+            [
+                (format!("key1"), format!("value1")),
+                (format!("key2"), format!("value2")),
+                (format!("key3"), format!("value3")),
+                (format!("key4"), format!("value4")),
+            ]
+            .iter()
+            .cloned(),
+        );
+
+        let bytes = b"test byte string";
+
+        let array = vec![format!("one"), format!("two"), format!("three")];
+        let unit_array = vec![UnitStruct, UnitStruct, UnitStruct];
+
+        let data = Struct {
+            tuple_struct,
+            tuple,
+            map,
+            bytes,
+            array,
+            unit_array,
+        };
+
+        let value = serde_cbor::value::to_value(data.clone()).unwrap();
+        println!("{:?}", value);
+
+        let data_ser = serde_cbor::to_vec(&value).unwrap();
+        let data_de_value: Value = serde_cbor::from_slice(&data_ser).unwrap();
+
+        fn as_object(value: &Value) -> &BTreeMap<Value, Value> {
+            if let Value::Map(ref v) = value {
+                return v;
+            }
+            panic!()
+        }
+
+        for ((k1, v1), (k2, v2)) in as_object(&value)
+            .iter()
+            .zip(as_object(&data_de_value).iter())
+        {
+            assert_eq!(k1, k2);
+            assert_eq!(v1, v2);
+        }
+
+        assert_eq!(value, data_de_value);
+    }
+
+    #[derive(Debug, Deserialize, Serialize)]
+    struct SmallStruct {
+        spam: u32,
+        eggs: u32,
+    }
+
+    #[test]
+    fn small_struct() {
+        // Test whether the packed format works.
+        // Field names should not be serialized,
+        // instead field indizes are serialized.
+        let value = SmallStruct { spam: 17, eggs: 42 };
+        let data = serde_cbor::ser::to_vec_packed(&value).unwrap();
+        let reference = b"\xa2\x00\x11\x01\x18\x2a";
+        assert_eq!(data, reference);
+    }
+}