Vendor jni-rs in draft
authorNick Alexander <nalexander@mozilla.com>
Wed, 31 May 2017 15:19:34 -0700
changeset 589164 e551383660b0049ec5f2860b6ce4069c66a77824
parent 589163 53fefa6d38dc8a52c9f8b8fdc62d18dc474d4521
child 589165 2bf5ecba58426d860a29b938c39beb386d3041c1
push id62262
push usernalexander@mozilla.com
push dateMon, 05 Jun 2017 18:25:07 +0000
milestone55.0a1
Vendor jni-rs in MozReview-Commit-ID: 1BvAhkbEnkj
mozglue/rustifoo/Cargo.lock
third_party/rust/ascii/.cargo-checksum.json
third_party/rust/ascii/.cargo-ok
third_party/rust/ascii/.gitignore
third_party/rust/ascii/.travis.yml
third_party/rust/ascii/Cargo.toml
third_party/rust/ascii/README.md
third_party/rust/ascii/RELEASES.md
third_party/rust/ascii/src/ascii_char.rs
third_party/rust/ascii/src/ascii_str.rs
third_party/rust/ascii/src/ascii_string.rs
third_party/rust/ascii/src/lib.rs
third_party/rust/ascii/tests.rs
third_party/rust/cesu8/.cargo-checksum.json
third_party/rust/cesu8/.cargo-ok
third_party/rust/cesu8/.gitignore
third_party/rust/cesu8/.travis.yml
third_party/rust/cesu8/COPYRIGHT-RUST.txt
third_party/rust/cesu8/Cargo.toml
third_party/rust/cesu8/README.md
third_party/rust/cesu8/src/lib.rs
third_party/rust/cesu8/src/unicode.rs
third_party/rust/combine/.cargo-checksum.json
third_party/rust/combine/.cargo-ok
third_party/rust/combine/.gitignore
third_party/rust/combine/.travis.yml
third_party/rust/combine/CHANGELOG.md
third_party/rust/combine/Cargo.toml
third_party/rust/combine/LICENSE
third_party/rust/combine/README.md
third_party/rust/combine/benches/data.json
third_party/rust/combine/benches/http-requests.txt
third_party/rust/combine/benches/http.rs
third_party/rust/combine/benches/json.rs
third_party/rust/combine/benches/mp4.rs
third_party/rust/combine/rustfmt.toml
third_party/rust/combine/src/byte.rs
third_party/rust/combine/src/char.rs
third_party/rust/combine/src/combinator.rs
third_party/rust/combine/src/lib.rs
third_party/rust/combine/src/primitives.rs
third_party/rust/combine/src/range.rs
third_party/rust/combine/tests/buffered_stream.rs
third_party/rust/combine/tests/date.rs
third_party/rust/combine/tests/ini.rs
third_party/rust/combine/tests/readme.rs
third_party/rust/error-chain/.cargo-checksum.json
third_party/rust/error-chain/.cargo-ok
third_party/rust/error-chain/.gitignore
third_party/rust/error-chain/.travis.yml
third_party/rust/error-chain/CHANGELOG.md
third_party/rust/error-chain/Cargo.toml
third_party/rust/error-chain/README.md
third_party/rust/error-chain/examples/all.rs
third_party/rust/error-chain/examples/doc.rs
third_party/rust/error-chain/examples/quickstart.rs
third_party/rust/error-chain/examples/size.rs
third_party/rust/error-chain/src/error_chain.rs
third_party/rust/error-chain/src/example_generated.rs
third_party/rust/error-chain/src/lib.rs
third_party/rust/error-chain/src/quick_error.rs
third_party/rust/error-chain/src/quick_main.rs
third_party/rust/error-chain/tests/quick_main.rs
third_party/rust/error-chain/tests/tests.rs
third_party/rust/jni-sys/.cargo-checksum.json
third_party/rust/jni-sys/.cargo-ok
third_party/rust/jni-sys/.gitignore
third_party/rust/jni-sys/Cargo.toml
third_party/rust/jni-sys/LICENSE-APACHE
third_party/rust/jni-sys/LICENSE-MIT
third_party/rust/jni-sys/README.md
third_party/rust/jni-sys/src/lib.rs
third_party/rust/jni/.cargo-checksum.json
third_party/rust/jni/.cargo-ok
third_party/rust/jni/.gitignore
third_party/rust/jni/.travis.yml
third_party/rust/jni/Cargo.toml
third_party/rust/jni/LICENSE-APACHE
third_party/rust/jni/LICENSE-MIT
third_party/rust/jni/README.md
third_party/rust/jni/example/HelloWorld.h
third_party/rust/jni/example/HelloWorld.java
third_party/rust/jni/rustfmt.toml
third_party/rust/jni/src/lib.rs
third_party/rust/jni/src/sys.rs
third_party/rust/jni/src/wrapper/descriptors/class_desc.rs
third_party/rust/jni/src/wrapper/descriptors/desc.rs
third_party/rust/jni/src/wrapper/descriptors/exception_desc.rs
third_party/rust/jni/src/wrapper/descriptors/field_desc.rs
third_party/rust/jni/src/wrapper/descriptors/method_desc.rs
third_party/rust/jni/src/wrapper/descriptors/mod.rs
third_party/rust/jni/src/wrapper/errors.rs
third_party/rust/jni/src/wrapper/jnienv.rs
third_party/rust/jni/src/wrapper/macros.rs
third_party/rust/jni/src/wrapper/objects/global_ref.rs
third_party/rust/jni/src/wrapper/objects/jclass.rs
third_party/rust/jni/src/wrapper/objects/jfieldid.rs
third_party/rust/jni/src/wrapper/objects/jmap.rs
third_party/rust/jni/src/wrapper/objects/jmethodid.rs
third_party/rust/jni/src/wrapper/objects/jobject.rs
third_party/rust/jni/src/wrapper/objects/jstaticmethodid.rs
third_party/rust/jni/src/wrapper/objects/jstring.rs
third_party/rust/jni/src/wrapper/objects/jthrowable.rs
third_party/rust/jni/src/wrapper/objects/jvalue.rs
third_party/rust/jni/src/wrapper/objects/mod.rs
third_party/rust/jni/src/wrapper/signature.rs
third_party/rust/jni/src/wrapper/strings/ffi_str.rs
third_party/rust/jni/src/wrapper/strings/java_str.rs
third_party/rust/jni/src/wrapper/strings/mod.rs
--- a/mozglue/rustifoo/Cargo.lock
+++ b/mozglue/rustifoo/Cargo.lock
@@ -1,14 +1,151 @@
 [root]
 name = "rustifoo"
 version = "0.1.0"
 dependencies = [
+ "jni 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "ascii"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "backtrace"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "backtrace-sys"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "gcc 0.3.49 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "cesu8"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "cfg-if"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "combine"
+version = "2.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "dbghelp-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "error-chain"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "gcc"
+version = "0.3.49"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "jni"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cesu8 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "combine 2.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "jni-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "jni-sys"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "kernel32-sys"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "lazy_static"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "libc"
+version = "0.2.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "log"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi-build"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [metadata]
+"checksum ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae7d751998c189c1d4468cf0a39bb2eae052a9c58d50ebb3b9591ee3813ad50"
+"checksum backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72f9b4182546f4b04ebc4ab7f84948953a118bd6021a1b6a6c909e3e94f6be76"
+"checksum backtrace-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3a0d842ea781ce92be2bf78a9b38883948542749640b8378b3b2f03d1fd9f1ff"
+"checksum cesu8 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
+"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
+"checksum combine 2.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d4e2b2f3e0e68b531bd90f79c0c897f2da8de4109fc1dd7cd427990621dd2d0"
+"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
+"checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8"
+"checksum gcc 0.3.49 (registry+https://github.com/rust-lang/crates.io-index)" = "9be730064c122681712957ba1a9abaf082150be8aaf94526a805d900015b65b9"
+"checksum jni 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "62bcf7e41257122be93f778b451b2d48476e1b35b9c780be0defca83c359379e"
+"checksum jni-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "83ba0fad4625733b25833da250d0c84058314e1a276f4939f3e87c195997c206"
+"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b"
+"checksum libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "e7eb6b826bfc1fdea7935d46556250d1799b7fe2d9f7951071f4291710665e3e"
+"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
+"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95"
+"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
+"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/ascii/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"c1e953ee360e77de57f7b02f1b7880bd6a3dc22d1a69e953c2ac2c52cc52d247",".travis.yml":"cb20002a6a529ce8dbd94260096b04fde7362872d84616501bf70cca31b04ba8","Cargo.toml":"78a28734d7b2c5d75253db37882550c7d48ecaa661e685134b0db231ce1991c3","README.md":"7bf5d2c1b63313f2090535c766e657e05dfddc23642a0365ff37d577789f6aea","RELEASES.md":"2c1fe6228d574b4ea37425b383e65b8a49829863a75e46f579297241599b9c94","src/ascii_char.rs":"431132a65a0d585f94ab20997031cb10b2d318b0f29db7e309b94d3ca82738a3","src/ascii_str.rs":"306bb422f6c6683def2046c9e68e990486a81918e21e589b6c1c8028ce2023db","src/ascii_string.rs":"8ab0443b05049166a06fe64886e75a4b4699514847f9896e48e3ccf8af6d6ca7","src/lib.rs":"26165a691e742994c965d0d0bb677169cc4bba54d6cacb7b13e1a0dac1d9477a","tests.rs":"be3d9da276e111458cc31491ded6f8888120ca20363a7681e4f63c12f1f476ac"},"package":"3ae7d751998c189c1d4468cf0a39bb2eae052a9c58d50ebb3b9591ee3813ad50"}
\ No newline at end of file
new file mode 100644
new file mode 100644
--- /dev/null
+++ b/third_party/rust/ascii/.gitignore
@@ -0,0 +1,2 @@
+/target
+/Cargo.lock
new file mode 100644
--- /dev/null
+++ b/third_party/rust/ascii/.travis.yml
@@ -0,0 +1,29 @@
+sudo: false
+language: rust
+
+rust:
+  - nightly
+  - beta
+  - stable
+  - 1.9.0
+
+before_script:
+  - |
+    pip install 'travis-cargo<0.2' --user &&
+    export PATH=$HOME/.local/bin:$PATH
+
+script:
+  - |
+    travis-cargo build &&
+    travis-cargo test &&
+    travis-cargo build -- --features=no_std &&
+    travis-cargo test -- --features=no_std &&
+    travis-cargo --only stable doc
+
+after_success:
+  - travis-cargo --only stable doc-upload
+
+env:
+  global:
+    - TRAVIS_CARGO_NIGHTLY_FEATURE="" # no unstable feature
+    - secure: ddcWXicVcCooC+Dy8guGruZY2bAU3oyGjrxdC3YNfBYdatEKzW1toAiQyN8SRyZyfoHsbb7lh4YeBfv1rpmTPM6nvHMz9CHMlvED8Y+/QuYoKN2qrNiQ7eQ9xSVhOVlha/GMPSZXxmEIuJVj0Dn1D/S4RWyNMKCJdj2YvybPzOU=
new file mode 100644
--- /dev/null
+++ b/third_party/rust/ascii/Cargo.toml
@@ -0,0 +1,16 @@
+test = [{name = "tests", path = "tests.rs"}]
+
+[package]
+name = "ascii"
+version = "0.7.1"
+authors = ["Thomas Bahn <thomas@thomas-bahn.net>",
+           "Torbjørn Birch Moltu <t.b.moltu@lyse.net>",
+           "Simon Sapin <simon.sapin@exyr.org>"]
+
+description = "ASCII-only equivalents to `char`, `str` and `String`."
+documentation = "https://tomprogrammer.github.io/rust-ascii/ascii/index.html"
+license = "Apache-2.0 / MIT"
+repository = "https://github.com/tomprogrammer/rust-ascii"
+
+[features]
+no_std = []
new file mode 100644
--- /dev/null
+++ b/third_party/rust/ascii/README.md
@@ -0,0 +1,25 @@
+# ascii
+
+A library that provides ASCII-only string and character types, equivalent to the `char`, `str` and
+`String` types in the standard library.
+
+Types and conversion traits are described in the
+[Documentation](https://tomprogrammer.github.io/rust-ascii/ascii/index.html)
+
+# Using ascii without libstd
+
+Most of `AsciiChar` and `AsciiStr` can be used without `std` by enabling the feature `no_std`. The
+owned string type `AsciiString` and the conversion trait `IntoAsciiString` as well as all methods
+referring to these types aren't available without `std`.
+
+# Requirements
+
+The `ascii` library requires rustc 1.9.0 or greater, due to the
+[stabilization of `AsciiExt`](https://github.com/rust-lang/rust/pull/32804). Using the `no_std`
+feature lowers this requirement to rustc 1.6.0 or greater.
+
+# History
+
+This packages included the Ascii types that were removed from the Rust standard library by the
+2014-12 [reform of the `std::ascii` module] (https://github.com/rust-lang/rfcs/pull/486). The API
+changed significantly since then.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/ascii/RELEASES.md
@@ -0,0 +1,60 @@
+Unreleased
+==========
+* Fix the implementation of `AsciiExt::to_ascii_lowercase()` for `AsciiChar` converting to uppercase. (introduced in 0.7.0)
+
+Version 0.7.0 (2016-06-25)
+==========
+* Rename `Ascii` to `AsciiChar` and convert it into an enum. (with a variant for every ASCII character)
+* Replace `OwnedAsciiCast` with `IntoAsciiString`.
+* Replace `AsciiCast` with `As[Mut]AsciiStr` and `IntoAsciiChar`.
+* Add *from[_ascii]_unchecked* methods.
+* Replace *from_bytes* with *from_ascii* in method names.
+* Return `std::error::Error`-implementing types on error instead of `Option::None` or `Err(())`.
+* Implement `AsciiExt` without the `unstable` Cargo feature flag, which is removed.
+* Require Rust 1.9 or later.
+* Add `#[no_std]` support in a Cargo feature.
+* Implement `From<{&,&mut,Box<}AsciiStr>` for `[Ascii]`, `[u8]` and `str`
+* Implement `From<{&,&mut,Box<}[Ascii]>`, `As{Ref,Mut}<[Ascii]>` and Default for `AsciiStr`
+* Implement `From<Vec<Ascii>>` for `AsciiString`.
+* Implement `AsMut<AsciiStr>` for `AsciiString`.
+* Stop some `Ascii::is_xxx()` methods from panicking.
+* Add `Ascii::is_whitespace()`.
+* Add `AsciiString::as_mut_slice()`.
+* Add raw pointer methods on `AsciiString`:
+  * `from_raw_parts`
+  * `as_ptr`
+  * `as_mut_ptr`
+
+Version 0.6.0 (2015-12-30)
+==========================
+* Add `Ascii::from_byte()`
+* Add `AsciiStr::trim[_{left,right}]()`
+
+Version 0.5.4 (2015-07-29)
+==========================
+Implement `IndexMut` for AsciiStr and AsciiString.
+
+Version 0.5.1 (2015-06-13)
+==========================
+* Add `Ascii::from()`.
+* Implement `Index` for `AsciiStr` and `AsciiString`.
+* Implement `Default`,`FromIterator`,`Extend` and `Add` for `AsciiString`
+* Added inherent methods on `AsciiString`:
+  * `with_capacity`
+  * `push_str`
+  * `capacity`
+  * `reserve`
+  * `reserve_exact`
+  * `shrink_to_fit`
+  * `push`
+  * `truncate`
+  * `pop`
+  * `remove`
+  * `insert`
+  * `len`
+  * `is_empty`
+  * `clear`
+
+Version 0.5.0 (2015-05-05)
+==========================
+First release compatible with Rust 1.0.0.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/ascii/src/ascii_char.rs
@@ -0,0 +1,629 @@
+extern crate core;
+
+use self::core::mem::transmute;
+use self::core::fmt;
+#[cfg(not(feature = "no_std"))]
+use std::error::Error;
+#[cfg(not(feature = "no_std"))]
+use std::ascii::AsciiExt;
+
+#[allow(non_camel_case_types)]
+/// An ASCII character. It wraps a `u8`, with the highest bit always zero.
+#[derive(Clone, PartialEq, PartialOrd, Ord, Eq, Hash, Copy)]
+#[repr(u8)]
+pub enum AsciiChar {
+    /// `'\0'`
+    Null            =   0,
+    /// [Start Of Heading](http://en.wikipedia.org/wiki/Start_of_Heading)
+    SOH             =   1,
+    /// [Start Of teXt](http://en.wikipedia.org/wiki/Start_of_Text)
+    SOX             =   2,
+    /// [End of TeXt](http://en.wikipedia.org/wiki/End-of-Text_character)
+    ETX             =   3,
+    /// [End Of Transmission](http://en.wikipedia.org/wiki/End-of-Transmission_character)
+    EOT             =   4,
+    /// [Enquiry](http://en.wikipedia.org/wiki/Enquiry_character)
+    ENQ             =   5,
+    /// [Acknowledgement](http://en.wikipedia.org/wiki/Acknowledge_character)
+    ACK             =   6,
+    /// [bell / alarm / audible](http://en.wikipedia.org/wiki/Bell_character)
+    ///
+    /// `'\a'` is not recognized by Rust.
+    Bell            =   7,
+    /// [Backspace](http://en.wikipedia.org/wiki/Backspace)
+    ///
+    /// `'\b'` is not recognized by Rust.
+    BackSpace       =   8,
+    /// `'\t'`
+    Tab             =   9,
+    /// `'\n'`
+    LineFeed        =  10,
+    /// [Vertical tab](http://en.wikipedia.org/wiki/Vertical_Tab)
+    ///
+    /// `'\v'` is not recognized by Rust.
+    VT              =  11,
+    /// [Form Feed](http://en.wikipedia.org/wiki/Form_Feed)
+    ///
+    /// `'\f'` is not recognized by Rust.
+    FF              =  12,
+    /// `'\r'`
+    CarriageReturn  =  13,
+    /// [Shift In](http://en.wikipedia.org/wiki/Shift_Out_and_Shift_In_characters)
+    SI              =  14,
+    /// [Shift Out](http://en.wikipedia.org/wiki/Shift_Out_and_Shift_In_characters)
+    SO              =  15,
+    /// [Data Link Escape](http://en.wikipedia.org/wiki/Data_Link_Escape)
+    DLE             =  16,
+    /// [Device control 1, often XON](http://en.wikipedia.org/wiki/Device_Control_1)
+    DC1             =  17,
+    /// Device control 2
+    DC2             =  18,
+    /// Device control 3, Often XOFF
+    DC3             =  19,
+    /// Device control 4
+    DC4             =  20,
+    /// [Negative AcKnowledgement](http://en.wikipedia.org/wiki/Negative-acknowledge_character)
+    NAK             =  21,
+    /// [Synchronous idle](http://en.wikipedia.org/wiki/Synchronous_Idle)
+    SYN             =  22,
+    /// [End of Transmission Block](http://en.wikipedia.org/wiki/End-of-Transmission-Block_character)
+    ETB             =  23,
+    /// [Cancel](http://en.wikipedia.org/wiki/Cancel_character)
+    CAN             =  24,
+    /// [End of Medium](http://en.wikipedia.org/wiki/End_of_Medium)
+    EM              =  25,
+    /// [Substitute](http://en.wikipedia.org/wiki/Substitute_character)
+    SUB             =  26,
+    /// [Escape](http://en.wikipedia.org/wiki/Escape_character)
+    ///
+    /// `'\e'` is not recognized by Rust.
+    ESC             =  27,
+    /// [File Separator](http://en.wikipedia.org/wiki/File_separator)
+    FS              =  28,
+    /// [Group Separator](http://en.wikipedia.org/wiki/Group_separator)
+    GS              =  29,
+    /// [Record Separator](http://en.wikipedia.org/wiki/Record_separator)
+    RS              =  30,
+    /// [Unit Separator](http://en.wikipedia.org/wiki/Unit_separator)
+    US              =  31,
+    /// `' '`
+    Space           =  32,
+    /// `'!'`
+    Exclamation     =  33,
+    /// `'"'`
+    Quotation       =  34,
+    /// `'#'`
+    Hash            =  35,
+    /// `'$'`
+    Dollar          =  36,
+    /// `'%'`
+    Percent         =  37,
+    /// `'&'`
+    Ampersand       =  38,
+    /// `'\''`
+    Apostrophe      =  39,
+    /// `'('`
+    ParenOpen       =  40,
+    /// `')'`
+    ParenClose      =  41,
+    /// `'*'`
+    Asterisk        =  42,
+    /// `'+'`
+    Plus            =  43,
+    /// `','`
+    Comma           =  44,
+    /// `'-'`
+    Minus           =  45,
+    /// `'.'`
+    Dot             =  46,
+    /// `'/'`
+    Slash           =  47,
+    /// `'0'`
+    _0              =  48,
+    /// `'1'`
+    _1              =  49,
+    /// `'2'`
+    _2              =  50,
+    /// `'3'`
+    _3              =  51,
+    /// `'4'`
+    _4              =  52,
+    /// `'5'`
+    _5              =  53,
+    /// `'6'`
+    _6              =  54,
+    /// `'7'`
+    _7              =  55,
+    /// `'8'`
+    _8              =  56,
+    /// `'9'`
+    _9              =  57,
+    /// `':'`
+    Colon           =  58,
+    /// `';'`
+    Semicolon       =  59,
+    /// `'<'`
+    LessThan        =  60,
+    /// `'='`
+    Equal           =  61,
+    /// `'>'`
+    GreaterThan     =  62,
+    /// `'?'`
+    Question        =  63,
+    /// `'@'`
+    At              =  64,
+    /// `'A'`
+    A               =  65,
+    /// `'B'`
+    B               =  66,
+    /// `'C'`
+    C               =  67,
+    /// `'D'`
+    D               =  68,
+    /// `'E'`
+    E               =  69,
+    /// `'F'`
+    F               =  70,
+    /// `'G'`
+    G               =  71,
+    /// `'H'`
+    H               =  72,
+    /// `'I'`
+    I               =  73,
+    /// `'J'`
+    J               =  74,
+    /// `'K'`
+    K               =  75,
+    /// `'L'`
+    L               =  76,
+    /// `'M'`
+    M               =  77,
+    /// `'N'`
+    N               =  78,
+    /// `'O'`
+    O               =  79,
+    /// `'P'`
+    P               =  80,
+    /// `'Q'`
+    Q               =  81,
+    /// `'R'`
+    R               =  82,
+    /// `'S'`
+    S               =  83,
+    /// `'T'`
+    T               =  84,
+    /// `'U'`
+    U               =  85,
+    /// `'V'`
+    V               =  86,
+    /// `'W'`
+    W               =  87,
+    /// `'X'`
+    X               =  88,
+    /// `'Y'`
+    Y               =  89,
+    /// `'Z'`
+    Z               =  90,
+    /// `'['`
+    BracketOpen     =  91,
+    /// `'\'`
+    BackSlash       =  92,
+    /// `']'`
+    BracketClose    =  93,
+    /// `'_'`
+    Caret           =  94,
+    /// `'_'`
+    UnderScore      =  95,
+    /// `'`'`
+    Grave           =  96,
+    /// `'a'`
+    a               =  97,
+    /// `'b'`
+    b               =  98,
+    /// `'c'`
+    c               =  99,
+    /// `'d'`
+    d               = 100,
+    /// `'e'`
+    e               = 101,
+    /// `'f'`
+    f               = 102,
+    /// `'g'`
+    g               = 103,
+    /// `'h'`
+    h               = 104,
+    /// `'i'`
+    i               = 105,
+    /// `'j'`
+    j               = 106,
+    /// `'k'`
+    k               = 107,
+    /// `'l'`
+    l               = 108,
+    /// `'m'`
+    m               = 109,
+    /// `'n'`
+    n               = 110,
+    /// `'o'`
+    o               = 111,
+    /// `'p'`
+    p               = 112,
+    /// `'q'`
+    q               = 113,
+    /// `'r'`
+    r               = 114,
+    /// `'s'`
+    s               = 115,
+    /// `'t'`
+    t               = 116,
+    /// `'u'`
+    u               = 117,
+    /// `'v'`
+    v               = 118,
+    /// `'w'`
+    w               = 119,
+    /// `'x'`
+    x               = 120,
+    /// `'y'`
+    y               = 121,
+    /// `'z'`
+    z               = 122,
+    /// `'{'`
+    CurlyBraceOpen  = 123,
+    /// `'|'`
+    VerticalBar     = 124,
+    /// `'}'`
+    CurlyBraceClose = 125,
+    /// `'~'`
+    Tilde           = 126,
+    /// [Delete](http://en.wikipedia.org/wiki/Delete_character)
+    DEL             = 127,
+}
+
+impl AsciiChar {
+    /// Constructs an ASCII character from a `u8`, `char` or other character type.
+    ///
+    /// # Failure
+    /// Returns `Err(())` if the character can't be ASCII encoded.
+    ///
+    /// # Example
+    /// ```
+    /// # use ascii::AsciiChar;
+    /// let a = AsciiChar::from('g').unwrap();
+    /// assert_eq!(a.as_char(), 'g');
+    /// ```
+    #[inline]
+    pub fn from<C:ToAsciiChar>(ch: C) -> Result<Self, ToAsciiCharError> {
+        ch.to_ascii_char()
+    }
+
+    /// Constructs an ASCII character from a `char` or `u8` without any checks.
+    pub unsafe fn from_unchecked<C:ToAsciiChar>(ch: C) -> Self {
+        ch.to_ascii_char_unchecked()
+    }
+
+    /// Converts an ASCII character into a `u8`.
+    #[inline]
+    pub fn as_byte(&self) -> u8 {
+        *self as u8
+    }
+
+    /// Converts an ASCII character into a `char`.
+    #[inline]
+    pub fn as_char(&self) -> char {
+        self.as_byte() as char
+    }
+
+    // the following methods are like ctype, and the implementation is inspired by musl
+
+    /// Check if the character is a letter (a-z, A-Z)
+    #[inline]
+    pub fn is_alphabetic(&self) -> bool {
+        let c = self.as_byte() | 0b010_0000;// Turns uppercase into lowercase.
+        c >= b'a' && c <= b'z'
+    }
+
+    /// Check if the character is a number (0-9)
+    #[inline]
+    pub fn is_digit(&self) -> bool {
+        self >= &AsciiChar::_0 && self <= &AsciiChar::_9
+    }
+
+    /// Check if the character is a letter or number
+    #[inline]
+    pub fn is_alphanumeric(&self) -> bool {
+        self.is_alphabetic() || self.is_digit()
+    }
+
+    /// Check if the character is a space or horizontal tab
+    #[inline]
+    pub fn is_blank(&self) -> bool {
+        *self == AsciiChar::Space || *self == AsciiChar::Tab
+    }
+
+    /// Check if the character is a ' ', '\t', '\n' or '\r'
+    #[inline]
+    pub fn is_whitespace(&self) -> bool {
+        self.is_blank() || *self == AsciiChar::LineFeed
+                        || *self == AsciiChar::CarriageReturn
+    }
+
+    /// Check if the character is a control character
+    ///
+    /// # Examples
+    /// ```
+    /// use ascii::ToAsciiChar;
+    /// assert_eq!('\0'.to_ascii_char().unwrap().is_control(), true);
+    /// assert_eq!('n'.to_ascii_char().unwrap().is_control(), false);
+    /// assert_eq!(' '.to_ascii_char().unwrap().is_control(), false);
+    /// assert_eq!('\n'.to_ascii_char().unwrap().is_control(), true);
+    /// ```
+    #[inline]
+    pub fn is_control(&self) -> bool {
+        *self < AsciiChar::Space || *self == AsciiChar::DEL
+    }
+
+    /// Checks if the character is printable (except space)
+    ///
+    /// # Examples
+    /// ```
+    /// use ascii::ToAsciiChar;
+    /// assert_eq!('n'.to_ascii_char().unwrap().is_graph(), true);
+    /// assert_eq!(' '.to_ascii_char().unwrap().is_graph(), false);
+    /// assert_eq!('\n'.to_ascii_char().unwrap().is_graph(), false);
+    /// ```
+    #[inline]
+    pub fn is_graph(&self) -> bool {
+        self.as_byte().wrapping_sub(b' '+1) < 0x5E
+    }
+
+    /// Checks if the character is printable (including space)
+    ///
+    /// # Examples
+    /// ```
+    /// use ascii::ToAsciiChar;
+    /// assert_eq!('n'.to_ascii_char().unwrap().is_print(), true);
+    /// assert_eq!(' '.to_ascii_char().unwrap().is_print(), true);
+    /// assert_eq!('\n'.to_ascii_char().unwrap().is_print(), false);
+    /// ```
+    #[inline]
+    pub fn is_print(&self) -> bool {
+        self.as_byte().wrapping_sub(b' ') < 0x5F
+    }
+
+    /// Checks if the character is alphabetic and lowercase
+    ///
+    /// # Examples
+    /// ```
+    /// use ascii::ToAsciiChar;
+    /// assert_eq!('a'.to_ascii_char().unwrap().is_lowercase(), true);
+    /// assert_eq!('A'.to_ascii_char().unwrap().is_lowercase(), false);
+    /// assert_eq!('@'.to_ascii_char().unwrap().is_lowercase(), false);
+    /// ```
+    #[inline]
+    pub fn is_lowercase(&self) -> bool {
+        self.as_byte().wrapping_sub(b'a') < 26
+    }
+
+    /// Checks if the character is alphabetic and uppercase
+    ///
+    /// # Examples
+    /// ```
+    /// use ascii::ToAsciiChar;
+    /// assert_eq!('A'.to_ascii_char().unwrap().is_uppercase(), true);
+    /// assert_eq!('a'.to_ascii_char().unwrap().is_uppercase(), false);
+    /// assert_eq!('@'.to_ascii_char().unwrap().is_uppercase(), false);
+    /// ```
+    #[inline]
+    pub fn is_uppercase(&self) -> bool {
+        self.as_byte().wrapping_sub(b'A') < 26
+    }
+
+    /// Checks if the character is punctuation
+    ///
+    /// # Examples
+    /// ```
+    /// use ascii::ToAsciiChar;
+    /// assert_eq!('n'.to_ascii_char().unwrap().is_punctuation(), false);
+    /// assert_eq!(' '.to_ascii_char().unwrap().is_punctuation(), false);
+    /// assert_eq!('_'.to_ascii_char().unwrap().is_punctuation(), true);
+    /// assert_eq!('~'.to_ascii_char().unwrap().is_punctuation(), true);
+    /// ```
+    #[inline]
+    pub fn is_punctuation(&self) -> bool {
+        self.is_graph() && !self.is_alphanumeric()
+    }
+
+    /// Checks if the character is a valid hex digit
+    ///
+    /// # Examples
+    /// ```
+    /// use ascii::ToAsciiChar;
+    /// assert_eq!('5'.to_ascii_char().unwrap().is_hex(), true);
+    /// assert_eq!('a'.to_ascii_char().unwrap().is_hex(), true);
+    /// assert_eq!('F'.to_ascii_char().unwrap().is_hex(), true);
+    /// assert_eq!('G'.to_ascii_char().unwrap().is_hex(), false);
+    /// assert_eq!(' '.to_ascii_char().unwrap().is_hex(), false);
+    /// ```
+    #[inline]
+    pub fn is_hex(&self) -> bool {
+        self.is_digit() || (self.as_byte() | 0x20u8).wrapping_sub(b'a') < 6
+    }
+}
+
+impl fmt::Display for AsciiChar {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.as_char().fmt(f)
+    }
+}
+
+impl fmt::Debug for AsciiChar {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.as_char().fmt(f)
+     }
+}
+
+#[cfg(not(feature = "no_std"))]
+impl AsciiExt for AsciiChar {
+    type Owned = AsciiChar;
+
+    #[inline]
+    fn is_ascii(&self) -> bool {
+        true
+    }
+
+    fn to_ascii_uppercase(&self) -> AsciiChar {
+        unsafe{ self.as_byte().to_ascii_uppercase().to_ascii_char_unchecked() }
+    }
+
+    fn to_ascii_lowercase(&self) -> AsciiChar {
+        unsafe{ self.as_byte().to_ascii_lowercase().to_ascii_char_unchecked() }
+    }
+
+    fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
+        self.as_byte().eq_ignore_ascii_case(&other.as_byte())
+    }
+
+    #[inline]
+    fn make_ascii_uppercase(&mut self) {
+        *self = self.to_ascii_uppercase();
+    }
+
+    #[inline]
+    fn make_ascii_lowercase(&mut self) {
+        *self = self.to_ascii_lowercase();
+    }
+}
+
+
+/// Error returned by `ToAsciiChar`.
+#[derive(PartialEq)]
+pub struct ToAsciiCharError(());
+
+const ERRORMSG_CHAR: &'static str = "not an ASCII character";
+
+impl fmt::Debug for ToAsciiCharError {
+    fn fmt(&self,  fmtr: &mut fmt::Formatter) -> fmt::Result {
+        write!(fmtr, "{}", ERRORMSG_CHAR)
+    }
+}
+
+impl fmt::Display for ToAsciiCharError {
+    fn fmt(&self,  fmtr: &mut fmt::Formatter) -> fmt::Result {
+        write!(fmtr, "{}", ERRORMSG_CHAR)
+    }
+}
+
+#[cfg(not(feature = "no_std"))]
+impl Error for ToAsciiCharError {
+    fn description(&self) -> &'static str {
+        ERRORMSG_CHAR
+    }
+}
+
+/// Convert `char`, `u8` and other character types to `AsciiChar`.
+pub trait ToAsciiChar {
+    /// Convert to `AsciiChar` without checking that it is an ASCII character.
+    unsafe fn to_ascii_char_unchecked(self) -> AsciiChar;
+    /// Convert to `AsciiChar`.
+    fn to_ascii_char(self) -> Result<AsciiChar, ToAsciiCharError>;
+}
+
+impl ToAsciiChar for AsciiChar {
+    fn to_ascii_char(self) -> Result<AsciiChar, ToAsciiCharError> {
+        Ok(self)
+    }
+    unsafe fn to_ascii_char_unchecked(self) -> AsciiChar {
+        self
+    }
+}
+
+impl ToAsciiChar for u8 {
+    fn to_ascii_char(self) -> Result<AsciiChar, ToAsciiCharError> {
+        unsafe{ if self <= 0x7F {
+            return Ok(self.to_ascii_char_unchecked());
+        }}
+        Err(ToAsciiCharError(()))
+    }
+    unsafe fn to_ascii_char_unchecked(self) -> AsciiChar {
+        transmute(self)
+    }
+}
+
+impl ToAsciiChar for char {
+    fn to_ascii_char(self) -> Result<AsciiChar, ToAsciiCharError> {
+        unsafe{ if self as u32 <= 0x7F {
+            return Ok(self.to_ascii_char_unchecked());
+        }}
+        Err(ToAsciiCharError(()))
+    }
+    unsafe fn to_ascii_char_unchecked(self) -> AsciiChar {
+        (self as u8).to_ascii_char_unchecked()
+    }
+}
+
+
+#[cfg(test)]
+mod tests {
+    use super::{AsciiChar, ToAsciiChar, ToAsciiCharError};
+    use AsciiChar::*;
+    #[cfg(not(feature = "no_std"))]
+    use std::ascii::AsciiExt;
+
+    #[test]
+    fn to_ascii_char() {
+        fn generic<C:ToAsciiChar>(ch: C) -> Result<AsciiChar, ToAsciiCharError> {
+            ch.to_ascii_char()
+        }
+        assert_eq!(generic(A), Ok(A));
+        assert_eq!(generic(b'A'), Ok(A));
+        assert_eq!(generic('A'), Ok(A));
+        assert!(generic(200).is_err());
+        assert!(generic('λ').is_err());
+    }
+
+    #[test]
+    fn as_byte_and_char() {
+        assert_eq!(A.as_byte(), b'A');
+        assert_eq!(A.as_char(),  'A');
+    }
+
+    #[test]
+    fn is_digit() {
+        assert_eq!('0'.to_ascii_char().unwrap().is_digit(), true);
+        assert_eq!('9'.to_ascii_char().unwrap().is_digit(), true);
+        assert_eq!('/'.to_ascii_char().unwrap().is_digit(), false);
+        assert_eq!(':'.to_ascii_char().unwrap().is_digit(), false);
+    }
+
+    #[test]
+    fn is_control() {
+        assert_eq!(US.is_control(), true);
+        assert_eq!(DEL.is_control(), true);
+        assert_eq!(Space.is_control(), false);
+    }
+
+    #[test]
+    #[cfg(not(feature = "no_std"))]
+    fn ascii_case() {
+        assert_eq!(At.to_ascii_lowercase(), At);
+        assert_eq!(At.to_ascii_uppercase(), At);
+        assert_eq!(A.to_ascii_lowercase(), a);
+        assert_eq!(A.to_ascii_uppercase(), A);
+        assert_eq!(a.to_ascii_lowercase(), a);
+        assert_eq!(a.to_ascii_uppercase(), A);
+
+        assert!(LineFeed.eq_ignore_ascii_case(&LineFeed));
+        assert!(!LineFeed.eq_ignore_ascii_case(&CarriageReturn));
+        assert!(z.eq_ignore_ascii_case(&Z));
+        assert!(Z.eq_ignore_ascii_case(&z));
+        assert!(!Z.eq_ignore_ascii_case(&DEL));
+    }
+
+    #[test]
+    #[cfg(not(feature = "no_std"))]
+    fn fmt_ascii() {
+        assert_eq!(format!("{}", t), "t".to_string());
+        assert_eq!(format!("{:?}", t), "'t'".to_string());
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/ascii/src/ascii_str.rs
@@ -0,0 +1,525 @@
+extern crate core;
+
+use self::core::{fmt, mem};
+use self::core::ops::{Index, IndexMut, Range, RangeTo, RangeFrom, RangeFull};
+#[cfg(not(feature = "no_std"))]
+use std::error::Error;
+#[cfg(not(feature = "no_std"))]
+use std::ascii::AsciiExt;
+
+use ascii_char::AsciiChar;
+#[cfg(not(feature = "no_std"))]
+use ascii_string::AsciiString;
+
+/// AsciiStr represents a byte or string slice that only contains ASCII characters.
+///
+/// It wraps an `[AsciiChar]` and implements many of `str`s methods and traits.
+///
+/// It can be created by a checked conversion from a `str` or `[u8]`,
+/// or borrowed from an `AsciiString`.
+#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct AsciiStr {
+    slice: [AsciiChar],
+}
+
+impl AsciiStr {
+    /// Coerces into an `AsciiStr` slice.
+    pub fn new<S: AsRef<AsciiStr> + ?Sized>(s: &S) -> &AsciiStr {
+        s.as_ref()
+    }
+
+    /// Converts `&self` to a `&str` slice.
+    pub fn as_str(&self) -> &str {
+        unsafe { mem::transmute(&self.slice) }
+    }
+
+    /// Converts `&self` into a byte slice.
+    pub fn as_bytes(&self) -> &[u8] {
+        unsafe { mem::transmute(&self.slice) }
+    }
+
+    /// Returns the entire string as slice of `AsciiChar`s.
+    pub fn as_slice(&self) -> &[AsciiChar] {
+        &self.slice
+    }
+
+    /// Returns the entire string as mutable slice of `AsciiChar`s.
+    pub fn as_mut_slice(&mut self) -> &mut [AsciiChar] {
+        &mut self.slice
+    }
+
+    /// Returns a raw pointer to the `AsciiStr`'s buffer.
+    ///
+    /// The caller must ensure that the slice outlives the pointer this function returns, or else it
+    /// will end up pointing to garbage. Modifying the `AsciiStr` may cause it's buffer to be
+    /// reallocated, which would also make any pointers to it invalid.
+    pub fn as_ptr(&self) -> *const AsciiChar {
+        self.as_slice().as_ptr()
+    }
+
+    /// Returns an unsafe mutable pointer to the `AsciiStr`'s buffer.
+    ///
+    /// The caller must ensure that the slice outlives the pointer this function returns, or else it
+    /// will end up pointing to garbage. Modifying the `AsciiStr` may cause it's buffer to be
+    /// reallocated, which would also make any pointers to it invalid.
+    pub fn as_mut_ptr(&mut self) -> *mut AsciiChar {
+        self.as_mut_slice().as_mut_ptr()
+    }
+
+    #[cfg(not(feature = "no_std"))]
+    /// Copies the content of this `AsciiStr` into an owned `AsciiString`.
+    pub fn to_ascii_string(&self) -> AsciiString {
+        AsciiString::from(self.slice.to_vec())
+    }
+
+    /// Converts anything that can represent a byte slice into an `AsciiStr`.
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::AsciiStr;
+    /// let foo = AsciiStr::from_ascii("foo");
+    /// let err = AsciiStr::from_ascii("Ŋ");
+    /// assert_eq!(foo.unwrap().as_str(), "foo");
+    /// assert_eq!(err.unwrap_err().valid_up_to(), 0);
+    /// ```
+    pub fn from_ascii<B: ?Sized>(bytes: &B) -> Result<&AsciiStr, AsAsciiStrError>
+        where B: AsRef<[u8]>
+    {
+        bytes.as_ref().as_ascii_str()
+    }
+
+    /// Converts anything that can be represented as a byte slice to an `AsciiStr` without checking
+    /// for non-ASCII characters..
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::AsciiStr;
+    /// let foo = unsafe{ AsciiStr::from_ascii_unchecked("foo") };
+    /// assert_eq!(foo.as_str(), "foo");
+    /// ```
+    pub unsafe fn from_ascii_unchecked<B: ?Sized>(bytes: &B) -> &AsciiStr
+        where B: AsRef<[u8]>
+    {
+        bytes.as_ref().as_ascii_str_unchecked()
+    }
+
+    /// Returns the number of characters / bytes in this ASCII sequence.
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::AsciiStr;
+    /// let s = AsciiStr::from_ascii("foo").unwrap();
+    /// assert_eq!(s.len(), 3);
+    /// ```
+    pub fn len(&self) -> usize {
+        self.slice.len()
+    }
+
+    /// Returns true if the ASCII slice contains zero bytes.
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::AsciiStr;
+    /// let mut empty = AsciiStr::from_ascii("").unwrap();
+    /// let mut full = AsciiStr::from_ascii("foo").unwrap();
+    /// assert!(empty.is_empty());
+    /// assert!(!full.is_empty());
+    /// ```
+    pub fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
+
+    /// Returns an ASCII string slice with leading and trailing whitespace removed.
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::AsciiStr;
+    /// let example = AsciiStr::from_ascii("  \twhite \tspace  \t").unwrap();
+    /// assert_eq!("white \tspace", example.trim());
+    /// ```
+    pub fn trim(&self) -> &Self {
+        self.trim_right().trim_left()
+    }
+
+    /// Returns an ASCII string slice with leading whitespace removed.
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::AsciiStr;
+    /// let example = AsciiStr::from_ascii("  \twhite \tspace  \t").unwrap();
+    /// assert_eq!("white \tspace  \t", example.trim_left());
+    /// ```
+    pub fn trim_left(&self) -> &Self {
+        &self[self.slice.iter().take_while(|a| a.is_whitespace() ).count()..]
+    }
+
+    /// Returns an ASCII string slice with trailing whitespace removed.
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::AsciiStr;
+    /// let example = AsciiStr::from_ascii("  \twhite \tspace  \t").unwrap();
+    /// assert_eq!("  \twhite \tspace", example.trim_right());
+    /// ```
+    pub fn trim_right(&self) -> &Self {
+        let trimmed = self.slice.into_iter()
+                          .rev().take_while(|a| a.is_whitespace() ).count();
+        &self[..self.len()-trimmed]
+    }
+}
+
+impl PartialEq<str> for AsciiStr {
+    fn eq(&self, other: &str) -> bool {
+        self.as_str() == other
+    }
+}
+
+impl PartialEq<AsciiStr> for str {
+    fn eq(&self, other: &AsciiStr) -> bool {
+        other.as_str() == self
+    }
+}
+
+#[cfg(not(feature = "no_std"))]
+impl ToOwned for AsciiStr {
+    type Owned = AsciiString;
+
+    fn to_owned(&self) -> AsciiString {
+        self.to_ascii_string()
+    }
+}
+
+impl AsRef<[u8]> for AsciiStr {
+    fn as_ref(&self) -> &[u8] {
+        self.as_bytes()
+    }
+}
+impl AsRef<str> for AsciiStr {
+    fn as_ref(&self) -> &str {
+        self.as_str()
+    }
+}
+impl AsRef<[AsciiChar]> for AsciiStr {
+    fn as_ref(&self) -> &[AsciiChar] {
+        &self.slice
+    }
+}
+impl AsMut<[AsciiChar]> for AsciiStr {
+    fn as_mut(&mut self) -> &mut[AsciiChar] {
+        &mut self.slice
+    }
+}
+
+impl Default for &'static AsciiStr {
+    fn default() -> &'static AsciiStr {
+        unsafe{ "".as_ascii_str_unchecked() }
+    }
+}
+impl<'a> From<&'a[AsciiChar]> for &'a AsciiStr {
+    fn from(slice: &[AsciiChar]) -> &AsciiStr {
+        unsafe{ mem::transmute(slice) }
+    }
+}
+impl<'a> From<&'a mut [AsciiChar]> for &'a mut AsciiStr {
+    fn from(slice: &mut[AsciiChar]) -> &mut AsciiStr {
+        unsafe{ mem::transmute(slice) }
+    }
+}
+#[cfg(not(feature = "no_std"))]
+impl From<Box<[AsciiChar]>> for Box<AsciiStr> {
+    fn from(owned: Box<[AsciiChar]>) -> Box<AsciiStr> {
+        unsafe{ mem::transmute(owned) }
+    }
+}
+
+macro_rules! impl_into {
+    ($wider: ty) => {
+        impl<'a> From<&'a AsciiStr> for &'a$wider {
+            fn from(slice: &AsciiStr) -> &$wider {
+                unsafe{ mem::transmute(slice) }
+            }
+        }
+        impl<'a> From<&'a mut AsciiStr> for &'a mut $wider {
+            fn from(slice: &mut AsciiStr) -> &mut $wider {
+                unsafe{ mem::transmute(slice) }
+            }
+        }
+        #[cfg(not(feature = "no_std"))]
+        impl From<Box<AsciiStr>> for Box<$wider> {
+            fn from(owned: Box<AsciiStr>) -> Box<$wider> {
+                unsafe{ mem::transmute(owned) }
+            }
+        }
+    }
+}
+impl_into! {[AsciiChar]}
+impl_into! {[u8]}
+impl_into! {str}
+
+impl fmt::Display for AsciiStr {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(self.as_str(), f)
+    }
+}
+
+impl fmt::Debug for AsciiStr {
+   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+       fmt::Debug::fmt(self.as_str(), f)
+   }
+}
+
+macro_rules! impl_index {
+    ($lhs:ty, $idx:ty, $rhs:ty) => {
+        impl Index<$idx> for $lhs {
+            type Output = $rhs;
+
+            #[inline]
+            fn index(&self, index: $idx) -> &$rhs {
+                unsafe { mem::transmute(&self.slice[index]) }
+            }
+        }
+
+        impl IndexMut<$idx> for $lhs {
+            #[inline]
+            fn index_mut(&mut self, index: $idx) -> &mut $rhs {
+                unsafe { mem::transmute(&mut self.slice[index]) }
+            }
+        }
+    }
+}
+
+impl_index! { AsciiStr, usize, AsciiChar }
+impl_index! { AsciiStr, Range<usize>, AsciiStr }
+impl_index! { AsciiStr, RangeTo<usize>, AsciiStr }
+impl_index! { AsciiStr, RangeFrom<usize>, AsciiStr }
+impl_index! { AsciiStr, RangeFull, AsciiStr }
+
+#[cfg(not(feature = "no_std"))]
+impl AsciiExt for AsciiStr {
+    type Owned = AsciiString;
+
+    #[inline]
+    fn is_ascii(&self) -> bool {
+        true
+    }
+
+    fn to_ascii_uppercase(&self) -> AsciiString {
+        let mut ascii_string = self.to_ascii_string();
+        ascii_string.make_ascii_uppercase();
+        ascii_string
+    }
+
+    fn to_ascii_lowercase(&self) -> AsciiString {
+        let mut ascii_string = self.to_ascii_string();
+        ascii_string.make_ascii_uppercase();
+        ascii_string
+    }
+
+    fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
+        self.len() == other.len() &&
+        self.slice.iter().zip(other.slice.iter()).all(|(a, b)| a.eq_ignore_ascii_case(b))
+    }
+
+    fn make_ascii_uppercase(&mut self) {
+        for ascii in &mut self.slice {
+            ascii.make_ascii_uppercase();
+        }
+    }
+
+    fn make_ascii_lowercase(&mut self) {
+        for ascii in &mut self.slice {
+            ascii.make_ascii_lowercase();
+        }
+    }
+}
+
+
+/// Error that is returned when a sequence of `u8` are not all ASCII.
+///
+/// Is used by `As[Mut]AsciiStr` and the `from_ascii` method on `AsciiStr` and `AsciiString`.
+#[derive(Clone,Copy, PartialEq,Eq, Debug)]
+pub struct AsAsciiStrError (usize);
+
+impl AsAsciiStrError {
+    /// Returns the index of the first non-ASCII byte.
+    ///
+    /// It is the maximum index such that `from_ascii(input[..index])` would return `Ok(_)`.
+    pub fn valid_up_to(self) -> usize {
+        self.0
+    }
+}
+impl fmt::Display for AsAsciiStrError {
+    fn fmt(&self,  fmtr: &mut fmt::Formatter) -> fmt::Result {
+        write!(fmtr, "the byte at index {} is not ASCII", self.0)
+    }
+}
+#[cfg(not(feature = "no_std"))]
+impl Error for AsAsciiStrError {
+    /// Returns "one or more bytes are not ASCII"
+    fn description(&self) -> &'static str {
+        "one or more bytes are not ASCII"
+    }
+}
+
+
+/// Convert slices of bytes to `AsciiStr`.
+pub trait AsAsciiStr {
+    /// Convert to an ASCII slice without checking for non-ASCII characters.
+    unsafe fn as_ascii_str_unchecked(&self) -> &AsciiStr;
+    /// Convert to an ASCII slice.
+    fn as_ascii_str(&self) -> Result<&AsciiStr,AsAsciiStrError>;
+}
+
+/// Convert mutable slices of bytes to `AsciiStr`.
+pub trait AsMutAsciiStr {
+    /// Convert to a mutable ASCII slice without checking for non-ASCII characters.
+    unsafe fn as_mut_ascii_str_unchecked(&mut self) -> &mut AsciiStr;
+    /// Convert to a mutable ASCII slice.
+    fn as_mut_ascii_str(&mut self) -> Result<&mut AsciiStr,AsAsciiStrError>;
+}
+
+impl AsAsciiStr for AsciiStr {
+    fn as_ascii_str(&self) -> Result<&AsciiStr,AsAsciiStrError> {
+        Ok(self)
+    }
+    unsafe fn as_ascii_str_unchecked(&self) -> &AsciiStr {
+        self
+    }
+}
+impl AsMutAsciiStr for AsciiStr {
+    fn as_mut_ascii_str(&mut self) -> Result<&mut AsciiStr,AsAsciiStrError> {
+        Ok(self)
+    }
+    unsafe fn as_mut_ascii_str_unchecked(&mut self) -> &mut AsciiStr {
+        self
+    }
+}
+
+impl AsAsciiStr for [AsciiChar] {
+    fn as_ascii_str(&self) -> Result<&AsciiStr,AsAsciiStrError> {
+        Ok(self.into())
+    }
+    unsafe fn as_ascii_str_unchecked(&self) -> &AsciiStr {
+        self.into()
+    }
+}
+impl AsMutAsciiStr for [AsciiChar] {
+    fn as_mut_ascii_str(&mut self) -> Result<&mut AsciiStr,AsAsciiStrError> {
+        Ok(self.into())
+    }
+    unsafe fn as_mut_ascii_str_unchecked(&mut self) -> &mut AsciiStr {
+        self.into()
+    }
+}
+
+impl AsAsciiStr for [u8] {
+    fn as_ascii_str(&self) -> Result<&AsciiStr,AsAsciiStrError> {
+        match self.iter().position(|&b| b > 127 ) {
+            Some(index) => Err(AsAsciiStrError(index)),
+            None => unsafe{ Ok(self.as_ascii_str_unchecked()) },
+        }
+    }
+    unsafe fn as_ascii_str_unchecked(&self) -> &AsciiStr {
+        mem::transmute(self)
+    }
+}
+impl AsMutAsciiStr for [u8] {
+    fn as_mut_ascii_str(&mut self) -> Result<&mut AsciiStr,AsAsciiStrError> {
+        match self.iter().position(|&b| b > 127 ) {
+            Some(index) => Err(AsAsciiStrError(index)),
+            None => unsafe{ Ok(self.as_mut_ascii_str_unchecked()) },
+        }
+    }
+    unsafe fn as_mut_ascii_str_unchecked(&mut self) -> &mut AsciiStr {
+        mem::transmute(self)
+    }
+}
+
+impl AsAsciiStr for str {
+    fn as_ascii_str(&self) -> Result<&AsciiStr,AsAsciiStrError> {
+        self.as_bytes().as_ascii_str()
+    }
+    unsafe fn as_ascii_str_unchecked(&self) -> &AsciiStr {
+        self.as_bytes().as_ascii_str_unchecked()
+    }
+}
+impl AsMutAsciiStr for str {
+    fn as_mut_ascii_str(&mut self) -> Result<&mut AsciiStr,AsAsciiStrError> {
+        match self.bytes().position(|b| b > 127 ) {
+            Some(index) => Err(AsAsciiStrError(index)),
+            None => unsafe{ Ok(self.as_mut_ascii_str_unchecked()) },
+        }
+    }
+    unsafe fn as_mut_ascii_str_unchecked(&mut self) -> &mut AsciiStr {
+        mem::transmute(self)
+    }
+}
+
+
+#[cfg(test)]
+mod tests {
+    use AsciiChar;
+    use super::{AsciiStr, AsAsciiStr, AsAsciiStrError};
+    #[cfg(not(feature = "no_std"))]
+    use super::AsMutAsciiStr;
+
+    #[test]
+    fn generic_as_ascii_str() {
+        fn generic<C:AsAsciiStr+?Sized>(c: &C) -> Result<&AsciiStr,AsAsciiStrError> {
+            c.as_ascii_str()
+        }
+        let arr = [AsciiChar::A];
+        let ascii_str: &AsciiStr = arr.as_ref().into();
+        assert_eq!(generic("A"), Ok(ascii_str));
+        assert_eq!(generic(&b"A"[..]), Ok(ascii_str));
+        assert_eq!(generic(ascii_str), Ok(ascii_str));
+    }
+
+    #[test]
+    #[cfg(not(feature = "no_std"))]
+    fn as_ascii_str() {
+        macro_rules! err {{$i:expr} => {Err(AsAsciiStrError($i))}}
+        let mut s: String = "abčd".to_string();
+        let mut b: Vec<u8> = s.clone().into();
+        assert_eq!(s.as_str().as_ascii_str(), err!(2));
+        assert_eq!(s.as_mut_str().as_mut_ascii_str(), err!(2));
+        assert_eq!(b.as_slice().as_ascii_str(), err!(2));
+        assert_eq!(b.as_mut_slice().as_mut_ascii_str(), err!(2));
+        let mut a = [AsciiChar::a, AsciiChar::b];
+        assert_eq!((&s[..2]).as_ascii_str(), Ok((&a[..]).into()));
+        assert_eq!((&b[..2]).as_ascii_str(), Ok((&a[..]).into()));
+        let a = Ok((&mut a[..]).into());
+        assert_eq!((&mut s[..2]).as_mut_ascii_str(), a);
+        assert_eq!((&mut b[..2]).as_mut_ascii_str(), a);
+    }
+
+    #[test]
+    fn default() {
+        let default: &'static AsciiStr = Default::default();
+        assert!(default.is_empty());
+    }
+
+    #[test]
+    fn as_str() {
+        let b = b"( ;";
+        let v = AsciiStr::from_ascii(b).unwrap();
+        assert_eq!(v.as_str(), "( ;");
+        assert_eq!(AsRef::<str>::as_ref(v), "( ;");
+    }
+
+    #[test]
+    fn as_bytes() {
+        let b = b"( ;";
+        let v = AsciiStr::from_ascii(b).unwrap();
+        assert_eq!(v.as_bytes(), b"( ;");
+        assert_eq!(AsRef::<[u8]>::as_ref(v), b"( ;");
+    }
+
+    #[test]
+    #[cfg(not(feature = "no_std"))]
+    fn fmt_ascii_str() {
+        let s = "abc".as_ascii_str().unwrap();
+        assert_eq!(format!("{}", s), "abc".to_string());
+        assert_eq!(format!("{:?}", s), "\"abc\"".to_string());
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/ascii/src/ascii_string.rs
@@ -0,0 +1,619 @@
+use std::{fmt, mem};
+use std::ascii::AsciiExt;
+use std::borrow::Borrow;
+use std::str::FromStr;
+use std::ops::{Deref, DerefMut, Add, Index, IndexMut};
+use std::iter::FromIterator;
+
+use ascii_char::AsciiChar;
+use ascii_str::{AsciiStr,AsAsciiStr,AsAsciiStrError};
+
+/// A growable string stored as an ASCII encoded buffer.
+#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct AsciiString {
+    vec: Vec<AsciiChar>,
+}
+
+impl AsciiString {
+    /// Creates a new, empty ASCII string buffer without allocating.
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::AsciiString;
+    /// let mut s = AsciiString::new();
+    /// ```
+    #[inline]
+    pub fn new() -> Self {
+        AsciiString { vec: Vec::new() }
+    }
+
+    /// Creates a new ASCII string buffer with the given capacity.
+    /// The string will be able to hold exactly `capacity` bytes without reallocating.
+    /// If `capacity` is 0, the ASCII string will not allocate.
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::AsciiString;
+    /// let mut s = AsciiString::with_capacity(10);
+    /// ```
+    #[inline]
+    pub fn with_capacity(capacity: usize) -> Self {
+        AsciiString {
+            vec: Vec::with_capacity(capacity),
+        }
+    }
+
+    /// Creates a new `AsciiString` from a length, capacity and pointer.
+    ///
+    /// # Safety
+    ///
+    /// This is highly unsafe, due to the number of invariants that aren't checked:
+    ///
+    /// * The memory at `ptr` need to have been previously allocated by the same allocator this
+    ///   library uses.
+    /// * `length` needs to be less than or equal to `capacity`.
+    /// * `capacity` needs to be the correct value.
+    ///
+    /// Violating these may cause problems like corrupting the allocator's internal datastructures.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// # use ascii::AsciiString;
+    /// use std::mem;
+    ///
+    /// unsafe {
+    ///    let s = AsciiString::from_ascii("hello").unwrap();
+    ///    let ptr = s.as_ptr();
+    ///    let len = s.len();
+    ///    let capacity = s.capacity();
+    ///
+    ///    mem::forget(s);
+    ///
+    ///    let s = AsciiString::from_raw_parts(ptr as *mut _, len, capacity);
+    ///
+    ///    assert_eq!(AsciiString::from_ascii("hello").unwrap(), s);
+    /// }
+    /// ```
+    pub unsafe fn from_raw_parts(buf: *mut AsciiChar, length: usize, capacity: usize) -> Self {
+        AsciiString {
+            vec: Vec::from_raw_parts(buf, length, capacity),
+        }
+    }
+
+    /// Converts a vector of bytes to an `AsciiString` without checking for non-ASCII characters.
+    ///
+    /// # Safety
+    /// This function is unsafe because it does not check that the bytes passed to it are valid
+    /// ASCII characters. If this constraint is violated, it may cause memory unsafety issues with
+    /// future of the `AsciiString`, as the rest of this library assumes that `AsciiString`s are
+    /// ASCII encoded.
+    pub unsafe fn from_ascii_unchecked<B>(bytes: B) -> Self
+        where B: Into<Vec<u8>>
+    {
+        let bytes: Vec<u8> = bytes.into();
+        let vec = Vec::from_raw_parts(bytes.as_ptr() as *mut AsciiChar,
+                                      bytes.len(),
+                                      bytes.capacity());
+
+        // We forget `src` to avoid freeing it at the end of the scope.
+        // Otherwise, the returned `AsciiString` would point to freed memory.
+        mem::forget(bytes);
+        AsciiString { vec: vec }
+    }
+
+    /// Converts anything that can represent a byte buffer into an `AsciiString`.
+    ///
+    /// # Failure
+    /// Returns the byte buffer if not all of the bytes are ASCII characters.
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::AsciiString;
+    /// let foo = AsciiString::from_ascii("foo").unwrap();
+    /// let err = AsciiString::from_ascii("Ŋ");
+    /// assert_eq!(foo.as_str(), "foo");
+    /// assert_eq!(err, Err("Ŋ"));
+    /// ```
+    pub fn from_ascii<B>(bytes: B) -> Result<AsciiString, B>
+        where B: Into<Vec<u8>> + AsRef<[u8]>
+    {
+        unsafe {
+            if bytes.as_ref().is_ascii() {
+                Ok( AsciiString::from_ascii_unchecked(bytes) )
+            } else {
+                Err(bytes)
+            }
+        }
+    }
+
+    /// Pushes the given ASCII string onto this ASCII string buffer.
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::{AsciiString, AsAsciiStr};
+    /// use std::str::FromStr;
+    /// let mut s = AsciiString::from_str("foo").unwrap();
+    /// s.push_str("bar".as_ascii_str().unwrap());
+    /// assert_eq!(s, "foobar".as_ascii_str().unwrap());
+    /// ```
+    #[inline]
+    pub fn push_str(&mut self, string: &AsciiStr) {
+        self.vec.extend(string.as_slice().iter().cloned())
+    }
+
+    /// Returns the number of bytes that this ASCII string buffer can hold without reallocating.
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::AsciiString;
+    /// let s = String::with_capacity(10);
+    /// assert!(s.capacity() >= 10);
+    /// ```
+    #[inline]
+    pub fn capacity(&self) -> usize {
+        self.vec.capacity()
+    }
+
+    /// Reserves capacity for at least `additional` more bytes to be inserted in the given
+    /// `AsciiString`. The collection may reserve more space to avoid frequent reallocations.
+    ///
+    /// # Panics
+    /// Panics if the new capacity overflows `usize`.
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::AsciiString;
+    /// let mut s = AsciiString::new();
+    /// s.reserve(10);
+    /// assert!(s.capacity() >= 10);
+    /// ```
+    #[inline]
+    pub fn reserve(&mut self, additional: usize) {
+        self.vec.reserve(additional)
+    }
+
+    /// Reserves the minimum capacity for exactly `additional` more bytes to be inserted in the
+    /// given `AsciiString`. Does nothing if the capacity is already sufficient.
+    ///
+    /// Note that the allocator may give the collection more space than it requests. Therefore
+    /// capacity can not be relied upon to be precisely minimal. Prefer `reserve` if future
+    /// insertions are expected.
+    ///
+    /// # Panics
+    /// Panics if the new capacity overflows `usize`.
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::AsciiString;
+    /// let mut s = AsciiString::new();
+    /// s.reserve_exact(10);
+    /// assert!(s.capacity() >= 10);
+    /// ```
+    #[inline]
+    pub fn reserve_exact(&mut self, additional: usize) {
+        self.vec.reserve_exact(additional)
+    }
+
+    /// Shrinks the capacity of this ASCII string buffer to match it's length.
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::AsciiString;
+    /// use std::str::FromStr;
+    /// let mut s = AsciiString::from_str("foo").unwrap();
+    /// s.reserve(100);
+    /// assert!(s.capacity() >= 100);
+    /// s.shrink_to_fit();
+    /// assert_eq!(s.capacity(), 3);
+    /// ```
+    #[inline]
+    pub fn shrink_to_fit(&mut self) {
+        self.vec.shrink_to_fit()
+    }
+
+    /// Adds the given ASCII character to the end of the ASCII string.
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::{ AsciiChar, AsciiString};
+    /// let mut s = AsciiString::from_ascii("abc").unwrap();
+    /// s.push(AsciiChar::from('1').unwrap());
+    /// s.push(AsciiChar::from('2').unwrap());
+    /// s.push(AsciiChar::from('3').unwrap());
+    /// assert_eq!(s, "abc123");
+    /// ```
+    #[inline]
+    pub fn push(&mut self, ch: AsciiChar) {
+        self.vec.push(ch)
+    }
+
+    /// Shortens a ASCII string to the specified length.
+    ///
+    /// # Panics
+    /// Panics if `new_len` > current length.
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::AsciiString;
+    /// let mut s = AsciiString::from_ascii("hello").unwrap();
+    /// s.truncate(2);
+    /// assert_eq!(s, "he");
+    /// ```
+    #[inline]
+    pub fn truncate(&mut self, new_len: usize) {
+        self.vec.truncate(new_len)
+    }
+
+    /// Removes the last character from the ASCII string buffer and returns it.
+    /// Returns `None` if this string buffer is empty.
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::AsciiString;
+    /// let mut s = AsciiString::from_ascii("foo").unwrap();
+    /// assert_eq!(s.pop().map(|c| c.as_char()), Some('o'));
+    /// assert_eq!(s.pop().map(|c| c.as_char()), Some('o'));
+    /// assert_eq!(s.pop().map(|c| c.as_char()), Some('f'));
+    /// assert_eq!(s.pop(), None);
+    /// ```
+    #[inline]
+    pub fn pop(&mut self) -> Option<AsciiChar> {
+        self.vec.pop()
+    }
+
+    /// Removes the ASCII character at position `idx` from the buffer and returns it.
+    ///
+    /// # Warning
+    /// This is an O(n) operation as it requires copying every element in the buffer.
+    ///
+    /// # Panics
+    /// If `idx` is out of bounds this function will panic.
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::AsciiString;
+    /// let mut s = AsciiString::from_ascii("foo").unwrap();
+    /// assert_eq!(s.remove(0).as_char(), 'f');
+    /// assert_eq!(s.remove(1).as_char(), 'o');
+    /// assert_eq!(s.remove(0).as_char(), 'o');
+    /// ```
+    #[inline]
+    pub fn remove(&mut self, idx: usize) -> AsciiChar {
+        self.vec.remove(idx)
+    }
+
+    /// Inserts an ASCII character into the buffer at position `idx`.
+    ///
+    /// # Warning
+    /// This is an O(n) operation as it requires copying every element in the buffer.
+    ///
+    /// # Panics
+    /// If `idx` is out of bounds this function will panic.
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::{AsciiString,AsciiChar};
+    /// let mut s = AsciiString::from_ascii("foo").unwrap();
+    /// s.insert(2, AsciiChar::b);
+    /// assert_eq!(s, "fobo");
+    /// ```
+    #[inline]
+    pub fn insert(&mut self, idx: usize, ch: AsciiChar) {
+        self.vec.insert(idx, ch)
+    }
+
+    /// Returns the number of bytes in this ASCII string.
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::AsciiString;
+    /// let s = AsciiString::from_ascii("foo").unwrap();
+    /// assert_eq!(s.len(), 3);
+    /// ```
+    #[inline]
+    pub fn len(&self) -> usize {
+        self.vec.len()
+    }
+
+    /// Returns true if the ASCII string contains zero bytes.
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::{AsciiChar, AsciiString};
+    /// let mut s = AsciiString::new();
+    /// assert!(s.is_empty());
+    /// s.push(AsciiChar::from('a').unwrap());
+    /// assert!(!s.is_empty());
+    /// ```
+    #[inline]
+    pub fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
+
+    /// Truncates the ASCII string, setting length (but not capacity) to zero.
+    ///
+    /// # Examples
+    /// ```
+    /// # use ascii::AsciiString;
+    /// let mut s = AsciiString::from_ascii("foo").unwrap();
+    /// s.clear();
+    /// assert!(s.is_empty());
+    /// ```
+    #[inline]
+    pub fn clear(&mut self) {
+        self.vec.clear()
+    }
+}
+
+impl Deref for AsciiString {
+    type Target = AsciiStr;
+
+    #[inline]
+    fn deref(&self) -> &AsciiStr {
+        unsafe { mem::transmute(&self.vec[..]) }
+    }
+}
+
+impl DerefMut for AsciiString {
+    #[inline]
+    fn deref_mut(&mut self) -> &mut AsciiStr {
+        unsafe { mem::transmute(&mut self.vec[..]) }
+    }
+}
+
+impl PartialEq<str> for AsciiString {
+    fn eq(&self, other: &str) -> bool {
+        **self == *other
+    }
+}
+
+impl PartialEq<AsciiString> for str {
+    fn eq(&self, other: &AsciiString) -> bool {
+        **other == *self
+    }
+}
+
+macro_rules! impl_eq {
+    ($lhs:ty, $rhs:ty) => {
+        impl<'a> PartialEq<$rhs> for $lhs {
+            #[inline]
+            fn eq(&self, other: &$rhs) -> bool {
+                PartialEq::eq(&**self, &**other)
+            }
+            #[inline]
+            fn ne(&self, other: &$rhs) -> bool {
+                PartialEq::ne(&**self, &**other)
+            }
+        }
+    }
+}
+
+impl_eq! { AsciiString, String }
+impl_eq! { String, AsciiString }
+impl_eq! { &'a AsciiStr, String }
+impl_eq! { String, &'a AsciiStr }
+impl_eq! { &'a AsciiStr, AsciiString }
+impl_eq! { AsciiString, &'a AsciiStr }
+impl_eq! { &'a str, AsciiString }
+impl_eq! { AsciiString, &'a str }
+
+impl Borrow<AsciiStr> for AsciiString {
+    fn borrow(&self) -> &AsciiStr {
+        &*self
+    }
+}
+
+impl From<Vec<AsciiChar>> for AsciiString {
+    fn from(vec: Vec<AsciiChar>) -> Self {
+        AsciiString { vec: vec }
+    }
+}
+
+impl Into<Vec<u8>> for AsciiString {
+    fn into(self) -> Vec<u8> {
+        unsafe {
+            let v = Vec::from_raw_parts(self.vec.as_ptr() as *mut u8,
+                                        self.vec.len(),
+                                        self.vec.capacity());
+
+            // We forget `self` to avoid freeing it at the end of the scope.
+            // Otherwise, the returned `Vec` would point to freed memory.
+            mem::forget(self);
+            v
+        }
+    }
+}
+
+impl Into<String> for AsciiString {
+    fn into(self) -> String {
+        unsafe { String::from_utf8_unchecked(self.into()) }
+    }
+}
+
+impl AsRef<AsciiStr> for AsciiString {
+    fn as_ref(&self) -> &AsciiStr {
+        &*self
+    }
+}
+
+impl AsMut<AsciiStr> for AsciiString {
+    fn as_mut(&mut self) -> &mut AsciiStr {
+        &mut *self
+    }
+}
+
+impl FromStr for AsciiString {
+    type Err = AsAsciiStrError;
+
+    fn from_str(s: &str) -> Result<AsciiString, AsAsciiStrError> {
+        s.as_ascii_str().map(AsciiStr::to_ascii_string)
+    }
+}
+
+impl fmt::Display for AsciiString {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(&**self, f)
+    }
+}
+
+impl fmt::Debug for AsciiString {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&**self, f)
+    }
+}
+
+impl FromIterator<AsciiChar> for AsciiString {
+    fn from_iter<I: IntoIterator<Item=AsciiChar>>(iter: I) -> AsciiString {
+        let mut buf = AsciiString::new();
+        buf.extend(iter);
+        buf
+    }
+}
+
+impl<'a> FromIterator<&'a AsciiStr> for AsciiString {
+    fn from_iter<I: IntoIterator<Item=&'a AsciiStr>>(iter: I) -> AsciiString {
+        let mut buf = AsciiString::new();
+        buf.extend(iter);
+        buf
+    }
+}
+
+impl Extend<AsciiChar> for AsciiString {
+    fn extend<I: IntoIterator<Item=AsciiChar>>(&mut self, iterable: I) {
+        let iterator = iterable.into_iter();
+        let (lower_bound, _) = iterator.size_hint();
+        self.reserve(lower_bound);
+        for ch in iterator {
+            self.push(ch)
+        }
+    }
+}
+
+impl<'a> Extend<&'a AsciiChar> for AsciiString {
+    fn extend<I: IntoIterator<Item=&'a AsciiChar>>(&mut self, iter: I) {
+        self.extend(iter.into_iter().cloned())
+    }
+}
+
+impl<'a> Extend<&'a AsciiStr> for AsciiString {
+    fn extend<I: IntoIterator<Item=&'a AsciiStr>>(&mut self, iterable: I) {
+        let iterator = iterable.into_iter();
+        let (lower_bound, _) = iterator.size_hint();
+        self.reserve(lower_bound);
+        for s in iterator {
+            self.push_str(s)
+        }
+    }
+}
+
+impl<'a> Add<&'a AsciiStr> for AsciiString {
+    type Output = AsciiString;
+
+    #[inline]
+    fn add(mut self, other: &AsciiStr) -> AsciiString {
+        self.push_str(other);
+        self
+    }
+}
+
+impl<T> Index<T> for AsciiString where AsciiStr: Index<T> {
+    type Output = <AsciiStr as Index<T>>::Output;
+
+    #[inline]
+    fn index(&self, index: T) -> &<AsciiStr as Index<T>>::Output {
+        &(**self)[index]
+    }
+}
+
+impl<T> IndexMut<T> for AsciiString where AsciiStr: IndexMut<T> {
+    #[inline]
+    fn index_mut(&mut self, index: T) -> &mut <AsciiStr as Index<T>>::Output {
+        &mut (**self)[index]
+    }
+}
+
+
+/// Convert vectors into `AsciiString`.
+pub trait IntoAsciiString : Sized {
+    /// Convert to `AsciiString` without checking for non-ASCII characters.
+    unsafe fn into_ascii_string_unchecked(self) -> AsciiString;
+    /// Convert to `AsciiString`.
+    fn into_ascii_string(self) -> Result<AsciiString,Self>;
+}
+
+impl IntoAsciiString for AsciiString {
+    unsafe fn into_ascii_string_unchecked(self) -> AsciiString {
+        self
+    }
+    fn into_ascii_string(self) -> Result<AsciiString,Self> {
+        Ok(self)
+    }
+}
+
+impl IntoAsciiString for Vec<AsciiChar> {
+    unsafe fn into_ascii_string_unchecked(self) -> AsciiString {
+        AsciiString::from(self)
+    }
+    fn into_ascii_string(self) -> Result<AsciiString,Self> {
+        Ok(AsciiString::from(self))
+    }
+}
+
+impl IntoAsciiString for Vec<u8> {
+    unsafe fn into_ascii_string_unchecked(self) -> AsciiString {
+        AsciiString::from_ascii_unchecked(self)
+    }
+    fn into_ascii_string(self) -> Result<AsciiString,Self> {
+        AsciiString::from_ascii(self)
+    }
+}
+
+impl IntoAsciiString for String {
+    unsafe fn into_ascii_string_unchecked(self) -> AsciiString {
+        self.into_bytes().into_ascii_string_unchecked()
+    }
+    fn into_ascii_string(self) -> Result<AsciiString,Self> {
+        AsciiString::from_ascii(self)
+    }
+}
+
+
+#[cfg(test)]
+mod tests {
+    use std::str::FromStr;
+    use AsciiChar;
+    use super::{AsciiString, IntoAsciiString};
+
+    #[test]
+    fn into_string() {
+        let v = AsciiString::from_ascii(&[40_u8, 32, 59][..]).unwrap();
+        assert_eq!(Into::<String>::into(v), "( ;".to_string());
+    }
+
+    #[test]
+    fn into_bytes() {
+        let v = AsciiString::from_ascii(&[40_u8, 32, 59][..]).unwrap();
+        assert_eq!(Into::<Vec<u8>>::into(v), vec![40_u8, 32, 59])
+    }
+
+    #[test]
+    fn from_ascii_vec() {
+        let vec = vec![AsciiChar::from('A').unwrap(), AsciiChar::from('B').unwrap()];
+        assert_eq!(AsciiString::from(vec), AsciiString::from_str("AB").unwrap());
+    }
+
+    #[test]
+    fn fmt_display_ascii_string() {
+        let s = "abc".to_string().into_ascii_string().unwrap();
+        assert_eq!(format!("{}", s), "abc".to_string());
+    }
+
+    #[test]
+    fn fmt_debug_ascii_string() {
+        let s = "abc".to_string().into_ascii_string().unwrap();
+        assert_eq!(format!("{:?}", s), "\"abc\"".to_string());
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/ascii/src/lib.rs
@@ -0,0 +1,42 @@
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// 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.
+
+//! A library that provides ASCII-only string and character types, equivalent to the `char`, `str` and
+//! `String` types in the standard library.
+//!
+//! # Using ascii without libstd
+//!
+//! Most of `AsciiChar` and `AsciiStr` can be used without `std` by enabling the feature `no_std`. The
+//! owned string type `AsciiString` and the conversion trait `IntoAsciiString` as well as all methods
+//! referring to these types aren't available without `std`.
+//!
+//! # Requirements
+//!
+//! The `ascii` library requires rustc 1.9.0 or greater, due to the [stabilization of
+//! `AsciiExt`](https://github.com/rust-lang/rust/pull/32804). Using the `no_std` feature lowers
+//! this requirement to rustc 1.6.0 or greater.
+//!
+//! # History
+//!
+//! This packages included the Ascii types that were removed from the Rust standard library by the
+//! 2014-12 [reform of the `std::ascii` module](https://github.com/rust-lang/rfcs/pull/486). The
+//! API changed significantly since then.
+
+#![cfg_attr(feature = "no_std", no_std)]
+
+mod ascii_char;
+mod ascii_str;
+#[cfg(not(feature = "no_std"))]
+mod ascii_string;
+
+pub use ascii_char::{AsciiChar, ToAsciiChar, ToAsciiCharError};
+pub use ascii_str::{AsciiStr, AsAsciiStr, AsMutAsciiStr, AsAsciiStrError};
+#[cfg(not(feature = "no_std"))]
+pub use ascii_string::{AsciiString, IntoAsciiString};
new file mode 100644
--- /dev/null
+++ b/third_party/rust/ascii/tests.rs
@@ -0,0 +1,106 @@
+extern crate ascii;
+
+use ascii::{AsciiChar, AsciiStr, AsAsciiStr};
+#[cfg(not(feature = "no_std"))]
+use ascii::{AsciiString, IntoAsciiString};
+
+#[test]
+#[cfg(not(feature = "no_std"))]
+fn ascii_vec() {
+    let test = b"( ;";
+    let a = AsciiStr::from_ascii(test).unwrap();
+    assert_eq!(test.as_ascii_str(), Ok(a));
+    assert_eq!("( ;".as_ascii_str(), Ok(a));
+    let v = test.to_vec();
+    assert_eq!(v.as_ascii_str(), Ok(a));
+    assert_eq!("( ;".to_string().as_ascii_str(), Ok(a));
+}
+
+#[test]
+fn to_ascii() {
+    assert!("zoä华".as_ascii_str().is_err());
+    assert!([127_u8, 128, 255].as_ascii_str().is_err());
+
+    let arr = [AsciiChar::ParenOpen, AsciiChar::Space, AsciiChar::Semicolon];
+    let a: &AsciiStr = (&arr[..]).into();
+    assert_eq!(b"( ;".as_ascii_str(), Ok(a));
+    assert_eq!("( ;".as_ascii_str(), Ok(a));
+}
+
+#[test]
+#[cfg(not(feature = "no_std"))]
+fn into_ascii() {
+    assert_eq!("zoä华".to_string().into_ascii_string(), Err("zoä华".to_string()));
+    assert_eq!(vec![127_u8, 128, 255].into_ascii_string(), Err(vec![127_u8, 128, 255]));
+
+    let arr = [AsciiChar::ParenOpen, AsciiChar::Space, AsciiChar::Semicolon];
+    let v = AsciiString::from(arr.to_vec());
+    assert_eq!(b"( ;".to_vec().into_ascii_string(), Ok(v.clone()));
+    assert_eq!("( ;".to_string().into_ascii_string(), Ok(v));
+}
+
+#[test]
+#[cfg(not(feature = "no_std"))]
+fn compare_ascii_string_ascii_str() {
+    let v = b"abc";
+    let ascii_string = AsciiString::from_ascii(&v[..]).unwrap();
+    let ascii_str = AsciiStr::from_ascii(v).unwrap();
+    assert!(ascii_string == ascii_str);
+    assert!(ascii_str == ascii_string);
+}
+
+#[test]
+#[cfg(not(feature = "no_std"))]
+fn compare_ascii_string_string() {
+    let v = b"abc";
+    let string = String::from_utf8(v.to_vec()).unwrap();
+    let ascii_string = AsciiString::from_ascii(&v[..]).unwrap();
+    assert!(string == ascii_string);
+    assert!(ascii_string == string);
+}
+
+#[test]
+#[cfg(not(feature = "no_std"))]
+fn compare_ascii_str_string() {
+    let v = b"abc";
+    let string = String::from_utf8(v.to_vec()).unwrap();
+    let ascii_str = AsciiStr::from_ascii(&v[..]).unwrap();
+    assert!(string == ascii_str);
+    assert!(ascii_str == string);
+}
+
+#[test]
+#[cfg(not(feature = "no_std"))]
+fn compare_ascii_string_str() {
+    let v = b"abc";
+    let sstr = ::std::str::from_utf8(v).unwrap();
+    let ascii_string = AsciiString::from_ascii(&v[..]).unwrap();
+    assert!(sstr == ascii_string);
+    assert!(ascii_string == sstr);
+}
+
+#[test]
+fn compare_ascii_str_str() {
+    let v = b"abc";
+    let sstr = ::std::str::from_utf8(v).unwrap();
+    let ascii_str = AsciiStr::from_ascii(v).unwrap();
+    assert!(sstr == ascii_str);
+    assert!(ascii_str == sstr);
+}
+
+#[test]
+fn compare_ascii_str_slice() {
+    let b = b"abc".as_ascii_str().unwrap();
+    let c = b"ab".as_ascii_str().unwrap();
+    assert_eq!(&b[..2], &c[..]);
+    assert_eq!(c[1].as_char(), 'b');
+}
+
+#[test]
+#[cfg(not(feature = "no_std"))]
+fn compare_ascii_string_slice() {
+    let b = AsciiString::from_ascii("abc").unwrap();
+    let c = AsciiString::from_ascii("ab").unwrap();
+    assert_eq!(&b[..2], &c[..]);
+    assert_eq!(c[1].as_char(), 'b');
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cesu8/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"c1e953ee360e77de57f7b02f1b7880bd6a3dc22d1a69e953c2ac2c52cc52d247",".travis.yml":"54b629f18a31fc4dfa0baec0177acc8627e5420a5e0c223af39d2a57ddafd7fb","COPYRIGHT-RUST.txt":"5ca77347e58205d3b543c04a9c5bdd11d20a9f3108a7b246640edffa999b5f35","Cargo.toml":"78e66dd24c12e0ac858e7524cdd7d51d1eee753c1e9c32e5b915dc9f1d767870","README.md":"4fcc5d9b5db444ad3c33c79aebe18de4fa6351982646da0b78830fbad67f9e8f","src/lib.rs":"402f647c80ccaa86f43a5571cc081aa66777d2a538ce9d9dc52a7e588ef137c9","src/unicode.rs":"66cc902b4dd323cef600890b6cd99186592919b03e55e3535adf0c5b95a8ce45"},"package":"6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"}
\ No newline at end of file
new file mode 100644
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cesu8/.gitignore
@@ -0,0 +1,2 @@
+/target
+/Cargo.lock
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cesu8/.travis.yml
@@ -0,0 +1,20 @@
+language: rust
+sudo: required
+rust:
+- nightly
+before_script:
+- |
+  pip install 'travis-cargo<0.2' --user &&
+  export PATH=$HOME/.local/bin:$PATH
+script:
+- |
+  travis-cargo build &&
+  travis-cargo test &&
+  travis-cargo bench &&
+  travis-cargo doc
+after_success:
+- travis-cargo --only nightly doc-upload
+- travis-cargo coveralls
+env:
+  global:
+    secure: FcTaelK4lX/mDGAjhoXSXcWF9hqYdhF5KTMgPrW0ZKMHow7axbdtQ3Hiz4UewmCs8TDhi42LIvttbg+13USwytKNqU6ZBiyYdmf/T/BapX09v07dBuo3tsmdwNtNr2iazp1U5ibRF2P8yBOjex1WEt5QfiJx5ofApPx/d4lYKF8=
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cesu8/COPYRIGHT-RUST.txt
@@ -0,0 +1,422 @@
+Short version for non-lawyers:
+
+The Rust Project is dual-licensed under Apache 2.0 and MIT
+terms.
+
+
+Longer version:
+
+The Rust Project is copyright 2014, The Rust Project
+Developers (given in the file AUTHORS.txt).
+
+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. All files in the project carrying such
+notice may not be copied, modified, or distributed except
+according to those terms.
+
+
+The Rust Project includes packages written by third parties.
+The following third party packages are included, and carry
+their own copyright notices and license terms:
+
+* Two header files that are part of the Valgrind
+  package. These files are found at src/rt/vg/valgrind.h and
+  src/rt/vg/memcheck.h, within this distribution. These files
+  are redistributed under the following terms, as noted in
+  them:
+
+  for src/rt/vg/valgrind.h:
+
+    This file is part of Valgrind, a dynamic binary
+    instrumentation framework.
+
+    Copyright (C) 2000-2010 Julian Seward.  All rights
+    reserved.
+
+    Redistribution and use in source and binary forms, with
+    or without modification, are permitted provided that the
+    following conditions are met:
+
+    1. Redistributions of source code must retain the above
+       copyright notice, this list of conditions and the
+       following disclaimer.
+
+    2. The origin of this software must not be
+       misrepresented; you must not claim that you wrote the
+       original software.  If you use this software in a
+       product, an acknowledgment in the product
+       documentation would be appreciated but is not
+       required.
+
+    3. Altered source versions must be plainly marked as
+       such, and must not be misrepresented as being the
+       original software.
+
+    4. The name of the author may not be used to endorse or
+       promote products derived from this software without
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+    AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+    NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+    USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+    USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+    OF SUCH DAMAGE.
+
+  for src/rt/vg/memcheck.h:
+
+    This file is part of MemCheck, a heavyweight Valgrind
+    tool for detecting memory errors.
+
+    Copyright (C) 2000-2010 Julian Seward.  All rights
+    reserved.
+
+    Redistribution and use in source and binary forms, with
+    or without modification, are permitted provided that the
+    following conditions are met:
+
+    1. Redistributions of source code must retain the above
+       copyright notice, this list of conditions and the
+       following disclaimer.
+
+    2. The origin of this software must not be
+       misrepresented; you must not claim that you wrote the
+       original software.  If you use this software in a
+       product, an acknowledgment in the product
+       documentation would be appreciated but is not
+       required.
+
+    3. Altered source versions must be plainly marked as
+       such, and must not be misrepresented as being the
+       original software.
+
+    4. The name of the author may not be used to endorse or
+       promote products derived from this software without
+       specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+    AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+    NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+    USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+    USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+    OF SUCH DAMAGE.
+
+* The auxiliary file src/etc/pkg/modpath.iss contains a
+  library routine compiled, by Inno Setup, into the Windows
+  installer binary. This file is licensed under the LGPL,
+  version 3, but, in our legal interpretation, this does not
+  affect the aggregate "collected work" license of the Rust
+  distribution (MIT/ASL2) nor any other components of it. We
+  believe that the terms governing distribution of the
+  binary Windows installer built from modpath.iss are
+  therefore LGPL, but not the terms governing distribution
+  of any of the files installed by such an installer (such
+  as the Rust compiler or runtime libraries themselves).
+
+* The src/rt/miniz.c file, carrying an implementation of
+  RFC1950/RFC1951 DEFLATE, by Rich Geldreich
+  <richgel99@gmail.com>. All uses of this file are
+  permitted by the embedded "unlicense" notice
+  (effectively: public domain with warranty disclaimer).
+
+* LLVM. Code for this package is found in src/llvm.
+
+    Copyright (c) 2003-2013 University of Illinois at
+    Urbana-Champaign.  All rights reserved.
+
+    Developed by:
+
+        LLVM Team
+
+        University of Illinois at Urbana-Champaign
+
+        http://llvm.org
+
+    Permission is hereby granted, free of charge, to any
+    person obtaining a copy of this software and associated
+    documentation files (the "Software"), to deal with the
+    Software without restriction, including without
+    limitation the rights to use, copy, modify, merge,
+    publish, distribute, sublicense, and/or sell copies of
+    the Software, and to permit persons to whom the Software
+    is furnished to do so, subject to the following
+    conditions:
+
+        * Redistributions of source code must retain the
+          above copyright notice, this list of conditions
+          and the following disclaimers.
+
+        * Redistributions in binary form must reproduce the
+          above copyright notice, this list of conditions
+          and the following disclaimers in the documentation
+          and/or other materials provided with the
+          distribution.
+
+        * Neither the names of the LLVM Team, University of
+          Illinois at Urbana-Champaign, nor the names of its
+          contributors may be used to endorse or promote
+          products derived from this Software without
+          specific prior written permission.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+    ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+    TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+    PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT
+    SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE
+    FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+    ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+    OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+    OTHER DEALINGS WITH THE SOFTWARE.
+
+* Additional libraries included in LLVM carry separate
+  BSD-compatible licenses. See src/llvm/LICENSE.txt for
+  details.
+
+* compiler-rt, in src/compiler-rt is dual licensed under
+  LLVM's license and MIT:
+
+    Copyright (c) 2009-2014 by the contributors listed in
+    CREDITS.TXT
+
+    All rights reserved.
+
+    Developed by:
+
+        LLVM Team
+
+        University of Illinois at Urbana-Champaign
+
+        http://llvm.org
+
+    Permission is hereby granted, free of charge, to any
+    person obtaining a copy of this software and associated
+    documentation files (the "Software"), to deal with the
+    Software without restriction, including without
+    limitation the rights to use, copy, modify, merge,
+    publish, distribute, sublicense, and/or sell copies of
+    the Software, and to permit persons to whom the Software
+    is furnished to do so, subject to the following
+    conditions:
+
+        * Redistributions of source code must retain the
+          above copyright notice, this list of conditions
+          and the following disclaimers.
+
+        * Redistributions in binary form must reproduce the
+          above copyright notice, this list of conditions
+          and the following disclaimers in the documentation
+          and/or other materials provided with the
+          distribution.
+
+        * Neither the names of the LLVM Team, University of
+          Illinois at Urbana-Champaign, nor the names of its
+          contributors may be used to endorse or promote
+          products derived from this Software without
+          specific prior written permission.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+    ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+    TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+    PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT
+    SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE
+    FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+    ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+    OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+    OTHER DEALINGS WITH THE SOFTWARE.
+
+    ========================================================
+
+    Copyright (c) 2009-2014 by the contributors listed in
+    CREDITS.TXT
+
+    Permission is hereby granted, free of charge, to any
+    person obtaining a copy of this software and associated
+    documentation files (the "Software"), to deal in the
+    Software without restriction, including without
+    limitation the rights to use, copy, modify, merge,
+    publish, distribute, sublicense, and/or sell copies of
+    the Software, and to permit persons to whom the Software
+    is furnished to do so, subject to the following
+    conditions:
+
+    The above copyright notice and this permission notice
+    shall be included in all copies or substantial portions
+    of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+    ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+    TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+    PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+    SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+    OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+    IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+    DEALINGS IN THE SOFTWARE.
+
+* Portions of the FFI code for interacting with the native ABI
+  is derived from the Clay programming language, which carries
+  the following license.
+
+    Copyright (C) 2008-2010 Tachyon Technologies.
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with
+    or without modification, are permitted provided that the
+    following conditions are met:
+
+    1. Redistributions of source code must retain the above
+       copyright notice, this list of conditions and the
+       following disclaimer.
+
+    2. Redistributions in binary form must reproduce the
+       above copyright notice, this list of conditions and
+       the following disclaimer in the documentation and/or
+       other materials provided with the distribution.
+
+    THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR
+    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+    DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+    USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+    USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+    OF SUCH DAMAGE.
+
+* Hoedown, the markdown parser, under src/rt/hoedown, is
+  licensed as follows.
+
+    Copyright (c) 2008, Natacha Porté
+    Copyright (c) 2011, Vicent Martí
+    Copyright (c) 2013, Devin Torres and the Hoedown authors
+
+    Permission to use, copy, modify, and distribute this
+    software for any purpose with or without fee is hereby
+    granted, provided that the above copyright notice and
+    this permission notice appear in all copies.
+
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR
+    DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+    INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+    FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+    SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR
+    ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
+    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+    OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+    CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+* libbacktrace, under src/libbacktrace:
+
+    Copyright (C) 2012-2014 Free Software Foundation, Inc.
+    Written by Ian Lance Taylor, Google.
+
+    Redistribution and use in source and binary forms, with
+    or without modification, are permitted provided that the
+    following conditions are met:
+
+        (1) Redistributions of source code must retain the
+        above copyright notice, this list of conditions and
+        the following disclaimer.
+
+        (2) Redistributions in binary form must reproduce
+        the above copyright notice, this list of conditions
+        and the following disclaimer in the documentation
+        and/or other materials provided with the
+        distribution.
+
+        (3) The name of the author may not be used to
+        endorse or promote products derived from this
+        software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+    AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+    NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+    USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+    USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+    OF SUCH DAMAGE.  */
+
+* jemalloc, under src/jemalloc:
+
+    Copyright (C) 2002-2014 Jason Evans
+    <jasone@canonware.com>. All rights reserved.
+    Copyright (C) 2007-2012 Mozilla Foundation.
+    All rights reserved.
+    Copyright (C) 2009-2014 Facebook, Inc.
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright notice(s),
+       this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright notice(s),
+       this list of conditions and the following disclaimer in the documentation
+       and/or other materials provided with the distribution.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S)
+    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S)
+    BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+    IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+    USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+    OF SUCH DAMAGE.
+
+* Additional copyright may be retained by contributors other
+  than Mozilla, the Rust Project Developers, or the parties
+  enumerated in this file. Such copyright can be determined
+  on a case-by-case basis by examining the author of each
+  portion of a file in the revision-control commit records
+  of the project, or by consulting representative comments
+  claiming copyright ownership for a file.
+
+  For example, the text:
+
+      "Copyright (c) 2011 Google Inc."
+
+  appears in some files, and these files thereby denote
+  that their author and copyright-holder is Google Inc.
+
+  In all such cases, the absence of explicit licensing text
+  indicates that the contributor chose to license their work
+  for distribution under identical terms to those Mozilla
+  has chosen for the collective work, enumerated at the top
+  of this file. The only difference is the retention of
+  copyright itself, held by the contributor.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cesu8/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+
+name = "cesu8"
+version = "1.1.0"
+authors = ["Eric Kidd <git@randomhacks.net>"]
+
+description = "Convert to and from CESU-8 encoding (similar to UTF-8)"
+license = "Apache-2.0/MIT"
+readme = "README.md"
+
+repository = "https://github.com/emk/cesu8-rs"
+documentation = "http://emk.github.io/cesu8-rs/cesu8/index.html"
+
+[features]
+# Allow access to unstable features when being built with a nightly compiler,
+# to keep travis-cargo happy and enable access to benchmarks if we want them.
+unstable = []
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cesu8/README.md
@@ -0,0 +1,33 @@
+# CESU-8 encoder/decoder for Rust
+
+[![Build Status](https://travis-ci.org/emk/cesu8-rs.svg)](https://travis-ci.org/emk/cesu8-rs) [![Latest version](https://img.shields.io/crates/v/cesu8.svg)](https://crates.io/crates/cesu8) [![License](https://img.shields.io/crates/l/cesu8.svg)](https://crates.io/crates/cesu8)
+
+[Documentation][apidoc].
+
+[apidoc]: http://emk.github.io/cesu8-rs/cesu8/index.html
+
+Convert between ordinary UTF-8 and [CESU-8][] encodings.
+
+CESU-8 encodes characters outside the Basic Multilingual Plane as two
+UTF-16 surrogate chacaters, which are then further re-encoded as invalid,
+3-byte UTF-8 characters.  This means that 4-byte UTF-8 sequences become
+6-byte CESU-8 sequences.
+
+**Note that CESU-8 is only intended for internal use within tightly-coupled
+systems, and not for data interchange.**
+
+This encoding is sometimes needed when working with Java, Oracle or MySQL,
+and when trying to store emoji, hieroglyphs, or other characters on the
+Supplementary Multilingual Plane or the Supplementary Ideographic Plane.
+
+[CESU-8]: http://www.unicode.org/reports/tr26/tr26-2.html
+
+## License
+
+Some of this code is adapted from Rust's [`src/libcore/str.rs` file][str.rs].
+This code is covered by LICENSE-RUST.txt and copyright by The Rust Project
+Developers and individual Rust contributors, as described in that file.
+
+The new code in this project is distributed under the same terms.
+
+[str.rs]: https://github.com/rust-lang/rust/blob/master/src/libcore/str.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cesu8/src/lib.rs
@@ -0,0 +1,453 @@
+// Copyright 2012-2014 The Rust Project Developers and Eric Kidd.  See the
+// COPYRIGHT-RUST.txt file at the top-level directory of this distribution.
+//
+// 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.
+
+
+//! A simple library implementing the [CESU-8 compatibility encoding
+//! scheme](http://www.unicode.org/reports/tr26/tr26-2.html).  This is a
+//! non-standard variant of UTF-8 that is used internally by some systems
+//! that need to represent UTF-16 data as 8-bit characters.  Yes, this is
+//! ugly.
+//!
+//! Use of this encoding is discouraged by the Unicode Consortium.  It's OK
+//! for working with existing internal APIs, but it should not be used for
+//! transmitting or storing data.
+//!
+//! ```
+//! use std::borrow::Cow;
+//! use cesu8::{from_cesu8, to_cesu8};
+//!
+//! // 16-bit Unicode characters are the same in UTF-8 and CESU-8.
+//! assert_eq!(Cow::Borrowed("aé日".as_bytes()),
+//!            to_cesu8("aé日"));
+//! assert_eq!(Cow::Borrowed("aé日"),
+//!            from_cesu8("aé日".as_bytes()).unwrap());
+//!
+//! // This string is CESU-8 data containing a 6-byte surrogate pair,
+//! // which decodes to a 4-byte UTF-8 string.
+//! let data = &[0xED, 0xA0, 0x81, 0xED, 0xB0, 0x81];
+//! assert_eq!(Cow::Borrowed("\u{10401}"),
+//!            from_cesu8(data).unwrap());
+//! ```
+//!
+//! ### A note about security
+//!
+//! As a general rule, this library is intended to fail on malformed or
+//! unexpected input.  CESU-8 is supposed to be an internal-only format,
+//! and if we're seeing malformed data, we assume that it's either a bug in
+//! somebody's code, or an attacker is trying to improperly encode data to
+//! evade security checks.
+//!
+//! If you have a use case for lossy conversion to UTF-8, or conversion
+//! from mixed UTF-8/CESU-8 data, please feel free to submit a pull request
+//! for `from_cesu8_lossy_permissive` with appropriate behavior.
+//!
+//! ### Java and U+0000, and other variants
+//!
+//! Java uses the CESU-8 encoding as described above, but with one
+//! difference: The null character U+0000 is represented as an overlong
+//! UTF-8 sequence `C0 80`. This is supported by the `from_java_cesu8` and
+//! `to_java_cesu8` methods.
+//!
+//! ### Surrogate pairs and UTF-8
+//!
+//! The UTF-16 encoding uses "surrogate pairs" to represent Unicode code
+//! points in the range from U+10000 to U+10FFFF.  These are 16-bit numbers
+//! in the range 0xD800 to 0xDFFF.
+//!
+//! * 0xD800 to 0xDBFF: First half of surrogate pair.  When encoded as
+//!   CESU-8, these become **1110**1101 **10**100000 **10**000000 to
+//!   **1110**1101 **10**101111 **10**111111.
+//!
+//! * 0xDC00 to 0xDFFF: Second half of surrogate pair.  These become
+//!   **1110**1101 **10**110000 **10**000000 to
+//!   **1110**1101 **10**111111 **10**111111.
+//!
+//! Wikipedia [explains](http://en.wikipedia.org/wiki/UTF-16) the
+//! code point to UTF-16 conversion process:
+//!
+//! > Consider the encoding of U+10437 (𐐷):
+//! >
+//! > * Subtract 0x10000 from 0x10437. The result is 0x00437, 0000 0000 0100
+//! >   0011 0111.
+//! > * Split this into the high 10-bit value and the low 10-bit value:
+//! >   0000000001 and 0000110111.
+//! > * Add 0xD800 to the high value to form the high surrogate: 0xD800 +
+//! >   0x0001 = 0xD801.
+//! > * Add 0xDC00 to the low value to form the low surrogate: 0xDC00 +
+//! >   0x0037 = 0xDC37.
+
+#![warn(missing_docs)]
+
+
+use std::borrow::Cow;
+use std::error::Error;
+use std::fmt;
+use std::result::Result;
+use std::slice;
+use std::str::{from_utf8, from_utf8_unchecked};
+use unicode::utf8_char_width;
+
+mod unicode;
+
+/// Mask of the value bits of a continuation byte.
+const CONT_MASK: u8 = 0b0011_1111u8;
+/// Value of the tag bits (tag mask is !CONT_MASK) of a continuation byte.
+const TAG_CONT_U8: u8 = 0b1000_0000u8;
+
+/// The CESU-8 data could not be decoded as valid UTF-8 data.
+#[derive(Clone, Copy, Debug)]
+pub struct Cesu8DecodingError;
+
+impl Error for Cesu8DecodingError {
+    fn description(&self) -> &str { "decoding error" }
+    fn cause(&self) -> Option<&Error> { None }
+}
+
+impl fmt::Display for Cesu8DecodingError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "could not convert CESU-8 data to UTF-8")
+    }
+}
+
+/// Which variant of the encoding are we working with?
+#[derive(PartialEq, Eq)]
+enum Variant {
+    /// Regular CESU-8, with '\0' represented by itself.
+    Standard,
+    /// This is technically Java's "Modified UTF-8", which is supposedly
+    /// like CESU-8, except that it UTF-8 encodes the '\0' byte.  I'm sure
+    /// it seemed like a good idea at the time.
+    Java,
+}
+
+/// Convert CESU-8 data to a Rust string, re-encoding only if necessary.
+/// Returns an error if the data cannot be represented as valid UTF-8.
+///
+/// ```
+/// use std::borrow::Cow;
+/// use cesu8::from_cesu8;
+///
+/// // This string is valid as UTF-8 or CESU-8, so it doesn't change,
+/// // and we can convert it without allocating memory.
+/// assert_eq!(Cow::Borrowed("aé日"),
+///            from_cesu8("aé日".as_bytes()).unwrap());
+///
+/// // This string is CESU-8 data containing a 6-byte surrogate pair,
+/// // which becomes a 4-byte UTF-8 string.
+/// let data = &[0xED, 0xA0, 0x81, 0xED, 0xB0, 0x81];
+/// assert_eq!(Cow::Borrowed("\u{10401}"),
+///            from_cesu8(data).unwrap());
+/// ```
+pub fn from_cesu8(bytes: &[u8]) -> Result<Cow<str>, Cesu8DecodingError> {
+    from_cesu8_internal(bytes, Variant::Standard)
+}
+
+/// Convert Java's modified UTF-8 data to a Rust string, re-encoding only if
+/// necessary. Returns an error if the data cannot be represented as valid
+/// UTF-8.
+///
+/// ```
+/// use std::borrow::Cow;
+/// use cesu8::from_java_cesu8;
+///
+/// // This string is valid as UTF-8 or modified UTF-8, so it doesn't change,
+/// // and we can convert it without allocating memory.
+/// assert_eq!(Cow::Borrowed("aé日"),
+///            from_java_cesu8("aé日".as_bytes()).unwrap());
+///
+/// // This string is modified UTF-8 data containing a 6-byte surrogate pair,
+/// // which becomes a 4-byte UTF-8 string.
+/// let data = &[0xED, 0xA0, 0x81, 0xED, 0xB0, 0x81];
+/// assert_eq!(Cow::Borrowed("\u{10401}"),
+///            from_java_cesu8(data).unwrap());
+///
+/// // This string is modified UTF-8 data containing null code-points.
+/// let data = &[0xC0, 0x80, 0xC0, 0x80];
+/// assert_eq!(Cow::Borrowed("\0\0"),
+///            from_java_cesu8(data).unwrap());
+/// ```
+pub fn from_java_cesu8(bytes: &[u8]) -> Result<Cow<str>, Cesu8DecodingError> {
+    from_cesu8_internal(bytes, Variant::Java)
+}
+
+/// Do the actual work of decoding.
+fn from_cesu8_internal(bytes: &[u8], variant: Variant) ->
+    Result<Cow<str>, Cesu8DecodingError>
+{
+    match from_utf8(bytes) {
+        Ok(str) => Ok(Cow::Borrowed(str)),
+        _ => {
+            let mut decoded = Vec::with_capacity(bytes.len());
+            if decode_from_iter(&mut decoded, &mut bytes.iter(), variant) {
+                // Keep this assertion in debug mode only.  It's important
+                // that this assertion is true, because Rust assumes that
+                // all UTF-8 strings are valid.
+                debug_assert!(from_utf8(&decoded[..]).is_ok());
+                Ok(Cow::Owned(unsafe { String::from_utf8_unchecked(decoded) }))
+            } else {
+                Err(Cesu8DecodingError)
+            }
+        }
+    }
+}
+
+#[test]
+fn test_from_cesu8() {
+    // The surrogate-encoded character below is from the ICU library's
+    // icu/source/test/testdata/conversion.txt test case.
+    let data = &[0x4D, 0xE6, 0x97, 0xA5, 0xED, 0xA0, 0x81, 0xED, 0xB0, 0x81, 0x7F];
+    assert_eq!(Cow::Borrowed("M日\u{10401}\u{7F}"),
+               from_cesu8(data).unwrap());
+
+    // We used to have test data from the CESU-8 specification, but when we
+    // worked it through manually, we got the wrong answer:
+    //
+    // Input: [0xED, 0xAE, 0x80, 0xED, 0xB0, 0x80]
+    // Binary: 11101101 10101110 10000000 11101101 10110000 10000000
+    //
+    // 0b1101_101110_000000 -> 0xDB80
+    // 0b1101_110000_000000 -> 0xDC00
+    //
+    // ((0xDB80 - 0xD800) << 10) | (0xDC00 - 0xDC00) -> 0xE0000
+    // 0x10000 + 0xE0000 -> 0xF0000
+    //
+    // The spec claims that we are supposed to get 0x10000, not 0xF0000.
+    // Since I can't reconcile this example data with the text of the
+    // specification, I decided to use a test character from ICU instead.
+}
+
+// Our internal decoder, based on Rust's is_utf8 implementation.
+fn decode_from_iter(
+    decoded: &mut Vec<u8>, iter: &mut slice::Iter<u8>, variant: Variant)
+    -> bool
+{
+    macro_rules! err {
+        () => { return false }
+    }
+    macro_rules! next {
+        () => {
+            match iter.next() {
+                Some(a) => *a,
+                // We needed data, but there was none: error!
+                None => err!()
+            }
+        }
+    }
+    macro_rules! next_cont {
+        () => {
+            {
+                let byte = next!();
+                if (byte) & !CONT_MASK == TAG_CONT_U8 { byte } else { err!() }
+            }
+        }
+    }
+
+    loop {
+        let first = match iter.next() {
+            Some(&b) => b,
+            // We're at the end of the iterator and a codepoint boundary at
+            // the same time, so this string is valid.
+            None => return true
+        };
+
+        if variant == Variant::Java && first == 0 {
+            // Java's modified UTF-8 should never contain \0 directly.
+            err!();
+        } else if first < 128 {
+            // Pass ASCII through directly.
+            decoded.push(first);
+        } else if first == 0xc0 && variant == Variant::Java {
+            match next!() {
+                0x80 => decoded.push(0),
+                _ => err!(),
+            }
+        } else {
+            let w = utf8_char_width(first);
+            let second = next_cont!();
+            match w {
+                // Two-byte sequences can be used directly.
+                2 => { decoded.extend([first, second].iter().cloned()); }
+                3 => {
+                    let third = next_cont!();
+                    match (first, second) {
+                        // These are valid UTF-8, so pass them through.
+                        (0xE0         , 0xA0 ... 0xBF) |
+                        (0xE1 ... 0xEC, 0x80 ... 0xBF) |
+                        (0xED         , 0x80 ... 0x9F) |
+                        (0xEE ... 0xEF, 0x80 ... 0xBF) => {
+                            decoded.extend([first, second, third].iter()
+                                               .cloned())
+                        }
+                        // First half a surrogate pair, so decode.
+                        (0xED         , 0xA0 ... 0xAF) => {
+                            if next!() != 0xED { err!() }
+                            let fifth = next_cont!();
+                            if fifth < 0xB0 || 0xBF < fifth { err!() }
+                            let sixth = next_cont!();
+                            let s = dec_surrogates(second, third, fifth, sixth);
+                            decoded.extend(s.iter().cloned());
+                        }
+                        _ => err!()
+                    }
+                }
+                _ => err!()
+            }
+        }
+    }
+}
+
+/// Convert the two trailing bytes from a CESU-8 surrogate to a regular
+/// surrogate value.
+fn dec_surrogate(second: u8, third: u8) -> u32 {
+    0xD000u32 | ((second & CONT_MASK) as u32) << 6 | (third & CONT_MASK) as u32
+}
+
+/// Convert the bytes from a CESU-8 surrogate pair into a valid UTF-8
+/// sequence.  Assumes input is valid.
+fn dec_surrogates(second: u8, third: u8, fifth: u8, sixth: u8) -> [u8; 4] {
+    // Convert to a 32-bit code point.
+    let s1 = dec_surrogate(second, third);
+    let s2 = dec_surrogate(fifth, sixth);
+    let c = 0x10000 + (((s1 - 0xD800) << 10) | (s2 - 0xDC00));
+    //println!("{:0>8b} {:0>8b} {:0>8b} -> {:0>16b}", 0xEDu8, second, third, s1);
+    //println!("{:0>8b} {:0>8b} {:0>8b} -> {:0>16b}", 0xEDu8, fifth, sixth, s2);
+    //println!("-> {:0>32b}", c);
+    assert!(0x010000 <= c && c <= 0x10FFFF);
+
+    // Convert to UTF-8.
+    // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+    [0b1111_0000u8 | ((c & 0b1_1100_0000_0000_0000_0000) >> 18) as u8,
+     TAG_CONT_U8   | ((c & 0b0_0011_1111_0000_0000_0000) >> 12) as u8,
+     TAG_CONT_U8   | ((c & 0b0_0000_0000_1111_1100_0000) >>  6) as u8,
+     TAG_CONT_U8   | ((c & 0b0_0000_0000_0000_0011_1111)      ) as u8]
+}
+
+/// Convert a Rust `&str` to CESU-8 bytes.
+///
+/// ```
+/// use std::borrow::Cow;
+/// use cesu8::to_cesu8;
+///
+/// // This string is valid as UTF-8 or CESU-8, so it doesn't change,
+/// // and we can convert it without allocating memory.
+/// assert_eq!(Cow::Borrowed("aé日".as_bytes()), to_cesu8("aé日"));
+///
+/// // This string is a 4-byte UTF-8 string, which becomes a 6-byte CESU-8
+/// // vector.
+/// assert_eq!(Cow::Borrowed(&[0xED, 0xA0, 0x81, 0xED, 0xB0, 0x81]),
+///            to_cesu8("\u{10401}"));
+/// ```
+pub fn to_cesu8(text: &str) -> Cow<[u8]> {
+    if is_valid_cesu8(text) {
+        Cow::Borrowed(text.as_bytes())
+    } else {
+        Cow::Owned(to_cesu8_internal(text, Variant::Standard))
+    }
+}
+
+/// Convert a Rust `&str` to Java's modified UTF-8 bytes.
+///
+/// ```
+/// use std::borrow::Cow;
+/// use cesu8::to_java_cesu8;
+///
+/// // This string is valid as UTF-8 or CESU-8, so it doesn't change,
+/// // and we can convert it without allocating memory.
+/// assert_eq!(Cow::Borrowed("aé日".as_bytes()), to_java_cesu8("aé日"));
+///
+/// // This string is a 4-byte UTF-8 string, which becomes a 6-byte modified
+/// // UTF-8 vector.
+/// assert_eq!(Cow::Borrowed(&[0xED, 0xA0, 0x81, 0xED, 0xB0, 0x81]),
+///            to_java_cesu8("\u{10401}"));
+///
+/// // This string contains null, which becomes 2-byte modified UTF-8 encoding
+/// assert_eq!(Cow::Borrowed(&[0xC0, 0x80, 0xC0, 0x80]),
+///            to_java_cesu8("\0\0"));
+/// ```
+pub fn to_java_cesu8(text: &str) -> Cow<[u8]> {
+    if is_valid_java_cesu8(text) {
+        Cow::Borrowed(text.as_bytes())
+    } else {
+        Cow::Owned(to_cesu8_internal(text, Variant::Java))
+    }
+}
+
+fn to_cesu8_internal(text: &str, variant: Variant) -> Vec<u8> {
+    let bytes = text.as_bytes();
+    let mut encoded = Vec::with_capacity(bytes.len() + bytes.len() >> 2);
+    let mut i = 0;
+    while i < bytes.len() {
+        let b = bytes[i];
+        if variant == Variant::Java && b == 0 {
+            encoded.push(0xc0);
+            encoded.push(0x80);
+            i += 1;
+        } else if b < 128 {
+            // Pass ASCII through quickly.
+            encoded.push(b);
+            i += 1;
+        } else {
+            // Figure out how many bytes we need for this character.
+            let w = utf8_char_width(b);
+            assert!(w <= 4);
+            assert!(i + w <= bytes.len());
+            if w != 4 {
+                // Pass through short UTF-8 sequences unmodified.
+                encoded.extend(bytes[i..i+w].iter().cloned());
+            } else {
+                // Encode 4-byte sequences as 6 bytes.
+                let s = unsafe { from_utf8_unchecked(&bytes[i..i+w]) };
+                let c = s.chars().next().unwrap() as u32 - 0x10000;
+                let mut s: [u16; 2] = [0; 2];
+                s[0] = ((c >> 10) as u16)   | 0xD800;
+                s[1] = ((c & 0x3FF) as u16) | 0xDC00;
+                encoded.extend(enc_surrogate(s[0]).iter().cloned());
+                encoded.extend(enc_surrogate(s[1]).iter().cloned());
+            }
+            i += w;
+        }
+    }
+    encoded
+}
+
+/// Check whether a Rust string contains valid CESU-8 data.
+pub fn is_valid_cesu8(text: &str) -> bool {
+    // We rely on the fact that Rust strings are guaranteed to be valid
+    // UTF-8.
+    for b in text.bytes() {
+        if (b & !CONT_MASK) == TAG_CONT_U8 { continue; }
+        if utf8_char_width(b) > 3 { return false; }
+    }
+    true
+}
+
+/// Check whether a Rust string contains valid Java's modified UTF-8 data.
+pub fn is_valid_java_cesu8(text: &str) -> bool {
+    !text.contains('\0') && is_valid_cesu8(text)
+}
+
+#[test]
+fn test_valid_cesu8() {
+    assert!(is_valid_cesu8("aé日"));
+    assert!(is_valid_java_cesu8("aé日"));
+    assert!(!is_valid_cesu8("\u{10401}"));
+    assert!(!is_valid_java_cesu8("\u{10401}"));
+    assert!(is_valid_cesu8("\0\0"));
+    assert!(!is_valid_java_cesu8("\0\0"));
+}
+
+
+/// Encode a single surrogate as CESU-8.
+fn enc_surrogate(surrogate: u16) -> [u8; 3] {
+    assert!(0xD800 <= surrogate && surrogate <= 0xDFFF);
+    // 1110xxxx 10xxxxxx 10xxxxxx
+    [0b11100000  | ((surrogate & 0b11110000_00000000) >> 12) as u8,
+     TAG_CONT_U8 | ((surrogate & 0b00001111_11000000) >>  6) as u8,
+     TAG_CONT_U8 | ((surrogate & 0b00000000_00111111)      ) as u8]
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cesu8/src/unicode.rs
@@ -0,0 +1,37 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at http://rust-lang.org/COPYRIGHT.
+//
+// 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.
+
+// (This used to be in the Rust unicode crate, which is now gone, so we'll
+// just include it inline.)
+
+// https://tools.ietf.org/html/rfc3629
+static UTF8_CHAR_WIDTH: [u8; 256] = [
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x1F
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x3F
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x5F
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x7F
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0x9F
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0xBF
+0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 0xDF
+3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 0xEF
+4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, // 0xFF
+];
+
+/// Given a first byte, determine how many bytes are in this UTF-8 character
+#[inline]
+pub fn utf8_char_width(b: u8) -> usize {
+    return UTF8_CHAR_WIDTH[b as usize] as usize;
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/combine/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"ce7eb76d33deb2c6b10a863a831c67edaf441f0cef1aaaef7a2824d18810d6f8",".travis.yml":"919faf51dd514eefd36f182b1bde66e57ae40b924d84335c39c6a2099c336381","CHANGELOG.md":"78f2772623b909545b9cd5ff5d7d3572bcf9ff40c0912affd8ca6fb97f01a6b5","Cargo.toml":"76cb5edbe29b816bf0e11abf9c8d284307376873b35a96f88756f48d0b3d5216","LICENSE":"64636d10db217e661c8f3a2c0f31050b9b29acf19c44fddb9bb45ab8c3f3ff41","README.md":"a7272b1ab0977621035e24c95b9384e93e62ec4ae46d9a46ce6c4ca8bc0be3ff","benches/data.json":"0f12cbafc501954c02b8e81ce181c46979704ad0a3313bd83aeb7b5289118da2","benches/http-requests.txt":"423fb29299647d8045492f4ea7d4d36307c31408989e83a64b8594a4d2d7cbb7","benches/http.rs":"c29a09dc2d63d2487a398e38085c1a04fc2132ed356af03c1c435eba8001b011","benches/json.rs":"c2bdb762490f4452e062f98ce7d08bf6ca63a0a941da42c736660470fa9a3fe3","benches/mp4.rs":"c8a4a7694c9123a3a5f6d9720b39fa7df21489c3b292b29bdd32716bb88e5c99","rustfmt.toml":"2a88277834b63a6f7fe9733b3e7d5a2d05f6de4b1c0b9e561b3df6f0104e97bb","src/byte.rs":"11f7cac57a34739fcba00ce2f0293e79bd820cc7efbc04dcd34a9c60ad1a6435","src/char.rs":"934617cdf477409ca27e84b4a189ce8055001cc6a0e164058c5adbec4e44ab7e","src/combinator.rs":"d5b5581ffad532cdaaae83163a92d7b9a4f6bcfb47d7774466ab7220e46d5ab5","src/lib.rs":"17d3fba6f07d4d2efeaccdfeb695e3ed1aa4a54df3dc538f2ebdd887f52c96e3","src/primitives.rs":"0bd57556631f9d6fc5503b16669f6c19ea2db739417ff2ccf841a4fc38905d84","src/range.rs":"db087585924b5b88bc7f4bce98eb991505dc27dfd0a38d5e6b466597646950a3","tests/buffered_stream.rs":"7a3ab08671f78370fa36dfd5977c261228bc4fb6b3b41e9146c7a15ccbca91a3","tests/date.rs":"1f23d5483e2c8d3cac34c7f78729058e2eccc9731aefb92c65ca3ff56dd239b2","tests/ini.rs":"7b9e92e384b025cc03ea1fe49367224d4c637eaf8a14f9af2055b10534b84ee1","tests/readme.rs":"b424b50eff4e84dd96708770c3f86df4b01027185e45e06af0b7304b777d1dc0"},"package":"0d4e2b2f3e0e68b531bd90f79c0c897f2da8de4109fc1dd7cd427990621dd2d0"}
\ No newline at end of file
new file mode 100644
new file mode 100644
--- /dev/null
+++ b/third_party/rust/combine/.gitignore
@@ -0,0 +1,9 @@
+/target
+/Cargo.lock
+
+
+#vim temporary files
+*.swp
+*.swo
+/.vscode
+/benches/small.mp4
new file mode 100644
--- /dev/null
+++ b/third_party/rust/combine/.travis.yml
@@ -0,0 +1,37 @@
+language: rust
+sudo: false
+addons:
+  apt:
+    packages:
+    - libcurl4-openssl-dev
+    - libelf-dev
+    - libdw-dev
+rust:
+- nightly
+- beta
+- stable
+- 1.11.0
+before_script:
+- |
+  pip install 'travis-cargo<0.2' --user &&
+  export PATH=$HOME/.local/bin:$PATH
+script:
+- |
+  cargo build &&
+  travis_wait cargo test &&
+  travis-cargo --only nightly bench &&
+  travis-cargo --only stable doc
+after_success:
+- travis-cargo --only stable doc-upload
+- travis-cargo coveralls --no-sudo
+env:
+  global:
+  - TRAVIS_CARGO_NIGHTLY_FEATURE=""
+  - secure: Z0JCbroitF6pKdImGLcar9UcXDFUoggvEwYsksoGX16/28iBXLmBX6DDWN1brVdasx/i5M5aEy8xbzcV680+HEbbUgz5uLAMp3xQFzu5FJ276PM9ZFZZgb02EJuYz9THfrC9ajlc+CirYF91i/yMZbpBGajmAzp61puRph/CgI8=
+notifications:
+  webhooks:
+    urls:
+      - https://webhooks.gitter.im/e/ee4400ef3d920e51415e
+    on_success: change  # options: [always|never|change] default: always
+    on_failure: always  # options: [always|never|change] default: always
+    on_start: never     # options: [always|never|change] default: always
new file mode 100644
--- /dev/null
+++ b/third_party/rust/combine/CHANGELOG.md
@@ -0,0 +1,92 @@
+<a name="v2.3.0"></a>
+## v2.3.0 (2017-02-22)
+
+
+#### Performance
+
+*   Don't call parse_stream in optional ([a4bf28d2](a4bf28d2))
+
+#### Features
+
+*   Add the choice! macro ([6f2cec69](6f2cec69))
+*   Add map functions for Error<> and Info<> ranges. (#86) 
+*   Add Parser::boxed ([3af9c9b3](3af9c9b3))
+
+<a name="2.1.0"></a>
+##  2.1.0 (2016-10-30)
+
+
+#### Features
+
+*   Add a read adapter for the stream trait ([a2a9f214](a2a9f214))
+
+
+
+<a name="2.0.0"></a>
+## 2.0.0 (2016-10-19)
+
+
+#### Features
+
+*   Version 2.0.0 ([80b24186](https://github.com/Marwes/combine/commit/80b24186fb4854d3242f32abc727107545e08c7b))
+*   Add the count parser ([a7949f3a](https://github.com/Marwes/combine/commit/a7949f3aef8585523e730e2c1224c3725b360d32))
+*   Add the Parser::by_ref method ([15554d0c](https://github.com/Marwes/combine/commit/15554d0c64a2415e8c234708595cc544ada6c585))
+*   Add the one_of and none_of parsers ([941b277c](https://github.com/Marwes/combine/commit/941b277c8f4d8e8af804c88678181be7743f912b))
+*   Add the position parser ([d6c65f6d](https://github.com/Marwes/combine/commit/d6c65f6da5a2af47254abe2db4b04c3ecbd74803))
+*   Add bytes_cmp and string_cmp ([ee6b430d](https://github.com/Marwes/combine/commit/ee6b430d17508daf305d5f48fabae2d662a94d34))
+*   Add the `tokens` parser ([886c4523](https://github.com/Marwes/combine/commit/886c45235be207241874a0a412ebcc0733959466))
+*   Version 2.0.0-beta3 ([55c59322](https://github.com/Marwes/combine/commit/55c59322f8ead037dad703a41e1f6d769c059f31))
+*   Break out the error formatting into a separate function ([b6ccb0c1](https://github.com/Marwes/combine/commit/b6ccb0c1807f0f182878b68d4dbdcfa739fd5157))
+*   Rename parse_state to parse_stream ([b375df48](https://github.com/Marwes/combine/commit/b375df4811570d14bbd8db7cb74a6834e54679cf))
+*   Simplify the flat_map parser ([08a91ce2](https://github.com/Marwes/combine/commit/08a91ce201b67f5528a18228bdfb079e7d86dd7f))
+*   Merge the ParserExt trait into Parser ([26a84154](https://github.com/Marwes/combine/commit/26a841540107b79542bb874a60abb83f99c78a58))
+*   Add the bytes parser ([9c73c053](https://github.com/Marwes/combine/commit/9c73c053f37b149c35d60377f6dcbbbfc145dda9))
+*   Add parsers specialized on byte streams ([01ba3759](https://github.com/Marwes/combine/commit/01ba375929daac2cb81a3e966e529f0909014620))
+*   Make ctry usable outside the crate ([f45740dd](https://github.com/Marwes/combine/commit/f45740dd71cf9c71e0900e932c2f10ccbefae35e))
+*   Add versions of parse_* which return an unpacked version of ParseResult ([2bbd14ab](https://github.com/Marwes/combine/commit/2bbd14abd2b372afbfda56fb73d4aa036bd427e1))
+*   Add the satisy_map parser ([4d97d296](https://github.com/Marwes/combine/commit/4d97d2968c48026e8369e1f0bcee3c6ef5784664))
+*   Replace the And parser with the pair parser ([b1f56113](https://github.com/Marwes/combine/commit/b1f561139169caa1a5a2e3e2d84248b28f22bb82))
+*   Remove reexport of the char module from the root module ([e39dacb5](https://github.com/Marwes/combine/commit/e39dacb57999c3cfb0bb4ae6d5db0b696da60a3f))
+*   Version 2.0.0-beta ([5bdbf584](https://github.com/Marwes/combine/commit/5bdbf58484800717c7d7c20b9161562520f425cb))
+*   Remove the buffered_stream feature ([3fdbf217](https://github.com/Marwes/combine/commit/3fdbf217ec0a66b052b8d11792ce3ff3d13b7463))
+*   Version 1.3.0 ([acea26cd](https://github.com/Marwes/combine/commit/acea26cda536ffc681ca4fa9e4c1bf28f5184582))
+*   Add the eof parser ([6a89cbf2](https://github.com/Marwes/combine/commit/6a89cbf2ef11ed5bf4145a296c208e5f5f90438c))
+*   Stabilize RangeStream and all functions using it ([d932375d](https://github.com/Marwes/combine/commit/d932375d13a196fc74602f8e76ad5bd3512ca370))
+*   Reexport Stream and StreamOnce from the crate root ([2c2b3f5c](https://github.com/Marwes/combine/commit/2c2b3f5cd21a04fbc157a95ce76fe72bfdc1a2c3))
+*   Merge the HasPosition trait into StreamOnce ([3bda4a16](https://github.com/Marwes/combine/commit/3bda4a163e8f3b57dd4efa65384c97f9c3554aeb))
+*   Add the StreamOnce trait ([9ea0ed5d](https://github.com/Marwes/combine/commit/9ea0ed5d6c8f8cead773a24b968d4a0bbb606721), breaks [#](https://github.com/Marwes/combine/issues/))
+*   Make Stream::uncons take &mut self ([4ddc4257](https://github.com/Marwes/combine/commit/4ddc4257d1e719a9f1c17a49c39f08ebf20d2999))
+*   Separate the Position type and position method from Stream ([9cfb9a89](https://github.com/Marwes/combine/commit/9cfb9a895be34b288ee9fc9f926cd1b9c5b97b03))
+*   Version 1.2.1 ([f737af27](https://github.com/Marwes/combine/commit/f737af27306160088188900a1cdad255b5ca58d3))
+*   Move the position handling inside the Stream trait ([f41f65e9](https://github.com/Marwes/combine/commit/f41f65e9f34b64481f81af078ecdb10a80e75f6f))
+* **range_stream:**  Implement RangeStream on State ([f5679dc9](https://github.com/Marwes/combine/commit/f5679dc954be093a7a0278d2311cf5a162396833))
+
+#### Performance
+
+*   Specialize and_then, then and flat_map ([9dc7dc6b](https://github.com/Marwes/combine/commit/9dc7dc6b9bcb638888be448efb7002d362aded16))
+*   Specialize the tuple parser to avoid unnecessary branches ([2b294f80](https://github.com/Marwes/combine/commit/2b294f8009021897d9652981dfb107dd2102a902))
+*   Add inline annotations and more forwarding parse functions ([0e5ee38e](https://github.com/Marwes/combine/commit/0e5ee38e1b15847908f6676c0c4032dc844e3462))
+*   Avoid indirection in Skip and With ([52d335ca](https://github.com/Marwes/combine/commit/52d335caa2e698de9be50e46e8fbcf241d4e3081))
+*   Optimize Iter by simplifying the state machine ([9631700a](https://github.com/Marwes/combine/commit/9631700a306cb5546e37dfb8f05d54728fb3bc8c))
+*   Speedup tuple parsers by simplifying the expanded code ([5d86dcf2](https://github.com/Marwes/combine/commit/5d86dcf2d14f1cae078d1a4b8831d37041eaf7a2))
+*   Avoid creating an error when take_while1 parses no input ([9bad15c0](https://github.com/Marwes/combine/commit/9bad15c0f79e3ff897fb92cdca6b92f988c69347))
+*   Possibly improve performance of the RangeStream impl for &str ([abb1de7f](https://github.com/Marwes/combine/commit/abb1de7f15b65b9bc2c40572319269191bd0819f))
+
+#### Bug Fixes
+
+*   Rename the String parser to Str ([d846bf0e](https://github.com/Marwes/combine/commit/d846bf0e7ddb3350ce9245b3682d7c054ff5cdd8))
+*   Use five copies in the large http test anyway to match nom_benchmarks ([eb089f5b](https://github.com/Marwes/combine/commit/eb089f5bef175b96e097286b9c8c3e7d5f6e3922))
+*   Avoid storing the position in primitives::uncons_while ([9912507a](https://github.com/Marwes/combine/commit/9912507a80e178737e16d4ff3d19d7a1fee9fbc8))
+*   Calling uncons_range with the same size as is remaining should succeed ([cce6214e](https://github.com/Marwes/combine/commit/cce6214ed4722880881c8c6998e00f4509a22588))
+*   Add Sync to to the Error::Other variant ([22add3ec](https://github.com/Marwes/combine/commit/22add3eca62ff5e6f4d58122a4b366290b1d9385))
+*   Fix positions of BufferedStream being for the next token ([66eab92a](https://github.com/Marwes/combine/commit/66eab92a7dd63269f48cf0fbd0722a6eeea9135d))
+*   Fix the position handling of BufferedStream ([f21148b3](https://github.com/Marwes/combine/commit/f21148b3c4c5c6f10d8b6d90ce4a7925596879b3))
+*   Remove the Positioner bound from Stream::Item an Stream::Range ([fba3f1e7](https://github.com/Marwes/combine/commit/fba3f1e760505305b6a586b6ff5a53eff645e1d1))
+* **buffered_stream:**  BufferedStream no longer emits the last token after EOF ([6532884c](https://github.com/Marwes/combine/commit/6532884cc16307e1753584dd40b2b59e3daa6267))
+* **travis:**
+  *  Dont pass the test feature to travis ([382a608d](https://github.com/Marwes/combine/commit/382a608da2851c5cc2d3477025951e9a133732bc))
+  *  Add travis_wait so travis does not time out the beta builds ([a3f0792a](https://github.com/Marwes/combine/commit/a3f0792ab347805e3f0ce619997a2c154f5e8c87))
+
+#### Breaking Changes
+
+*   Add the StreamOnce trait ([9ea0ed5d](https://github.com/Marwes/combine/commit/9ea0ed5d6c8f8cead773a24b968d4a0bbb606721), breaks [#](https://github.com/Marwes/combine/issues/))
new file mode 100644
--- /dev/null
+++ b/third_party/rust/combine/Cargo.toml
@@ -0,0 +1,33 @@
+[package]
+
+name = "combine"
+version = "2.3.2"
+authors = ["Markus Westerlind <marwes91@gmail.com>"]
+
+description = "Fast parser combinators on arbitrary streams with zero-copy support."
+
+repository = "https://github.com/Marwes/combine"
+documentation = "https://docs.rs/combine"
+
+readme = "README.md"
+
+keywords = ["parser", "parsing", "combinators", "ll"]
+
+categories = ["parsing"]
+
+license = "MIT"
+
+[lib]
+name = "combine"
+path = "src/lib.rs"
+
+[dependencies]
+ascii = "0.7.0"
+
+[dev-dependencies]
+byteorder = "0.5.3"
+
+
+[features]
+# Run the mp4 benchmark, requires a mp4 file named `small.mp4` in the benches directory
+mp4 = []
new file mode 100644
--- /dev/null
+++ b/third_party/rust/combine/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Markus Westerlind
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
new file mode 100644
--- /dev/null
+++ b/third_party/rust/combine/README.md
@@ -0,0 +1,105 @@
+# combine
+[![Build Status](https://travis-ci.org/Marwes/combine.svg?branch=master)](https://travis-ci.org/Marwes/combine) [![Docs v1](https://docs.rs/combine/badge.svg?version=^1)](https://docs.rs/combine/^1) [![Docs](https://docs.rs/combine/badge.svg)](https://docs.rs/combine) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Marwes/combine?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
+
+An implementation of parser combinators for Rust, inspired by the Haskell library [Parsec](https://hackage.haskell.org/package/parsec). As in Parsec the parsers are [LL(1)](https://en.wikipedia.org/wiki/LL_parser) by default but they can opt-in to arbitrary lookahead using the [try  combinator](https://marwes.github.io/combine/combine/fn.try.html).
+
+##Example
+
+```rust
+extern crate combine;
+use combine::{many, Parser};
+use combine::char::letter;
+
+let result = many(letter()).parse("hello world");
+assert_eq!(result, Ok(("hello".to_string(), " world")));
+```
+
+Larger examples can be found in the [tests][tests] and [benches][benches] folders.
+
+[tests]:https://github.com/Marwes/combine/tree/master/tests
+[benches]:https://github.com/Marwes/combine/tree/master/benches
+
+## Links
+
+[Documentation and examples](https://docs.rs/crate/combine)
+
+[crates.io](https://crates.io/crates/combine)
+
+## About
+
+A parser combinator is, broadly speaking, a function which takes several parsers as arguments and returns a new parser, created by combining those parsers. For instance, the [many](https://marwes.github.io/combine/combine/fn.many.html) parser takes one parser, `p`, as input and returns a new parser which applies `p` zero or more times. Thanks to the modularity that parser combinators gives it is possible to define parsers for a wide range of tasks without needing to implement the low level plumbing while still having the full power of Rust when you need it. 
+
+The library adheres to [semantic versioning](http://semver.org).
+
+If you end up trying it I welcome any feedback from your experience with it. I am usually reachable within a day by opening an issue, sending an email or posting a message on gitter.
+
+## FAQ
+
+### Why does my errors contain inscrutable positions?
+
+Since `combine` aims to crate parsers with little to no overhead streams over `&str` and `&[T]` do not carry any extra position information but instead only rely on comparing the pointer of the buffer to check which `Stream` is further ahead than another `Stream`. To retrieve a better position, either call `translate_position` on the `ParseError` or wrap your stream with `State`.
+
+## Extra
+
+There is an additional crate which has parsers to lex and parse programming languages in [combine-language](https://github.com/Marwes/combine-language).
+
+You can find older versions of combine (parser-combinators) [here](https://crates.io/crates/parser-combinators).
+
+## Contributing
+
+The easiest way to contribute is to just open an issue about any problems you encounter using combine but if you are interested in adding something to the library here is a list of some of the easier things to work on to get started.
+
+* __Add additional parsers__ There is a list of parsers which aren't implemented [here][add parsers] but if you have a suggestion for another parser just leave a suggestion on the issue itself.
+* __Add additional examples__ More examples for using combine will always be useful!
+* __Add and improve the docs__ Not the fanciest of work but one cannot overstate the importance of good documentation.
+
+[add parsers]: https://github.com/Marwes/combine/issues/2
+
+## Breaking changes
+
+Here is a list containing most of the breaking changes in older versions of combine (parser-combinators).
+
+### 2.0.0-beta3
+
+* `parse_state` renamed to `parse_stream`.
+* `parse_lazy` changed to return a `ConsumedResult`. To make calls to `parse_lazy` return a `Result` you can call `parser.parse_lazy(input).into()`.
+* `char::String` renamed to `char::Str` to avoid name collisions with `std::string::String`.
+* The amount of reexports from the root module has been reduced.
+* `ParserExt` removed, all methods now exist directly on `Parser`.
+* `Stream` split into `Stream` and `StreamOnce`.
+* `StreamOnce::uncons` now takes `&mut self` instead of `self`.
+* `Position` added as an associated type on `StreamOnce`.
+
+### 1.0.0
+* `&[T]` streams has had the `Item` type changed from `&T` to `T` and requires a `T: Copy` bound. If you need the old behavior you can wrap the `&[T]` in the `SliceStream` newtype i.e `parser.parse(SliceStream(slice))`.
+
+### 1.0.0-beta.3
+* `Error::Unexpected` holds an `Info<T, R>` instead of just a T to make it consistent with the other variants.
+
+### 1.0.0-beta.2
+* `Info<T>` and `Error<T>` has had their signatures changed to `Info<T, R>` and `Error<T, R>`. `Info` has a new variant which is specified by `R` and defines the type for range errors. `ParseError<T: Positioner>` has been changed to `ParseError<S: Stream>` (S is the stream type of the parser).
+* If you were using `ParseResult` from primitives you should no longer specify the item type of the stream.
+
+### 0.7.0
+* `Stream::uncons` changed its signature to allow it to return errors. Return `Error::end_of_input()` instead of `()` if you implemented `Stream`.
+
+### 0.6.0
+* Addition of `Parser::parse_lazy`, should not break anything but I can't say for certain.
+
+### 0.5.0
+* `any_char` -> `any`, `uncons_char` -> `uncons`
+* Introduction of the `Positioner` trait which needs to be implemented on an custom token types.
+* `satisfy` is moved to the `combinators` module and made generic, might cause type inference issues.
+
+### 0.4.0
+* `any_char` is no longer a free function but returns a parser when called as all parser functions (and its called `any` after 0.5.0)
+* `Cow` is replaced by `Info` in the error messages.
+
+### 0.3.2 / 0.3.0
+* Added variant to `Error` which can hold any kind of `::std::error::Error`
+* `choice_vec` and `choice_slice` is replaced by just `choice`
+
+### 0.2.6
+* Iterators cannot directly be used as streams but must be wrapped using `from_iter` function
+
+If you have trouble updating to a newer version feel free to open an issue and I can take a look.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/combine/benches/data.json
@@ -0,0 +1,317 @@
+[
+  {
+    "_id": "54d38af178bf1fbfe80a59e5",
+    "index": 0,
+    "guid": "cc631fea-7bf2-4595-950c-097880a818bc",
+    "isActive": false,
+    "balance": "$3,397.06",
+    "picture": "http://placehold.it/32x32",
+    "age": 39,
+    "eyeColor": "brown",
+    "name": "Corina Tyler",
+    "gender": "female",
+    "company": "GEEKOL",
+    "email": "corinatyler@geekol.com",
+    "phone": "+1 (899) 452-2754",
+    "address": "608 Leonard Street, Yettem, Connecticut, 6707",
+    "about": "Ea dolore pariatur aliqua veniam officia est et fugiat ipsum do sunt mollit id aute. Nisi ad elit ut et et. Duis in aliquip id labore ex et laboris anim magna proident Lorem est ut. Consectetur sint aliqua eu exercitation anim cupidatat fugiat. Enim exercitation amet ex irure quis anim est fugiat et laborum.\r\n",
+    "registered": "2014-03-27T05:29:11 -01:00",
+    "latitude": -57.157547,
+    "longitude": -23.548119,
+    "tags": [
+      "est",
+      "est",
+      "exercitation",
+      "ipsum",
+      "tempor",
+      "id",
+      "aliqua"
+    ],
+    "friends": [
+      {
+        "id": 0,
+        "name": "Bates Lynch"
+      },
+      {
+        "id": 1,
+        "name": "Duffy Townsend"
+      },
+      {
+        "id": 2,
+        "name": "Nelson Good"
+      }
+    ],
+    "greeting": "Hello, Corina Tyler! You have 8 unread messages.",
+    "favoriteFruit": "apple"
+  },
+  {
+    "_id": "54d38af1c9a8d04d5e35f211",
+    "index": 1,
+    "guid": "d8dd5231-048f-4a5a-b392-8f7c3492ad15",
+    "isActive": false,
+    "balance": "$1,646.89",
+    "picture": "http://placehold.it/32x32",
+    "age": 22,
+    "eyeColor": "brown",
+    "name": "Santos Boyd",
+    "gender": "male",
+    "company": "AUTOGRATE",
+    "email": "santosboyd@autograte.com",
+    "phone": "+1 (872) 545-2605",
+    "address": "428 Homecrest Avenue, Century, Kentucky, 1905",
+    "about": "Quis cillum mollit adipisicing duis sunt. Eiusmod culpa reprehenderit proident magna laborum voluptate incididunt et ipsum in laboris consectetur. Nostrud consequat excepteur nisi magna officia.\r\n",
+    "registered": "2015-02-03T03:03:32 -01:00",
+    "latitude": 47.505093,
+    "longitude": -138.153509,
+    "tags": [
+      "aliquip",
+      "et",
+      "eu",
+      "minim",
+      "non",
+      "eiusmod",
+      "deserunt"
+    ],
+    "friends": [
+      {
+        "id": 0,
+        "name": "Annmarie Larson"
+      },
+      {
+        "id": 1,
+        "name": "Cherie Potts"
+      },
+      {
+        "id": 2,
+        "name": "Catalina Bass"
+      }
+    ],
+    "greeting": "Hello, Santos Boyd! You have 1 unread messages.",
+    "favoriteFruit": "apple"
+  },
+  {
+    "_id": "54d38af171fedb95c2841d64",
+    "index": 2,
+    "guid": "f4b131d7-871f-4503-8674-275c4c8e3121",
+    "isActive": false,
+    "balance": "$3,311.55",
+    "picture": "http://placehold.it/32x32",
+    "age": 23,
+    "eyeColor": "green",
+    "name": "Jeannie Daugherty",
+    "gender": "female",
+    "company": "COMTRAK",
+    "email": "jeanniedaugherty@comtrak.com",
+    "phone": "+1 (853) 445-3806",
+    "address": "189 Narrows Avenue, Cascades, Arkansas, 5738",
+    "about": "Velit labore mollit in sint culpa dolor consequat voluptate cupidatat ut. Laborum dolore incididunt deserunt adipisicing aliquip nisi cupidatat. Aliqua cillum consequat voluptate nulla velit deserunt cillum do reprehenderit cupidatat quis labore anim nulla. Irure do nisi et ea excepteur culpa mollit aliqua occaecat id dolore ullamco ad. Magna enim consectetur ea ullamco tempor magna eu consequat sint irure. In Lorem est id est do anim ex.\r\n",
+    "registered": "2014-01-29T22:48:53 -01:00",
+    "latitude": 72.451611,
+    "longitude": -89.847471,
+    "tags": [
+      "consequat",
+      "deserunt",
+      "ipsum",
+      "commodo",
+      "magna",
+      "ut",
+      "ut"
+    ],
+    "friends": [
+      {
+        "id": 0,
+        "name": "Kenya Alford"
+      },
+      {
+        "id": 1,
+        "name": "Francesca Carpenter"
+      },
+      {
+        "id": 2,
+        "name": "Celina Petty"
+      }
+    ],
+    "greeting": "Hello, Jeannie Daugherty! You have 3 unread messages.",
+    "favoriteFruit": "strawberry"
+  },
+  {
+    "_id": "54d38af16b1001dc2ee7f7b0",
+    "index": 3,
+    "guid": "c905d47f-8e7a-488d-a1a0-df61bf1af2eb",
+    "isActive": true,
+    "balance": "$2,311.19",
+    "picture": "http://placehold.it/32x32",
+    "age": 39,
+    "eyeColor": "green",
+    "name": "Jordan Horton",
+    "gender": "female",
+    "company": "ENERSOL",
+    "email": "jordanhorton@enersol.com",
+    "phone": "+1 (910) 467-2211",
+    "address": "123 Harwood Place, Northchase, Guam, 5138",
+    "about": "Cupidatat aliqua nisi minim ad culpa cupidatat proident fugiat veniam aliquip minim anim et. Ullamco consequat consequat aute exercitation aliqua eiusmod sunt ea. Et laborum dolor ex proident do non adipisicing nostrud voluptate qui reprehenderit elit ad nostrud. Excepteur exercitation laborum nulla laboris incididunt. Est sunt nisi eu id fugiat excepteur. In sunt laborum aliquip aute ipsum.\r\n",
+    "registered": "2014-10-08T23:32:53 -02:00",
+    "latitude": -52.78747,
+    "longitude": -121.825343,
+    "tags": [
+      "voluptate",
+      "non",
+      "dolor",
+      "nisi",
+      "minim",
+      "mollit",
+      "minim"
+    ],
+    "friends": [
+      {
+        "id": 0,
+        "name": "Fields Ballard"
+      },
+      {
+        "id": 1,
+        "name": "Peterson Reese"
+      },
+      {
+        "id": 2,
+        "name": "Montoya Mccullough"
+      }
+    ],
+    "greeting": "Hello, Jordan Horton! You have 3 unread messages.",
+    "favoriteFruit": "banana"
+  },
+  {
+    "_id": "54d38af1ae98fd5f8860a1a0",
+    "index": 4,
+    "guid": "d6f73551-9672-4f4a-b832-1d2942a53203",
+    "isActive": false,
+    "balance": "$1,178.62",
+    "picture": "http://placehold.it/32x32",
+    "age": 36,
+    "eyeColor": "green",
+    "name": "Mae Roy",
+    "gender": "female",
+    "company": "BUGSALL",
+    "email": "maeroy@bugsall.com",
+    "phone": "+1 (859) 452-3883",
+    "address": "266 Berriman Street, Logan, Rhode Island, 2566",
+    "about": "Adipisicing id incididunt ut excepteur officia incididunt enim quis dolor incididunt esse esse. Nulla laboris pariatur eiusmod veniam duis ipsum Lorem ex cupidatat do sunt commodo cillum. Laboris enim aute irure qui officia laborum. Veniam ullamco ad laboris nulla minim laboris ut ad minim non duis.\r\n",
+    "registered": "2014-07-31T12:08:03 -02:00",
+    "latitude": 49.234132,
+    "longitude": -86.652077,
+    "tags": [
+      "ut",
+      "mollit",
+      "duis",
+      "ea",
+      "cillum",
+      "in",
+      "ut"
+    ],
+    "friends": [
+      {
+        "id": 0,
+        "name": "Acevedo Kent"
+      },
+      {
+        "id": 1,
+        "name": "Wood Edwards"
+      },
+      {
+        "id": 2,
+        "name": "Kris Brennan"
+      }
+    ],
+    "greeting": "Hello, Mae Roy! You have 3 unread messages.",
+    "favoriteFruit": "strawberry"
+  },
+  {
+    "_id": "54d38af1638743947b6d15c2",
+    "index": 5,
+    "guid": "db331420-0216-4a92-93eb-23aa0f69a533",
+    "isActive": true,
+    "balance": "$2,375.71",
+    "picture": "http://placehold.it/32x32",
+    "age": 20,
+    "eyeColor": "blue",
+    "name": "Mooney Manning",
+    "gender": "male",
+    "company": "HOMELUX",
+    "email": "mooneymanning@homelux.com",
+    "phone": "+1 (865) 585-2829",
+    "address": "833 Madison Street, Mulino, Iowa, 249",
+    "about": "Et ex irure magna culpa fugiat magna exercitation laborum velit quis nostrud et minim in. Sint nulla laboris non non. Do excepteur dolor ipsum proident anim.\r\n",
+    "registered": "2014-12-23T16:46:55 -01:00",
+    "latitude": -37.873914,
+    "longitude": 11.797406,
+    "tags": [
+      "cupidatat",
+      "labore",
+      "culpa",
+      "esse",
+      "amet",
+      "nostrud",
+      "irure"
+    ],
+    "friends": [
+      {
+        "id": 0,
+        "name": "Avila Lawrence"
+      },
+      {
+        "id": 1,
+        "name": "Wright Stokes"
+      },
+      {
+        "id": 2,
+        "name": "Joann Ramirez"
+      }
+    ],
+    "greeting": "Hello, Mooney Manning! You have 8 unread messages.",
+    "favoriteFruit": "banana"
+  },
+  {
+    "_id": "54d38af187f8159129b215ef",
+    "index": 6,
+    "guid": "0a7a0751-3ed3-480e-8b87-082f440d4bde",
+    "isActive": false,
+    "balance": "$2,258.43",
+    "picture": "http://placehold.it/32x32",
+    "age": 26,
+    "eyeColor": "brown",
+    "name": "Sylvia Roberts",
+    "gender": "female",
+    "company": "ZOLARITY",
+    "email": "sylviaroberts@zolarity.com",
+    "phone": "+1 (852) 580-3720",
+    "address": "604 Boardwalk , Greensburg, Pennsylvania, 9876",
+    "about": "Amet mollit mollit nostrud dolor ut et. Eiusmod amet id nulla commodo qui ullamco pariatur nulla magna nisi proident. Irure aliquip eu excepteur incididunt nisi consectetur.\r\n",
+    "registered": "2014-09-20T02:58:52 -02:00",
+    "latitude": 3.989497,
+    "longitude": -111.05834,
+    "tags": [
+      "culpa",
+      "quis",
+      "commodo",
+      "laboris",
+      "consectetur",
+      "pariatur",
+      "enim"
+    ],
+    "friends": [
+      {
+        "id": 0,
+        "name": "Logan Rivas"
+      },
+      {
+        "id": 1,
+        "name": "Bryan Sullivan"
+      },
+      {
+        "id": 2,
+        "name": "Bobbie Cleveland"
+      }
+    ],
+    "greeting": "Hello, Sylvia Roberts! You have 9 unread messages.",
+    "favoriteFruit": "banana"
+  }
+]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/combine/benches/http-requests.txt
@@ -0,0 +1,494 @@
+GET / HTTP/1.1
+Host: www.reddit.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+
+GET /reddit.v_EZwRzV-Ns.css HTTP/1.1
+Host: www.redditstatic.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: text/css,*/*;q=0.1
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /reddit-init.en-us.O1zuMqOOQvY.js HTTP/1.1
+Host: www.redditstatic.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: */*
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /reddit.en-us.31yAfSoTsfo.js HTTP/1.1
+Host: www.redditstatic.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: */*
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /kill.png HTTP/1.1
+Host: www.redditstatic.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /icon.png HTTP/1.1
+Host: www.redditstatic.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+
+GET /favicon.ico HTTP/1.1
+Host: www.redditstatic.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+
+GET /AMZM4CWd6zstSC8y.jpg HTTP/1.1
+Host: b.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /jz1d5Nm0w97-YyNm.jpg HTTP/1.1
+Host: b.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /aWGO99I6yOcNUKXB.jpg HTTP/1.1
+Host: a.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /rZ_rD5TjrJM0E9Aj.css HTTP/1.1
+Host: e.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: text/css,*/*;q=0.1
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /tmsPwagFzyTvrGRx.jpg HTTP/1.1
+Host: a.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /KYgUaLvXCK3TCEJx.jpg HTTP/1.1
+Host: a.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /81pzxT5x2ozuEaxX.jpg HTTP/1.1
+Host: e.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /MFqCUiUVPO5V8t6x.jpg HTTP/1.1
+Host: a.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /TFpYTiAO5aEowokv.jpg HTTP/1.1
+Host: e.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /eMWMpmm9APNeNqcF.jpg HTTP/1.1
+Host: e.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /S-IpsJrOKuaK9GZ8.jpg HTTP/1.1
+Host: c.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /3V6dj9PDsNnheDXn.jpg HTTP/1.1
+Host: c.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /wQ3-VmNXhv8sg4SJ.jpg HTTP/1.1
+Host: c.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /ixd1C1njpczEWC22.jpg HTTP/1.1
+Host: c.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /nGsQj15VyOHMwmq8.jpg HTTP/1.1
+Host: c.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /zT4yQmDxQLbIxK1b.jpg HTTP/1.1
+Host: c.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /L5e1HcZLv1iu4nrG.jpg HTTP/1.1
+Host: f.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /WJFFPxD8X4JO_lIG.jpg HTTP/1.1
+Host: f.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /hVMVTDdjuY3bQox5.jpg HTTP/1.1
+Host: f.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /rnWf8CjBcyPQs5y_.jpg HTTP/1.1
+Host: f.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /gZJL1jNylKbGV4d-.jpg HTTP/1.1
+Host: d.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /aNd2zNRLXiMnKUFh.jpg HTTP/1.1
+Host: c.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /droparrowgray.gif HTTP/1.1
+Host: www.redditstatic.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.redditstatic.com/reddit.v_EZwRzV-Ns.css
+
+GET /sprite-reddit.an0Lnf61Ap4.png HTTP/1.1
+Host: www.redditstatic.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.redditstatic.com/reddit.v_EZwRzV-Ns.css
+
+GET /ga.js HTTP/1.1
+Host: www.google-analytics.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: */*
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+If-Modified-Since: Tue, 29 Oct 2013 19:33:51 GMT
+
+GET /reddit/ads.html?sr=-reddit.com&bust2 HTTP/1.1
+Host: static.adzerk.net
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /pixel/of_destiny.png?v=hOlmDALJCWWdjzfBV4ZxJPmrdCLWB%2Ftq7Z%2Ffp4Q%2FxXbVPPREuMJMVGzKraTuhhNWxCCwi6yFEZg%3D&r=783333388 HTTP/1.1
+Host: pixel.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /UNcO-h_QcS9PD-Gn.jpg HTTP/1.1
+Host: c.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://e.thumbs.redditmedia.com/rZ_rD5TjrJM0E9Aj.css
+
+GET /welcome-lines.png HTTP/1.1
+Host: www.redditstatic.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.redditstatic.com/reddit.v_EZwRzV-Ns.css
+
+GET /welcome-upvote.png HTTP/1.1
+Host: www.redditstatic.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.redditstatic.com/reddit.v_EZwRzV-Ns.css
+
+GET /__utm.gif?utmwv=5.5.1&utms=1&utmn=720496082&utmhn=www.reddit.com&utme=8(site*srpath*usertype*uitype)9(%20reddit.com*%20reddit.com-GET_listing*guest*web)11(3!2)&utmcs=UTF-8&utmsr=2560x1600&utmvp=1288x792&utmsc=24-bit&utmul=en-us&utmje=1&utmfl=13.0%20r0&utmdt=reddit%3A%20the%20front%20page%20of%20the%20internet&utmhid=2129416330&utmr=-&utmp=%2F&utmht=1400862512705&utmac=UA-12131688-1&utmcc=__utma%3D55650728.585571751.1400862513.1400862513.1400862513.1%3B%2B__utmz%3D55650728.1400862513.1.1.utmcsr%3D(direct)%7Cutmccn%3D(direct)%7Cutmcmd%3D(none)%3B&utmu=qR~ HTTP/1.1
+Host: www.google-analytics.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /ImnpOQhbXUPkwceN.png HTTP/1.1
+Host: a.thumbs.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /ajax/libs/jquery/1.7.1/jquery.min.js HTTP/1.1
+Host: ajax.googleapis.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: */*
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://static.adzerk.net/reddit/ads.html?sr=-reddit.com&bust2
+
+GET /__utm.gif?utmwv=5.5.1&utms=2&utmn=1493472678&utmhn=www.reddit.com&utmt=event&utme=5(AdBlock*enabled*false)(0)8(site*srpath*usertype*uitype)9(%20reddit.com*%20reddit.com-GET_listing*guest*web)11(3!2)&utmcs=UTF-8&utmsr=2560x1600&utmvp=1288x792&utmsc=24-bit&utmul=en-us&utmje=1&utmfl=13.0%20r0&utmdt=reddit%3A%20the%20front%20page%20of%20the%20internet&utmhid=2129416330&utmr=-&utmp=%2F&utmht=1400862512708&utmac=UA-12131688-1&utmni=1&utmcc=__utma%3D55650728.585571751.1400862513.1400862513.1400862513.1%3B%2B__utmz%3D55650728.1400862513.1.1.utmcsr%3D(direct)%7Cutmccn%3D(direct)%7Cutmcmd%3D(none)%3B&utmu=6R~ HTTP/1.1
+Host: www.google-analytics.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /ados.js?q=43 HTTP/1.1
+Host: secure.adzerk.net
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: */*
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://static.adzerk.net/reddit/ads.html?sr=-reddit.com&bust2
+
+GET /fetch-trackers?callback=jQuery111005268222517967478_1400862512407&ids%5B%5D=t3_25jzeq-t8_k2ii&_=1400862512408 HTTP/1.1
+Host: tracker.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: */*
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /ados?t=1400862512892&request={%22Placements%22:[{%22A%22:5146,%22S%22:24950,%22D%22:%22main%22,%22AT%22:5},{%22A%22:5146,%22S%22:24950,%22D%22:%22sponsorship%22,%22AT%22:8}],%22Keywords%22:%22-reddit.com%22,%22Referrer%22:%22http%3A%2F%2Fwww.reddit.com%2F%22,%22IsAsync%22:true,%22WriteResults%22:true} HTTP/1.1
+Host: engine.adzerk.net
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: */*
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://static.adzerk.net/reddit/ads.html?sr=-reddit.com&bust2
+
+GET /pixel/of_doom.png?id=t3_25jzeq-t8_k2ii&hash=da31d967485cdbd459ce1e9a5dde279fef7fc381&r=1738649500 HTTP/1.1
+Host: pixel.redditmedia.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /Extensions/adFeedback.js HTTP/1.1
+Host: static.adzrk.net
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: */*
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://static.adzerk.net/reddit/ads.html?sr=-reddit.com&bust2
+
+GET /Extensions/adFeedback.css HTTP/1.1
+Host: static.adzrk.net
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: text/css,*/*;q=0.1
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://static.adzerk.net/reddit/ads.html?sr=-reddit.com&bust2
+
+GET /reddit/ads-load.html?bust2 HTTP/1.1
+Host: static.adzerk.net
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://www.reddit.com/
+
+GET /Advertisers/a774d7d6148046efa89403a8db635a81.jpg HTTP/1.1
+Host: static.adzerk.net
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://static.adzerk.net/reddit/ads.html?sr=-reddit.com&bust2
+
+GET /i.gif?e=eyJhdiI6NjIzNTcsImF0Ijo1LCJjbSI6MTE2MzUxLCJjaCI6Nzk4NCwiY3IiOjMzNzAxNSwiZGkiOiI4NmI2Y2UzYWM5NDM0MjhkOTk2ZTg4MjYwZDE5ZTE1YyIsImRtIjoxLCJmYyI6NDE2MTI4LCJmbCI6MjEwNDY0LCJrdyI6Ii1yZWRkaXQuY29tIiwibWsiOiItcmVkZGl0LmNvbSIsIm53Ijo1MTQ2LCJwYyI6MCwicHIiOjIwMzYyLCJydCI6MSwicmYiOiJodHRwOi8vd3d3LnJlZGRpdC5jb20vIiwic3QiOjI0OTUwLCJ1ayI6InVlMS01ZWIwOGFlZWQ5YTc0MDFjOTE5NWNiOTMzZWI3Yzk2NiIsInRzIjoxNDAwODYyNTkzNjQ1fQ&s=lwlbFf2Uywt7zVBFRj_qXXu7msY HTTP/1.1
+Host: engine.adzerk.net
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://static.adzerk.net/reddit/ads.html?sr=-reddit.com&bust2
+Cookie: azk=ue1-5eb08aeed9a7401c9195cb933eb7c966
+
+GET /BurstingPipe/adServer.bs?cn=tf&c=19&mc=imp&pli=9994987&PluID=0&ord=1400862593644&rtu=-1 HTTP/1.1
+Host: bs.serving-sys.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://static.adzerk.net/reddit/ads.html?sr=-reddit.com&bust2
+
+GET /Advertisers/63cfd0044ffd49c0a71a6626f7a1d8f0.jpg HTTP/1.1
+Host: static.adzerk.net
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://static.adzerk.net/reddit/ads-load.html?bust2
+
+GET /BurstingPipe/adServer.bs?cn=tf&c=19&mc=imp&pli=9962555&PluID=0&ord=1400862593645&rtu=-1 HTTP/1.1
+Host: bs.serving-sys.com
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://static.adzerk.net/reddit/ads-load.html?bust2
+Cookie: S_9994987=6754579095859875029; A4=01fmFvgRnI09SF00000; u2=d1263d39-874b-4a89-86cd-a2ab0860ed4e3Zl040
+
+GET /i.gif?e=eyJhdiI6NjIzNTcsImF0Ijo4LCJjbSI6MTE2MzUxLCJjaCI6Nzk4NCwiY3IiOjMzNzAxOCwiZGkiOiI3OTdlZjU3OWQ5NjE0ODdiODYyMGMyMGJkOTE4YzNiMSIsImRtIjoxLCJmYyI6NDE2MTMxLCJmbCI6MjEwNDY0LCJrdyI6Ii1yZWRkaXQuY29tIiwibWsiOiItcmVkZGl0LmNvbSIsIm53Ijo1MTQ2LCJwYyI6MCwicHIiOjIwMzYyLCJydCI6MSwicmYiOiJodHRwOi8vd3d3LnJlZGRpdC5jb20vIiwic3QiOjI0OTUwLCJ1ayI6InVlMS01ZWIwOGFlZWQ5YTc0MDFjOTE5NWNiOTMzZWI3Yzk2NiIsInRzIjoxNDAwODYyNTkzNjQ2fQ&s=OjzxzXAgQksbdQOHNm-bjZcnZPA HTTP/1.1
+Host: engine.adzerk.net
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
+Accept: image/png,image/*;q=0.8,*/*;q=0.5
+Accept-Language: en-us,en;q=0.5
+Accept-Encoding: gzip, deflate
+Connection: keep-alive
+Referer: http://static.adzerk.net/reddit/ads-load.html?bust2
+Cookie: azk=ue1-5eb08aeed9a7401c9195cb933eb7c966
+
+GET /subscribe?host_int=1042356184&ns_map=571794054_374233948806,464381511_13349283399&user_id=245722467&nid=1399334269710011966&ts=1400862514 HTTP/1.1
+Host: notify8.dropbox.com
+Accept-Encoding: identity
+Connection: keep-alive
+X-Dropbox-Locale: en_US
+User-Agent: DropboxDesktopClient/2.7.54 (Macintosh; 10.8; ('i32',); en_US)
+
new file mode 100644
--- /dev/null
+++ b/third_party/rust/combine/benches/http.rs
@@ -0,0 +1,121 @@
+#![feature(test)]
+extern crate test;
+extern crate combine;
+
+use combine::*;
+use combine::primitives::Error;
+use combine::range::{take_while1, range};
+
+#[derive(Debug)]
+struct Request<'a> {
+    method: &'a [u8],
+    uri: &'a [u8],
+    version: &'a [u8],
+}
+
+#[derive(Debug)]
+struct Header<'a> {
+    name: &'a [u8],
+    value: Vec<&'a [u8]>,
+}
+
+fn is_token(c: u8) -> bool {
+    match c {
+        128...255 | 0...31 | b'(' | b')' | b'<' | b'>' | b'@' | b',' | b';' | b':' | b'\\' |
+        b'"' | b'/' | b'[' | b']' | b'?' | b'=' | b'{' | b'}' | b' ' => false,
+        _ => true,
+    }
+}
+
+fn is_horizontal_space(c: u8) -> bool {
+    c == b' ' || c == b'\t'
+}
+fn is_space(c: u8) -> bool {
+    c == b' '
+}
+fn is_not_space(c: u8) -> bool {
+    c != b' '
+}
+fn is_http_version(c: u8) -> bool {
+    c >= b'0' && c <= b'9' || c == b'.'
+}
+
+fn parse_http_request(input: &[u8]) -> Result<((Request, Vec<Header>), &[u8]), ParseError<&[u8]>> {
+    // Making a closure, because parser instances cannot be reused
+    let end_of_line = || (token(b'\r'), token(b'\n')).map(|_| b'\r').or(token(b'\n'));
+
+    let http_version = range(&b"HTTP/"[..]).with(take_while1(is_http_version));
+
+    let request_line = (take_while1(is_token),
+                        take_while1(is_space),
+                        take_while1(is_not_space),
+                        take_while1(is_space),
+                        http_version)
+            .map(|(method, _, uri, _, version)| {
+                Request {
+                    method: method,
+                    uri: uri,
+                    version: version,
+                }
+            });
+
+
+    let message_header_line = (take_while1(is_horizontal_space),
+                               take_while1(|c| c != b'\r' && c != b'\n'),
+                               end_of_line())
+            .map(|(_, line, _)| line);
+
+    let message_header = (take_while1(is_token), token(b':'), many1(message_header_line))
+        .map(|(name, _, value)| {
+                 Header {
+                     name: name,
+                     value: value,
+                 }
+             });
+
+    let mut request = (request_line, end_of_line(), many(message_header), end_of_line())
+        .map(|(request, _, headers, _)| (request, headers));
+
+    request.parse(input)
+}
+
+static REQUESTS: &'static [u8] = include_bytes!("http-requests.txt");
+
+#[bench]
+fn http_requests_small(b: &mut ::test::Bencher) {
+    http_requests_bench(b, REQUESTS)
+}
+
+#[bench]
+fn http_requests_large(b: &mut ::test::Bencher) {
+    use std::iter;
+
+    let mut buffer = Vec::with_capacity(REQUESTS.len() * 5);
+    for buf in iter::repeat(REQUESTS).take(5) {
+        buffer.extend_from_slice(buf);
+    }
+    http_requests_bench(b, &buffer)
+}
+
+fn http_requests_bench(b: &mut ::test::Bencher, buffer: &[u8]) {
+    b.iter(|| {
+        let mut i = 0;
+        let mut buf = test::black_box(buffer);
+
+        while !buf.is_empty() {
+            // Needed for inferrence for many(message_header)
+            match parse_http_request(buf) {
+                Ok(((_, _), b)) => {
+                    i += 1;
+
+                    buf = b
+                }
+                Err(ref err) if err.errors[0] == Error::end_of_input() => {
+                    test::black_box(i);
+                    return;
+                }
+                Err(err) => panic!("{:?}", err),
+            }
+        }
+    });
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/combine/benches/json.rs
@@ -0,0 +1,239 @@
+#![feature(test)]
+extern crate combine as pc;
+extern crate test;
+
+use std::collections::HashMap;
+use std::io::Read;
+use std::fs::File;
+use std::path::Path;
+
+use pc::primitives::{Consumed, Parser, ParseError, ParseResult, State, Stream, BufferedStream};
+use pc::combinator::{any, between, choice, many, many1, optional, parser, satisfy, sep_by, Expected,
+                     FnParser, Skip};
+use pc::char::{char, digit, spaces, Spaces, string};
+use pc::from_iter;
+
+#[derive(PartialEq, Debug)]
+enum Value {
+    Number(f64),
+    String(String),
+    Bool(bool),
+    Null,
+    Object(HashMap<String, Value>),
+    Array(Vec<Value>),
+}
+
+fn lex<P>(p: P) -> Skip<P, Spaces<P::Input>>
+    where P: Parser,
+          P::Input: Stream<Item = char>
+{
+    p.skip(spaces())
+}
+struct Json<I>(::std::marker::PhantomData<fn(I) -> I>);
+
+type FnPtrParser<O, I> = FnParser<I, fn(I) -> ParseResult<O, I>>;
+type JsonParser<O, I> = Expected<FnPtrParser<O, I>>;
+
+fn fn_parser<O, I>(f: fn(I) -> ParseResult<O, I>, err: &'static str) -> JsonParser<O, I>
+    where I: Stream<Item = char>
+{
+    parser(f).expected(err)
+}
+
+impl<I> Json<I>
+    where I: Stream<Item = char>
+{
+    fn integer() -> JsonParser<i64, I> {
+        fn_parser(Json::<I>::integer_, "integer")
+    }
+    fn integer_(input: I) -> ParseResult<i64, I> {
+        let (s, input) = try!(lex(many1::<String, _>(digit())).parse_lazy(input).into());
+        let mut n = 0;
+        for c in s.chars() {
+            n = n * 10 + (c as i64 - '0' as i64);
+        }
+        Ok((n, input))
+    }
+
+    fn number() -> JsonParser<f64, I> {
+        fn_parser(Json::<I>::number_, "number")
+    }
+    fn number_(input: I) -> ParseResult<f64, I> {
+        let i = char('0').map(|_| 0.0).or(Json::<I>::integer().map(|x| x as f64));
+        let fractional = many(digit()).map(|digits: String| {
+            let mut magnitude = 1.0;
+            digits.chars().fold(0.0, |acc, d| {
+                magnitude /= 10.0;
+                match d.to_digit(10) {
+                    Some(d) => acc + (d as f64) * magnitude,
+                    None => panic!("Not a digit"),
+                }
+            })
+        });
+
+        let exp = satisfy(|c| c == 'e' || c == 'E').with(optional(char('-'))
+                                                             .and(Json::<I>::integer()));
+        lex(optional(char('-'))
+                .and(i)
+                .map(|(sign, n)| if sign.is_some() { -n } else { n })
+                .and(optional(char('.')).with(fractional))
+                .map(|(x, y)| if x >= 0.0 { x + y } else { x - y })
+                .and(optional(exp))
+                .map(|(n, exp_option)| match exp_option {
+                         Some((sign, e)) => {
+            let e = if sign.is_some() { -e } else { e };
+            n * 10.0f64.powi(e as i32)
+        }
+                         None => n,
+                     }))
+                .parse_lazy(input)
+                .into()
+    }
+
+    fn char() -> JsonParser<char, I> {
+        fn_parser(Json::<I>::char_, "char")
+    }
+    fn char_(input: I) -> ParseResult<char, I> {
+        let (c, input) = try!(any().parse_lazy(input).into());
+        let mut back_slash_char = satisfy(|c| "\"\\/bfnrt".chars().any(|x| x == c)).map(|c| {
+            match c {
+                '"' => '"',
+                '\\' => '\\',
+                '/' => '/',
+                'b' => '\u{0008}',
+                'f' => '\u{000c}',
+                'n' => '\n',
+                'r' => '\r',
+                't' => '\t',
+                c => c,//Should never happen
+            }
+        });
+        match c {
+            '\\' => input.combine(|input| back_slash_char.parse_stream(input)),
+            '"' => {
+                Err(Consumed::Empty(ParseError::from_errors(input.into_inner().position(),
+                                                            Vec::new())))
+            }
+            _ => Ok((c, input)),
+        }
+    }
+    fn string() -> JsonParser<String, I> {
+        fn_parser(Json::<I>::string_, "string")
+    }
+    fn string_(input: I) -> ParseResult<String, I> {
+        between(char('"'), lex(char('"')), many(Json::<I>::char())).parse_lazy(input).into()
+    }
+
+    fn object() -> JsonParser<Value, I> {
+        fn_parser(Json::<I>::object_, "object")
+    }
+    fn object_(input: I) -> ParseResult<Value, I> {
+        let field = (Json::<I>::string(), lex(char(':')), Json::<I>::value()).map(|t| (t.0, t.2));
+        let fields = sep_by(field, lex(char(',')));
+        between(lex(char('{')), lex(char('}')), fields).map(Value::Object).parse_lazy(input).into()
+    }
+
+    fn value() -> FnPtrParser<Value, I> {
+        parser(Json::<I>::value_ as fn(_) -> _)
+    }
+    #[allow(unconditional_recursion)]
+    fn value_(input: I) -> ParseResult<Value, I> {
+        let mut array = between(lex(char('[')),
+                                lex(char(']')),
+                                sep_by(Json::<I>::value(), lex(char(','))))
+                .map(Value::Array);
+
+        choice::<[&mut Parser<Input = I, Output = Value>;
+                  7],
+                 _>([&mut Json::<I>::string().map(Value::String),
+                     &mut Json::<I>::object(),
+                     &mut array,
+                     &mut Json::<I>::number().map(Value::Number),
+                     &mut lex(string("false").map(|_| Value::Bool(false))),
+                     &mut lex(string("true").map(|_| Value::Bool(true))),
+                     &mut lex(string("null").map(|_| Value::Null))])
+                .parse_lazy(input)
+                .into()
+    }
+}
+
+#[test]
+fn json_test() {
+    use self::Value::*;
+    let input = r#"{
+    "array": [1, ""],
+    "object": {},
+    "number": 3.14,
+    "small_number": 0.59,
+    "int": -100,
+    "exp": -1e2,
+    "exp_neg": 23e-2,
+    "true": true,
+    "false"  : false,
+    "null" : null
+}"#;
+    let result = Json::value().parse(input);
+    let expected = Object(vec![("array", Array(vec![Number(1.0), String("".to_string())])),
+                               ("object", Object(HashMap::new())),
+                               ("number", Number(3.14)),
+                               ("small_number", Number(0.59)),
+                               ("int", Number(-100.)),
+                               ("exp", Number(-1e2)),
+                               ("exp_neg", Number(23E-2)),
+                               ("true", Bool(true)),
+                               ("false", Bool(false)),
+                               ("null", Null)]
+                                  .into_iter()
+                                  .map(|(k, v)| (k.to_string(), v))
+                                  .collect());
+    match result {
+        Ok(result) => assert_eq!(result, (expected, "")),
+        Err(e) => {
+            println!("{}", e);
+            assert!(false);
+        }
+    }
+}
+
+#[bench]
+fn bench_json(bencher: &mut ::test::Bencher) {
+    let mut data = String::new();
+    File::open(&Path::new(&"benches/data.json"))
+        .and_then(|mut file| file.read_to_string(&mut data))
+        .unwrap();
+    let mut parser = Json::value();
+    match parser.parse(State::new(&data[..])) {
+        Ok((Value::Array(_), _)) => (),
+        Ok(_) => assert!(false),
+        Err(err) => {
+            println!("{}", err);
+            assert!(false);
+        }
+    }
+    bencher.iter(|| {
+                     let result = parser.parse(State::new(&data[..]));
+                     ::test::black_box(result)
+                 });
+}
+
+#[bench]
+fn bench_buffered_json(bencher: &mut ::test::Bencher) {
+    let mut data = String::new();
+    File::open(&Path::new(&"benches/data.json"))
+        .and_then(|mut file| file.read_to_string(&mut data))
+        .unwrap();
+    bencher.iter(|| {
+        let buffer = BufferedStream::new(from_iter(data.chars()), 1);
+        let mut parser = Json::value();
+        match parser.parse(State::new(buffer.as_stream())) {
+            Ok((Value::Array(v), _)) => {
+                ::test::black_box(v);
+            }
+            Ok(_) => assert!(false),
+            Err(err) => {
+                println!("{}", err);
+                assert!(false);
+            }
+        }
+    });
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/combine/benches/mp4.rs
@@ -0,0 +1,70 @@
+#![cfg(feature = "mp4")]
+#![feature(test)]
+extern crate test;
+
+extern crate combine;
+extern crate byteorder;
+
+use test::{Bencher, black_box};
+
+use std::str::from_utf8;
+
+use byteorder::{BigEndian, ByteOrder};
+
+use combine::*;
+use combine::range::{range, take};
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+struct FileType<'a> {
+    major_brand: &'a str,
+    major_brand_version: &'a [u8],
+    compatible_brands: Vec<&'a str>,
+}
+
+#[derive(Clone, Debug)]
+enum MP4Box<'a> {
+    Ftyp(FileType<'a>),
+    Moov,
+    Mdat,
+    Free,
+    Skip,
+    Wide,
+    Unknown,
+}
+
+fn parse_mp4(data: &[u8]) -> Result<(Vec<MP4Box>, &[u8]), ParseError<&[u8]>> {
+    let brand_name = || take(4).and_then(from_utf8);
+    let filetype_box = (range(&b"ftyp"[..]), brand_name(), take(4), many(brand_name()))
+        .map(|(_, m, v, c)| {
+            MP4Box::Ftyp(FileType {
+                             major_brand: m,
+                             major_brand_version: v,
+                             compatible_brands: c,
+                         })
+        });
+
+    let mp4_box = take(4).map(BigEndian::read_u32).then(|offset| take(offset as usize - 4));
+    let mut box_parser = filetype_box.or(range(&b"moov"[..]).map(|_| MP4Box::Moov))
+        .or(range(&b"mdat"[..]).map(|_| MP4Box::Mdat))
+        .or(range(&b"free"[..]).map(|_| MP4Box::Free))
+        .or(range(&b"skip"[..]).map(|_| MP4Box::Skip))
+        .or(range(&b"wide"[..]).map(|_| MP4Box::Wide))
+        .or(value(MP4Box::Unknown));
+    let data_interpreter = mp4_box.flat_map(|box_data| box_parser.parse(box_data).map(|t| t.0));
+
+    many(data_interpreter).parse(data)
+}
+
+static MP4_SMALL: &'static [u8] = include_bytes!("small.mp4");
+
+fn run_test(b: &mut Bencher, data: &[u8]) {
+    b.iter(|| match parse_mp4(data) {
+               Ok(x) => black_box(x),
+               Err(err) => panic!("{:?}", err),
+           });
+}
+
+#[bench]
+fn mp4_small_test(b: &mut Bencher) {
+    run_test(b, MP4_SMALL)
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/combine/rustfmt.toml
@@ -0,0 +1,1 @@
+newline_style = "Native"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/combine/src/byte.rs
@@ -0,0 +1,240 @@
+extern crate ascii;
+
+use std::marker::PhantomData;
+
+use self::ascii::AsciiChar;
+
+use combinator::{Expected, satisfy, Satisfy, skip_many, SkipMany, token, Token, tokens, With};
+use primitives::{ConsumedResult, Info, Parser, ParseError, Stream};
+
+/// Parses a character and succeeds if the character is equal to `c`.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::byte::byte;
+/// # fn main() {
+/// let result = byte(b'!')
+///     .parse(&b"!"[..])
+///     .map(|x| x.0);
+/// assert_eq!(result, Ok(b'!'));
+/// # }
+/// ```
+#[inline(always)]
+pub fn byte<I>(c: u8) -> Token<I>
+    where I: Stream<Item = u8>
+{
+    token(c)
+}
+
+impl_token_parser! { Digit(), u8, Expected<Satisfy<I, fn (u8) -> bool>> }
+
+macro_rules! byte_parser {
+    ($name: ident, $ty : ident, $f : ident) => ({
+        let f = static_fn!((c, u8) -> bool {
+            AsciiChar::from(c).map(|c| c.$f()).unwrap_or(false)
+        });
+        $ty(satisfy(f).expected(stringify!($name)), PhantomData)
+    })
+}
+
+/// Parses a base-10 digit (0–9).
+#[inline(always)]
+pub fn digit<I>() -> Digit<I>
+    where I: Stream<Item = u8>
+{
+    byte_parser!(digit, Digit, is_digit)
+}
+
+impl_token_parser! { Space(), u8, Expected<Satisfy<I, fn (u8) -> bool>> }
+
+/// Parses a `b' '`, `b'\t'`, `b'\n'` or `'b\'r'`.
+#[inline(always)]
+pub fn space<I>() -> Space<I>
+    where I: Stream<Item = u8>
+{
+    byte_parser!(space, Space, is_whitespace)
+}
+
+impl_token_parser! { Spaces(), u8, Expected<SkipMany<Space<I>>> }
+/// Skips over [`space`] zero or more times
+///
+/// [`space`]: fn.space.html
+#[inline(always)]
+pub fn spaces<I>() -> Spaces<I>
+    where I: Stream<Item = u8>
+{
+    Spaces(skip_many(space()).expected("whitespaces"), PhantomData)
+}
+
+impl_token_parser! { Newline(), u8, Expected<Satisfy<I, fn (u8) -> bool>> }
+
+/// Parses a newline character (`b'\n'`).
+#[inline(always)]
+pub fn newline<I>() -> Newline<I>
+    where I: Stream<Item = u8>
+{
+    Newline(satisfy(static_fn!((ch, u8) -> bool { ch == b'\n' })).expected("lf newline"),
+            PhantomData)
+}
+
+impl_token_parser! { CrLf(), u8, Expected<With<Satisfy<I, fn (u8) -> bool>, Newline<I>>> }
+
+/// Parses carriage return and newline (`b"\r\n"`), returning the newline character.
+#[inline(always)]
+pub fn crlf<I>() -> CrLf<I>
+    where I: Stream<Item = u8>
+{
+    CrLf(satisfy(static_fn!((ch, u8) -> bool { ch == b'\r' }))
+             .with(newline())
+             .expected("crlf newline"),
+         PhantomData)
+}
+
+impl_token_parser! { Tab(), u8, Expected<Satisfy<I, fn (u8) -> bool>> }
+/// Parses a tab character (`b'\t'`).
+#[inline(always)]
+pub fn tab<I>() -> Tab<I>
+    where I: Stream<Item = u8>
+{
+    Tab(satisfy(static_fn!((ch, u8) -> bool { ch == b'\t' })).expected("tab"),
+        PhantomData)
+}
+
+impl_token_parser! { Upper(), u8, Expected<Satisfy<I, fn (u8) -> bool>> }
+/// Parses an uppercase ASCII letter (A–Z).
+#[inline(always)]
+pub fn upper<I>() -> Upper<I>
+    where I: Stream<Item = u8>
+{
+    byte_parser!(upper, Upper, is_uppercase)
+}
+
+impl_token_parser! { Lower(), u8, Expected<Satisfy<I, fn (u8) -> bool>> }
+/// Parses an lowercase ASCII letter (a–z).
+#[inline(always)]
+pub fn lower<I>() -> Lower<I>
+    where I: Stream<Item = u8>
+{
+    byte_parser!(lower, Lower, is_lowercase)
+}
+
+impl_token_parser! { AlphaNum(), u8, Expected<Satisfy<I, fn (u8) -> bool>> }
+/// Parses either an ASCII alphabet letter or digit (a–z, A–Z, 0–9).
+#[inline(always)]
+pub fn alpha_num<I>() -> AlphaNum<I>
+    where I: Stream<Item = u8>
+{
+    byte_parser!(alpha_num, AlphaNum, is_alphanumeric)
+}
+
+impl_token_parser! { Letter(), u8, Expected<Satisfy<I, fn (u8) -> bool>> }
+/// Parses an ASCII alphabet letter (a–z, A–Z).
+#[inline(always)]
+pub fn letter<I>() -> Letter<I>
+    where I: Stream<Item = u8>
+{
+    byte_parser!(letter, Letter, is_alphabetic)
+}
+
+impl_token_parser! { HexDigit(), u8, Expected<Satisfy<I, fn (u8) -> bool>> }
+/// Parses an ASCII hexdecimal digit (accepts both uppercase and lowercase).
+#[inline(always)]
+pub fn hex_digit<I>() -> HexDigit<I>
+    where I: Stream<Item = u8>
+{
+    byte_parser!(hex_digit, HexDigit, is_hex)
+}
+
+#[derive(Clone)]
+pub struct Bytes<I>(&'static [u8], PhantomData<I>) where I: Stream<Item = u8>;
+
+impl<'a, I> Parser for Bytes<I>
+    where I: Stream<Item = u8, Range = &'a [u8]>
+{
+    type Input = I;
+    type Output = &'static [u8];
+    #[inline]
+    fn parse_lazy(&mut self, input: Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+        tokens(|&l, r| l == r, Info::Range(self.0), self.0.iter())
+            .parse_lazy(input)
+            .map(|chars| chars.as_slice())
+    }
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        tokens(|&l, r| l == r, Info::Range(self.0), self.0.iter()).add_error(errors)
+    }
+}
+
+/// Parses the bytes `s`.
+///
+/// If you have a stream implementing [`RangeStream`] such as `&[u8]` you can also use the
+/// [`range`] parser which may be more efficient.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::byte::bytes;
+/// # fn main() {
+/// let result = bytes(b"rust")
+///     .parse(&b"rust"[..])
+///     .map(|x| x.0);
+/// assert_eq!(result, Ok(&b"rust"[..]));
+/// # }
+/// ```
+///
+/// [`RangeStream`]: ../primitives/trait.RangeStream.html
+/// [`range`]: ../range/fn.range.html
+#[inline(always)]
+pub fn bytes<'a, I>(s: &'static [u8]) -> Bytes<I>
+    where I: Stream<Item = u8, Range = &'a [u8]>
+{
+    Bytes(s, PhantomData)
+}
+
+#[derive(Clone)]
+pub struct BytesCmp<C, I>(&'static [u8], C, PhantomData<I>) where I: Stream<Item = u8>;
+
+impl<'a, C, I> Parser for BytesCmp<C, I>
+    where C: FnMut(u8, u8) -> bool,
+          I: Stream<Item = u8, Range = &'a [u8]>
+{
+    type Input = I;
+    type Output = &'static [u8];
+    #[inline]
+    fn parse_lazy(&mut self, input: Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+        let cmp = &mut self.1;
+        tokens(|&l, r| cmp(l, r), Info::Range(self.0), self.0).parse_lazy(input)
+    }
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        let cmp = &mut self.1;
+        tokens(|&l, r| cmp(l, r), Info::Range(self.0), self.0.iter()).add_error(errors)
+    }
+}
+
+/// Parses the bytes `s` using `cmp` to compare each token.
+///
+/// If you have a stream implementing [`RangeStream`] such as `&[u8]` you can also use the
+/// [`range`] parser which may be more efficient.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::byte::bytes_cmp;
+/// # use combine::primitives::Info;
+/// # fn main() {
+/// use std::ascii::AsciiExt;
+/// let result = bytes_cmp(&b"abc"[..], |l, r| l.eq_ignore_ascii_case(&r))
+///     .parse(&b"AbC"[..]);
+/// assert_eq!(result, Ok((&b"abc"[..], &b""[..])));
+/// # }
+/// ```
+///
+/// [`RangeStream`]: ../primitives/trait.RangeStream.html
+/// [`range`]: ../range/fn.range.html
+#[inline(always)]
+pub fn bytes_cmp<'a, C, I>(s: &'static [u8], cmp: C) -> BytesCmp<C, I>
+    where C: FnMut(u8, u8) -> bool,
+          I: Stream<Item = u8, Range = &'a [u8]>
+{
+    BytesCmp(s, cmp, PhantomData)
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/combine/src/char.rs
@@ -0,0 +1,294 @@
+use primitives::{Parser, ParseError, ConsumedResult, Stream};
+use combinator::{Expected, satisfy, Satisfy, skip_many, SkipMany, token, Token, tokens, With};
+use std::marker::PhantomData;
+
+/// Parses a character and succeeds if the character is equal to `c`.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::char::char;
+/// # fn main() {
+/// let result = char('!')
+///     .parse("!")
+///     .map(|x| x.0);
+/// assert_eq!(result, Ok('!'));
+/// # }
+/// ```
+#[inline(always)]
+pub fn char<I>(c: char) -> Token<I>
+    where I: Stream<Item = char>
+{
+    token(c)
+}
+
+impl_token_parser! { Digit(), char, Expected<Satisfy<I, fn (char) -> bool>> }
+
+/// Parses a base-10 digit.
+#[inline(always)]
+pub fn digit<I>() -> Digit<I>
+    where I: Stream<Item = char>
+{
+    Digit(satisfy(static_fn!((c, char) -> bool { c.is_digit(10) })).expected("digit"),
+          PhantomData)
+}
+
+impl_token_parser! { Space(), char, Expected<Satisfy<I, fn (char) -> bool>> }
+
+/// Parse a single whitespace according to [`std::char::is_whitespace`].
+///
+/// This includes space characters, tabs and newlines.
+///
+/// [`std::char::is_whitespace`]: https://doc.rust-lang.org/std/primitive.char.html#method.is_whitespace
+#[inline(always)]
+pub fn space<I>() -> Space<I>
+    where I: Stream<Item = char>
+{
+    let f: fn(char) -> bool = char::is_whitespace;
+    Space(satisfy(f).expected("whitespace"), PhantomData)
+}
+
+impl_token_parser! { Spaces(), char, Expected<SkipMany<Space<I>>> }
+
+/// Skips over zero or more spaces according to [`std::char::is_whitespace`].
+///
+/// This includes space characters, tabs and newlines.
+///
+/// [`std::char::is_whitespace`]: https://doc.rust-lang.org/std/primitive.char.html#method.is_whitespace
+#[inline(always)]
+pub fn spaces<I>() -> Spaces<I>
+    where I: Stream<Item = char>
+{
+    Spaces(skip_many(space()).expected("whitespaces"), PhantomData)
+}
+
+impl_token_parser! { Newline(), char, Expected<Satisfy<I, fn (char) -> bool>> }
+
+/// Parses a newline character.
+#[inline(always)]
+pub fn newline<I>() -> Newline<I>
+    where I: Stream<Item = char>
+{
+    Newline(satisfy(static_fn!((ch, char) -> bool { ch == '\n' })).expected("lf newline"),
+            PhantomData)
+}
+
+impl_token_parser! { CrLf(), char, Expected<With<Satisfy<I, fn (char) -> bool>, Newline<I>>> }
+
+/// Parses carriage return and newline, returning the newline character.
+#[inline(always)]
+pub fn crlf<I>() -> CrLf<I>
+    where I: Stream<Item = char>
+{
+    CrLf(satisfy(static_fn!((ch, char) -> bool { ch == '\r' }))
+             .with(newline())
+             .expected("crlf newline"),
+         PhantomData)
+}
+
+impl_token_parser! { Tab(), char, Expected<Satisfy<I, fn (char) -> bool>> }
+
+/// Parses a tab character.
+#[inline(always)]
+pub fn tab<I>() -> Tab<I>
+    where I: Stream<Item = char>
+{
+    Tab(satisfy(static_fn!((ch, char) -> bool { ch == '\t' })).expected("tab"),
+        PhantomData)
+}
+
+impl_token_parser! { Upper(), char, Expected<Satisfy<I, fn (char) -> bool>> }
+
+/// Parses an uppercase letter according to [`std::char::is_uppercase`].
+///
+/// [`std::char::is_uppercase`]: https://doc.rust-lang.org/std/primitive.char.html#method.is_uppercase
+#[inline(always)]
+pub fn upper<I>() -> Upper<I>
+    where I: Stream<Item = char>
+{
+    Upper(satisfy(static_fn!((ch, char) -> bool { ch.is_uppercase()})).expected("uppercase letter"),
+          PhantomData)
+}
+
+impl_token_parser! { Lower(), char, Expected<Satisfy<I, fn (char) -> bool>> }
+
+/// Parses an lowercase letter according to [`std::char::is_lowercase`].
+///
+/// [`std::char::is_lowercase`]: https://doc.rust-lang.org/std/primitive.char.html#method.is_lowercase
+#[inline(always)]
+pub fn lower<I>() -> Lower<I>
+    where I: Stream<Item = char>
+{
+    Lower(satisfy(static_fn!((ch, char) -> bool { ch.is_lowercase() }))
+              .expected("lowercase letter"),
+          PhantomData)
+}
+
+impl_token_parser! { AlphaNum(), char, Expected<Satisfy<I, fn (char) -> bool>> }
+
+/// Parses either an alphabet letter or digit according to [`std::char::is_alphanumeric`].
+///
+/// [`std::char::is_alphanumeric`]: https://doc.rust-lang.org/std/primitive.char.html#method.is_alphanumeric
+#[inline(always)]
+pub fn alpha_num<I>() -> AlphaNum<I>
+    where I: Stream<Item = char>
+{
+    AlphaNum(satisfy(static_fn!((ch, char) -> bool { ch.is_alphanumeric() }))
+                 .expected("letter or digit"),
+             PhantomData)
+}
+
+impl_token_parser! { Letter(), char, Expected<Satisfy<I, fn (char) -> bool>> }
+
+/// Parses an alphabet letter according to [`std::char::is_alphabetic`].
+///
+/// [`std::char::is_alphabetic`]: https://doc.rust-lang.org/std/primitive.char.html#method.is_alphabetic
+#[inline(always)]
+pub fn letter<I>() -> Letter<I>
+    where I: Stream<Item = char>
+{
+    Letter(satisfy(static_fn!((ch, char) -> bool { ch.is_alphabetic() })).expected("letter"),
+           PhantomData)
+}
+
+impl_token_parser! { OctDigit(), char, Expected<Satisfy<I, fn (char) -> bool>> }
+
+/// Parses an octal digit.
+#[inline(always)]
+pub fn oct_digit<I>() -> OctDigit<I>
+    where I: Stream<Item = char>
+{
+    OctDigit(satisfy(static_fn!((ch, char) -> bool { ch.is_digit(8) })).expected("octal digit"),
+             PhantomData)
+}
+
+impl_token_parser! { HexDigit(), char, Expected<Satisfy<I, fn (char) -> bool>> }
+
+/// Parses a hexdecimal digit with uppercase and lowercase.
+#[inline(always)]
+pub fn hex_digit<I>() -> HexDigit<I>
+    where I: Stream<Item = char>
+{
+    HexDigit(satisfy(static_fn!((ch, char) -> bool { ch.is_digit(0x10) }))
+                 .expected("hexadecimal digit"),
+             PhantomData)
+}
+
+fn eq(l: char, r: char) -> bool {
+    l == r
+}
+
+#[derive(Clone)]
+pub struct Str<I>(&'static str, PhantomData<fn(I) -> I>) where I: Stream<Item = char>;
+impl<I> Parser for Str<I>
+    where I: Stream<Item = char>
+{
+    type Input = I;
+    type Output = &'static str;
+    #[inline]
+    fn parse_lazy(&mut self, input: Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+        tokens(eq, self.0.into(), self.0.chars()).parse_lazy(input).map(|_| self.0)
+    }
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        tokens(eq, self.0.into(), self.0.chars()).add_error(errors)
+    }
+}
+
+/// Parses the string `s`.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::char::string;
+/// # fn main() {
+/// let result = string("rust")
+///     .parse("rust")
+///     .map(|x| x.0);
+/// assert_eq!(result, Ok("rust"));
+/// # }
+/// ```
+#[inline(always)]
+pub fn string<I>(s: &'static str) -> Str<I>
+    where I: Stream<Item = char>
+{
+    Str(s, PhantomData)
+}
+
+#[derive(Clone)]
+pub struct StrCmp<C, I>(&'static str, C, PhantomData<fn(I) -> I>) where I: Stream<Item = char>;
+impl<C, I> Parser for StrCmp<C, I>
+    where C: FnMut(char, char) -> bool,
+          I: Stream<Item = char>
+{
+    type Input = I;
+    type Output = &'static str;
+    #[inline]
+    fn parse_lazy(&mut self, input: Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+        tokens(&mut self.1, self.0.into(), self.0.chars()).parse_lazy(input).map(|_| self.0)
+    }
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        tokens(&mut self.1, self.0.into(), self.0.chars()).add_error(errors)
+    }
+}
+
+/// Parses the string `s`, using `cmp` to compare each character.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::char::string_cmp;
+/// use std::ascii::AsciiExt;
+/// # fn main() {
+/// let result = string_cmp("rust", |l, r| l.eq_ignore_ascii_case(&r))
+///     .parse("RusT")
+///     .map(|x| x.0);
+/// assert_eq!(result, Ok("rust"));
+/// # }
+/// ```
+#[inline(always)]
+pub fn string_cmp<C, I>(s: &'static str, cmp: C) -> StrCmp<C, I>
+    where C: FnMut(char, char) -> bool,
+          I: Stream<Item = char>
+{
+    StrCmp(s, cmp, PhantomData)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use primitives::{Error, ParseError, Parser, SourcePosition, State};
+
+    #[test]
+    fn space_error() {
+        let result = space().parse("");
+        assert!(result.is_err());
+        assert_eq!(result.unwrap_err().errors,
+                   vec![Error::end_of_input(), Error::Expected("whitespace".into())]);
+
+    }
+
+    #[test]
+    fn string_consumed() {
+        let result = string("a").parse(State::new("b"));
+        assert!(result.is_err());
+        assert_eq!(result.unwrap_err().position,
+                   SourcePosition {
+                       line: 1,
+                       column: 1,
+                   });
+    }
+
+    #[test]
+    fn string_error() {
+        let result = string("abc").parse(State::new("bc"));
+        assert_eq!(result,
+                   Err(ParseError {
+                           position: SourcePosition {
+                               line: 1,
+                               column: 1,
+                           },
+                           errors: vec![Error::Unexpected('b'.into()),
+                                        Error::Expected("abc".into())],
+                       }));
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/combine/src/combinator.rs
@@ -0,0 +1,2235 @@
+use std::iter::FromIterator;
+use std::marker::PhantomData;
+use primitives::{Info, Parser, ParseResult, ConsumedResult, ParseError, Stream, StreamOnce, Error,
+                 Consumed};
+use primitives::FastResult::*;
+
+macro_rules! impl_parser {
+    ($name: ident ($first: ident, $($ty_var: ident),*), $inner_type: ty) => {
+    #[derive(Clone)]
+    pub struct $name<$first $(,$ty_var)*>($inner_type)
+        where $first: Parser $(,$ty_var : Parser<Input=<$first as Parser>::Input>)*;
+    impl <$first, $($ty_var),*> Parser for $name<$first $(,$ty_var)*>
+        where $first: Parser $(, $ty_var : Parser<Input=<$first as Parser>::Input>)* {
+        type Input = <$first as Parser>::Input;
+        type Output = <$inner_type as Parser>::Output;
+        fn parse_stream(&mut self,
+                       input: Self::Input) -> ParseResult<Self::Output, Self::Input> {
+            self.0.parse_stream(input)
+        }
+        fn parse_stream_consumed(&mut self,
+                      input: Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+            self.0.parse_stream_consumed(input)
+        }
+        fn parse_lazy(&mut self,
+                      input: Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+            self.0.parse_lazy(input)
+        }
+        fn add_error(&mut self, error: &mut ParseError<Self::Input>) {
+            self.0.add_error(error)
+        }
+    }
+}
+}
+
+#[derive(Clone)]
+pub struct Any<I>(PhantomData<fn(I) -> I>);
+
+impl<I> Parser for Any<I>
+    where I: Stream
+{
+    type Input = I;
+    type Output = I::Item;
+    #[inline]
+    fn parse_lazy(&mut self, mut input: I) -> ConsumedResult<I::Item, I> {
+        let position = input.position();
+        match input.uncons() {
+            Ok(x) => ConsumedOk((x, input)),
+            Err(err) => ConsumedErr(ParseError::new(position, err)),
+        }
+    }
+}
+
+/// Parses any token.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # fn main() {
+/// let mut char_parser = any();
+/// assert_eq!(char_parser.parse("!").map(|x| x.0), Ok('!'));
+/// assert!(char_parser.parse("").is_err());
+/// let mut byte_parser = any();
+/// assert_eq!(byte_parser.parse(&b"!"[..]).map(|x| x.0), Ok(b'!'));
+/// assert!(byte_parser.parse(&b""[..]).is_err());
+/// # }
+/// ```
+#[inline(always)]
+pub fn any<I>() -> Any<I>
+    where I: Stream
+{
+    Any(PhantomData)
+}
+
+
+
+#[derive(Clone)]
+pub struct Satisfy<I, P> {
+    predicate: P,
+    _marker: PhantomData<I>,
+}
+
+fn satisfy_impl<I, P, R>(mut input: I, mut predicate: P) -> ConsumedResult<R, I>
+    where I: Stream,
+          P: FnMut(I::Item) -> Option<R>
+{
+    let position = input.position();
+    match input.uncons() {
+        Ok(c) => {
+            match predicate(c.clone()) {
+                Some(c) => ConsumedOk((c, input)),
+                None => EmptyErr(ParseError::empty(position)),
+            }
+        }
+        Err(err) => EmptyErr(ParseError::new(position, err)),
+    }
+}
+
+impl<I, P> Parser for Satisfy<I, P>
+    where I: Stream,
+          P: FnMut(I::Item) -> bool
+{
+    type Input = I;
+    type Output = I::Item;
+    #[inline]
+    fn parse_lazy(&mut self, input: I) -> ConsumedResult<I::Item, I> {
+        satisfy_impl(input, |c| if (self.predicate)(c.clone()) {
+            Some(c)
+        } else {
+            None
+        })
+    }
+}
+
+/// Parses a token and succeeds depending on the result of `predicate`.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # fn main() {
+/// let mut parser = satisfy(|c| c == '!' || c == '?');
+/// assert_eq!(parser.parse("!").map(|x| x.0), Ok('!'));
+/// assert_eq!(parser.parse("?").map(|x| x.0), Ok('?'));
+/// # }
+/// ```
+#[inline(always)]
+pub fn satisfy<I, P>(predicate: P) -> Satisfy<I, P>
+    where I: Stream,
+          P: FnMut(I::Item) -> bool
+{
+    Satisfy {
+        predicate: predicate,
+        _marker: PhantomData,
+    }
+}
+
+#[derive(Clone)]
+pub struct SatisfyMap<I, P> {
+    predicate: P,
+    _marker: PhantomData<I>,
+}
+
+impl<I, P, R> Parser for SatisfyMap<I, P>
+    where I: Stream,
+          P: FnMut(I::Item) -> Option<R>
+{
+    type Input = I;
+    type Output = R;
+    #[inline]
+    fn parse_lazy(&mut self, input: I) -> ConsumedResult<R, I> {
+        satisfy_impl(input, &mut self.predicate)
+    }
+}
+
+/// Parses a token and passes it to `predicate`. If `predicate` returns `Some` the parser succeeds
+/// and returns the value inside the `Option`. If `predicate` returns `None` the parser fails
+/// without consuming any input.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # fn main() {
+/// #[derive(Debug, PartialEq)]
+/// enum YesNo {
+///     Yes,
+///     No,
+/// }
+/// let mut parser = satisfy_map(|c| {
+///     match c {
+///         'Y' => Some(YesNo::Yes),
+///         'N' => Some(YesNo::No),
+///         _ => None,
+///     }
+/// });
+/// assert_eq!(parser.parse("Y").map(|x| x.0), Ok(YesNo::Yes));
+/// assert!(parser.parse("A").map(|x| x.0).is_err());
+/// # }
+/// ```
+#[inline(always)]
+pub fn satisfy_map<I, P, R>(predicate: P) -> SatisfyMap<I, P>
+    where I: Stream,
+          P: FnMut(I::Item) -> Option<R>
+{
+    SatisfyMap {
+        predicate: predicate,
+        _marker: PhantomData,
+    }
+}
+
+#[derive(Clone)]
+pub struct Token<I>
+    where I: Stream,
+          I::Item: PartialEq
+{
+    c: I::Item,
+    _marker: PhantomData<I>,
+}
+
+impl<I> Parser for Token<I>
+    where I: Stream,
+          I::Item: PartialEq + Clone
+{
+    type Input = I;
+    type Output = I::Item;
+    #[inline]
+    fn parse_lazy(&mut self, input: I) -> ConsumedResult<I::Item, I> {
+        satisfy_impl(input, |c| if c == self.c { Some(c) } else { None })
+    }
+    fn add_error(&mut self, error: &mut ParseError<Self::Input>) {
+        error.errors.push(Error::Expected(Info::Token(self.c.clone())));
+    }
+}
+
+/// Parses a character and succeeds if the character is equal to `c`.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # fn main() {
+/// let result = token('!')
+///     .parse("!")
+///     .map(|x| x.0);
+/// assert_eq!(result, Ok('!'));
+/// # }
+/// ```
+#[inline(always)]
+pub fn token<I>(c: I::Item) -> Token<I>
+    where I: Stream,
+          I::Item: PartialEq
+{
+    Token {
+        c: c,
+        _marker: PhantomData,
+    }
+}
+
+#[derive(Clone)]
+pub struct Tokens<C, T, I>
+    where I: Stream
+{
+    cmp: C,
+    expected: Info<I::Item, I::Range>,
+    tokens: T,
+    _marker: PhantomData<I>,
+}
+
+impl<C, T, I> Parser for Tokens<C, T, I>
+    where C: FnMut(T::Item, I::Item) -> bool,
+          T: Clone + IntoIterator,
+          I: Stream
+{
+    type Input = I;
+    type Output = T;
+    #[inline]
+    fn parse_lazy(&mut self, mut input: I) -> ConsumedResult<T, I> {
+        let start = input.position();
+        let mut consumed = false;
+        for c in self.tokens.clone() {
+            match ::primitives::uncons(input) {
+                Ok((other, rest)) => {
+                    if !(self.cmp)(c, other.clone()) {
+                        return if consumed {
+                                   let errors = vec![Error::Unexpected(Info::Token(other)),
+                                              Error::Expected(self.expected.clone())];
+                                   let error = ParseError::from_errors(start, errors);
+                                   ConsumedErr(error)
+                               } else {
+                                   EmptyErr(ParseError::empty(start))
+                               };
+                    }
+                    consumed = true;
+                    input = rest.into_inner();
+                }
+                Err(error) => {
+                    return error.combine_consumed(|mut error| {
+                        error.position = start;
+                        if consumed {
+                            ConsumedErr(error)
+                        } else {
+                            EmptyErr(error)
+                        }
+                    })
+                }
+            }
+        }
+        if consumed {
+            ConsumedOk((self.tokens.clone(), input))
+        } else {
+            EmptyOk((self.tokens.clone(), input))
+        }
+    }
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        errors.add_error(Error::Expected(self.expected.clone()));
+    }
+}
+
+/// Parses multiple tokens.
+///
+/// Consumes items from the input and compares them to the values from `tokens` using the
+/// comparison function `cmp`. Succeeds if all the items from `tokens` are matched in the input
+/// stream and fails otherwise with `expected` used as part of the error.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::primitives::Info;
+/// # fn main() {
+/// use std::ascii::AsciiExt;
+/// let result = tokens(|l, r| l.eq_ignore_ascii_case(&r), "abc".into(), "abc".chars())
+///     .parse("AbC")
+///     .map(|x| x.0.as_str());
+/// assert_eq!(result, Ok("abc"));
+/// let result = tokens(|&l, r| (if l < r { r - l } else { l - r }) <= 2, Info::Range(&b"025"[..]), &b"025"[..])
+///     .parse(&b"123"[..])
+///     .map(|x| x.0);
+/// assert_eq!(result, Ok(&b"025"[..]));
+/// # }
+/// ```
+#[inline(always)]
+pub fn tokens<C, T, I>(cmp: C, expected: Info<I::Item, I::Range>, tokens: T) -> Tokens<C, T, I>
+    where C: FnMut(T::Item, I::Item) -> bool,
+          T: Clone + IntoIterator,
+          I: Stream
+{
+    Tokens {
+        cmp: cmp,
+        expected: expected,
+        tokens: tokens,
+        _marker: PhantomData,
+    }
+}
+
+
+#[derive(Clone)]
+pub struct Position<I>
+    where I: Stream
+{
+    _marker: PhantomData<I>,
+}
+
+impl<I> Parser for Position<I>
+    where I: Stream
+{
+    type Input = I;
+    type Output = I::Position;
+
+    #[inline]
+    fn parse_lazy(&mut self, input: I) -> ConsumedResult<I::Position, I> {
+        EmptyOk((input.position(), input))
+    }
+}
+
+/// Parser which just returns the current position in the stream.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::primitives::SourcePosition;
+/// # fn main() {
+/// let result = (position(), token('!'), position())
+///     .parse(State::new("!"))
+///     .map(|x| x.0);
+/// assert_eq!(result, Ok((SourcePosition { line: 1, column: 1 },
+///                        '!',
+///                        SourcePosition { line: 1, column: 2 })));
+/// # }
+/// ```
+#[inline(always)]
+pub fn position<I>() -> Position<I>
+    where I: Stream
+{
+    Position { _marker: PhantomData }
+}
+
+#[derive(Clone)]
+pub struct Choice<S, P>(S, PhantomData<P>);
+
+impl<I, O, S, P> Parser for Choice<S, P>
+    where I: Stream,
+          S: AsMut<[P]>,
+          P: Parser<Input = I, Output = O>
+{
+    type Input = I;
+    type Output = O;
+    #[inline]
+    fn parse_lazy(&mut self, input: I) -> ConsumedResult<O, I> {
+        let mut empty_err = None;
+        for p in AsMut::as_mut(&mut self.0) {
+            match p.parse_lazy(input.clone()) {
+                consumed_err @ ConsumedErr(_) => return consumed_err,
+                EmptyErr(err) => {
+                    empty_err = match empty_err {
+                        None => Some(err),
+                        Some(prev_err) => Some(prev_err.merge(err)),
+                    };
+                }
+                ok @ ConsumedOk(_) |
+                ok @ EmptyOk(_) => return ok,
+            }
+        }
+        EmptyErr(match empty_err {
+                     None => {
+                         ParseError::new(input.position(),
+                                         Error::Message("parser choice is empty".into()))
+                     }
+                     Some(err) => err,
+                 })
+    }
+    fn add_error(&mut self, error: &mut ParseError<Self::Input>) {
+        for p in self.0.as_mut() {
+            p.add_error(error);
+        }
+    }
+}
+
+#[derive(Clone)]
+pub struct OneOf<T, I>
+    where I: Stream
+{
+    tokens: T,
+    _marker: PhantomData<I>,
+}
+
+impl<T, I> Parser for OneOf<T, I>
+    where T: Clone + IntoIterator<Item = I::Item>,
+          I: Stream,
+          I::Item: PartialEq
+{
+    type Input = I;
+    type Output = I::Item;
+
+    #[inline]
+    fn parse_lazy(&mut self, input: I) -> ConsumedResult<I::Item, I> {
+        satisfy(|c| {
+                    self.tokens
+                        .clone()
+                        .into_iter()
+                        .any(|t| t == c)
+                })
+                .parse_lazy(input)
+    }
+
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        for expected in self.tokens.clone() {
+            errors.add_error(Error::Expected(Info::Token(expected)));
+        }
+    }
+}
+
+/// Extract one token and succeeds if it is part of `tokens`.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::primitives::Info;
+/// # fn main() {
+/// let result = many(one_of("abc".chars()))
+///     .parse("abd");
+/// assert_eq!(result, Ok((String::from("ab"), "d")));
+/// # }
+/// ```
+#[inline(always)]
+pub fn one_of<T, I>(tokens: T) -> OneOf<T, I>
+    where T: Clone + IntoIterator,
+          I: Stream,
+          I::Item: PartialEq<T::Item>
+{
+    OneOf {
+        tokens: tokens,
+        _marker: PhantomData,
+    }
+}
+
+#[derive(Clone)]
+pub struct NoneOf<T, I>
+    where I: Stream
+{
+    tokens: T,
+    _marker: PhantomData<I>,
+}
+
+impl<T, I> Parser for NoneOf<T, I>
+    where T: Clone + IntoIterator<Item = I::Item>,
+          I: Stream,
+          I::Item: PartialEq
+{
+    type Input = I;
+    type Output = I::Item;
+
+    #[inline]
+    fn parse_lazy(&mut self, input: I) -> ConsumedResult<I::Item, I> {
+        satisfy(|c| {
+                    self.tokens
+                        .clone()
+                        .into_iter()
+                        .all(|t| t != c)
+                })
+                .parse_lazy(input)
+    }
+}
+
+/// Extract one token and succeeds if it is not part of `tokens`.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::primitives::{BytePosition, Error, Info};
+/// # fn main() {
+/// let mut parser = many1(none_of(b"abc".iter().cloned()));
+/// let result = parser.parse(State::new(&b"xyb"[..]))
+///     .map(|(output, input)| (output, input.input));
+/// assert_eq!(result, Ok((b"xy"[..].to_owned(), &b"b"[..])));
+///
+/// let result = parser.parse(State::new(&b"ab"[..]));
+/// assert_eq!(result, Err(ParseError {
+///     position: BytePosition { position: 0 },
+///     errors: vec![
+///         Error::Unexpected(Info::Token(b'a')),
+///     ]
+/// }));
+/// # }
+/// ```
+#[inline(always)]
+pub fn none_of<T, I>(tokens: T) -> NoneOf<T, I>
+    where T: Clone + IntoIterator,
+          I: Stream,
+          I::Item: PartialEq<T::Item>
+{
+    NoneOf {
+        tokens: tokens,
+        _marker: PhantomData,
+    }
+}
+
+#[derive(Clone)]
+pub struct Count<F, P> {
+    parser: P,
+    count: usize,
+    _marker: PhantomData<fn() -> F>,
+}
+
+impl<P, F> Parser for Count<F, P>
+    where P: Parser,
+          F: FromIterator<P::Output>
+{
+    type Input = P::Input;
+    type Output = F;
+
+    #[inline]
+    fn parse_lazy(&mut self, input: P::Input) -> ConsumedResult<F, P::Input> {
+        let mut iter = self.parser.by_ref().iter(input);
+        let value = iter.by_ref().take(self.count).collect();
+        iter.into_result_fast(value)
+    }
+
+    fn add_error(&mut self, error: &mut ParseError<Self::Input>) {
+        self.parser.add_error(error)
+    }
+}
+
+/// Parses `parser` from zero up to `count` times.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::primitives::{BytePosition, Error, Info};
+/// # fn main() {
+/// let mut parser = count(2, token(b'a'));
+///
+/// let result = parser.parse(&b"aaab"[..]);
+/// assert_eq!(result, Ok((b"aa"[..].to_owned(), &b"ab"[..])));
+/// # }
+/// ```
+#[inline(always)]
+pub fn count<F, P>(count: usize, parser: P) -> Count<F, P>
+    where P: Parser,
+          F: FromIterator<P::Output>
+{
+    Count {
+        parser: parser,
+        count: count,
+        _marker: PhantomData,
+    }
+}
+
+/// Takes an array of parsers and tries to apply them each in order.
+/// Fails if all the parsers fails or if an applied parser consumes input before failing.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::char::string;
+/// # use combine::primitives::Error;
+/// # fn main() {
+/// let mut parser = choice([string("Apple"), string("Banana"), string("Orange")]);
+/// assert_eq!(parser.parse("Banana"), Ok(("Banana", "")));
+/// assert_eq!(parser.parse("Orangexx"), Ok(("Orange", "xx")));
+/// assert!(parser.parse("Appl").is_err());
+/// assert!(parser.parse("Pear").is_err());
+///
+/// let mut parser2 = choice([string("one"), string("two"), string("three")]);
+/// // Fails as the parser for "two" consumes the first 't' before failing
+/// assert!(parser2.parse("three").is_err());
+///
+/// // Use 'try' to make failing parsers always act as if they have not consumed any input
+/// let mut parser3 = choice([try(string("one")), try(string("two")), try(string("three"))]);
+/// assert_eq!(parser3.parse("three"), Ok(("three", "")));
+/// # }
+/// ```
+#[inline(always)]
+pub fn choice<S, P>(ps: S) -> Choice<S, P>
+    where S: AsMut<[P]>,
+          P: Parser
+{
+    Choice(ps, PhantomData)
+}
+
+/// Takes a number of parsers and tries to apply them each in order.
+/// Fails if all the parsers fails or if an applied parser consumes input before failing.
+///
+/// ```
+/// # #[macro_use]
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::char::{digit, letter, string};
+/// # use combine::primitives::Error;
+/// # fn main() {
+/// let mut parser = choice!(
+///     many1(digit()),
+///     string("let").map(|s| s.to_string()),
+///     many1(letter()));
+/// assert_eq!(parser.parse("let"), Ok(("let".to_string(), "")));
+/// assert_eq!(parser.parse("123abc"), Ok(("123".to_string(), "abc")));
+/// assert!(parser.parse(":123").is_err());
+/// # }
+/// ```
+#[macro_export]
+macro_rules! choice {
+    ($first : expr) => {
+        $first
+    };
+    ($first : expr, $($rest : expr),+) => {
+        $first.or(choice!($($rest),+))
+    }
+}
+
+#[derive(Clone)]
+pub struct Unexpected<I>(Info<I::Item, I::Range>, PhantomData<fn(I) -> I>) where I: Stream;
+impl<I> Parser for Unexpected<I>
+    where I: Stream
+{
+    type Input = I;
+    type Output = ();
+    #[inline]
+    fn parse_lazy(&mut self, input: I) -> ConsumedResult<(), I> {
+        EmptyErr(ParseError::empty(input.position()))
+    }
+    fn add_error(&mut self, error: &mut ParseError<Self::Input>) {
+        error.errors.push(Error::Unexpected(self.0.clone()));
+    }
+}
+/// Always fails with `message` as an unexpected error.
+/// Never consumes any input.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::primitives::Error;
+/// # fn main() {
+/// let result = unexpected("token")
+///     .parse("a");
+/// assert!(result.is_err());
+/// assert!(result.err().unwrap().errors.iter().any(|m| *m == Error::Unexpected("token".into())));
+/// # }
+/// ```
+#[inline(always)]
+pub fn unexpected<I, S>(message: S) -> Unexpected<I>
+    where I: Stream,
+          S: Into<Info<I::Item, I::Range>>
+{
+    Unexpected(message.into(), PhantomData)
+}
+
+#[derive(Clone)]
+pub struct Value<I, T>(T, PhantomData<fn(I) -> I>);
+impl<I, T> Parser for Value<I, T>
+    where I: Stream,
+          T: Clone
+{
+    type Input = I;
+    type Output = T;
+    #[inline]
+    fn parse_lazy(&mut self, input: I) -> ConsumedResult<T, I> {
+        EmptyOk((self.0.clone(), input))
+    }
+}
+
+/// Always returns the value `v` without consuming any input.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # fn main() {
+/// let result = value(42)
+///     .parse("hello world")
+///     .map(|x| x.0);
+/// assert_eq!(result, Ok(42));
+/// # }
+/// ```
+#[inline(always)]
+pub fn value<I, T>(v: T) -> Value<I, T>
+    where I: Stream,
+          T: Clone
+{
+    Value(v, PhantomData)
+}
+
+impl_parser! { NotFollowedBy(P,),
+               Or<Then<Try<P>, fn(P::Output) -> Unexpected<P::Input>>, Value<P::Input, ()>>
+}
+
+/// Succeeds only if `parser` fails.
+/// Never consumes any input.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::char::{alpha_num, string};
+/// # fn main() {
+/// let result = string("let")
+///     .skip(not_followed_by(alpha_num()))
+///     .parse("letx")
+///     .map(|x| x.0);
+/// assert!(result.is_err());
+/// # }
+/// ```
+#[inline(always)]
+pub fn not_followed_by<P>(parser: P) -> NotFollowedBy<P>
+    where P: Parser,
+          P::Output: ::std::fmt::Display
+{
+    fn f<T: ::std::fmt::Display, I: Stream>(t: T) -> Unexpected<I> {
+        unexpected(format!("{}", t))
+    }
+    let f: fn(P::Output) -> Unexpected<P::Input> = f;
+    NotFollowedBy(try(parser).then(f).or(value(())))
+}
+
+#[derive(Clone)]
+pub struct Eof<I>(PhantomData<I>);
+impl<I> Parser for Eof<I>
+    where I: Stream
+{
+    type Input = I;
+    type Output = ();
+
+    #[inline]
+    fn parse_lazy(&mut self, input: I) -> ConsumedResult<(), I> {
+        match input.clone().uncons() {
+            Err(ref err) if *err == Error::end_of_input() => EmptyOk(((), input)),
+            _ => EmptyErr(ParseError::empty(input.position())),
+        }
+    }
+
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        errors.add_error(Error::Expected("end of input".into()))
+    }
+}
+
+/// Succeeds only if the stream is at end of input, fails otherwise.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::primitives::{Error, Positioner};
+/// # fn main() {
+/// let mut parser = eof();
+/// assert_eq!(parser.parse(State::new("")), Ok(((), State::new(""))));
+/// assert_eq!(parser.parse(State::new("x")), Err(ParseError {
+///     position: <char as Positioner>::start(),
+///     errors: vec![
+///         Error::Unexpected('x'.into()),
+///         Error::Expected("end of input".into())
+///     ]
+/// }));
+/// # }
+/// ```
+#[inline(always)]
+pub fn eof<I>() -> Eof<I>
+    where I: Stream
+{
+    Eof(PhantomData)
+}
+
+pub struct Iter<P: Parser> {
+    parser: P,
+    input: P::Input,
+    consumed: bool,
+    state: State<P::Input>,
+}
+
+enum State<I: StreamOnce> {
+    Ok,
+    EmptyErr,
+    ConsumedErr(ParseError<I>),
+}
+
+impl<P: Parser> Iter<P> {
+    pub fn new(parser: P, input: P::Input) -> Iter<P> {
+        Iter {
+            parser: parser,
+            input: input,
+            consumed: false,
+            state: State::Ok,
+        }
+    }
+    /// Converts the iterator to a `ParseResult`, returning `Ok` if the parsing so far has be done
+    /// without any errors which consumed data.
+    pub fn into_result<O>(self, value: O) -> ParseResult<O, P::Input> {
+        self.into_result_fast(value).into()
+    }
+
+    fn into_result_fast<O>(self, value: O) -> ConsumedResult<O, P::Input> {
+        match self.state {
+            State::Ok | State::EmptyErr => {
+                if self.consumed {
+                    ConsumedOk((value, self.input))
+                } else {
+                    EmptyOk((value, self.input))
+                }
+            }
+            State::ConsumedErr(e) => ConsumedErr(e),
+        }
+    }
+}
+
+impl<P: Parser> Iterator for Iter<P> {
+    type Item = P::Output;
+    fn next(&mut self) -> Option<P::Output> {
+        match self.state {
+            State::Ok => {
+                match self.parser.parse_lazy(self.input.clone()) {
+                    EmptyOk((v, input)) => {
+                        self.input = input;
+                        Some(v)
+                    }
+                    ConsumedOk((v, input)) => {
+                        self.input = input;
+                        self.consumed = true;
+                        Some(v)
+                    }
+                    EmptyErr(_) => {
+                        self.state = State::EmptyErr;
+                        None
+                    }
+                    ConsumedErr(e) => {
+                        self.state = State::ConsumedErr(e);
+                        None
+                    }
+                }
+            }
+            State::ConsumedErr(_) |
+            State::EmptyErr => None,
+        }
+    }
+}
+
+#[derive(Clone)]
+pub struct Many<F, P>(P, PhantomData<F>) where P: Parser;
+impl<F, P> Parser for Many<F, P>
+    where P: Parser,
+          F: FromIterator<P::Output>
+{
+    type Input = P::Input;
+    type Output = F;
+    fn parse_stream_consumed(&mut self, input: P::Input) -> ConsumedResult<F, P::Input> {
+        let mut iter = (&mut self.0).iter(input);
+        let result = iter.by_ref().collect();
+        iter.into_result_fast(result)
+    }
+}
+
+/// Parses `p` zero or more times returning a collection with the values from `p`.
+///
+/// If the returned collection cannot be inferred type annotations must be supplied, either by
+/// annotating the resulting type binding `let collection: Vec<_> = ...` or by specializing when
+/// calling many, `many::<Vec<_>, _>(...)`.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::char::digit;
+/// # fn main() {
+/// let result = many(digit())
+///     .parse("123A")
+///     .map(|x| x.0);
+/// assert_eq!(result, Ok(vec!['1', '2', '3']));
+/// # }
+/// ```
+#[inline(always)]
+pub fn many<F, P>(p: P) -> Many<F, P>
+    where P: Parser,
+          F: FromIterator<P::Output>
+{
+    Many(p, PhantomData)
+}
+
+
+#[derive(Clone)]
+pub struct Many1<F, P>(P, PhantomData<fn() -> F>);
+impl<F, P> Parser for Many1<F, P>
+    where F: FromIterator<P::Output>,
+          P: Parser
+{
+    type Input = P::Input;
+    type Output = F;
+    #[inline]
+    fn parse_lazy(&mut self, input: P::Input) -> ConsumedResult<F, P::Input> {
+        let (first, input) = ctry!(self.0.parse_lazy(input));
+        let mut iter = Iter {
+            parser: &mut self.0,
+            consumed: !input.is_empty(),
+            input: input.into_inner(),
+            state: State::Ok,
+        };
+        let result = Some(first).into_iter().chain(iter.by_ref()).collect();
+        iter.into_result_fast(result)
+    }
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        self.0.add_error(errors)
+    }
+}
+
+impl_parser!{ SkipMany(P,), Map<Many<Vec<()>, Map<P, fn (P::Output)>>, fn (Vec<()>)> }
+
+/// Parses `p` zero or more times ignoring the result.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::char::digit;
+/// # fn main() {
+/// let result = skip_many(digit())
+///     .parse("A");
+/// assert_eq!(result, Ok(((), "A")));
+/// # }
+/// ```
+#[inline(always)]
+pub fn skip_many<P>(p: P) -> SkipMany<P>
+    where P: Parser
+{
+    fn ignore<T>(_: T) {}
+    let ignore1: fn(P::Output) = ignore;
+    let ignore2: fn(Vec<()>) = ignore;
+    SkipMany(many(p.map(ignore1)).map(ignore2))
+}
+
+impl_parser!{ SkipMany1(P,), Map<Many1<Vec<()>, Map<P, fn (P::Output)>>, fn (Vec<()>)> }
+
+/// Parses `p` one or more times ignoring the result.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::char::digit;
+/// # fn main() {
+/// let result = skip_many1(digit())
+///     .parse("123A");
+/// assert_eq!(result, Ok(((), "A")));
+/// # }
+/// ```
+#[inline(always)]
+pub fn skip_many1<P>(p: P) -> SkipMany1<P>
+    where P: Parser
+{
+    fn ignore<T>(_: T) {}
+    let ignore1: fn(P::Output) = ignore;
+    let ignore2: fn(Vec<()>) = ignore;
+    SkipMany1(many1(p.map(ignore1)).map(ignore2))
+}
+
+/// Parses `p` one or more times returning a collection with the values from `p`.
+///
+/// If the returned collection cannot be inferred type annotations must be supplied, either by
+/// annotating the resulting type binding `let collection: Vec<_> = ...` or by specializing when
+/// calling many1 `many1::<Vec<_>, _>(...)`.
+///
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::char::digit;
+/// # fn main() {
+/// let result = many1::<Vec<_>, _>(digit())
+///     .parse("A123");
+/// assert!(result.is_err());
+/// # }
+/// ```
+#[inline(always)]
+pub fn many1<F, P>(p: P) -> Many1<F, P>
+    where F: FromIterator<P::Output>,
+          P: Parser
+{
+    Many1(p, PhantomData)
+}
+
+#[derive(Clone)]
+pub struct SepBy<F, P, S> {
+    parser: P,
+    separator: S,
+    _marker: PhantomData<fn() -> F>,
+}
+impl<F, P, S> Parser for SepBy<F, P, S>
+    where F: FromIterator<P::Output>,
+          P: Parser,
+          S: Parser<Input = P::Input>
+{
+    type Input = P::Input;
+    type Output = F;
+
+    #[inline]
+    fn parse_lazy(&mut self, input: P::Input) -> ConsumedResult<F, P::Input> {
+        sep_by1(&mut self.parser, &mut self.separator)
+            .or(parser(|input| Ok((None.into_iter().collect(), Consumed::Empty(input)))))
+            .parse_lazy(input)
+    }
+
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        self.parser.add_error(errors)
+    }
+}
+
+/// Parses `parser` zero or more time separated by `separator`, returning a collection with the
+/// values from `p`.
+///
+/// If the returned collection cannot be inferred type annotations must be supplied, either by
+/// annotating the resulting type binding `let collection: Vec<_> = ...` or by specializing when
+/// calling `sep_by`, `sep_by::<Vec<_>, _, _>(...)`.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::char::digit;
+/// # fn main() {
+/// let mut parser = sep_by(digit(), token(','));
+/// let result_ok = parser.parse("1,2,3");
+/// assert_eq!(result_ok, Ok((vec!['1', '2', '3'], "")));
+/// let result_ok2 = parser.parse("");
+/// assert_eq!(result_ok2, Ok((vec![], "")));
+/// # }
+/// ```
+#[inline(always)]
+pub fn sep_by<F, P, S>(parser: P, separator: S) -> SepBy<F, P, S>
+    where F: FromIterator<P::Output>,
+          P: Parser,
+          S: Parser<Input = P::Input>
+{
+    SepBy {
+        parser: parser,
+        separator: separator,
+        _marker: PhantomData,
+    }
+}
+
+#[derive(Clone)]
+pub struct SepBy1<F, P, S> {
+    parser: P,
+    separator: S,
+    _marker: PhantomData<fn() -> F>,
+}
+impl<F, P, S> Parser for SepBy1<F, P, S>
+    where F: FromIterator<P::Output>,
+          P: Parser,
+          S: Parser<Input = P::Input>
+{
+    type Input = P::Input;
+    type Output = F;
+
+    #[inline]
+    fn parse_lazy(&mut self, input: P::Input) -> ConsumedResult<F, P::Input> {
+        let (first, rest) = ctry!(self.parser.parse_lazy(input.clone()));
+
+        rest.combine_consumed(move |input| {
+            let rest = (&mut self.separator).with(&mut self.parser);
+            let mut iter = Iter::new(rest, input);
+            let result = Some(first)
+                .into_iter()
+                .chain(iter.by_ref())
+                .collect();
+            iter.into_result_fast(result)
+        })
+    }
+
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        self.parser.add_error(errors)
+    }
+}
+
+/// Parses `parser` one or more time separated by `separator`, returning a collection with the
+/// values from `p`.
+///
+/// If the returned collection cannot be inferred type annotations must be supplied, either by
+/// annotating the resulting type binding `let collection: Vec<_> = ...` or by specializing when
+/// calling `sep_by`, `sep_by1::<Vec<_>, _, _>(...)`.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::char::digit;
+/// # use combine::primitives::{Error, Positioner};
+/// # fn main() {
+/// let mut parser = sep_by1(digit(), token(','));
+/// let result_ok = parser.parse(State::new("1,2,3"))
+///                       .map(|(vec, state)| (vec, state.input));
+/// assert_eq!(result_ok, Ok((vec!['1', '2', '3'], "")));
+/// let result_err = parser.parse(State::new(""));
+/// assert_eq!(result_err, Err(ParseError {
+///     position: <char as Positioner>::start(),
+///     errors: vec![
+///         Error::end_of_input(),
+///         Error::Expected("digit".into())
+///     ]
+/// }));
+/// # }
+/// ```
+#[inline(always)]
+pub fn sep_by1<F, P, S>(parser: P, separator: S) -> SepBy1<F, P, S>
+    where F: FromIterator<P::Output>,
+          P: Parser,
+          S: Parser<Input = P::Input>
+{
+    SepBy1 {
+        parser: parser,
+        separator: separator,
+        _marker: PhantomData,
+    }
+}
+
+#[derive(Clone)]
+pub struct SepEndBy<F, P, S> {
+    parser: P,
+    separator: S,
+    _marker: PhantomData<fn() -> F>,
+}
+
+impl<F, P, S> Parser for SepEndBy<F, P, S>
+    where F: FromIterator<P::Output>,
+          P: Parser,
+          S: Parser<Input = P::Input>
+{
+    type Input = P::Input;
+    type Output = F;
+
+    #[inline]
+    fn parse_lazy(&mut self, input: P::Input) -> ConsumedResult<F, P::Input> {
+        sep_end_by1(&mut self.parser, &mut self.separator)
+            .or(parser(|input| Ok((None.into_iter().collect(), Consumed::Empty(input)))))
+            .parse_lazy(input)
+    }
+
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        self.parser.add_error(errors)
+    }
+}
+
+/// Parses `parser` zero or more times separated and ended by `separator`, returning a collection
+/// with the values from `p`.
+///
+/// If the returned collection cannot be inferred type annotations must be supplied, either by
+/// annotating the resulting type binding `let collection: Vec<_> = ...` or by specializing when
+/// calling `sep_by`, `sep_by::<Vec<_>, _, _>(...)`
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::char::digit;
+/// # fn main() {
+/// let mut parser = sep_end_by(digit(), token(';'));
+/// let result_ok = parser.parse("1;2;3;");
+/// assert_eq!(result_ok, Ok((vec!['1', '2', '3'], "")));
+/// let result_ok2 = parser.parse("1;2;3");
+/// assert_eq!(result_ok2, Ok((vec!['1', '2', '3'], "")));
+/// # }
+/// ```
+#[inline(always)]
+pub fn sep_end_by<F, P, S>(parser: P, separator: S) -> SepEndBy<F, P, S>
+    where F: FromIterator<P::Output>,
+          P: Parser,
+          S: Parser<Input = P::Input>
+{
+    SepEndBy {
+        parser: parser,
+        separator: separator,
+        _marker: PhantomData,
+    }
+}
+
+#[derive(Clone)]
+pub struct SepEndBy1<F, P, S> {
+    parser: P,
+    separator: S,
+    _marker: PhantomData<fn() -> F>,
+}
+
+impl<F, P, S> Parser for SepEndBy1<F, P, S>
+    where F: FromIterator<P::Output>,
+          P: Parser,
+          S: Parser<Input = P::Input>
+{
+    type Input = P::Input;
+    type Output = F;
+
+    #[inline]
+    fn parse_lazy(&mut self, input: P::Input) -> ConsumedResult<F, P::Input> {
+        let (first, input) = ctry!(self.parser.parse_lazy(input.clone()));
+
+        input.combine_consumed(|input| {
+            let rest = (&mut self.separator).with(optional(&mut self.parser));
+            let mut iter = Iter::new(rest, input);
+            // `iter` yields Option<P::Output>, by using flat map we make sure that we stop
+            // iterating once a None element is received, i.e `self.parser` did not parse
+            // successfully
+            let result = Some(first).into_iter().chain(iter.by_ref().flat_map(|x| x)).collect();
+            iter.into_result_fast(result)
+        })
+    }
+
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        self.parser.add_error(errors)
+    }
+}
+
+/// Parses `parser` one or more times separated and ended by `separator`, returning a collection
+/// with the values from `p`.
+///
+/// If the returned collection cannot be inferred type annotations must be
+/// supplied, either by annotating the resulting type binding `let collection: Vec<_> = ...` or by
+/// specializing when calling `sep_by`, `sep_by1::<Vec<_>, _, _>(...)`.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::char::digit;
+/// # use combine::primitives::{Error, Positioner};
+/// # fn main() {
+/// let mut parser = sep_end_by1(digit(), token(';'));
+/// let result_ok = parser.parse(State::new("1;2;3;"))
+///                       .map(|(vec, state)| (vec, state.input));
+/// assert_eq!(result_ok, Ok((vec!['1', '2', '3'], "")));
+/// let result_err = parser.parse(State::new(""));
+/// assert_eq!(result_err, Err(ParseError {
+///     position: <char as Positioner>::start(),
+///     errors: vec![
+///         Error::end_of_input(),
+///         Error::Expected("digit".into())
+///     ]
+/// }));
+/// # }
+/// ```
+#[inline(always)]
+pub fn sep_end_by1<F, P, S>(parser: P, separator: S) -> SepEndBy1<F, P, S>
+    where F: FromIterator<P::Output>,
+          P: Parser,
+          S: Parser<Input = P::Input>
+{
+    SepEndBy1 {
+        parser: parser,
+        separator: separator,
+        _marker: PhantomData,
+    }
+}
+
+impl<'a, I: Stream, O> Parser for FnMut(I) -> ParseResult<O, I> + 'a {
+    type Input = I;
+    type Output = O;
+    fn parse_stream(&mut self, input: I) -> ParseResult<O, I> {
+        self(input)
+    }
+}
+#[derive(Clone)]
+pub struct FnParser<I, F>(F, PhantomData<fn(I) -> I>);
+
+/// Wraps a function, turning it into a parser.
+///
+/// Mainly needed to turn closures into parsers as function types can be casted to function pointers
+/// to make them usable as a parser.
+///
+/// ```
+/// extern crate combine;
+/// # use combine::*;
+/// # use combine::char::digit;
+/// # use combine::primitives::{Consumed, Error};
+/// # fn main() {
+/// let mut even_digit = parser(|input| {
+///     // Help type inference out
+///     let _: &str = input;
+///     let position = input.position();
+///     let (char_digit, input) = try!(digit().parse_stream(input));
+///     let d = (char_digit as i32) - ('0' as i32);
+///     if d % 2 == 0 {
+///         Ok((d, input))
+///     }
+///     else {
+///         //Return an empty error since we only tested the first token of the stream
+///         let errors = ParseError::new(position, Error::Expected(From::from("even number")));
+///         Err(Consumed::Empty(errors))
+///     }
+/// });
+/// let result = even_digit
+///     .parse("8")
+///     .map(|x| x.0);
+/// assert_eq!(result, Ok(8));
+/// # }
+/// ```
+#[inline(always)]
+pub fn parser<I, O, F>(f: F) -> FnParser<I, F>
+    where I: Stream,
+          F: FnMut(I) -> ParseResult<O, I>
+{
+    FnParser(f, PhantomData)
+}
+
+impl<I, O, F> Parser for FnParser<I, F>
+    where I: Stream,
+          F: FnMut(I) -> ParseResult<O, I>
+{
+    type Input = I;
+    type Output = O;
+    fn parse_stream(&mut self, input: I) -> ParseResult<O, I> {
+        (self.0)(input)
+    }
+}
+
+impl<I, O> Parser for fn(I) -> ParseResult<O, I>
+    where I: Stream
+{
+    type Input = I;
+    type Output = O;
+    fn parse_stream(&mut self, input: I) -> ParseResult<O, I> {
+        self(input)
+    }
+}
+
+#[derive(Clone)]
+pub struct Optional<P>(P);
+impl<P> Parser for Optional<P>
+    where P: Parser
+{
+    type Input = P::Input;
+    type Output = Option<P::Output>;
+    #[inline]
+    fn parse_lazy(&mut self, input: P::Input) -> ConsumedResult<Option<P::Output>, P::Input> {
+        match self.0.parse_lazy(input.clone()) {
+            EmptyOk((x, rest)) => EmptyOk((Some(x), rest)),
+            ConsumedOk((x, rest)) => ConsumedOk((Some(x), rest)),
+            ConsumedErr(err) => ConsumedErr(err),
+            EmptyErr(_) => EmptyOk((None, input)),
+        }
+    }
+}
+
+/// Parses `parser` and outputs `Some(value)` if it succeeds, `None` if it fails without
+/// consuming any input. Fails if `parser` fails after having consumed some input.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::char::string;
+/// # fn main() {
+/// let mut parser = optional(string("hello"));
+/// assert_eq!(parser.parse("hello"), Ok((Some("hello"), "")));
+/// assert_eq!(parser.parse("world"), Ok((None, "world")));
+/// assert!(parser.parse("heya").is_err());
+/// # }
+/// ```
+#[inline(always)]
+pub fn optional<P>(parser: P) -> Optional<P>
+    where P: Parser
+{
+    Optional(parser)
+}
+
+impl_parser! { Between(L, R, P), Skip<With<L, P>, R> }
+/// Parses `open` followed by `parser` followed by `close`.
+/// Returns the value of `parser`.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::char::string;
+/// # fn main() {
+/// let result = between(token('['), token(']'), string("rust"))
+///     .parse("[rust]")
+///     .map(|x| x.0);
+/// assert_eq!(result, Ok("rust"));
+/// # }
+/// ```
+#[inline(always)]
+pub fn between<I, L, R, P>(open: L, close: R, parser: P) -> Between<L, R, P>
+    where I: Stream,
+          L: Parser<Input = I>,
+          R: Parser<Input = I>,
+          P: Parser<Input = I>
+{
+    Between(open.with(parser).skip(close))
+}
+
+#[derive(Clone)]
+pub struct Chainl1<P, Op>(P, Op);
+impl<I, P, Op> Parser for Chainl1<P, Op>
+    where I: Stream,
+          P: Parser<Input = I>,
+          Op: Parser<Input = I>,
+          Op::Output: FnOnce(P::Output, P::Output) -> P::Output
+{
+    type Input = I;
+    type Output = P::Output;
+
+    #[inline]
+    fn parse_lazy(&mut self, input: I) -> ConsumedResult<P::Output, I> {
+        let (mut l, mut input) = ctry!(self.0.parse_lazy(input));
+        loop {
+            match (&mut self.1, &mut self.0).parse_lazy(input.clone().into_inner()).into() {
+                Ok(((op, r), rest)) => {
+                    l = op(l, r);
+                    input = input.merge(rest);
+                }
+                Err(Consumed::Consumed(err)) => return ConsumedErr(err),
+                Err(Consumed::Empty(_)) => break,
+            }
+        }
+        Ok((l, input)).into()
+    }
+
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        self.0.add_error(errors)
+    }
+}
+
+/// Parses `p` 1 or more times separated by `op`. The value returned is the one produced by the
+/// left associative application of the function returned by the parser `op`.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::char::digit;
+/// # fn main() {
+/// let number = digit().map(|c: char| c.to_digit(10).unwrap());
+/// let sub = token('-').map(|_| |l: u32, r: u32| l - r);
+/// let mut parser = chainl1(number, sub);
+/// assert_eq!(parser.parse("9-3-5"), Ok((1, "")));
+/// # }
+/// ```
+#[inline(always)]
+pub fn chainl1<P, Op>(parser: P, op: Op) -> Chainl1<P, Op>
+    where P: Parser,
+          Op: Parser<Input = P::Input>,
+          Op::Output: FnOnce(P::Output, P::Output) -> P::Output
+{
+    Chainl1(parser, op)
+}
+
+#[derive(Clone)]
+pub struct Chainr1<P, Op>(P, Op);
+impl<I, P, Op> Parser for Chainr1<P, Op>
+    where I: Stream,
+          P: Parser<Input = I>,
+          Op: Parser<Input = I>,
+          Op::Output: FnOnce(P::Output, P::Output) -> P::Output
+{
+    type Input = I;
+    type Output = P::Output;
+    #[inline]
+    fn parse_lazy(&mut self, input: I) -> ConsumedResult<P::Output, I> {
+        // FIXME FastResult
+        let (mut l, mut input) = ctry!(self.0.parse_lazy(input));
+        loop {
+            let op = match self.1.parse_lazy(input.clone().into_inner()).into() {
+                Ok((x, rest)) => {
+                    input = input.merge(rest);
+                    x
+                }
+                Err(Consumed::Consumed(err)) => return ConsumedErr(err),
+                Err(Consumed::Empty(_)) => break,
+            };
+            match self.parse_lazy(input.clone().into_inner()).into() {
+                Ok((r, rest)) => {
+                    l = op(l, r);
+                    input = input.merge(rest);
+                }
+                Err(Consumed::Consumed(err)) => return ConsumedErr(err),
+                Err(Consumed::Empty(_)) => break,
+            }
+        }
+        Ok((l, input)).into()
+    }
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        self.0.add_error(errors)
+    }
+}
+
+/// Parses `p` one or more times separated by `op`. The value returned is the one produced by the
+/// right associative application of the function returned by `op`.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::char::digit;
+/// # fn main() {
+/// let number = digit().map(|c: char| c.to_digit(10).unwrap());
+/// let pow = token('^').map(|_| |l: u32, r: u32| l.pow(r));
+/// let mut parser = chainr1(number, pow);
+///     assert_eq!(parser.parse("2^3^2"), Ok((512, "")));
+/// }
+/// ```
+#[inline(always)]
+pub fn chainr1<P, Op>(parser: P, op: Op) -> Chainr1<P, Op>
+    where P: Parser,
+          Op: Parser<Input = P::Input>,
+          Op::Output: FnOnce(P::Output, P::Output) -> P::Output
+{
+    Chainr1(parser, op)
+}
+
+#[derive(Clone)]
+pub struct Try<P>(P);
+impl<I, O, P> Parser for Try<P>
+    where I: Stream,
+          P: Parser<Input = I, Output = O>
+{
+    type Input = I;
+    type Output = O;
+    #[inline]
+    fn parse_lazy(&mut self, input: I) -> ConsumedResult<O, I> {
+        self.0
+            .parse_stream(input)
+            .map_err(Consumed::into_empty)
+            .into()
+    }
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        self.0.add_error(errors)
+    }
+}
+
+/// `try(p)` behaves as `p` except it acts as if the parser hadn't consumed any input if `p` fails after
+/// consuming input.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::char::string;
+/// # fn main() {
+/// let mut p = try(string("let"))
+///     .or(string("lex"));
+/// let result = p.parse("lex").map(|x| x.0);
+/// assert_eq!(result, Ok("lex"));
+/// let result = p.parse("aet").map(|x| x.0);
+/// assert!(result.is_err());
+/// # }
+/// ```
+#[inline(always)]
+pub fn try<P>(p: P) -> Try<P>
+    where P: Parser
+{
+    Try(p)
+}
+
+#[derive(Clone)]
+pub struct LookAhead<P>(P);
+
+impl<I, O, P> Parser for LookAhead<P>
+    where I: Stream,
+          P: Parser<Input = I, Output = O>
+{
+    type Input = I;
+    type Output = O;
+
+    #[inline]
+    fn parse_lazy(&mut self, input: I) -> ConsumedResult<O, I> {
+        let (o, _input) = ctry!(self.0.parse_lazy(input.clone()));
+        EmptyOk((o, input))
+    }
+
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        self.0.add_error(errors);
+    }
+}
+
+/// `look_ahead(p)` acts as `p` but doesn't consume input on success.
+///
+/// ```
+/// # extern crate combine;
+/// # use combine::*;
+/// # use combine::char::string;
+/// # fn main() {
+/// let mut p = look_ahead(string("test"));
+///
+/// let result = p.parse("test str");
+/// assert_eq!(result, Ok(("test", "test str")));
+///
+/// let result = p.parse("aet");
+/// assert!(result.is_err());
+/// # }
+/// ```
+#[inline(always)]
+pub fn look_ahead<P>(p: P) -> LookAhead<P>
+    where P: Parser
+{
+    LookAhead(p)
+}
+
+#[derive(Clone)]
+pub struct With<P1, P2>((P1, P2))
+    where P1: Parser,
+          P2: Parser;
+impl<I, P1, P2> Parser for With<P1, P2>
+    where I: Stream,
+          P1: Parser<Input = I>,
+          P2: Parser<Input = I>
+{
+    type Input = I;
+    type Output = P2::Output;
+    #[inline]
+    fn parse_lazy(&mut self, input: I) -> ConsumedResult<Self::Output, I> {
+        self.0.parse_lazy(input).map(|(_, b)| b)
+    }
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        self.0.add_error(errors)
+    }
+}
+
+/// Equivalent to [`p1.with(p2)`].
+///
+/// [`p1.with(p2)`]: ../primitives/trait.Parser.html#method.with
+#[inline(always)]
+pub fn with<P1, P2>(p1: P1, p2: P2) -> With<P1, P2>
+    where P1: Parser,
+          P2: Parser<Input = P1::Input>
+{
+    With((p1, p2))
+}
+
+#[derive(Clone)]
+pub struct Skip<P1, P2>((P1, P2))
+    where P1: Parser,
+          P2: Parser;
+impl<I, P1, P2> Parser for Skip<P1, P2>
+    where I: Stream,
+          P1: Parser<Input = I>,
+          P2: Parser<Input = I>
+{
+    type Input = I;
+    type Output = P1::Output;
+    #[inline]
+    fn parse_lazy(&mut self, input: I) -> ConsumedResult<Self::Output, I> {
+        self.0.parse_lazy(input).map(|(a, _)| a)
+    }
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        self.0.add_error(errors)
+    }
+}
+
+#[inline(always)]
+pub fn skip<P1, P2>(p1: P1, p2: P2) -> Skip<P1, P2>
+    where P1: Parser,
+          P2: Parser<Input = P1::Input>
+{
+    Skip((p1, p2))
+}
+
+#[derive(Clone)]
+pub struct Message<P>(P, Info<<P::Input as StreamOnce>::Item, <P::Input as StreamOnce>::Range>)
+    where P: Parser;
+impl<I, P> Parser for Message<P>
+    where I: Stream,
+          P: Parser<Input = I>
+{
+    type Input = I;
+    type Output = P::Output;
+
+    #[inline]
+    fn parse_lazy(&mut self, input: I) -> ConsumedResult<Self::Output, I> {
+        match self.0.parse_lazy(input) {
+            ConsumedOk(x) => ConsumedOk(x),
+            EmptyOk(x) => EmptyOk(x),
+
+            // The message should always be added even if some input was consumed before failing
+            ConsumedErr(mut err) => {
+                err.add_error(Error::Message(self.1.clone()));
+                ConsumedErr(err)
+            },
+
+            // The message will be added in `add_error`
+            EmptyErr(err) => EmptyErr(err),
+        }
+    }
+
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        self.0.add_error(errors);
+        errors.add_error(Error::Message(self.1.clone()));
+    }
+}
+
+/// Equivalent to [`p1.message(msg)`].
+///
+/// [`p1.message(msg)`]: ../primitives/trait.Parser.html#method.message
+#[inline(always)]
+pub fn message<P>(p: P,
+                  msg: Info<<P::Input as StreamOnce>::Item, <P::Input as StreamOnce>::Range>)
+                  -> Message<P>
+    where P: Parser
+{
+    Message(p, msg)
+}
+
+#[derive(Clone)]
+pub struct Or<P1, P2>(P1, P2)
+    where P1: Parser,
+          P2: Parser;
+impl<I, O, P1, P2> Parser for Or<P1, P2>
+    where I: Stream,
+          P1: Parser<Input = I, Output = O>,
+          P2: Parser<Input = I, Output = O>
+{
+    type Input = I;
+    type Output = O;
+    #[inline]
+    fn parse_lazy(&mut self, input: I) -> ConsumedResult<O, I> {
+        match self.0.parse_lazy(input.clone()) {
+            ConsumedOk(x) => ConsumedOk(x),
+            EmptyOk(x) => EmptyOk(x),
+            ConsumedErr(err) => ConsumedErr(err),
+            EmptyErr(error1) => {
+                match self.1.parse_lazy(input) {
+                    ConsumedOk(x) => ConsumedOk(x),
+                    EmptyOk(x) => EmptyOk(x),
+                    ConsumedErr(err) => ConsumedErr(err),
+                    EmptyErr(error2) => EmptyErr(error1.merge(error2)),
+                }
+            }
+        }
+    }
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        self.0.add_error(errors);
+        self.1.add_error(errors);
+    }
+}
+
+/// Equivalent to [`p1.or(p2)`].
+///
+/// If you are looking to chain 3 or more parsers using `or` you may consider using the
+/// [`choice!`] macro instead, which can be clearer and may result in a faster parser.
+///
+/// [`p1.or(p2)`]: ../primitives/trait.Parser.html#method.or
+#[inline(always)]
+pub fn or<P1, P2>(p1: P1, p2: P2) -> Or<P1, P2>
+    where P1: Parser,
+          P2: Parser<Input = P1::Input, Output = P1::Output>
+{
+    Or(p1, p2)
+}
+
+#[derive(Clone)]
+pub struct Map<P, F>(P, F);
+impl<I, A, B, P, F> Parser for Map<P, F>
+    where I: Stream,
+          P: Parser<Input = I, Output = A>,
+          F: FnMut(A) -> B
+{
+    type Input = I;
+    type Output = B;
+    #[inline]
+    fn parse_lazy(&mut self, input: I) -> ConsumedResult<B, I> {
+        match self.0.parse_lazy(input) {
+            ConsumedOk((x, input)) => ConsumedOk(((self.1)(x), input)),
+            EmptyOk((x, input)) => EmptyOk(((self.1)(x), input)),
+            ConsumedErr(err) => ConsumedErr(err),
+            EmptyErr(err) => EmptyErr(err),
+        }
+    }
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        self.0.add_error(errors);
+    }
+}
+
+/// Equivalent to [`p.map(f)`].
+///
+/// [`p.map(f)`]: ../primitives/trait.Parser.html#method.map
+#[inline(always)]
+pub fn map<P, F, B>(p: P, f: F) -> Map<P, F>
+    where P: Parser,
+          F: FnMut(P::Output) -> B
+{
+    Map(p, f)
+}
+
+#[derive(Clone)]
+pub struct FlatMap<P, F>(P, F);
+impl<I, A, B, P, F> Parser for FlatMap<P, F>
+    where I: Stream,
+          P: Parser<Input = I, Output = A>,
+          F: FnMut(A) -> Result<B, ParseError<I>>
+{
+    type Input = I;
+    type Output = B;
+    #[inline]
+    fn parse_lazy(&mut self, input: I) -> ConsumedResult<B, I> {
+        match self.0.parse_lazy(input) {
+            EmptyOk((o, input)) => {
+                match (self.1)(o) {
+                    Ok(x) => EmptyOk((x, input)),
+                    Err(err) => EmptyErr(err),
+                }
+            }
+            ConsumedOk((o, input)) => {
+                match (self.1)(o) {
+                    Ok(x) => ConsumedOk((x, input)),
+                    Err(err) => ConsumedErr(err),
+                }
+            }
+            EmptyErr(err) => EmptyErr(err),
+            ConsumedErr(err) => ConsumedErr(err),
+        }
+    }
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        self.0.add_error(errors);
+    }
+}
+
+/// Equivalent to [`p.flat_map(f)`].
+///
+/// [`p.flat_map(f)`]: ../primitives/trait.Parser.html#method.flat_map
+#[inline(always)]
+pub fn flat_map<P, F, B>(p: P, f: F) -> FlatMap<P, F>
+    where P: Parser,
+          F: FnMut(P::Output) -> Result<B, ParseError<P::Input>>
+{
+    FlatMap(p, f)
+}
+
+#[derive(Clone)]
+pub struct Then<P, F>(P, F);
+impl<P, N, F> Parser for Then<P, F>
+    where F: FnMut(P::Output) -> N,
+          P: Parser,
+          N: Parser<Input = P::Input>
+{
+    type Input = N::Input;
+    type Output = N::Output;
+    #[inline]
+    fn parse_lazy(&mut self, input: Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+        match self.0.parse_lazy(input) {
+            EmptyOk((value, input)) => {
+                let mut next = (self.1)(value);
+                next.parse_stream_consumed(input)
+            }
+            ConsumedOk((value, input)) => {
+                let mut next = (self.1)(value);
+                match next.parse_stream_consumed(input) {
+                    EmptyOk(x) | ConsumedOk(x) => ConsumedOk(x),
+                    EmptyErr(x) | ConsumedErr(x) => ConsumedErr(x),
+                }
+            }
+            EmptyErr(err) => EmptyErr(err),
+            ConsumedErr(err) => ConsumedErr(err),
+        }
+    }
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        self.0.add_error(errors);
+    }
+}
+
+/// Equivalent to [`p.then(f)`].
+///
+/// [`p.then(f)`]: ../primitives/trait.Parser.html#method.then
+#[inline(always)]
+pub fn then<P, F, N>(p: P, f: F) -> Then<P, F>
+    where F: FnMut(P::Output) -> N,
+          P: Parser,
+          N: Parser<Input = P::Input>
+{
+    Then(p, f)
+}
+
+#[derive(Clone)]
+pub struct Expected<P>(P, Info<<P::Input as StreamOnce>::Item, <P::Input as StreamOnce>::Range>)
+    where P: Parser;
+impl<P> Parser for Expected<P>
+    where P: Parser
+{
+    type Input = P::Input;
+    type Output = P::Output;
+
+    fn parse_stream(&mut self, input: Self::Input) -> ParseResult<Self::Output, Self::Input> {
+        // add_error is only called on unconsumed inputs but we want this expected message to always
+        // replace the ones always present in the ParseError
+        self.0.parse_stream(input).map_err(|errors| {
+                                               errors.map(|mut errors| {
+                                                              errors.set_expected(self.1.clone());
+                                                              errors
+                                                          })
+                                           })
+    }
+
+    #[inline]
+    fn parse_lazy(&mut self, input: Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+        self.0.parse_lazy(input)
+    }
+
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        let start = errors.errors.len();
+        self.0.add_error(errors);
+        // Replace all expected errors that where added from the previous add_error
+        // with this expected error
+        let mut i = 0;
+        errors.errors.retain(|e| if i < start {
+                                 i += 1;
+                                 true
+                             } else {
+                                 match *e {
+                                     Error::Expected(_) => false,
+                                     _ => true,
+                                 }
+                             });
+        errors.add_error(Error::Expected(self.1.clone()));
+    }
+}
+
+/// Equivalent to [`p.expected(info)`].
+///
+/// [`p.expected(info)`]: ../primitives/trait.Parser.html#method.expected
+#[inline(always)]
+pub fn expected<P>(p: P,
+                   info: Info<<P::Input as StreamOnce>::Item, <P::Input as StreamOnce>::Range>)
+                   -> Expected<P>
+    where P: Parser
+{
+    Expected(p, info)
+}
+
+#[derive(Clone)]
+pub struct AndThen<P, F>(P, F);
+impl<P, F, O, E> Parser for AndThen<P, F>
+    where P: Parser,
+          F: FnMut(P::Output) -> Result<O, E>,
+          E: Into<Error<<P::Input as StreamOnce>::Item, <P::Input as StreamOnce>::Range>>
+{
+    type Input = P::Input;
+    type Output = O;
+    #[inline]
+    fn parse_lazy(&mut self, input: Self::Input) -> ConsumedResult<O, Self::Input> {
+        match self.0.parse_lazy(input) {
+            EmptyOk((o, input)) => {
+                match (self.1)(o) {
+                    Ok(o) => EmptyOk((o, input)),
+                    Err(err) => EmptyErr(ParseError::new(input.position(), err.into())),
+                }
+            }
+            ConsumedOk((o, input)) => {
+                match (self.1)(o) {
+                    Ok(o) => ConsumedOk((o, input)),
+                    Err(err) => ConsumedErr(ParseError::new(input.position(), err.into())),
+                }
+            }
+            EmptyErr(err) => EmptyErr(err),
+            ConsumedErr(err) => ConsumedErr(err),
+        }
+    }
+    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+        self.0.add_error(errors);
+    }
+}
+
+/// Equivalent to [`p.and_then(f)`].
+///
+/// [`p.and_then(f)`]: ../primitives/trait.Parser.html#method.and_then
+#[inline(always)]
+pub fn and_then<P, F, O, E>(p: P, f: F) -> AndThen<P, F>
+    where P: Parser,
+          F: FnMut(P::Output) -> Result<O, E>,
+          E: Into<Error<<P::Input as StreamOnce>::Item, <P::Input as StreamOnce>::Range>>
+{
+    AndThen(p, f)
+}
+
+macro_rules! tuple_parser {
+    ($h: ident, $($id: ident),+) => {
+        impl <Input: Stream, $h:, $($id:),+> Parser for ($h, $($id),+)
+            where Input: Stream,
+                  $h: Parser<Input=Input>,
+                  $($id: Parser<Input=Input>),+
+        {
+            type Input = Input;
+            type Output = ($h::Output, $($id::Output),+);
+            #[allow(non_snake_case)]
+            fn parse_lazy(&mut self,
+                          mut input: Input)
+                          -> ConsumedResult<($h::Output, $($id::Output),+), Input> {
+                let (ref mut $h, $(ref mut $id),+) = *self;
+                let mut consumed = false;
+                let $h = match $h.parse_lazy(input) {
+                    ConsumedOk((x, new_input)) => {
+                        consumed = true;
+                        input = new_input;
+                        x
+                    }
+                    EmptyErr(err) => return EmptyErr(err),
+                    ConsumedErr(err) => return ConsumedErr(err),
+                    EmptyOk((x, new_input)) => {
+                        input = new_input;
+                        x
+                    }
+                };
+                $(
+                    let $id = match $id.parse_lazy(input.clone()) {
+                        ConsumedOk((x, new_input)) => {
+                            consumed = true;
+                            input = new_input;
+                            x
+                        }
+                        EmptyErr(mut err) => {
+                            if let Ok(t) = input.uncons() {
+                                err.add_error(Error::Unexpected(Info::Token(t)));
+                            }
+                            $id.add_error(&mut err);
+                            if consumed {
+                                return ConsumedErr(err)
+                            } else {
+                                return EmptyErr(err)
+                            }
+                        }
+                        ConsumedErr(err) => return ConsumedErr(err),
+                        EmptyOk((x, new_input)) => {
+                            input = new_input;
+                            x
+                        }
+                    };
+                )+
+                if consumed {
+                    ConsumedOk((($h, $($id),+), input))
+                } else {
+                    EmptyOk((($h, $($id),+), input))
+                }
+            }
+            fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+                self.0.add_error(errors);
+            }
+        }
+    }
+}
+
+tuple_parser!(A, B);
+tuple_parser!(A, B, C);
+tuple_parser!(A, B, C, D);
+tuple_parser!(A, B, C, D, E);
+tuple_parser!(A, B, C, D, E, F);
+tuple_parser!(A, B, C, D, E, F, G);
+tuple_parser!(A, B, C, D, E, F, G, H);
+tuple_parser!(A, B, C, D, E, F, G, H, I);
+tuple_parser!(A, B, C, D, E, F, G, H, I, J);
+tuple_parser!(A, B, C, D, E, F, G, H, I, J, K);
+tuple_parser!(A, B, C, D, E, F, G, H, I, J, K, L);
+
+#[derive(Copy, Clone)]
+pub struct EnvParser<E, I, T>
+    where I: Stream
+{
+    env: E,
+    parser: fn(E, I) -> ParseResult<T, I>,
+}
+
+impl<E, I, O> Parser for EnvParser<E, I, O>
+    where E: Clone,
+          I: Stream
+{
+    type Input = I;
+    type Output = O;
+
+    #[inline]
+    fn parse_lazy(&mut self, input: I) -> ConsumedResult<O, I> {
+        (self.parser)(self.env.clone(), input).into()
+    }
+}
+
+/// Constructs a parser out of an environment and a function which needs the given environment to
+/// do the parsing. This is commonly useful to allow multiple parsers to share some environment
+/// while still allowing the parsers to be written in separate functions.
+///
+/// ```
+/// # extern crate combine;
+/// # use std::collections::HashMap;
+/// # use combine::*;
+/// # use combine::char::letter;
+/// # fn main() {
+/// struct Interner(HashMap<String, u32>);
+/// impl Interner {
+///     fn string<I>(&self, input: I) -> ParseResult<u32, I>
+///         where I: Stream<Item=char>
+///     {
+///         many(letter())
+///             .map(|s: String| self.0.get(&s).cloned().unwrap_or(0))
+///             .parse_stream(input)
+///     }
+/// }
+///
+/// let mut map = HashMap::new();
+/// map.insert("hello".into(), 1);
+/// map.insert("test".into(), 2);
+///
+/// let env = Interner(map);
+/// let mut parser = env_parser(&env, Interner::string);
+///
+/// let result = parser.parse("hello");
+/// assert_eq!(result, Ok((1, "")));
+///
+/// let result = parser.parse("world");
+/// assert_eq!(result, Ok((0, "")));
+/// # }
+/// ```
+#[inline(always)]
+pub fn env_parser<E, I, O>(env: E, parser: fn(E, I) -> ParseResult<O, I>) -> EnvParser<E, I, O>
+    where E: Clone,
+          I: Stream
+{
+    EnvParser {
+        env: env,
+        parser: parser,
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use primitives::{Error, ParseError, Positioner, Parser, SourcePosition, State};
+    use char::{char, digit, letter};
+
+    #[test]
+    fn choice_empty() {
+        let mut parser = choice::<&mut [Token<&str>], Token<&str>>(&mut []);
+        let result_err = parser.parse("a");
+        assert!(result_err.is_err());
+    }
+    #[test]
+    fn sep_by_consumed_error() {
+        let mut parser2 = sep_by((letter(), letter()), token(','));
+        let result_err: Result<(Vec<(char, char)>, &str), ParseError<&str>> = parser2.parse("a,bc");
+        assert!(result_err.is_err());
+    }
+
+    #[test]
+    fn tuple() {
+        let mut parser = (digit(), token(','), digit(), token(','), letter());
+        assert_eq!(parser.parse("1,2,z"), Ok((('1', ',', '2', ',', 'z'), "")));
+    }
+
+    /// The expected combinator should retain only errors that are not `Expected`
+    #[test]
+    fn expected_retain_errors() {
+        let mut parser = digit().message("message").expected("N/A").expected("my expected digit");
+        assert_eq!(parser.parse(State::new("a")),
+                   Err(ParseError {
+                           position: <char as Positioner>::start(),
+                           errors: vec![Error::Unexpected('a'.into()),
+                                        Error::Message("message".into()),
+                                        Error::Expected("my expected digit".into())],
+                       }));
+    }
+
+    #[test]
+    fn tuple_parse_error() {
+        let mut parser = (digit(), digit());
+        let result = parser.parse(State::new("a"));
+        assert_eq!(result,
+                   Err(ParseError {
+                           position: <char as Positioner>::start(),
+                           errors: vec![Error::Unexpected('a'.into()),
+                                        Error::Expected("digit".into())],
+                       }));
+    }
+
+    #[derive(Clone, PartialEq, Debug)]
+    struct CloneOnly {
+        s: String,
+    }
+
+    #[test]
+    fn token_clone_but_not_copy() {
+        // Verify we can use token() with a StreamSlice with an item type that is Clone but not
+        // Copy.
+        let input = &[CloneOnly { s: "x".to_string() }, CloneOnly { s: "y".to_string() }][..];
+        let result = token(CloneOnly { s: "x".to_string() }).parse(input);
+        assert_eq!(result,
+                   Ok((CloneOnly { s: "x".to_string() }, &[CloneOnly { s: "y".to_string() }][..])));
+    }
+
+    #[test]
+    fn message_tests() {
+        // Ensure message adds to both consumed and empty errors, interacting with parse_lazy and
+        // parse_stream correctly on either side
+        let input = "hi";
+
+        let mut ok        = char('h').message("not expected");
+        let mut empty0    = char('o').message("expected message");
+        let mut empty1    = char('o').message("expected message").map(|x| x);
+        let mut empty2    = char('o').map(|x| x).message("expected message");
+        let mut consumed0 = char('h').with(char('o')).message("expected message");
+        let mut consumed1 = char('h').with(char('o')).message("expected message").map(|x| x);
+        let mut consumed2 = char('h').with(char('o')).map(|x| x).message("expected message");
+
+        assert!(ok.parse(State::new(input)).is_ok());
+
+        let empty_expected =
+            Err(ParseError {
+               position: SourcePosition { line: 1, column: 1 },
+               errors: vec![Error::Unexpected('h'.into()),
+                            Error::Expected('o'.into()),
+                            Error::Message("expected message".into())],
+            });
+
+        let consumed_expected =
+            Err(ParseError {
+               position: SourcePosition { line: 1, column: 2 },
+               errors: vec![Error::Unexpected('i'.into()),
+                            Error::Expected('o'.into()),
+                            Error::Message("expected message".into())],
+            });
+
+        assert_eq!(empty0.parse(State::new(input)), empty_expected);
+        assert_eq!(empty1.parse(State::new(input)), empty_expected);
+        assert_eq!(empty2.parse(State::new(input)), empty_expected);
+
+        assert_eq!(consumed0.parse(State::new(input)), consumed_expected);
+        assert_eq!(consumed1.parse(State::new(input)), consumed_expected);
+        assert_eq!(consumed2.parse(State::new(input)), consumed_expected);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/combine/src/lib.rs
@@ -0,0 +1,563 @@
+//! This crate contains parser combinators, roughly based on the Haskell library
+//! [parsec](http://hackage.haskell.org/package/parsec).
+//!
+//! A parser in this library can be described as a function which takes some input and if it
+//! is succesful, returns a value together with the remaining input.
+//! A parser combinator is a function which takes one or more parsers and returns a new parser.
+//! For instance the [`many`] parser can be used to convert a parser for single digits into one that
+//! parses multiple digits. By modeling parsers in this way it becomes simple to compose complex
+//! parsers in an almost declarative way.
+//!
+//! # Overview
+//!
+//! `combine` limits itself to creating [LL(1) parsers](https://en.wikipedia.org/wiki/LL_parser)
+//! (it is possible to opt-in to LL(k) parsing using the [`try`] combinator) which makes the
+//! parsers easy to reason about in both function and performance while sacrificing
+//! some generality. In addition to you being able to reason better about the parsers you
+//! construct `combine` the library also takes the knowledge of being an LL parser and uses it to
+//! automatically construct good error messages.
+//!
+//! ```rust
+//! extern crate combine;
+//! use combine::{Parser, State};
+//! use combine::char::{digit, letter};
+//! const MSG: &'static str = r#"Parse error at line: 1, column: 1
+//! Unexpected `|`
+//! Expected `digit` or `letter`
+//! "#;
+//!
+//! fn main() {
+//!     // Wrapping a `&str` with `State` provides automatic line and column tracking. If `State`
+//!     // was not used the positions would instead only be pointers into the `&str`
+//!     if let Err(err) = digit().or(letter()).parse(State::new("|")) {
+//!         assert_eq!(MSG, format!("{}", err));
+//!     }
+//! }
+//! ```
+//!
+//! This library currently contains five modules:
+//!
+//! * [`combinator`] contains the before mentioned parser combinators and thus contains the main
+//! building blocks for creating any sort of complex parsers. It consists of free functions such
+//! as [`many`] and [`satisfy`] as well as a few methods on the [`Parser`] trait which provides a few
+//! functions such as [`or`] which are more natural to use method calls.
+//!
+//! * [`primitives`] contains the [`Parser`] and [`Stream`] traits which are the core abstractions in
+//! combine as well as various structs dealing with input streams and errors. You usually only need
+//! to use this module if you want more control over parsing and input streams.
+//!
+//! * [`char`] and [`byte`] provides parsers specifically working with streams of characters
+//! (`char`) and bytes (`u8`) respectively. As a few examples it has parsers for accepting digits,
+//! letters or whitespace.
+//!
+//! * [`range`] provides some zero-copy parsers for [`RangeStream`]s.
+//!
+//! # Examples
+//!
+//! ```
+//! extern crate combine;
+//! use combine::char::{spaces, digit, char};
+//! use combine::{many1, sep_by, Parser, ParseError};
+//!
+//! fn main() {
+//!     //Parse spaces first and use the with method to only keep the result of the next parser
+//!     let integer = spaces()
+//!         //parse a string of digits into an i32
+//!         .with(many1(digit()).map(|string: String| string.parse::<i32>().unwrap()));
+//!
+//!     //Parse integers separated by commas, skipping whitespace
+//!     let mut integer_list = sep_by(integer, spaces().skip(char(',')));
+//!
+//!     //Call parse with the input to execute the parser
+//!     let input = "1234, 45,78";
+//!     let result: Result<(Vec<i32>, &str), ParseError<&str>> = integer_list.parse(input);
+//!     match result {
+//!         Ok((value, _remaining_input)) => println!("{:?}", value),
+//!         Err(err) => println!("{}", err)
+//!     }
+//! }
+//! ```
+//!
+//! If we need a parser that is mutually recursive we can define a free function which internally
+//! can in turn be used as a parser by using the [`parser`][fn parser] function which turns a function with the
+//! correct signature into a parser. In this case we define `expr` to work on any type of [`Stream`]
+//! which is combine's way of abstracting over different data sources such as array slices, string
+//! slices, iterators etc. If instead you would only need to parse string already in memory you
+//! could define `expr` as `fn expr(input: &str) -> ParseResult<Expr, &str>`
+//!
+//! ```
+//! extern crate combine;
+//! use combine::char::{char, letter, spaces};
+//! use combine::{between, many1, parser, sep_by, Parser};
+//! use combine::primitives::{State, Stream, ParseResult};
+//!
+//! #[derive(Debug, PartialEq)]
+//! enum Expr {
+//!     Id(String),
+//!     Array(Vec<Expr>),
+//!     Pair(Box<Expr>, Box<Expr>)
+//! }
+//!
+//! fn expr<I>(input: I) -> ParseResult<Expr, I>
+//!     where I: Stream<Item=char>
+//! {
+//!     let word = many1(letter());
+//!
+//!     //Creates a parser which parses a char and skips any trailing whitespace
+//!     let lex_char = |c| char(c).skip(spaces());
+//!
+//!     let comma_list = sep_by(parser(expr::<I>), lex_char(','));
+//!     let array = between(lex_char('['), lex_char(']'), comma_list);
+//!
+//!     //We can use tuples to run several parsers in sequence
+//!     //The resulting type is a tuple containing each parsers output
+//!     let pair = (lex_char('('),
+//!                 parser(expr::<I>),
+//!                 lex_char(','),
+//!                 parser(expr::<I>),
+//!                 lex_char(')'))
+//!                    .map(|t| Expr::Pair(Box::new(t.1), Box::new(t.3)));
+//!
+//!     word.map(Expr::Id)
+//!         .or(array.map(Expr::Array))
+//!         .or(pair)
+//!         .skip(spaces())
+//!         .parse_stream(input)
+//! }
+//!
+//! fn main() {
+//!     let result = parser(expr)
+//!         .parse("[[], (hello, world), [rust]]");
+//!     let expr = Expr::Array(vec![
+//!           Expr::Array(Vec::new())
+//!         , Expr::Pair(Box::new(Expr::Id("hello".to_string())),
+//!                      Box::new(Expr::Id("world".to_string())))
+//!         , Expr::Array(vec![Expr::Id("rust".to_string())])
+//!     ]);
+//!     assert_eq!(result, Ok((expr, "")));
+//! }
+//! ```
+//!
+//! [`combinator`]: combinator/index.html
+//! [`primitives`]: primitives/index.html
+//! [`char`]: char/index.html
+//! [`byte`]: byte/index.html
+//! [`range`]: range/index.html
+//! [`many`]: combinator/fn.many.html
+//! [`try`]: combinator/fn.try.html
+//! [`satisfy`]: combinator/fn.satisfy.html
+//! [`or`]: primitives/trait.Parser.html#method.or
+//! [`Stream`]: primitives/trait.Stream.html
+//! [`RangeStream`]: primitives/trait.RangeStream.html
+//! [`Parser`]: primitives/trait.Parser.html
+//! [fn parser]: combinator/fn.parser.html
+
+// inline(always) is only used on trivial functions returning parsers
+#![cfg_attr(feature = "cargo-clippy", allow(inline_always))]
+
+#[doc(inline)]
+pub use primitives::{Parser, ParseError, ConsumedResult, ParseResult, State, from_iter, Stream,
+                     StreamOnce};
+#[doc(inline)]
+pub use combinator::{any, between, chainl1, chainr1, choice, count, eof, env_parser, many, many1,
+                     none_of, one_of, optional, parser, position, satisfy, satisfy_map, sep_by,
+                     sep_by1, sep_end_by, sep_end_by1, skip_many, skip_many1, token, tokens, try,
+                     look_ahead, value, unexpected, not_followed_by};
+
+macro_rules! static_fn {
+    (($($arg: pat, $arg_ty: ty),*) -> $ret: ty { $body: expr }) => { {
+        fn temp($($arg: $arg_ty),*) -> $ret { $body }
+        temp as fn(_) -> _
+    } }
+}
+
+macro_rules! impl_token_parser {
+    ($name: ident($($ty_var: ident),*), $ty: ty, $inner_type: ty) => {
+    #[derive(Clone)]
+    pub struct $name<I $(,$ty_var)*>($inner_type, PhantomData<fn (I) -> I>)
+        where I: Stream<Item=$ty> $(, $ty_var : Parser<Input=I>)*;
+    impl <I $(,$ty_var)*> Parser for $name<I $(,$ty_var)*>
+        where I: Stream<Item=$ty> $(, $ty_var : Parser<Input=I>)* {
+        type Input = I;
+        type Output = <$inner_type as Parser>::Output;
+        #[inline]
+        fn parse_lazy(&mut self,
+                      input: Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+            self.0.parse_lazy(input)
+        }
+        fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
+            self.0.add_error(errors)
+        }
+    }
+}
+}
+
+/// Module containing the primitive types which is used to create and compose more advanced
+/// parsers.
+#[macro_use]
+pub mod primitives;
+/// Module containing all specific parsers.
+pub mod combinator;
+/// Module containing zero-copy parsers.
+pub mod range;
+/// Module containing parsers specialized on byte streams.
+pub mod byte;
+/// Module containing parsers specialized on character streams.
+pub mod char;
+
+
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use super::primitives::{SourcePosition, Error, Consumed};
+    use char::{alpha_num, char, digit, letter, spaces, string};
+
+
+    fn integer<'a, I>(input: I) -> ParseResult<i64, I>
+        where I: Stream<Item = char>
+    {
+        let (s, input) = try!(many1::<String, _>(digit()).expected("integer").parse_stream(input));
+        let mut n = 0;
+        for c in s.chars() {
+            n = n * 10 + (c as i64 - '0' as i64);
+        }
+        Ok((n, input))
+    }
+
+    #[test]
+    fn test_integer() {
+        let result = parser(integer).parse("123");
+        assert_eq!(result, Ok((123i64, "")));
+    }
+    #[test]
+    fn list() {
+        let mut p = sep_by(parser(integer), char(','));
+        let result = p.parse("123,4,56");
+        assert_eq!(result, Ok((vec![123i64, 4, 56], "")));
+    }
+    #[test]
+    fn iterator() {
+        let result =
+            parser(integer).parse(from_iter("123".chars())).map(|(i, mut input)| {
+                                                                    (i, input.uncons().is_err())
+                                                                });
+        assert_eq!(result, Ok((123i64, true)));
+    }
+    #[test]
+    fn field() {
+        let word = || many(alpha_num());
+        let spaces = spaces();
+        let c_decl =
+            (word(), spaces.clone(), char(':'), spaces, word()).map(|t| (t.0, t.4)).parse("x: int");
+        assert_eq!(c_decl, Ok((("x".to_string(), "int".to_string()), "")));
+    }
+    #[test]
+    fn source_position() {
+        let source = r"
+123
+";
+        let result =
+            (spaces(), parser(integer), spaces()).map(|t| t.1).parse_stream(State::new(source));
+        let state = Consumed::Consumed(State {
+                                           position: SourcePosition {
+                                               line: 3,
+                                               column: 1,
+                                           },
+                                           input: "",
+                                       });
+        assert_eq!(result, Ok((123i64, state)));
+    }
+
+    #[derive(Debug, PartialEq)]
+    enum Expr {
+        Id(String),
+        Int(i64),
+        Array(Vec<Expr>),
+        Plus(Box<Expr>, Box<Expr>),
+        Times(Box<Expr>, Box<Expr>),
+    }
+
+    #[allow(unconditional_recursion)]
+    fn expr<I>(input: I) -> ParseResult<Expr, I>
+        where I: Stream<Item = char>
+    {
+        let word = many1(letter()).expected("identifier");
+        let integer = parser(integer);
+        let array = between(char('['), char(']'), sep_by(parser(expr), char(','))).expected("[");
+        let paren_expr = between(char('('), char(')'), parser(term)).expected("(");
+        let spaces = spaces();
+        spaces.clone()
+            .with(word.map(Expr::Id)
+                      .or(integer.map(Expr::Int))
+                      .or(array.map(Expr::Array))
+                      .or(paren_expr))
+            .skip(spaces)
+            .parse_stream(input)
+    }
+
+    #[test]
+    fn expression() {
+        let result = sep_by(parser(expr), char(',')).parse("int, 100, [[], 123]");
+        let exprs = vec![Expr::Id("int".to_string()),
+                         Expr::Int(100),
+                         Expr::Array(vec![Expr::Array(vec![]), Expr::Int(123)])];
+        assert_eq!(result, Ok((exprs, "")));
+    }
+
+    #[test]
+    fn expression_error() {
+        let input = r"
+,123
+";
+        let result = parser(expr).parse(State::new(input));
+        let err = ParseError {
+            position: SourcePosition {
+                line: 2,
+                column: 1,
+            },
+            errors: vec![Error::Unexpected(','.into()),
+                         Error::Expected("integer".into()),
+                         Error::Expected("identifier".into()),
+                         Error::Expected("[".into()),
+                         Error::Expected("(".into())],
+        };
+        assert_eq!(result, Err(err));
+    }
+
+    fn term<I>(input: I) -> ParseResult<Expr, I>
+        where I: Stream<Item = char>
+    {
+        fn times(l: Expr, r: Expr) -> Expr {
+            Expr::Times(Box::new(l), Box::new(r))
+        }
+        fn plus(l: Expr, r: Expr) -> Expr {
+            Expr::Plus(Box::new(l), Box::new(r))
+        }
+        let mul = char('*').map(|_| times);
+        let add = char('+').map(|_| plus);
+        let factor = chainl1(parser(expr), mul);
+        chainl1(factor, add).parse_stream(input)
+    }
+
+    #[test]
+    fn operators() {
+        let input = r"
+1 * 2 + 3 * test
+";
+        let (result, _) = parser(term).parse(State::new(input)).unwrap();
+
+        let e1 = Expr::Times(Box::new(Expr::Int(1)), Box::new(Expr::Int(2)));
+        let e2 = Expr::Times(Box::new(Expr::Int(3)),
+                             Box::new(Expr::Id("test".to_string())));
+        assert_eq!(result, Expr::Plus(Box::new(e1), Box::new(e2)));
+    }
+
+
+    fn follow(input: State<&str>) -> ParseResult<(), State<&str>> {
+        match input.clone().uncons() {
+            Ok(c) => {
+                if c.is_alphanumeric() {
+                    let e = Error::Unexpected(c.into());
+                    Err(Consumed::Empty(ParseError::new(input.position(), e)))
+                } else {
+                    Ok(((), Consumed::Empty(input)))
+                }
+            }
+            Err(_) => Ok(((), Consumed::Empty(input))),
+        }
+    }
+    #[test]
+    fn error_position() {
+        let mut p = string("let").skip(parser(follow)).map(|x| x.to_string()).or(many1(digit()));
+        match p.parse(State::new("le123")) {
+            Ok(_) => assert!(false),
+            Err(err) => {
+                assert_eq!(err.position,
+                           SourcePosition {
+                               line: 1,
+                               column: 1,
+                           })
+            }
+        }
+        match p.parse(State::new("let1")) {
+            Ok(_) => assert!(false),
+            Err(err) => {
+                assert_eq!(err.position,
+                           SourcePosition {
+                               line: 1,
+                               column: 4,
+                           })
+            }
+        }
+    }
+
+    #[test]
+    fn sep_by_error_consume() {
+        let mut p = sep_by::<Vec<_>, _, _>(string("abc"), char(','));
+        let err = p.parse(State::new("ab,abc")).map(|x| format!("{:?}", x)).unwrap_err();
+        assert_eq!(err.position,
+                   SourcePosition {
+                       line: 1,
+                       column: 1,
+                   });
+    }
+
+    #[test]
+    fn optional_error_consume() {
+        let mut p = optional(string("abc"));
+        let err = p.parse(State::new("ab")).map(|x| format!("{:?}", x)).unwrap_err();
+        assert_eq!(err.position,
+                   SourcePosition {
+                       line: 1,
+                       column: 1,
+                   });
+    }
+    #[test]
+    fn chainl1_error_consume() {
+        fn first<T, U>(t: T, _: U) -> T {
+            t
+        }
+        let mut p = chainl1(string("abc"), char(',').map(|_| first));
+        assert!(p.parse("abc,ab").is_err());
+    }
+
+    #[test]
+    fn inner_error_consume() {
+        let mut p = many::<Vec<_>, _>(between(char('['), char(']'), digit()));
+        let result = p.parse(State::new("[1][2][]"));
+        assert!(result.is_err(), format!("{:?}", result));
+        let error = result.map(|x| format!("{:?}", x)).unwrap_err();
+        assert_eq!(error.position,
+                   SourcePosition {
+                       line: 1,
+                       column: 8,
+                   });
+    }
+
+    #[test]
+    fn infinite_recursion_in_box_parser() {
+        let _: Result<(Vec<_>, _), _> = (many(Box::new(digit()))).parse("1");
+    }
+
+    #[test]
+    fn unsized_parser() {
+        let mut parser: Box<Parser<Input = &str, Output = char>> = Box::new(digit());
+        let borrow_parser = &mut *parser;
+        assert_eq!(borrow_parser.parse("1"), Ok(('1', "")));
+    }
+
+    #[test]
+    fn choice_strings() {
+        let mut fruits = [try(string("Apple")),
+                          try(string("Banana")),
+                          try(string("Cherry")),
+                          try(string("Date")),
+                          try(string("Fig")),
+                          try(string("Grape"))];
+        let mut parser = choice(&mut fruits);
+        assert_eq!(parser.parse("Apple"), Ok(("Apple", "")));
+        assert_eq!(parser.parse("Banana"), Ok(("Banana", "")));
+        assert_eq!(parser.parse("Cherry"), Ok(("Cherry", "")));
+        assert_eq!(parser.parse("DateABC"), Ok(("Date", "ABC")));
+        assert_eq!(parser.parse("Fig123"), Ok(("Fig", "123")));
+        assert_eq!(parser.parse("GrapeApple"), Ok(("Grape", "Apple")));
+    }
+
+    #[test]
+    fn std_error() {
+        use std::fmt;
+        use std::error::Error as StdError;
+        #[derive(Debug)]
+        struct Error;
+        impl fmt::Display for Error {
+            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+                write!(f, "error")
+            }
+        }
+        impl StdError for Error {
+            fn description(&self) -> &str {
+                "error"
+            }
+        }
+        let result: Result<((), _), ParseError<&str>> =
+            string("abc").and_then(|_| Err(Error)).parse("abc");
+        assert!(result.is_err());
+        // Test that ParseError can be coerced to a StdError
+        let _ = result.map_err(|err| {
+                                   let err: Box<StdError> = Box::new(err);
+                                   err
+                               });
+    }
+
+    #[test]
+    fn extract_std_error() {
+        // The previous test verified that we could map a ParseError to a StdError by dropping the
+        // internal error details.  This test verifies that we can map a ParseError to a StdError
+        // without dropping the internal error details.  Consumers using `error-chain` will
+        // appreciate this.  For technical reasons this is pretty janky; see the discussion in
+        // https://github.com/Marwes/combine/issues/86, and excuse the test with significant
+        // boilerplate!
+        use std::fmt;
+        use std::error::Error as StdError;
+
+        #[derive(Clone, PartialEq, Debug)]
+        struct CloneOnly(String);
+
+        #[derive(Debug)]
+        struct DisplayVec<T>(Vec<T>);
+
+        #[derive(Debug)]
+        struct ExtractedError(usize, DisplayVec<Error<CloneOnly, DisplayVec<CloneOnly>>>);
+
+        impl StdError for ExtractedError {
+            fn description(&self) -> &str {
+                "extracted error"
+            }
+        }
+
+        impl fmt::Display for CloneOnly {
+            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+                write!(f, "{}", self.0)
+            }
+        }
+
+        impl<T: fmt::Debug> fmt::Display for DisplayVec<T> {
+            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+                write!(f, "[{:?}]", self.0)
+            }
+        }
+
+        impl fmt::Display for ExtractedError {
+            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+                try!(writeln!(f, "Parse error at {}", self.0));
+                Error::fmt_errors(&(self.1).0, f)
+            }
+        }
+
+        let input = &[CloneOnly("x".to_string()), CloneOnly("y".to_string())][..];
+        let result = token(CloneOnly("z".to_string()))
+            .parse(input)
+            .map_err(|e| e.translate_position(input))
+            .map_err(|e| {
+                ExtractedError(e.position,
+                               DisplayVec(e.errors
+                                              .into_iter()
+                                              .map(|e| {
+                                                       e.map_range(|r| DisplayVec(r.to_owned()))
+                                                   })
+                                              .collect()))
+            });
+
+        assert!(result.is_err());
+        // Test that the fresh ExtractedError is Display, so that the internal errors can be
+        // inspected by consuming code; and that the ExtractedError can be coerced to StdError.
+        let _ = result.map_err(|err| {
+            let s = format!("{}", err);
+            assert!(s.starts_with("Parse error at 0"));
+            assert!(s.contains("Expected"));
+            let err: Box<StdError> = Box::new(err);
+            err
+        });
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/combine/src/primitives.rs
@@ -0,0 +1,1937 @@
+use std::any::Any;
+use std::cell::UnsafeCell;
+use std::collections::VecDeque;
+use std::error::Error as StdError;
+use std::fmt;
+use std::io::{Read, Bytes};
+
+use self::FastResult::*;
+
+use combinator::{AndThen, and_then, Expected, expected, FlatMap, flat_map, Iter, Map, map, Message,
+                 message, Or, or, Skip, skip, Then, then, With, with};
+
+#[macro_export]
+macro_rules! ctry {
+    ($result: expr) => {
+        match $result {
+            $crate::primitives::FastResult::ConsumedOk((x, i)) => (x, $crate::primitives::Consumed::Consumed(i)),
+            $crate::primitives::FastResult::EmptyOk((x, i)) => (x, $crate::primitives::Consumed::Empty(i)),
+            $crate::primitives::FastResult::ConsumedErr(err) => return $crate::primitives::FastResult::ConsumedErr(err.into()),
+            $crate::primitives::FastResult::EmptyErr(err) => return $crate::primitives::FastResult::EmptyErr(err.into()),
+        }
+    }
+}
+
+/// Struct which represents a position in a source file.
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
+pub struct SourcePosition {
+    /// Current line of the input
+    pub line: i32,
+    /// Current column of the input
+    pub column: i32,
+}
+
+/// Struct which represents a position in a byte stream.
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
+pub struct BytePosition {
+    /// Current position
+    pub position: usize,
+}
+
+impl fmt::Display for BytePosition {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "position: {}", self.position)
+    }
+}
+
+/// Enum holding error information. Variants are defined for `Stream::Item` and `Stream::Range` as
+/// well as string variants holding simple descriptions.
+///
+/// As there is implementations of `From` for `T: Positioner`, `String` and `&'static str` the
+/// constructor need not be used directly as calling `msg.into()` should turn a message into the
+/// correct `Info` variant.
+#[derive(Clone, Debug)]
+pub enum Info<T, R> {
+    Token(T),
+    Range(R),
+    Owned(String),
+    Borrowed(&'static str),
+}
+
+impl<T, R> Info<T, R> {
+    pub fn map_token<F, U>(self, f: F) -> Info<U, R>
+        where F: FnOnce(T) -> U
+    {
+        use self::Info::*;
+        match self {
+            Token(t) => Token(f(t)),
+            Range(r) => Range(r),
+            Owned(s) => Owned(s),
+            Borrowed(x) => Borrowed(x),
+        }
+    }
+
+    pub fn map_range<F, S>(self, f: F) -> Info<T, S>
+        where F: FnOnce(R) -> S
+    {
+        use self::Info::*;
+        match self {
+            Token(t) => Token(t),
+            Range(r) => Range(f(r)),
+            Owned(s) => Owned(s),
+            Borrowed(x) => Borrowed(x),
+        }
+    }
+}
+
+impl<T: PartialEq, R: PartialEq> PartialEq for Info<T, R> {
+    fn eq(&self, other: &Info<T, R>) -> bool {
+        match (self, other) {
+            (&Info::Token(ref l), &Info::Token(ref r)) => l == r,
+            (&Info::Range(ref l), &Info::Range(ref r)) => l == r,
+            (&Info::Owned(ref l), &Info::Owned(ref r)) => l == r,
+            (&Info::Borrowed(l), &Info::Owned(ref r)) => l == r,
+            (&Info::Owned(ref l), &Info::Borrowed(r)) => l == r,
+            (&Info::Borrowed(l), &Info::Borrowed(r)) => l == r,
+            _ => false,
+        }
+    }
+}
+impl<T: fmt::Display, R: fmt::Display> fmt::Display for Info<T, R> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            Info::Token(ref c) => write!(f, "{}", c),
+            Info::Range(ref c) => write!(f, "{}", c),
+            Info::Owned(ref s) => write!(f, "{}", s),
+            Info::Borrowed(s) => write!(f, "{}", s),
+        }
+    }
+}
+
+impl<R> From<char> for Info<char, R> {
+    fn from(s: char) -> Info<char, R> {
+        Info::Token(s)
+    }
+}
+impl<T, R> From<String> for Info<T, R> {
+    fn from(s: String) -> Info<T, R> {
+        Info::Owned(s)
+    }
+}
+
+impl<T, R> From<&'static str> for Info<T, R> {
+    fn from(s: &'static str) -> Info<T, R> {
+        Info::Borrowed(s)
+    }
+}
+
+/// Enum used to store information about an error that has occurred during parsing.
+#[derive(Debug)]
+pub enum Error<T, R> {
+    /// Error indicating an unexpected token has been encountered in the stream
+    Unexpected(Info<T, R>),
+    /// Error indicating that the parser expected something else
+    Expected(Info<T, R>),
+    /// Generic message
+    Message(Info<T, R>),
+    /// Variant for containing other types of errors
+    Other(Box<StdError + Send + Sync>),
+}
+
+impl<T, R> Error<T, R> {
+    pub fn map_token<F, U>(self, f: F) -> Error<U, R>
+        where F: FnOnce(T) -> U
+    {
+        use self::Error::*;
+        match self {
+            Unexpected(x) => Unexpected(x.map_token(f)),
+            Expected(x) => Expected(x.map_token(f)),
+            Message(x) => Message(x.map_token(f)),
+            Other(x) => Other(x),
+        }
+    }
+
+    pub fn map_range<F, S>(self, f: F) -> Error<T, S>
+        where F: FnOnce(R) -> S
+    {
+        use self::Error::*;
+        match self {
+            Unexpected(x) => Unexpected(x.map_range(f)),
+            Expected(x) => Expected(x.map_range(f)),
+            Message(x) => Message(x.map_range(f)),
+            Other(x) => Other(x),
+        }
+    }
+}
+
+impl<T: PartialEq, R: PartialEq> PartialEq for Error<T, R> {
+    fn eq(&self, other: &Error<T, R>) -> bool {
+        match (self, other) {
+            (&Error::Unexpected(ref l), &Error::Unexpected(ref r)) |
+            (&Error::Expected(ref l), &Error::Expected(ref r)) |
+            (&Error::Message(ref l), &Error::Message(ref r)) => l == r,
+            _ => false,
+        }
+    }
+}
+
+impl<E, T, R> From<E> for Error<T, R>
+    where E: StdError + 'static + Send + Sync
+{
+    fn from(e: E) -> Error<T, R> {
+        Error::Other(Box::new(e))
+    }
+}
+
+impl<T, R> Error<T, R> {
+    /// Returns the `end_of_input` error.
+    pub fn end_of_input() -> Error<T, R> {
+        Error::Unexpected("end of input".into())
+    }
+
+    /// Formats a slice of errors in a human readable way.
+    ///
+    /// ```rust
+    /// # extern crate combine;
+    /// # use combine::*;
+    /// # use combine::char::*;
+    ///
+    /// # fn main() {
+    /// let input = r"
+    ///   ,123
+    /// ";
+    /// let result = spaces().with(char('.').or(char('a')).or(digit()))
+    ///     .parse(State::new(input));
+    /// let m = format!("{}", result.unwrap_err());
+    /// let expected = r"Parse error at line: 2, column: 3
+    /// Unexpected `,`
+    /// Expected `.`, `a` or `digit`
+    /// ";
+    /// assert_eq!(m, expected);
+    /// # }
+    /// ```
+    pub fn fmt_errors(errors: &[Error<T, R>], f: &mut fmt::Formatter) -> fmt::Result
+        where T: fmt::Display,
+              R: fmt::Display
+    {
+        // First print the token that we did not expect
+        // There should really just be one unexpected message at this point though we print them
+        // all to be safe
+        let unexpected = errors.iter().filter(|e| match **e {
+                                                  Error::Unexpected(_) => true,
+                                                  _ => false,
+                                              });
+        for error in unexpected {
+            try!(writeln!(f, "{}", error));
+        }
+
+        // Then we print out all the things that were expected in a comma separated list
+        // 'Expected 'a', 'expression' or 'let'
+        let iter = || {
+            errors.iter().filter_map(|e| match *e {
+                                         Error::Expected(ref err) => Some(err),
+                                         _ => None,
+                                     })
+        };
+        let expected_count = iter().count();
+        for (i, message) in iter().enumerate() {
+            let s = match i {
+                0 => "Expected",
+                _ if i < expected_count - 1 => ",",
+                // Last expected message to be written
+                _ => " or",
+            };
+            try!(write!(f, "{} `{}`", s, message));
+        }
+        if expected_count != 0 {
+            try!(writeln!(f, ""));
+        }
+        // If there are any generic messages we print them out last
+        let messages = errors.iter().filter(|e| match **e {
+                                                Error::Message(_) |
+                                                Error::Other(_) => true,
+                                                _ => false,
+                                            });
+        for error in messages {
+            try!(writeln!(f, "{}", error));
+        }
+        Ok(())
+    }
+}
+
+/// Enum used to indicate if a parser consumed any items of the stream it was given as an input.
+///
+/// This is used by parsers such as `or` and `choice` to determine if they should try to parse
+/// with another parser as they will only be able to provide good error reporting if the preceding
+/// parser did not consume any tokens.
+#[derive(Clone, PartialEq, Debug, Copy)]
+pub enum Consumed<T> {
+    /// Constructor indicating that the parser has consumed elements
+    Consumed(T),
+    /// Constructor indicating that the parser did not consume any elements
+    Empty(T),
+}
+
+impl<T> AsMut<T> for Consumed<T> {
+    fn as_mut(&mut self) -> &mut T {
+        match *self {
+            Consumed::Empty(ref mut t) |
+            Consumed::Consumed(ref mut t) => t,
+        }
+    }
+}
+
+impl<T> AsRef<T> for Consumed<T> {
+    fn as_ref(&self) -> &T {
+        match *self {
+            Consumed::Empty(ref t) |
+            Consumed::Consumed(ref t) => t,
+        }
+    }
+}
+
+impl<T> Consumed<T> {
+    /// Returns true if `self` is empty.
+    pub fn is_empty(&self) -> bool {
+        match *self {
+            Consumed::Empty(_) => true,
+            Consumed::Consumed(_) => false,
+        }
+    }
+
+    /// Extracts the contained value.
+    pub fn into_inner(self) -> T {
+        match self {
+            Consumed::Empty(x) |
+            Consumed::Consumed(x) => x,
+        }
+    }
+
+    /// Converts `self` into the `Consumed` state.
+    #[deprecated(since = "2.3.1", note = "Renamed to into_consumed")]
+    pub fn as_consumed(self) -> Consumed<T> {
+        self.into_consumed()
+    }
+
+    /// Converts `self` into the `Consumed` state.
+    pub fn into_consumed(self) -> Consumed<T> {
+        Consumed::Consumed(self.into_inner())
+    }
+
+    /// Converts `self` into the `Empty` state.
+    #[deprecated(since = "2.3.1", note = "Renamed to into_empty")]
+    pub fn as_empty(self) -> Consumed<T> {
+        self.into_empty()
+    }
+
+    /// Converts `self` into the `Empty` state.
+    pub fn into_empty(self) -> Consumed<T> {
+        Consumed::Empty(self.into_inner())
+    }
+
+    /// Maps over the contained value without changing the consumed state.
+    pub fn map<F, U>(self, f: F) -> Consumed<U>
+        where F: FnOnce(T) -> U
+    {
+        match self {
+            Consumed::Empty(x) => Consumed::Empty(f(x)),
+            Consumed::Consumed(x) => Consumed::Consumed(f(x)),
+        }
+    }
+
+    pub fn merge(&self, current: Consumed<T>) -> Consumed<T> {
+        match *self {
+            Consumed::Empty(_) => current,
+            Consumed::Consumed(_) => current.into_consumed(),
+        }
+    }
+
+    /// Combines the `Consumed` flags from `self` and the result of `f`.
+    ///
+    /// ```text
+    /// Empty    <> Empty    -> Empty
+    /// Consumed <> Empty    -> Consumed
+    /// Empty    <> Consumed -> Consumed
+    /// Consumed <> Consumed -> Consumed
+    /// ```
+    ///
+    /// ```
+    /// # extern crate combine as pc;
+    /// # use pc::*;
+    /// # fn main() {
+    /// //Parses a character of string literal and handles the escaped characters \\ and \" as \
+    /// //and " respectively
+    /// fn char(input: &str) -> ParseResult<char, &str> {
+    ///     let (c, input) = try!(satisfy(|c| c != '"').parse_stream(input));
+    ///     match c {
+    ///         //Since the `char` parser has already consumed some of the input `combine` is used
+    ///         //propagate the consumed state to the next part of the parser
+    ///         '\\' => input.combine(|input| {
+    ///             satisfy(|c| c == '"' || c == '\\')
+    ///                 .map(|c| {
+    ///                     match c {
+    ///                         '"' => '"',
+    ///                         '\\' => '\\',
+    ///                         c => c
+    ///                     }
+    ///                 })
+    ///                 .parse_stream(input)
+    ///             }),
+    ///         _ => Ok((c, input))
+    ///     }
+    /// }
+    /// let result = many(parser(char))
+    ///     .parse(r#"abc\"\\"#);
+    /// assert_eq!(result, Ok((r#"abc"\"#.to_string(), "")));
+    /// }
+    /// ```
+    pub fn combine<F, U, I>(self, f: F) -> ParseResult<U, I>
+        where F: FnOnce(T) -> ParseResult<U, I>,
+              I: StreamOnce
+    {
+        match self {
+            Consumed::Consumed(x) => {
+                match f(x) {
+                    Ok((v, Consumed::Empty(rest))) => Ok((v, Consumed::Consumed(rest))),
+                    Err(Consumed::Empty(err)) => Err(Consumed::Consumed(err)),
+                    y => y,
+                }
+            }
+            Consumed::Empty(x) => f(x),
+        }
+    }
+    pub fn combine_consumed<F, U, I>(self, f: F) -> ConsumedResult<U, I>
+        where F: FnOnce(T) -> ConsumedResult<U, I>,
+              I: StreamOnce
+    {
+        use self::FastResult::*;
+        match self {
+            Consumed::Consumed(x) => {
+                match f(x) {
+                    EmptyOk((v, rest)) => ConsumedOk((v, rest)),
+                    EmptyErr(err) => ConsumedErr(err),
+                    y => y,
+                }
+            }
+            Consumed::Empty(x) => f(x),
+        }
+    }
+}
+/// Struct which hold information about an error that occurred at a specific position.
+/// Can hold multiple instances of `Error` if more that one error occurred in the same position.
+pub struct ParseError<S: StreamOnce> {
+    /// The position where the error occurred
+    pub position: S::Position,
+    /// A vector containing specific information on what errors occurred at `position`. Usually
+    /// a fully formed message contains one `Unexpected` error and one or more `Expected` errors.
+    /// `Message` and `Other` may also appear (`combine` never generates these errors on its own)
+    /// and may warrant custom handling.
+    pub errors: Vec<Error<S::Item, S::Range>>,
+}
+
+impl<S: StreamOnce> ParseError<S> {
+    /// Constructs a new `ParseError` which occurred at `position`.
+    pub fn new(position: S::Position, error: Error<S::Item, S::Range>) -> ParseError<S> {
+        ParseError::from_errors(position, vec![error])
+    }
+
+    /// Constructs an error with no other information than the position it occurred at.
+    pub fn empty(position: S::Position) -> ParseError<S> {
+        ParseError::from_errors(position, vec![])
+    }
+
+    /// Constructs a `ParseError` with multiple causes.
+    pub fn from_errors(position: S::Position,
+                       errors: Vec<Error<S::Item, S::Range>>)
+                       -> ParseError<S> {
+        ParseError {
+            position: position,
+            errors: errors,
+        }
+    }
+
+    /// Constructs an end of input error. Should be returned by parsers which encounter end of
+    /// input unexpectedly.
+    pub fn end_of_input(position: S::Position) -> ParseError<S> {
+        ParseError::new(position, Error::end_of_input())
+    }
+
+    /// Adds a `Message` error, taking care not to add duplicated errors.
+    #[deprecated(since = "2.3.0", note = "Use `add_error(Error::Message())` instead")]
+    pub fn add_message<M>(&mut self, message: M)
+        where M: Into<Info<S::Item, S::Range>>
+    {
+        self.add_error(Error::Message(message.into()));
+    }
+
+    /// Adds an error if `error` does not exist in this `ParseError` already (as determined byte
+    /// `PartialEq`).
+    pub fn add_error(&mut self, error: Error<S::Item, S::Range>) {
+        // Don't add duplicate errors
+        if self.errors.iter().all(|err| *err != error) {
+            self.errors.push(error);
+        }
+    }
+
+    /// Remvoes all `Expected` errors in `self` and adds `info` instead.
+    pub fn set_expected(&mut self, info: Info<S::Item, S::Range>) {
+        // Remove all other expected messages
+        self.errors.retain(|e| match *e {
+                               Error::Expected(_) => false,
+                               _ => true,
+                           });
+        self.errors.push(Error::Expected(info));
+    }
+
+    /// Merges two `ParseError`s. If they exist at the same position the errors of `other` are
+    /// added to `self` (using `add_error` to skip duplicates). If they are not at the same
+    /// position the error furthest ahead are returned, ignoring the other `ParseError`.
+    pub fn merge(mut self, other: ParseError<S>) -> ParseError<S> {
+        use std::cmp::Ordering;
+        // Only keep the errors which occurred after consuming the most amount of data
+        match self.position.cmp(&other.position) {
+            Ordering::Less => other,
+            Ordering::Greater => self,
+            Ordering::Equal => {
+                for message in other.errors {
+                    self.add_error(message);
+                }
+                self
+            }
+        }
+    }
+}
+
+impl<'s> ParseError<&'s str> {
+    /// Converts the pointer-based position into an indexed position.
+    ///
+    /// ```rust
+    /// # extern crate combine;
+    /// # use combine::*;
+    /// # fn main() {
+    /// let text = "b";
+    /// let err = token('a').parse(text).unwrap_err();
+    /// assert_eq!(err.position, text.as_ptr() as usize);
+    /// assert_eq!(err.translate_position(text).position, 0);
+    /// # }
+    /// ```
+    pub fn translate_position(mut self, initial_string: &'s str) -> ParseError<&'s str> {
+        self.position -= initial_string.as_ptr() as usize;
+        self
+    }
+}
+
+impl<'s, T: 's> ParseError<&'s [T]>
+    where T: Clone + PartialEq
+{
+    /// Converts the pointer-based position into an indexed position.
+    ///
+    /// ```rust
+    /// # extern crate combine;
+    /// # use combine::*;
+    /// # fn main() {
+    /// let text = b"b";
+    /// let err = token(b'a').parse(&text[..]).unwrap_err();
+    /// assert_eq!(err.position, text.as_ptr() as usize);
+    /// assert_eq!(err.translate_position(text).position, 0);
+    /// # }
+    /// ```
+    pub fn translate_position(mut self, initial_string: &'s [T]) -> ParseError<&'s [T]> {
+        self.position -= initial_string.as_ptr() as usize;
+        self
+    }
+}
+
+impl<S> StdError for ParseError<S>
+    where S: Stream,
+          S::Range: fmt::Display + fmt::Debug + Any,
+          S::Item: fmt::Display + fmt::Debug + Any,
+          S::Position: fmt::Display + fmt::Debug + Any
+{
+    fn description(&self) -> &str {
+        "parse error"
+    }
+}
+
+impl<S> PartialEq for ParseError<S>
+    where S: Stream,
+          S::Position: PartialEq
+{
+    fn eq(&self, other: &ParseError<S>) -> bool {
+        self.position == other.position && self.errors == other.errors
+    }
+}
+
+impl<S> fmt::Debug for ParseError<S>
+    where S: Stream,
+          S::Range: fmt::Debug,
+          S::Item: fmt::Debug,
+          S::Position: fmt::Debug
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f,
+               "ParseError {{ position: {:?}, errors: {:?} }}",
+               self.position,
+               self.errors)
+    }
+}
+
+impl<S> fmt::Display for ParseError<S>
+    where S: Stream,
+          S::Item: fmt::Display,
+          S::Range: fmt::Display,
+          S::Position: fmt::Display
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        try!(writeln!(f, "Parse error at {}", self.position));
+        Error::fmt_errors(&self.errors, f)
+    }
+}
+
+impl fmt::Display for SourcePosition {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "line: {}, column: {}", self.line, self.column)
+    }
+}
+impl<T: fmt::Display, R: fmt::Display> fmt::Display for Error<T, R> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            Error::Unexpected(ref c) => write!(f, "Unexpected `{}`", c),
+            Error::Expected(ref s) => write!(f, "Expected `{}`", s),
+            Error::Message(ref msg) => msg.fmt(f),
+            Error::Other(ref err) => err.fmt(f),
+        }
+    }
+}
+
+/// The `State<I>` struct keeps track of the current position in the stream `I` using the
+/// `Positioner` trait to update the position.
+#[derive(Clone, PartialEq)]
+pub struct State<I>
+    where I: Stream,
+          I::Item: Positioner
+{
+    /// The current position
+    pub position: <I::Item as Positioner>::Position,
+    /// The input stream used when items are requested
+    pub input: I,
+}
+
+impl<I> fmt::Debug for State<I>
+    where I: Stream + fmt::Debug,
+          I::Item: Positioner,
+          <I::Item as Positioner>::Position: fmt::Debug
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f,
+               "State {{ position: {:?}, input: {:?} }}",
+               self.position,
+               self.input)
+    }
+}
+
+impl<I> State<I>
+    where I: Stream,
+          I::Item: P