Repository: Marwes/combine (language: rust)

Issue:
chore: Use criterion for benchmarks 

Fix doc links in the readme



Discussion / hints:

Fix patch:
diff --git a/.travis.yml b/.travis.yml
index 6fd59b38..8cade41d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -13,7 +13,7 @@ rust:
 - nightly
 - beta
 - stable
-- 1.20.0
+- 1.31.0
 before_script:
 - |
   pip install 'travis-cargo<0.2' --user &&
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9efc4e45..3b567e04 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,31 @@
+<a name="4.0.0-alpha.1"></a>
+## 4.0.0-alpha.1 (2019-05-07)
+
+
+#### Breaking Changes
+
+*   Drop support for regex 0.2 ([bf6aeb06](https://github.com/Marwes/combine/commit/bf6aeb06494abe2f1890c5bf90db86ac01ec9772), closes [#247](https://github.com/Marwes/combine/issues/247), breaks [#](https://github.com/Marwes/combine/issues/))
+*   Rename tokens2 to tokens and tokens to tokens_cmp ([3dadbb4f](https://github.com/Marwes/combine/commit/3dadbb4f2adb0447c883ea56bdbfcfd53c58d384), closes [#166](https://github.com/Marwes/combine/issues/166), breaks [#](https://github.com/Marwes/combine/issues/))
+*   Remove the std::result::Result returning parse functions ([6ec094ef](https://github.com/Marwes/combine/commit/6ec094efd2eecefeb2281fb99687143e7a5580e8), closes [#244](https://github.com/Marwes/combine/issues/244), breaks [#](https://github.com/Marwes/combine/issues/))
+*   Make PointerOffset easier to understand and use ([5f6d65b3](https://github.com/Marwes/combine/commit/5f6d65b30679d39c4c8a41ef0877bca8dc199095), closes [#238](https://github.com/Marwes/combine/issues/238), breaks [#](https://github.com/Marwes/combine/issues/))
+*   Allow reset to return errors ([3055c810](https://github.com/Marwes/combine/commit/3055c810fd4904d2eba3f51ea232ef0232f8fbe7), closes [#231](https://github.com/Marwes/combine/issues/231), breaks [#](https://github.com/Marwes/combine/issues/))
+*   Remove the PartialEq bound from Item and Range ([24e1087c](https://github.com/Marwes/combine/commit/24e1087cbff4938d48ae3e5947e2eb0dcbb8cc87), closes [#219](https://github.com/Marwes/combine/issues/219), breaks [#](https://github.com/Marwes/combine/issues/))
+
+#### Features
+
+*   Drop support for regex 0.2 ([bf6aeb06](https://github.com/Marwes/combine/commit/bf6aeb06494abe2f1890c5bf90db86ac01ec9772), closes [#247](https://github.com/Marwes/combine/issues/247), breaks [#](https://github.com/Marwes/combine/issues/))
+*   Rename tokens2 to tokens and tokens to tokens_cmp ([3dadbb4f](https://github.com/Marwes/combine/commit/3dadbb4f2adb0447c883ea56bdbfcfd53c58d384), closes [#166](https://github.com/Marwes/combine/issues/166), breaks [#](https://github.com/Marwes/combine/issues/))
+*   Remove the std::result::Result returning parse functions ([6ec094ef](https://github.com/Marwes/combine/commit/6ec094efd2eecefeb2281fb99687143e7a5580e8), closes [#244](https://github.com/Marwes/combine/issues/244), breaks [#](https://github.com/Marwes/combine/issues/))
+*   Allow reset to return errors ([3055c810](https://github.com/Marwes/combine/commit/3055c810fd4904d2eba3f51ea232ef0232f8fbe7), closes [#231](https://github.com/Marwes/combine/issues/231), breaks [#](https://github.com/Marwes/combine/issues/))
+*   Remove the PartialEq bound from Item and Range ([24e1087c](https://github.com/Marwes/combine/commit/24e1087cbff4938d48ae3e5947e2eb0dcbb8cc87), closes [#219](https://github.com/Marwes/combine/issues/219), breaks [#](https://github.com/Marwes/combine/issues/))
+
+#### Bug Fixes
+
+*   Don't require macro_use when using parser! in rust 2018 ([72e4c70f](https://github.com/Marwes/combine/commit/72e4c70fda2f283e1feadfd926ed9bb0d384cb59), closes [#241](https://github.com/Marwes/combine/issues/241))
+*   Make PointerOffset easier to understand and use ([5f6d65b3](https://github.com/Marwes/combine/commit/5f6d65b30679d39c4c8a41ef0877bca8dc199095), closes [#238](https://github.com/Marwes/combine/issues/238), breaks [#](https://github.com/Marwes/combine/issues/))
+
+
+
 <a name="3.8.1"></a>
 ### 3.8.1 (2019-03-13)
 
diff --git a/Cargo.lock b/Cargo.lock
index 4a03a172..a4dd9afa 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,3 +1,5 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
 [[package]]
 name = "aho-corasick"
 version = "0.6.9"
@@ -6,6 +8,14 @@ dependencies = [
  "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "ansi_term"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "ascii"
 version = "0.9.1"
@@ -22,9 +32,31 @@ dependencies = [
 ]
 
 [[package]]
-name = "bencher"
-version = "0.1.5"
+name = "autocfg"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "backtrace"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "backtrace-sys"
+version = "0.1.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
 name = "bitflags"
@@ -45,20 +77,43 @@ dependencies = [
  "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "cast"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "cc"
+version = "1.0.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "cfg-if"
 version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "clap"
+version = "2.33.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "combine"
-version = "3.8.2-alpha.0"
+version = "4.0.0-alpha.1"
 dependencies = [
  "ascii 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "bencher 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "combine-regex-1 1.0.0",
+ "criterion 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -66,17 +121,75 @@ dependencies = [
  "partial-io 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "quickcheck 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
-name = "combine-regex-1"
-version = "1.0.0"
+name = "criterion"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "criterion-plot 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "criterion-stats 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "csv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "handlebars 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools-num 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "criterion-plot"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "criterion-stats"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread-scoped 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "csv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "csv-core"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -96,6 +209,26 @@ dependencies = [
  "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "failure"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "failure_derive"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "fuchsia-zircon"
 version = "0.3.3"
@@ -115,6 +248,22 @@ name = "futures"
 version = "0.1.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "handlebars"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pest_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "humantime"
 version = "1.2.0"
@@ -132,6 +281,27 @@ dependencies = [
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "itertools"
+version = "0.7.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "itertools-num"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "itoa"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "lazy_static"
 version = "1.1.0"
@@ -157,6 +327,22 @@ dependencies = [
 name = "memchr"
 version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "num_cpus"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
 name = "partial-io"
@@ -168,6 +354,29 @@ dependencies = [
  "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "pest"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "pest_derive"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "0.4.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "quick-error"
 version = "1.2.2"
@@ -183,6 +392,19 @@ dependencies = [
  "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "quote"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "quote"
+version = "0.6.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rand"
 version = "0.4.3"
@@ -208,42 +430,109 @@ dependencies = [
 
 [[package]]
 name = "regex"
-version = "0.2.11"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
-name = "regex"
-version = "1.1.0"
+name = "regex-syntax"
+version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
-name = "regex-syntax"
-version = "0.5.6"
+name = "rustc-demangle"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "ryu"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "same-file"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
-name = "regex-syntax"
-version = "0.6.4"
+name = "serde"
+version = "1.0.90"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "serde_derive"
+version = "1.0.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.33 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.39"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "strsim"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "syn"
+version = "0.11.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syn"
+version = "0.15.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "synom"
+version = "0.11.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "synstructure"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -264,6 +553,19 @@ dependencies = [
  "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "textwrap"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "thread-scoped"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "thread_local"
 version = "0.3.6"
@@ -297,6 +599,21 @@ name = "ucd-util"
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "unicode-width"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "unicode-xid"
+version = "0.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "unicode-xid"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "unreachable"
 version = "1.0.0"
@@ -310,6 +627,11 @@ name = "utf8-ranges"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "vec_map"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "version_check"
 version = "0.1.5"
@@ -320,6 +642,16 @@ name = "void"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "walkdir"
+version = "2.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "winapi"
 version = "0.2.8"
@@ -363,44 +695,84 @@ dependencies = [
 
 [metadata]
 "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e"
+"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
 "checksum ascii 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a5fc969a8ce2c9c0c4b0429bb8431544f6658283c8326ba5ff8c762b75369335"
 "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
-"checksum bencher 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7dfdb4953a096c551ce9ace855a604d702e6e62d77fac690575ae347571717f5"
+"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
+"checksum backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f106c02a3604afcdc0df5d36cc47b44b55917dbaf3d808f71c163a0ddba64637"
+"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6"
 "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
 "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
 "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa"
+"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427"
+"checksum cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a0c56216487bb80eec9c4516337b2588a4f2a2290d72a1416d930e4dcdb0c90d"
 "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
+"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
+"checksum criterion 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f8df98670b866802f983ae1aa1bc5ac96d4b71ed0a5f4f550eb8cf0e0e9796ba"
+"checksum criterion-plot 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5f81689739e463ece7a6b62c6ec63bdab5c4e28fe05ff451769e87d1511411"
+"checksum criterion-stats 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "387df94cb74ada1b33e10ce034bb0d9360cc73edb5063e7d7d4120a40ee1c9d2"
+"checksum csv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9044e25afb0924b5a5fc5511689b0918629e85d68ea591e5e87fbf1e85ea1b3b"
+"checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65"
 "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
 "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38"
+"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
+"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
 "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
 "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
 "checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b"
+"checksum handlebars 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3623110a77811256820e92df1b3b286f6f44f99d1f77a94b75e262c28d5034f4"
 "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114"
 "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
+"checksum itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d"
+"checksum itertools-num 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a872a22f9e6f7521ca557660adb96dd830e54f0f490fa115bb55dd69d38b27e7"
+"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
 "checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7"
 "checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74"
 "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
 "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
+"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
+"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba"
 "checksum partial-io 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acacf02f958eb2317b7412f2a54f42b5dd58113532eafc6c22dcae0839d720aa"
+"checksum pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0fce5d8b5cc33983fc74f78ad552b5522ab41442c4ca91606e4236eb4b5ceefc"
+"checksum pest_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3294f437119209b084c797604295f40227cffa35c57220b1e99a6ff3bf8ee4"
+"checksum proc-macro2 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)" = "64c827cea7a7ab30ce4593e5e04d7a11617ad6ece2fa230605a78b00ff965316"
 "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
 "checksum quickcheck 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c01babc5ffd48a2a83744b3024814bb46dfd4f2a4705ccb44b1b60e644fdcab7"
+"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
+"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
 "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd"
 "checksum redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "a84bcd297b87a545980a2d25a0beb72a1f490c31f0a9fde52fca35bfbb1ceb70"
 "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
-"checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384"
 "checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f"
-"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7"
 "checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1"
+"checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288"
+"checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f"
+"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
+"checksum serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "aa5f7c20820475babd2c077c3ab5f8c77a31c15e16ea38687b4c02d3e48680f4"
+"checksum serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "58fc82bec244f168b23d1963b45c8bf5726e9a15a9d146a067f9081aeed2de79"
+"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d"
+"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
+"checksum syn 0.15.33 (registry+https://github.com/rust-lang/crates.io-index)" = "ec52cd796e5f01d0067225a5392e70084acc4c0013fa71d55166d38a8b307836"
+"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
+"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
 "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"
 "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
+"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+"checksum thread-scoped 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bcbb6aa301e5d3b0b5ef639c9a9c7e2f1c944f177b460c04dc24c69b1fa2bd99"
 "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
 "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f"
 "checksum tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a5c9635ee806f26d302b8baa1e145689a280d8f5aa8d0552e7344808da54cc21"
 "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
+"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
+"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
+"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
 "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
 "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
+"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
 "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
+"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
 "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
 "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
diff --git a/Cargo.toml b/Cargo.toml
index c825cef0..d5dbd388 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 
 name = "combine"
-version = "3.8.2-alpha.0"
+version = "4.0.0-alpha.1"
 authors = ["Markus Westerlind <marwes91@gmail.com>"]
 
 description = "Fast parser combinators on arbitrary streams with zero-copy support."
@@ -17,6 +17,8 @@ categories = ["parsing", "no-std"]
 
 license = "MIT"
 
+edition = "2018"
+
 [lib]
 name = "combine"
 path = "src/lib.rs"
@@ -26,12 +28,11 @@ ascii = { version = "0.9.1", default-features = false }
 byteorder = { version = "1.1.0", default-features = false }
 either = { version = "1", default-features = false }
 unreachable = "1.0.0"
-regex = { version = "0.2.0", optional = true }
-combine-regex-1 = { version = "1", path = "combine-regex-1", optional = true }
+regex = { version = "1", optional = true }
 memchr = { version = "2.2", default-features = false }
 
 [dev-dependencies]
-bencher = "0.1.3"
+criterion = "0.2"
 lazy_static = "1.0"
 
 futures = "0.1"
@@ -46,9 +47,7 @@ quick-error = "1.0"
 default = ["std"]
 # Run the mp4 benchmark, requires a mp4 file named `small.mp4` in the benches directory
 mp4 = []
-# Enables use of regex version 1 in the regex parsers
-regex-1 = ["combine-regex-1"]
-doc = ["regex", "regex-1"]
+doc = ["regex"]
 std = ["memchr/use_std", "either/use_std", "byteorder/std", "ascii/std"]
 
 [[bench]]
diff --git a/README.md b/README.md
index c67a5efe..1ff5d478 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
 [![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).
+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 [attempt combinator](https://docs.rs/combine*/combine/fn.attempt.html).
 
 ## Example
 
@@ -50,7 +50,7 @@ Larger examples can be found in the [examples][], [tests][] and [benches][] fold
 
 ## 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. 
+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://docs.rs/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).
 
diff --git a/benches/http.rs b/benches/http.rs
index 9be42f8a..22b7e622 100644
--- a/benches/http.rs
+++ b/benches/http.rs
@@ -1,9 +1,9 @@
 #[macro_use]
-extern crate bencher;
+extern crate criterion;
 #[macro_use]
 extern crate combine;
 
-use bencher::{black_box, Bencher};
+use criterion::{black_box, Bencher, Criterion};
 
 use std::fmt;
 
@@ -98,12 +98,12 @@ where
     let http_version = range(&b"HTTP/"[..]).with(take_while1(is_http_version));
 
     let request_line = struct_parser!(Request {
-            method: take_while1(is_token),
-            _: take_while1(is_space),
-            uri: take_while1(is_not_space),
-            _: take_while1(is_space),
-            version: http_version,
-        });
+        method: take_while1(is_token),
+        _: take_while1(is_space),
+        uri: take_while1(is_not_space),
+        _: take_while1(is_space),
+        version: http_version,
+    });
 
     let mut request = (
         request_line,
@@ -161,10 +161,14 @@ where
     });
 }
 
-benchmark_group!(
-    http,
-    http_requests_small,
-    http_requests_large,
-    http_requests_large_cheap_error
-);
-benchmark_main!(http);
+fn http_requests(c: &mut Criterion) {
+    c.bench_function("http_requests_small", http_requests_small);
+    c.bench_function("http_requests_large", http_requests_large);
+    c.bench_function(
+        "http_requests_large_cheap_error",
+        http_requests_large_cheap_error,
+    );
+}
+
+criterion_group!(http, http_requests,);
+criterion_main!(http);
diff --git a/benches/json.rs b/benches/json.rs
index be6f11cc..c08c555c 100644
--- a/benches/json.rs
+++ b/benches/json.rs
@@ -2,7 +2,7 @@
 // significantly simplify things
 
 #[macro_use]
-extern crate bencher;
+extern crate criterion;
 
 #[macro_use]
 extern crate combine;
@@ -12,10 +12,10 @@ use std::fs::File;
 use std::io::Read;
 use std::path::Path;
 
-use bencher::{black_box, Bencher};
+use criterion::{black_box, Bencher, Criterion};
 
 use combine::error::{Consumed, ParseError};
-use combine::stream::buffered::BufferedStream;
+use combine::stream::buffered;
 use combine::{Parser, Stream, StreamOnce};
 
 use combine::parser::char::{char, digit, spaces, string};
@@ -107,7 +107,7 @@ where
     I::Error: ParseError<I::Item, I::Range, I::Position>,
 {
     parser(|input: &mut I| {
-        let (c, consumed) = try!(any().parse_lazy(input).into());
+        let (c, consumed) = r#try!(any().parse_lazy(input).into());
         let mut back_slash_char = satisfy_map(|c| {
             Some(match c {
                 '"' => '"',
@@ -122,7 +122,7 @@ where
             })
         });
         match c {
-            '\\' => consumed.combine(|_| back_slash_char.parse_stream(input)),
+            '\\' => consumed.combine(|_| back_slash_char.parse_stream(input).into_result()),
             '"' => Err(Consumed::Empty(I::Error::empty(input.position()).into())),
             _ => Ok((c, consumed)),
         }
@@ -160,7 +160,7 @@ where
 
 // We need to use `parser!` to break the recursive use of `value` to prevent the returned parser
 // from containing itself
-parser!{
+parser! {
     #[inline(always)]
     fn json_value_[I]()(I) -> Value
         where [ I: Stream<Item = char> ]
@@ -287,7 +287,7 @@ fn bench_json_core_error_no_position(bencher: &mut Bencher) {
 fn bench_buffered_json(bencher: &mut Bencher) {
     let data = test_data();
     bencher.iter(|| {
-        let buffer = BufferedStream::new(State::new(IteratorStream::new(data.chars())), 1);
+        let buffer = buffered::Stream::new(State::new(IteratorStream::new(data.chars())), 1);
         let mut parser = json_value();
         match parser.easy_parse(State::with_positioner(buffer, SourcePosition::default())) {
             Ok((Value::Array(v), _)) => {
@@ -302,11 +302,15 @@ fn bench_buffered_json(bencher: &mut Bencher) {
     });
 }
 
-benchmark_group!(
-    json,
-    bench_json,
-    bench_json_core_error,
-    bench_json_core_error_no_position,
-    bench_buffered_json
-);
-benchmark_main!(json);
+fn bench(c: &mut Criterion) {
+    c.bench_function("json", bench_json);
+    c.bench_function("json_core_error", bench_json_core_error);
+    c.bench_function(
+        "json_core_error_no_position",
+        bench_json_core_error_no_position,
+    );
+    c.bench_function("buffered_json", bench_buffered_json);
+}
+
+criterion_group!(json, bench);
+criterion_main!(json);
diff --git a/benches/mp4.rs b/benches/mp4.rs
index 2ddfa4cf..9caf62ec 100644
--- a/benches/mp4.rs
+++ b/benches/mp4.rs
@@ -1,11 +1,11 @@
 #![cfg(feature = "mp4")]
 #[macro_use]
-extern crate bencher;
+extern crate criterion;
 
 extern crate byteorder;
 extern crate combine;
 
-use bencher::{black_box, Bencher};
+use criterion::{black_box, Bencher, Criterion};
 
 use std::fs::File;
 use std::io::Read;
@@ -76,13 +76,14 @@ fn run_test(b: &mut Bencher, data: &[u8]) {
     });
 }
 
-fn mp4_small_test(b: &mut Bencher) {
+fn mp4_small_test(c: &mut Criterion) {
     let mut mp4_small = Vec::new();
     File::open("benches/small.mp4")
         .and_then(|mut f| f.read_to_end(&mut mp4_small))
         .expect("Unable to read benches/small.mp4");
-    run_test(b, &mp4_small)
+
+    c.bench_function("mp4_small", move |b| run_test(b, &mp4_small));
 }
 
-benchmark_group!(mp4, mp4_small_test);
-benchmark_main!(mp4);
+criterion_group!(mp4, mp4_small_test);
+criterion_main!(mp4);
diff --git a/src/error.rs b/src/error.rs
index c239524d..0b359035 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,26 +1,39 @@
-use lib::fmt;
+use crate::lib::fmt;
 
 #[cfg(feature = "std")]
 use std::error::Error as StdError;
 
-use self::FastResult::*;
+use self::ParseResult::*;
 
-use ErrorOffset;
+use crate::ErrorOffset;
 
-use stream::StreamOnce;
+use crate::stream::StreamOnce;
+
+pub(crate) trait ResultExt<E, T> {
+    fn consumed(self) -> ParseResult<E, T>;
+}
+
+impl<E, T> ResultExt<E, T> for Result<E, T> {
+    fn consumed(self) -> ParseResult<E, T> {
+        match self {
+            Ok(x) => ConsumedOk(x),
+            Err(x) => ConsumedErr(x),
+        }
+    }
+}
 
 #[macro_export]
 #[doc(hidden)]
 macro_rules! ctry {
     ($result:expr) => {
         match $result {
-            $crate::error::FastResult::ConsumedOk(x) => (x, $crate::error::Consumed::Consumed(())),
-            $crate::error::FastResult::EmptyOk(x) => (x, $crate::error::Consumed::Empty(())),
-            $crate::error::FastResult::ConsumedErr(err) => {
-                return $crate::error::FastResult::ConsumedErr(err.into())
+            $crate::error::ParseResult::ConsumedOk(x) => (x, $crate::error::Consumed::Consumed(())),
+            $crate::error::ParseResult::EmptyOk(x) => (x, $crate::error::Consumed::Empty(())),
+            $crate::error::ParseResult::ConsumedErr(err) => {
+                return $crate::error::ParseResult::ConsumedErr(err.into())
             }
-            $crate::error::FastResult::EmptyErr(err) => {
-                return $crate::error::FastResult::EmptyErr(err.into())
+            $crate::error::ParseResult::EmptyErr(err) => {
+                return $crate::error::ParseResult::EmptyErr(err.into())
             }
         }
     };
@@ -139,11 +152,11 @@ impl<T> Consumed<T> {
     /// # fn main() {
     /// //Parses a character of string literal and handles the escaped characters \\ and \" as \
     /// //and " respectively
-    /// fn char<I>(input: &mut I) -> ParseResult<char, I>
+    /// fn char<I>(input: &mut I) -> StdParseResult<char, I>
     ///     where I: Stream<Item = char>,
     ///           I::Error: ParseError<I::Item, I::Range, I::Position>,
     /// {
-    ///     let (c, consumed) = try!(satisfy(|c| c != '"').parse_stream(input));
+    ///     let (c, consumed) = satisfy(|c| c != '"').parse_stream(input).into_result()?;
     ///     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
@@ -157,6 +170,7 @@ impl<T> Consumed<T> {
     ///                     }
     ///                 })
     ///                 .parse_stream(input)
+    ///                 .into_result()
     ///             }),
     ///         _ => Ok((c, consumed))
     ///     }
@@ -166,9 +180,9 @@ impl<T> Consumed<T> {
     /// assert_eq!(result, Ok((r#"abc"\"#.to_string(), "")));
     /// }
     /// ```
-    pub fn combine<F, U, E>(self, f: F) -> ParseResult2<U, E>
+    pub fn combine<F, U, E>(self, f: F) -> StdParseResult2<U, E>
     where
-        F: FnOnce(T) -> ParseResult2<U, E>,
+        F: FnOnce(T) -> StdParseResult2<U, E>,
     {
         match self {
             Consumed::Consumed(x) => match f(x) {
@@ -179,11 +193,11 @@ impl<T> Consumed<T> {
             Consumed::Empty(x) => f(x),
         }
     }
-    pub fn combine_consumed<F, U, E>(self, f: F) -> FastResult<U, E>
+    pub fn combine_consumed<F, U, E>(self, f: F) -> ParseResult<U, E>
     where
-        F: FnOnce(T) -> FastResult<U, E>,
+        F: FnOnce(T) -> ParseResult<U, E>,
     {
-        use self::FastResult::*;
+        use self::ParseResult::*;
         match self {
             Consumed::Consumed(x) => match f(x) {
                 EmptyOk(v) => ConsumedOk(v),
@@ -199,14 +213,15 @@ impl<T> Consumed<T> {
 /// successful or not.
 /// `O` is the type that is output on success.
 /// `I` is the specific stream type used in the parser.
-pub type ParseResult<O, I> = Result<(O, Consumed<()>), Consumed<Tracked<<I as StreamOnce>::Error>>>;
-pub type ParseResult2<O, E> = Result<(O, Consumed<()>), Consumed<Tracked<E>>>;
+pub type StdParseResult<O, I> =
+    Result<(O, Consumed<()>), Consumed<Tracked<<I as StreamOnce>::Error>>>;
+pub type StdParseResult2<O, E> = Result<(O, Consumed<()>), Consumed<Tracked<E>>>;
 
 /// `StreamError` represents a single error returned from a `Stream` or a `Parser`.
 ///
 /// Usually multiple instances of `StreamError` is composed into a `ParseError` to build the final
 /// error value.
-pub trait StreamError<Item, Range>: Sized + PartialEq {
+pub trait StreamError<Item, Range>: Sized {
     fn unexpected_token(token: Item) -> Self;
     fn unexpected_range(token: Range) -> Self;
     fn unexpected_message<T>(msg: T) -> Self
@@ -267,6 +282,8 @@ pub trait StreamError<Item, Range>: Sized + PartialEq {
         Self::unexpected_static_message("end of input")
     }
 
+    fn is_unexpected_end_of_input(&self) -> bool;
+
     /// Converts `self` into a different `StreamError` type.
     ///
     /// This should aim to preserve as much information as possible into the returned `T` value but
@@ -409,6 +426,11 @@ impl<Item, Range> StreamError<Item, Range> for UnexpectedParse {
         UnexpectedParse::Eoi
     }
 
+    #[inline]
+    fn is_unexpected_end_of_input(&self) -> bool {
+        *self == UnexpectedParse::Eoi
+    }
+
     #[inline]
     fn into_other<T>(self) -> T
     where
@@ -552,6 +574,10 @@ impl<Item, Range> StreamError<Item, Range> for StringStreamError {
         StringStreamError::Eoi
     }
     #[inline]
+    fn is_unexpected_end_of_input(&self) -> bool {
+        *self == StringStreamError::Eoi
+    }
+    #[inline]
     fn into_other<T>(self) -> T
     where
         T: StreamError<Item, Range>,
@@ -631,15 +657,18 @@ impl<E> From<E> for Tracked<E> {
     }
 }
 
+/// A `Result` type which has the consumed status flattened into the result.
+/// Conversions to and from `std::result::Result` can be done using `result.into()` or
+/// `From::from(result)`
 #[derive(Clone, PartialEq, Debug, Copy)]
-pub enum FastResult<T, E> {
+pub enum ParseResult<T, E> {
     ConsumedOk(T),
     EmptyOk(T),
     ConsumedErr(E),
     EmptyErr(Tracked<E>),
 }
 
-impl<T, E> FastResult<T, E> {
+impl<T, E> ParseResult<T, E> {
     #[inline]
     pub fn is_ok(&self) -> bool {
         match *self {
@@ -647,7 +676,7 @@ impl<T, E> FastResult<T, E> {
             ConsumedErr(_) | EmptyErr(_) => false,
         }
     }
-    pub fn as_ref(&self) -> FastResult<&T, &E> {
+    pub fn as_ref(&self) -> ParseResult<&T, &E> {
         match *self {
             ConsumedOk(ref t) => ConsumedOk(t),
             EmptyOk(ref t) => EmptyOk(t),
@@ -661,7 +690,7 @@ impl<T, E> FastResult<T, E> {
 
     pub fn and_then<F, T2>(self, f: F) -> F::Output
     where
-        F: FnOnce(T) -> FastResult<T2, E>,
+        F: FnOnce(T) -> ParseResult<T2, E>,
     {
         match self {
             ConsumedOk(t) => match f(t) {
@@ -675,7 +704,7 @@ impl<T, E> FastResult<T, E> {
         }
     }
 
-    pub fn map_err<F, E2>(self, f: F) -> FastResult<T, F::Output>
+    pub fn map_err<F, E2>(self, f: F) -> ParseResult<T, F::Output>
     where
         F: FnOnce(E) -> E2,
     {
@@ -689,10 +718,8 @@ impl<T, E> FastResult<T, E> {
             }),
         }
     }
-}
 
-impl<T, E> FastResult<T, E> {
-    pub fn map<F, T2>(self, f: F) -> FastResult<F::Output, E>
+    pub fn map<F, T2>(self, f: F) -> ParseResult<F::Output, E>
     where
         F: FnOnce(T) -> T2,
     {
@@ -705,12 +732,13 @@ impl<T, E> FastResult<T, E> {
     }
 }
 
-/// A `Result` type which has the consumed status flattened into the result.
-/// Conversions to and from `std::result::Result` can be done using `result.into()` or
-/// `From::from(result)`
-pub type ConsumedResult<O, I> = FastResult<O, <I as StreamOnce>::Error>;
+impl<O, E> ParseResult<O, E> {
+    pub fn into_result(self) -> StdParseResult2<O, E> {
+        self.into()
+    }
+}
 
-impl<T, E> Into<Result<Consumed<T>, Consumed<Tracked<E>>>> for FastResult<T, E> {
+impl<T, E> Into<Result<Consumed<T>, Consumed<Tracked<E>>>> for ParseResult<T, E> {
     #[inline(always)]
     fn into(self) -> Result<Consumed<T>, Consumed<Tracked<E>>> {
         match self {
@@ -722,10 +750,10 @@ impl<T, E> Into<Result<Consumed<T>, Consumed<Tracked<E>>>> for FastResult<T, E>
     }
 }
 
-impl<O, E> Into<ParseResult2<O, E>> for FastResult<O, E> {
+impl<O, E> Into<StdParseResult2<O, E>> for ParseResult<O, E> {
     #[inline(always)]
-    fn into(self) -> ParseResult2<O, E> {
-        use self::FastResult::*;
+    fn into(self) -> StdParseResult2<O, E> {
+        use self::ParseResult::*;
         match self {
             ConsumedOk(t) => Ok((t, Consumed::Consumed(()))),
             EmptyOk(t) => Ok((t, Consumed::Empty(()))),
@@ -735,10 +763,10 @@ impl<O, E> Into<ParseResult2<O, E>> for FastResult<O, E> {
     }
 }
 
-impl<O, E> From<ParseResult2<O, E>> for FastResult<O, E> {
+impl<O, E> From<StdParseResult2<O, E>> for ParseResult<O, E> {
     #[inline(always)]
-    fn from(result: ParseResult2<O, E>) -> FastResult<O, E> {
-        use self::FastResult::*;
+    fn from(result: StdParseResult2<O, E>) -> ParseResult<O, E> {
+        use self::ParseResult::*;
         match result {
             Ok((t, Consumed::Consumed(()))) => ConsumedOk(t),
             Ok((t, Consumed::Empty(()))) => EmptyOk(t),
@@ -750,7 +778,7 @@ impl<O, E> From<ParseResult2<O, E>> for FastResult<O, E> {
 
 #[cfg(all(feature = "std", test))]
 mod tests_std {
-    use Parser;
+    use crate::Parser;
 
     #[derive(Clone, PartialEq, Debug)]
     struct CloneOnly {
@@ -765,7 +793,7 @@ mod tests_std {
             CloneOnly { s: "y".to_string() },
         ][..];
         let result =
-            ::parser::range::take_while(|c: CloneOnly| c.s == "x".to_string()).parse(input);
+            crate::parser::range::take_while(|c: CloneOnly| c.s == "x".to_string()).parse(input);
         assert_eq!(
             result,
             Ok((
diff --git a/src/lib.rs b/src/lib.rs
index 3117f1ed..3e7972ac 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -94,7 +94,7 @@
 //! extern crate combine;
 //! use combine::parser::char::{char, letter, spaces};
 //! use combine::{between, choice, many1, parser, sep_by, Parser};
-//! use combine::error::{ParseError, ParseResult};
+//! use combine::error::{ParseError, StdParseResult};
 //! use combine::stream::{Stream, Positioned};
 //! use combine::stream::state::State;
 //!
@@ -194,26 +194,26 @@
 #![cfg_attr(not(feature = "std"), no_std)]
 
 #[doc(inline)]
-pub use error::{ConsumedResult, ParseError, ParseResult};
+pub use crate::error::{ParseError, ParseResult, StdParseResult};
 #[doc(inline)]
-pub use parser::Parser;
+pub use crate::parser::Parser;
 #[doc(inline)]
-pub use stream::{Positioned, RangeStream, RangeStreamOnce, Stream, StreamOnce};
+pub use crate::stream::{Positioned, RangeStream, RangeStreamOnce, Stream, StreamOnce};
 
 #[doc(inline)]
 #[allow(deprecated)] // Needed to re-export `try`
-pub use combinator::{
+pub use crate::combinator::{
     any, attempt, between, chainl1, chainr1, count, count_min_max, env_parser, eof, look_ahead,
     many, many1, none_of, not_followed_by, one_of, optional, parser, position, satisfy,
     satisfy_map, sep_by, sep_by1, sep_end_by, sep_end_by1, skip_count, skip_count_min_max,
-    skip_many, skip_many1, token, tokens, try, unexpected, unexpected_any, value,
+    skip_many, skip_many1, token, tokens, unexpected, unexpected_any, value,
 };
 #[doc(inline)]
-pub use parser::choice::choice;
+pub use crate::parser::choice::choice;
 #[doc(inline)]
-pub use parser::combinator::from_str;
+pub use crate::parser::combinator::from_str;
 #[doc(inline)]
-pub use parser::item::tokens2;
+pub use crate::parser::item::tokens_cmp;
 
 macro_rules! static_fn {
     (($($arg: pat, $arg_ty: ty),*) -> $ret: ty { $body: expr }) => { {
@@ -364,7 +364,7 @@ macro_rules! parser {
             where [$($where_clause: tt)*]
         $parser: block
     ) => {
-        combine_parser_impl!{
+        $crate::combine_parser_impl!{
             (pub)
             struct $name;
             type PartialState = (());
@@ -381,7 +381,7 @@ macro_rules! parser {
             where [$($where_clause: tt)*]
         $parser: block
     ) => {
-        combine_parser_impl!{
+        $crate::combine_parser_impl!{
             ()
             struct $name;
             type PartialState = (());
@@ -400,7 +400,7 @@ macro_rules! parser {
             where [$($where_clause: tt)*]
         $parser: block
     ) => {
-        combine_parser_impl!{
+        $crate::combine_parser_impl!{
             (pub)
             $(#[$derive])*
             struct $type_name;
@@ -420,7 +420,7 @@ macro_rules! parser {
             where [$($where_clause: tt)*]
         $parser: block
     ) => {
-        combine_parser_impl!{
+        $crate::combine_parser_impl!{
             ()
             $(#[$derive])*
             struct $type_name;
@@ -469,7 +469,7 @@ macro_rules! parser {
             where [$($where_clause: tt)*]
         $parser: block
     ) => {
-        combine_parser_impl!{
+        $crate::combine_parser_impl!{
             (pub)
             struct $name;
             type PartialState = ($partial_state);
@@ -487,7 +487,7 @@ macro_rules! parser {
             where [$($where_clause: tt)*]
         $parser: block
     ) => {
-        combine_parser_impl!{
+        $crate::combine_parser_impl!{
             ()
             struct $name;
             type PartialState = ($partial_state);
@@ -507,7 +507,7 @@ macro_rules! parser {
             where [$($where_clause: tt)*]
         $parser: block
     ) => {
-        combine_parser_impl!{
+        $crate::combine_parser_impl!{
             (pub)
             $(#[$derive])*
             struct $type_name;
@@ -528,7 +528,7 @@ macro_rules! parser {
             where [$($where_clause: tt)*]
         $parser: block
     ) => {
-        combine_parser_impl!{
+        $crate::combine_parser_impl!{
             ()
             $(#[$derive])*
             struct $type_name;
@@ -600,18 +600,18 @@ macro_rules! combine_parser_impl {
             type Output = $output_type;
             type PartialState = $($partial_state)*;
 
-            parse_mode!();
+            $crate::parse_mode!();
             #[inline]
             fn parse_mode_impl<M>(
                 &mut self,
                 mode: M,
                 input: &mut Self::Input,
                 state: &mut Self::PartialState,
-                ) -> $crate::error::ConsumedResult<$output_type, $input_type>
+                ) -> $crate::error::ParseResult<$output_type, <$input_type as $crate::stream::StreamOnce>::Error>
             where M: $crate::parser::ParseMode
             {
                 let $type_name { $( $arg: ref mut $arg,)* .. } = *self;
-                combine_parse_partial!(($($partial_state)*) mode input state $parser)
+                $crate::combine_parse_partial!(($($partial_state)*) mode input state $parser)
             }
 
             #[inline]
@@ -688,7 +688,7 @@ macro_rules! forward_parser {
             mode: M,
             input: &mut Self::Input,
             state: &mut Self::PartialState,
-        ) -> ConsumedResult<Self::Output, Self::Input>
+        ) -> ParseResult<Self::Output, <Self::Input as $crate::StreamOnce>::Error>
         where
             M: ParseMode,
         {
@@ -699,7 +699,7 @@ macro_rules! forward_parser {
         fn parse_lazy(
             &mut self,
             input: &mut Self::Input,
-        ) -> ConsumedResult<Self::Output, Self::Input> {
+        ) -> ParseResult<Self::Output, <Self::Input as $crate::StreamOnce>::Error> {
             self.$($field)+.parse_lazy(input)
         }
     };
@@ -708,7 +708,7 @@ macro_rules! forward_parser {
             &mut self,
             input: &mut Self::Input,
             state: &mut Self::PartialState,
-        ) -> ConsumedResult<Self::Output, Self::Input> {
+        ) -> ParseResult<Self::Output, <Self::Input as $crate::StreamOnce>::Error> {
             self.$($field)+.parse_first(input, state)
         }
     };
@@ -717,18 +717,18 @@ macro_rules! forward_parser {
             &mut self,
             input: &mut Self::Input,
             state: &mut Self::PartialState,
-        ) -> ConsumedResult<Self::Output, Self::Input> {
+        ) -> ParseResult<Self::Output, <Self::Input as $crate::StreamOnce>::Error> {
             self.$($field)+.parse_partial(input, state)
         }
     };
     (add_error $($field: tt)+) => {
 
-        fn add_error(&mut self, error: &mut Tracked<<Self::Input as StreamOnce>::Error>) {
+        fn add_error(&mut self, error: &mut Tracked<<Self::Input as $crate::StreamOnce>::Error>) {
             self.$($field)+.add_error(error)
         }
     };
     (add_consumed_expected_error $($field: tt)+) => {
-        fn add_consumed_expected_error(&mut self, error: &mut Tracked<<Self::Input as StreamOnce>::Error>) {
+        fn add_consumed_expected_error(&mut self, error: &mut Tracked<<Self::Input as $crate::StreamOnce>::Error>) {
             self.$($field)+.add_consumed_expected_error(error)
         }
     };
@@ -754,7 +754,7 @@ pub mod lib {
 
 #[cfg(feature = "std")]
 #[doc(inline)]
-pub use stream::easy;
+pub use crate::stream::easy;
 
 /// Error types and traits which define what kind of errors combine parsers may emit
 #[macro_use]
@@ -772,35 +772,35 @@ pub mod parser;
 )]
 pub mod combinator {
     #[doc(inline)]
-    pub use parser::choice::*;
+    pub use crate::parser::choice::*;
     #[doc(inline)]
-    pub use parser::combinator::*;
+    pub use crate::parser::combinator::*;
     #[doc(inline)]
-    pub use parser::error::*;
+    pub use crate::parser::error::*;
     #[doc(inline)]
-    pub use parser::function::*;
+    pub use crate::parser::function::*;
     #[doc(inline)]
-    pub use parser::item::*;
+    pub use crate::parser::item::*;
     #[doc(inline)]
-    pub use parser::repeat::*;
+    pub use crate::parser::repeat::*;
     #[doc(inline)]
-    pub use parser::sequence::*;
+    pub use crate::parser::sequence::*;
 }
 
 #[doc(hidden)]
 #[deprecated(since = "3.0.0", note = "Please use the `parser::char` module instead")]
-pub use parser::char;
+pub use crate::parser::char;
 
 #[doc(hidden)]
 #[deprecated(since = "3.0.0", note = "Please use the `parser::byte` module instead")]
-pub use parser::byte;
+pub use crate::parser::byte;
 
 #[doc(hidden)]
 #[deprecated(
     since = "3.0.0",
     note = "Please use the `parser::range` module instead"
 )]
-pub use parser::range;
+pub use crate::parser::range;
 
 #[doc(hidden)]
 #[deprecated(
@@ -808,7 +808,7 @@ pub use parser::range;
     note = "Please use the `parser::regex` module instead"
 )]
 #[cfg(any(feature = "regex", feature = "regex-1"))]
-pub use parser::regex;
+pub use crate::parser::regex;
 
 #[doc(hidden)]
 #[derive(Clone, PartialOrd, PartialEq, Debug, Copy)]
@@ -817,7 +817,7 @@ pub struct ErrorOffset(u8);
 #[cfg(test)]
 mod tests {
     use super::*;
-    use parser::char::{char, string};
+    use crate::parser::char::{char, string};
 
     #[test]
     fn chainl1_error_consume() {
@@ -834,8 +834,8 @@ mod tests {
         // `attempt` is an alias for `try`. This is a small smoke test for
         // `try`, since the main functionality is tested with `attempt`
         let mut parser = choice((
-            try((string("abc"), string("def"))),
-            try((string("abc"), string("ghi"))),
+            attempt((string("abc"), string("def"))),
+            attempt((string("abc"), string("ghi"))),
         ));
         assert_eq!(parser.parse("abcghi"), Ok((("abc", "ghi"), "")));
     }
@@ -867,9 +867,9 @@ mod std_tests {
     use super::stream::IteratorStream;
     use super::*;
 
-    use parser::char::{alpha_num, char, digit, letter, spaces, string};
-    use stream::easy;
-    use stream::state::{SourcePosition, State};
+    use crate::parser::char::{alpha_num, char, digit, letter, spaces, string};
+    use crate::stream::easy;
+    use crate::stream::state::{SourcePosition, State};
 
     #[test]
     fn optional_error_consume() {
@@ -878,16 +878,19 @@ mod std_tests {
         assert_eq!(err.position, SourcePosition { line: 1, column: 1 });
     }
 
-    fn follow<I>(input: &mut I) -> ParseResult<(), I>
+    fn follow<I>(input: &mut I) -> StdParseResult<(), I>
     where
         I: Stream<Item = char, Error = easy::ParseError<I>>,
+        I::Item: PartialEq,
+        I::Range: PartialEq,
         I::Position: Default,
+        I::Error: std::fmt::Debug,
     {
         let before = input.checkpoint();
         match input.uncons() {
             Ok(c) => {
                 if c.is_alphanumeric() {
-                    input.reset(before);
+                    input.reset(before).unwrap();
                     let e = Error::Unexpected(c.into());
                     Err(Consumed::Empty(
                         easy::Errors::new(input.position(), e).into(),
@@ -900,14 +903,15 @@ mod std_tests {
         }
     }
 
-    fn integer<'a, I>(input: &mut I) -> ParseResult<i64, I>
+    fn integer<'a, I>(input: &mut I) -> StdParseResult<i64, I>
     where
         I: Stream<Item = char>,
         I::Error: ParseError<I::Item, I::Range, I::Position>,
     {
-        let (s, input) = try!(many1::<String, _>(digit())
+        let (s, input) = many1::<String, _>(digit())
             .expected("integer")
-            .parse_stream(input));
+            .parse_stream(input)
+            .into_result()?;
         let mut n = 0;
         for c in s.chars() {
             n = n * 10 + (c as i64 - '0' as i64);
@@ -953,7 +957,8 @@ mod std_tests {
         let mut parsed_state = State::with_positioner(source, SourcePosition::new());
         let result = (spaces(), parser(integer), spaces())
             .map(|t| t.1)
-            .parse_stream(&mut parsed_state);
+            .parse_stream(&mut parsed_state)
+            .into_result();
         let state = Consumed::Consumed(State {
             positioner: SourcePosition { line: 3, column: 1 },
             input: "",
@@ -1024,7 +1029,7 @@ mod std_tests {
         assert_eq!(result, Err(err));
     }
 
-    fn term<I>(input: &mut I) -> ParseResult<Expr, I>
+    fn term<I>(input: &mut I) -> StdParseResult<Expr, I>
     where
         I: Stream<Item = char>,
         I::Error: ParseError<I::Item, I::Range, I::Position>,
@@ -1038,7 +1043,7 @@ mod std_tests {
         let mul = char('*').map(|_| times);
         let add = char('+').map(|_| plus);
         let factor = chainl1(expr(), mul);
-        chainl1(factor, add).parse_stream(input)
+        chainl1(factor, add).parse_stream(input).into()
     }
 
     #[test]
@@ -1167,7 +1172,7 @@ mod std_tests {
 
         impl fmt::Display for ExtractedError {
             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-                try!(writeln!(f, "Parse error at {}", self.0));
+                writeln!(f, "Parse error at {}", self.0)?;
                 Error::fmt_errors(&(self.1).0, f)
             }
         }
diff --git a/src/parser/byte.rs b/src/parser/byte.rs
index cccf9b2b..620f99cf 100644
--- a/src/parser/byte.rs
+++ b/src/parser/byte.rs
@@ -1,18 +1,19 @@
 //! Module containing parsers specialized on byte streams.
 extern crate ascii;
 
-use lib::marker::PhantomData;
+use crate::lib::marker::PhantomData;
 
 use self::ascii::AsciiChar;
 
-use combinator::{satisfy, skip_many, token, tokens, Expected, Satisfy, SkipMany, Token};
-use error::{ConsumedResult, Info, ParseError, Tracked};
-use parser::range::{take_fn, TakeRange};
-use parser::sequence::With;
-use stream::{FullRangeStream, RangeStream, Stream, StreamOnce};
-use Parser;
+use crate::combinator::{satisfy, skip_many, token, Expected, Satisfy, SkipMany, Token};
+use crate::error::{Info, ParseError, ParseResult, Tracked};
+use crate::parser::item::tokens_cmp;
+use crate::parser::range::{take_fn, TakeRange};
+use crate::parser::sequence::With;
+use crate::stream::{FullRangeStream, RangeStream, Stream, StreamOnce};
+use crate::Parser;
 
-use error::FastResult::*;
+use crate::error::ParseResult::*;
 
 /// Parses a byte and succeeds if the byte is equal to `c`.
 ///
@@ -283,32 +284,6 @@ where
     byte_parser!(hex_digit, HexDigit, is_hex)
 }
 
-#[derive(Copy, Clone)]
-pub struct Bytes<I>(&'static [u8], PhantomData<I>)
-where
-    I: Stream<Item = u8>,
-    I::Error: ParseError<I::Item, I::Range, I::Position>;
-
-impl<'a, I> Parser for Bytes<I>
-where
-    I: Stream<Item = u8, Range = &'a [u8]>,
-    I::Error: ParseError<I::Item, I::Range, I::Position>,
-{
-    type Input = I;
-    type Output = &'static [u8];
-    type PartialState = ();
-
-    #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
-        tokens(|&l, r| l == r, Info::Range(self.0), self.0.iter())
-            .parse_lazy(input)
-            .map(|bytes| bytes.as_slice())
-    }
-    fn add_error(&mut self, errors: &mut Tracked<<Self::Input as StreamOnce>::Error>) {
-        tokens::<_, _, I>(|&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
@@ -329,39 +304,12 @@ where
 /// [`RangeStream`]: ../stream/trait.RangeStream.html
 /// [`range`]: ../range/fn.range.html
 #[inline(always)]
-pub fn bytes<'a, I>(s: &'static [u8]) -> Bytes<I>
+pub fn bytes<'a, 'b, I>(s: &'static [u8]) -> impl Parser<Input = I, Output = &'a [u8]>
 where
-    I: Stream<Item = u8, Range = &'a [u8]>,
+    I: Stream<Item = u8, Range = &'b [u8]>,
     I::Error: ParseError<I::Item, I::Range, I::Position>,
 {
-    Bytes(s, PhantomData)
-}
-
-#[derive(Copy, Clone)]
-pub struct BytesCmp<C, I>(&'static [u8], C, PhantomData<I>)
-where
-    I: Stream<Item = u8>,
-    I::Error: ParseError<I::Item, I::Range, I::Position>;
-
-impl<'a, C, I> Parser for BytesCmp<C, I>
-where
-    C: FnMut(u8, u8) -> bool,
-    I: Stream<Item = u8, Range = &'a [u8]>,
-    I::Error: ParseError<I::Item, I::Range, I::Position>,
-{
-    type Input = I;
-    type Output = &'static [u8];
-    type PartialState = ();
-
-    #[inline]
-    fn parse_lazy(&mut self, input: &mut 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 Tracked<<Self::Input as StreamOnce>::Error>) {
-        let cmp = &mut self.1;
-        tokens::<_, _, I>(|&l, r| cmp(l, r), Info::Range(self.0), self.0.iter()).add_error(errors)
-    }
+    bytes_cmp(s, |l: u8, r: u8| l == r)
 }
 
 /// Parses the bytes `s` using `cmp` to compare each token.
@@ -385,13 +333,18 @@ where
 /// [`RangeStream`]: ../stream/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>
+pub fn bytes_cmp<'a, 'b, C, I>(
+    s: &'static [u8],
+    cmp: C,
+) -> impl Parser<Input = I, Output = &'a [u8]>
 where
     C: FnMut(u8, u8) -> bool,
-    I: Stream<Item = u8, Range = &'a [u8]>,
+    I: Stream<Item = u8, Range = &'b [u8]>,
     I::Error: ParseError<I::Item, I::Range, I::Position>,
 {
-    BytesCmp(s, cmp, PhantomData)
+    tokens_cmp(s.iter().cloned(), cmp)
+        .map(move |_| s)
+        .expected(Info::Range(s))
 }
 
 macro_rules! take_until {
@@ -407,7 +360,7 @@ macro_rules! take_until {
             pub fn $func_name[I]($($param : u8),*)(I) -> I::Range
                 where [
                     I: RangeStream + FullRangeStream,
-                    I::Range: AsRef<[u8]> + ::stream::Range,
+                    I::Range: AsRef<[u8]> + crate::stream::Range,
                 ]
             {
                 take_fn(move |haystack: I::Range| {
@@ -504,7 +457,7 @@ parser! {
 pub fn take_until_bytes['a, I](needle: &'a [u8])(I) -> I::Range
 where [
     I: RangeStream + FullRangeStream,
-    I::Range: AsRef<[u8]> + ::stream::Range,
+    I::Range: AsRef<[u8]> + crate::stream::Range,
 ]
 {
     take_fn(move |haystack: I::Range| {
@@ -535,11 +488,11 @@ fn memslice(needle: &[u8], haystack: &[u8]) -> Option<usize> {
 /// Parsers for decoding numbers in big-endian or little-endian order.
 pub mod num {
     use super::*;
-    use stream::uncons;
+    use crate::stream::uncons;
 
     use byteorder::{ByteOrder, BE, LE};
 
-    use lib::mem::size_of;
+    use crate::lib::mem::size_of;
 
     macro_rules! integer_parser {
         (
@@ -564,7 +517,7 @@ pub mod num {
                 fn parse_lazy(
                     &mut self,
                     input: &mut Self::Input
-                    ) -> ConsumedResult<Self::Output, Self::Input> {
+                    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
                     let buffer = &mut [0u8; 8][..size_of::<Self::Output>()];
                     for elem in &mut *buffer {
                         *elem = ctry!(uncons(input)).0;
@@ -721,9 +674,9 @@ pub mod num {
     #[cfg(test)]
     mod tests {
         use super::*;
-        use stream::buffered::BufferedStream;
-        use stream::state::State;
-        use stream::IteratorStream;
+        use crate::stream::buffered;
+        use crate::stream::state::State;
+        use crate::stream::IteratorStream;
 
         #[test]
         fn no_rangestream() {
@@ -731,7 +684,7 @@ pub mod num {
             LE::write_f64(&mut buf, 123.45);
             assert_eq!(
                 f64::<LE, _>()
-                    .parse(BufferedStream::new(
+                    .parse(buffered::Stream::new(
                         State::new(IteratorStream::new(buf.iter().cloned())),
                         1
                     ))
@@ -740,7 +693,7 @@ pub mod num {
             );
             assert_eq!(
                 le_f64()
-                    .parse(BufferedStream::new(
+                    .parse(buffered::Stream::new(
                         State::new(IteratorStream::new(buf.iter().cloned())),
                         1
                     ))
@@ -751,7 +704,7 @@ pub mod num {
             BE::write_f64(&mut buf, 123.45);
             assert_eq!(
                 be_f64()
-                    .parse(BufferedStream::new(
+                    .parse(buffered::Stream::new(
                         State::new(IteratorStream::new(buf.iter().cloned())),
                         1
                     ))
diff --git a/src/parser/char.rs b/src/parser/char.rs
index 49f940e3..cde50dff 100644
--- a/src/parser/char.rs
+++ b/src/parser/char.rs
@@ -1,11 +1,12 @@
 //! Module containing parsers specialized on character streams.
 
-use combinator::{satisfy, skip_many, token, tokens, Expected, Satisfy, SkipMany, Token};
-use error::{ConsumedResult, ParseError, Tracked};
-use lib::marker::PhantomData;
-use parser::sequence::With;
-use stream::{Stream, StreamOnce};
-use Parser;
+use crate::combinator::{satisfy, skip_many, token, Expected, Satisfy, SkipMany, Token};
+use crate::error::{ParseError, ParseResult, Tracked};
+use crate::lib::marker::PhantomData;
+use crate::parser::item::tokens_cmp;
+use crate::parser::sequence::With;
+use crate::stream::Stream;
+use crate::Parser;
 
 /// Parses a character and succeeds if the character is equal to `c`.
 ///
@@ -304,35 +305,6 @@ where
     )
 }
 
-fn eq(l: char, r: char) -> bool {
-    l == r
-}
-
-#[derive(Copy, Clone)]
-pub struct Str<I>(&'static str, PhantomData<fn(I) -> I>)
-where
-    I: Stream<Item = char>,
-    I::Error: ParseError<I::Item, I::Range, I::Position>;
-impl<I> Parser for Str<I>
-where
-    I: Stream<Item = char>,
-    I::Error: ParseError<I::Item, I::Range, I::Position>,
-{
-    type Input = I;
-    type Output = &'static str;
-    type PartialState = ();
-
-    #[inline]
-    fn parse_lazy(&mut self, input: &mut 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 Tracked<<Self::Input as StreamOnce>::Error>) {
-        tokens::<_, _, I>(eq, self.0.into(), self.0.chars()).add_error(errors)
-    }
-}
-
 /// Parses the string `s`.
 ///
 /// ```
@@ -347,38 +319,12 @@ where
 /// # }
 /// ```
 #[inline(always)]
-pub fn string<I>(s: &'static str) -> Str<I>
+pub fn string<'a, I>(s: &'static str) -> impl Parser<Input = I, Output = &'a str>
 where
     I: Stream<Item = char>,
     I::Error: ParseError<I::Item, I::Range, I::Position>,
 {
-    Str(s, PhantomData)
-}
-
-#[derive(Copy, Clone)]
-pub struct StrCmp<C, I>(&'static str, C, PhantomData<fn(I) -> I>)
-where
-    I: Stream<Item = char>,
-    I::Error: ParseError<I::Item, I::Range, I::Position>;
-impl<C, I> Parser for StrCmp<C, I>
-where
-    C: FnMut(char, char) -> bool,
-    I: Stream<Item = char>,
-    I::Error: ParseError<I::Item, I::Range, I::Position>,
-{
-    type Input = I;
-    type Output = &'static str;
-    type PartialState = ();
-
-    #[inline]
-    fn parse_lazy(&mut self, input: &mut 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 Tracked<<Self::Input as StreamOnce>::Error>) {
-        tokens::<_, _, I>(&mut self.1, self.0.into(), self.0.chars()).add_error(errors)
-    }
+    string_cmp(s, |l, r| l == r)
 }
 
 /// Parses the string `s`, using `cmp` to compare each character.
@@ -396,20 +342,20 @@ where
 /// # }
 /// ```
 #[inline(always)]
-pub fn string_cmp<C, I>(s: &'static str, cmp: C) -> StrCmp<C, I>
+pub fn string_cmp<'a, C, I>(s: &'static str, cmp: C) -> impl Parser<Input = I, Output = &'a str>
 where
     C: FnMut(char, char) -> bool,
     I: Stream<Item = char>,
     I::Error: ParseError<I::Item, I::Range, I::Position>,
 {
-    StrCmp(s, cmp, PhantomData)
+    tokens_cmp(s.chars(), cmp).map(move |_| s).expected(s)
 }
 
 #[cfg(all(feature = "std", test))]
 mod tests {
     use super::*;
-    use stream::easy::{Error, Errors};
-    use stream::state::{SourcePosition, State};
+    use crate::stream::easy::{Error, Errors};
+    use crate::stream::state::{SourcePosition, State};
 
     #[test]
     fn space_error() {
diff --git a/src/parser/choice.rs b/src/parser/choice.rs
index aaf09037..569c45f5 100644
--- a/src/parser/choice.rs
+++ b/src/parser/choice.rs
@@ -1,10 +1,9 @@
 //! Combinators which take one or more parsers and attempts to parse successfully with at least one
 //! of them.
-use error::FastResult::*;
-use error::{ConsumedResult, ParseError, StreamError, Tracked};
-use parser::ParseMode;
-use stream::Resetable;
-use {ErrorOffset, Parser, Stream, StreamOnce};
+use crate::error::{ParseError, ParseResult, ParseResult::*, ResultExt, StreamError, Tracked};
+use crate::parser::ParseMode;
+use crate::stream::ResetStream;
+use crate::{ErrorOffset, Parser, Stream, StreamOnce};
 
 /// 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.
@@ -43,7 +42,7 @@ macro_rules! parse_mode_choice {
             &mut self,
             input: &mut Self::Input,
             state: &mut Self::PartialState,
-        ) -> ConsumedResult<Self::Output, Self::Input> {
+        ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
             self.parse_mode_choice($crate::parser::PartialMode::default(), input, state)
         }
 
@@ -51,7 +50,7 @@ macro_rules! parse_mode_choice {
             &mut self,
             input: &mut Self::Input,
             state: &mut Self::PartialState,
-        ) -> ConsumedResult<Self::Output, Self::Input> {
+        ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
             self.parse_mode_choice($crate::parser::FirstMode, input, state)
         }
     }
@@ -70,20 +69,20 @@ pub trait ChoiceParser {
         &mut self,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>;
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>;
 
     fn parse_partial(
         &mut self,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>;
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>;
 
     fn parse_mode_choice<M>(
         &mut self,
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
         Self: Sized;
@@ -106,7 +105,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -169,7 +168,7 @@ macro_rules! do_choice {
     ) => { {
         let parser = $head;
         let mut state = $head::PartialState::default();
-        match parser.parse_mode(::parser::FirstMode, $input, &mut state) {
+        match parser.parse_mode(crate::parser::FirstMode, $input, &mut state) {
             ConsumedOk(x) => ConsumedOk(x),
             EmptyOk(x) => EmptyOk(x),
             ConsumedErr(err) => {
@@ -182,7 +181,7 @@ macro_rules! do_choice {
                 ConsumedErr(err)
             }
             EmptyErr($head) => {
-                $input.reset($before.clone());
+                ctry!($input.reset($before.clone()).consumed());
                 do_choice!(
                     $input
                     $before_position
@@ -242,7 +241,7 @@ macro_rules! tuple_choice_parser_inner {
                 mode: Mode,
                 input: &mut Self::Input,
                 state: &mut Self::PartialState,
-            ) -> ConsumedResult<Self::Output, Self::Input>
+            ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
             where
                 Mode: ParseMode,
             {
@@ -315,7 +314,7 @@ macro_rules! array_choice_parser {
                 mode: M,
                 input: &mut Self::Input,
                 state: &mut Self::PartialState,
-            ) -> ConsumedResult<Self::Output, Self::Input>
+            ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
             where
                 M: ParseMode,
             {
@@ -361,7 +360,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -380,7 +379,7 @@ fn slice_parse_mode<I, P, M>(
     mode: M,
     input: &mut P::Input,
     state: &mut (usize, P::PartialState),
-) -> ConsumedResult<P::Output, P::Input>
+) -> ParseResult<P::Output, <P::Input as StreamOnce>::Error>
 where
     P: Parser<Input = I>,
     I: Stream,
@@ -401,7 +400,7 @@ where
     }
 
     for i in 0..self_.len() {
-        input.reset(before.clone());
+        ctry!(input.reset(before.clone()).consumed());
 
         match self_[i].parse_mode(mode, input, child_state) {
             consumed_err @ ConsumedErr(_) => {
@@ -476,8 +475,8 @@ where
         &mut self,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input> {
-        slice_parse_mode(self, ::parser::PartialMode::default(), input, state)
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
+        slice_parse_mode(self, crate::parser::PartialMode::default(), input, state)
     }
 
     #[inline(always)]
@@ -485,8 +484,8 @@ where
         &mut self,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input> {
-        slice_parse_mode(self, ::parser::FirstMode, input, state)
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
+        slice_parse_mode(self, crate::parser::FirstMode, input, state)
     }
 
     #[inline(always)]
@@ -495,7 +494,7 @@ where
         _mode: M,
         _input: &mut Self::Input,
         _state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -573,7 +572,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -645,7 +644,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -655,7 +654,7 @@ where
             ConsumedOk(x) => ConsumedOk(Some(x)),
             ConsumedErr(err) => ConsumedErr(err),
             EmptyErr(_) => {
-                input.reset(before);
+                ctry!(input.reset(before).consumed());
                 EmptyOk(None)
             }
         }
@@ -689,7 +688,7 @@ where
 #[cfg(test)]
 mod tests {
     use super::*;
-    use parser::item::any;
+    use crate::parser::item::any;
 
     #[test]
     fn choice_single_parser() {
diff --git a/src/parser/combinator.rs b/src/parser/combinator.rs
index ff7d6fe2..a14b279a 100644
--- a/src/parser/combinator.rs
+++ b/src/parser/combinator.rs
@@ -1,18 +1,18 @@
 //! Various combinators which do not fit anywhere else.
 
-use lib::fmt;
-use lib::marker::PhantomData;
-use lib::mem;
-use lib::str;
+use crate::lib::fmt;
+use crate::lib::marker::PhantomData;
+use crate::lib::mem;
+use crate::lib::str;
 
-use error::{ConsumedResult, Info, ParseError, StreamError, Tracked};
-use parser::ParseMode;
-use stream::{input_at_eof, Positioned, Resetable, Stream, StreamErrorFor, StreamOnce};
-use Parser;
+use crate::error::{Info, ParseError, ParseResult, ResultExt, StreamError, Tracked};
+use crate::parser::ParseMode;
+use crate::stream::{input_at_eof, Positioned, ResetStream, Stream, StreamErrorFor, StreamOnce};
+use crate::Parser;
 
 use either::Either;
 
-use error::FastResult::*;
+use crate::error::ParseResult::*;
 
 #[derive(Copy, Clone)]
 pub struct NotFollowedBy<P>(P);
@@ -32,13 +32,13 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
         let checkpoint = input.checkpoint();
         let result = self.0.parse_mode(mode, input, state);
-        input.reset(checkpoint);
+        ctry!(input.reset(checkpoint).consumed());
         match result {
             ConsumedOk(_) | EmptyOk(_) => EmptyErr(I::Error::empty(input.position()).into()),
             ConsumedErr(_) | EmptyErr(_) => EmptyOk(()),
@@ -98,7 +98,10 @@ where
     type PartialState = P::PartialState;
 
     #[inline]
-    fn parse_stream_consumed(&mut self, input: &mut Self::Input) -> ConsumedResult<O, I> {
+    fn parse_stream(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<O, <I as StreamOnce>::Error> {
         self.parse_lazy(input)
     }
 
@@ -109,7 +112,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -122,7 +125,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -141,36 +144,6 @@ where
     forward_parser!(add_error add_consumed_expected_error parser_count, 0);
 }
 
-/// `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::parser::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());
-/// # }
-/// ```
-///
-/// Note: if you're on the 2018 edition, you'll need to either use `r#try`, or [`attempt`](fn.attempt.html)
-#[deprecated(
-    since = "3.5.2",
-    note = "try is a reserved keyword in Rust 2018. Use attempt instead."
-)]
-#[inline(always)]
-pub fn try<P>(p: P) -> Try<P>
-where
-    P: Parser,
-{
-    Try(p)
-}
-
 /// `attempt(p)` behaves as `p` except it acts as if the parser hadn't consumed any input if `p` fails
 /// after consuming input. (alias for [`try`](fn.try.html))
 ///
@@ -210,10 +183,10 @@ where
     type PartialState = ();
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<O, I> {
+    fn parse_lazy(&mut self, input: &mut Self::Input) -> ParseResult<O, <I as StreamOnce>::Error> {
         let before = input.checkpoint();
         let result = self.0.parse_lazy(input);
-        input.reset(before);
+        ctry!(input.reset(before).consumed());
         let (o, _input) = ctry!(result);
         EmptyOk(o)
     }
@@ -266,7 +239,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -312,7 +285,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -365,7 +338,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -378,7 +351,7 @@ where
                     let err = <Self::Input as StreamOnce>::Error::from_error(position, err.into());
 
                     if input.is_partial() && input_at_eof(input) {
-                        input.reset(checkpoint);
+                        ctry!(input.reset(checkpoint).consumed());
                         ConsumedErr(err)
                     } else {
                         EmptyErr(err.into())
@@ -389,7 +362,7 @@ where
                 Ok(o) => ConsumedOk(o),
                 Err(err) => {
                     if input.is_partial() && input_at_eof(input) {
-                        input.reset(checkpoint);
+                        ctry!(input.reset(checkpoint).consumed());
                     }
                     ConsumedErr(
                         <Self::Input as StreamOnce>::Error::from_error(position, err.into()).into(),
@@ -429,14 +402,14 @@ where
     #[inline]
     fn recognize_result(
         elements: &mut F,
-        before: <<Self as Parser>::Input as Resetable>::Checkpoint,
+        before: <<Self as Parser>::Input as ResetStream>::Checkpoint,
         input: &mut <Self as Parser>::Input,
-        result: ConsumedResult<P::Output, P::Input>,
-    ) -> ConsumedResult<F, P::Input> {
+        result: ParseResult<P::Output, <P::Input as StreamOnce>::Error>,
+    ) -> ParseResult<F, <P::Input as StreamOnce>::Error> {
         match result {
             EmptyOk(_) => {
                 let last_position = input.position();
-                input.reset(before);
+                ctry!(input.reset(before).consumed());
 
                 while input.position() != last_position {
                     match input.uncons() {
@@ -453,7 +426,7 @@ where
             }
             ConsumedOk(_) => {
                 let last_position = input.position();
-                input.reset(before);
+                ctry!(input.reset(before).consumed());
 
                 while input.position() != last_position {
                     match input.uncons() {
@@ -470,7 +443,7 @@ where
             }
             ConsumedErr(err) => {
                 let last_position = input.position();
-                input.reset(before);
+                ctry!(input.reset(before).consumed());
 
                 while input.position() != last_position {
                     match input.uncons() {
@@ -505,7 +478,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -553,7 +526,10 @@ where
     type PartialState = Option<Either<L::PartialState, R::PartialState>>;
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
         match *self {
             Either::Left(ref mut x) => x.parse_lazy(input),
             Either::Right(ref mut x) => x.parse_lazy(input),
@@ -567,7 +543,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -621,7 +597,10 @@ where
     type PartialState = ();
 
     #[inline(always)]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
         self.0.parse_lazy(input)
     }
 
@@ -632,7 +611,7 @@ where
         _mode: M,
         input: &mut Self::Input,
         _state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -661,7 +640,10 @@ where
     type PartialState = P::PartialState;
 
     #[inline(always)]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
         self.0.parse_lazy(input).map(|_| ())
     }
 
@@ -672,7 +654,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -708,7 +690,10 @@ where
     type PartialState = AnyPartialState;
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
         self.0.parse_lazy(input)
     }
 
@@ -719,7 +704,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -804,7 +789,10 @@ where
     type PartialState = AnySendPartialState;
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
         self.0.parse_lazy(input)
     }
 
@@ -815,7 +803,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -894,11 +882,14 @@ where
     type Output = O;
     type PartialState = R::PartialState;
 
-    fn parse_stream_consumed(&mut self, input: &mut Self::Input) -> ConsumedResult<O, I> {
-        (self.0)().parse_stream_consumed(input)
+    fn parse_stream(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<O, <I as StreamOnce>::Error> {
+        (self.0)().parse_stream(input)
     }
 
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<O, I> {
+    fn parse_lazy(&mut self, input: &mut Self::Input) -> ParseResult<O, <I as StreamOnce>::Error> {
         (self.0)().parse_lazy(input)
     }
 
@@ -909,7 +900,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -921,7 +912,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -990,7 +981,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -1159,13 +1150,16 @@ where
     type Output = O;
     type PartialState = S;
 
-    fn parse_stream_consumed(&mut self, input: &mut Self::Input) -> ConsumedResult<O, I> {
+    fn parse_stream(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<O, <I as StreamOnce>::Error> {
         let mut x = None;
-        (self.0)(&mut |parser| x = Some(parser.parse_stream_consumed(input)));
+        (self.0)(&mut |parser| x = Some(parser.parse_stream(input)));
         x.expect("Parser")
     }
 
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<O, I> {
+    fn parse_lazy(&mut self, input: &mut Self::Input) -> ParseResult<O, <I as StreamOnce>::Error> {
         let mut x = None;
         (self.0)(&mut |parser| x = Some(parser.parse_lazy(input)));
         x.expect("Parser")
@@ -1178,7 +1172,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
diff --git a/src/parser/error.rs b/src/parser/error.rs
index 34f5be22..a2474d5b 100644
--- a/src/parser/error.rs
+++ b/src/parser/error.rs
@@ -1,12 +1,12 @@
 //! Parsers which cause errors or modifies the returned error on parse failure.
 
-use lib::marker::PhantomData;
+use crate::lib::marker::PhantomData;
 
-use error::{ConsumedResult, Info, ParseError, StreamError, Tracked};
-use parser::ParseMode;
-use {Parser, Stream, StreamOnce};
+use crate::error::{Info, ParseError, ParseResult, StreamError, Tracked};
+use crate::parser::ParseMode;
+use crate::{Parser, Stream, StreamOnce};
 
-use error::FastResult::*;
+use crate::error::ParseResult::*;
 
 #[derive(Clone)]
 pub struct Unexpected<I, T>(Info<I::Item, I::Range>, PhantomData<fn(I) -> (I, T)>)
@@ -20,7 +20,7 @@ where
     type Output = T;
     type PartialState = ();
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<T, I> {
+    fn parse_lazy(&mut self, input: &mut Self::Input) -> ParseResult<T, <I as StreamOnce>::Error> {
         EmptyErr(<Self::Input as StreamOnce>::Error::empty(input.position()).into())
     }
     fn add_error(&mut self, errors: &mut Tracked<<Self::Input as StreamOnce>::Error>) {
@@ -114,7 +114,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -177,7 +177,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -226,7 +226,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
diff --git a/src/parser/function.rs b/src/parser/function.rs
index 0c5fcfe3..85949c00 100644
--- a/src/parser/function.rs
+++ b/src/parser/function.rs
@@ -1,18 +1,18 @@
 //! Parsers constructor from regular functions
 
-use lib::marker::PhantomData;
+use crate::lib::marker::PhantomData;
 
-use error::{ConsumedResult, ParseResult};
-use stream::Stream;
-use Parser;
+use crate::error::{ParseResult, StdParseResult};
+use crate::stream::{Stream, StreamOnce};
+use crate::Parser;
 
-impl<'a, I: Stream, O> Parser for FnMut(&mut I) -> ParseResult<O, I> + 'a {
+impl<'a, I: Stream, O> Parser for FnMut(&mut I) -> StdParseResult<O, I> + 'a {
     type Input = I;
     type Output = O;
     type PartialState = ();
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<O, I> {
+    fn parse_lazy(&mut self, input: &mut Self::Input) -> ParseResult<O, <I as StreamOnce>::Error> {
         self(input).into()
     }
 }
@@ -36,7 +36,7 @@ pub struct FnParser<I, F>(F, PhantomData<fn(I) -> I>);
 ///     // Help type inference out
 ///     let _: &mut easy::Stream<&str> = input;
 ///     let position = input.position();
-///     let (char_digit, consumed) = try!(digit().parse_stream(input));
+///     let (char_digit, consumed) = digit().parse_stream(input).into_result()?;
 ///     let d = (char_digit as i32) - ('0' as i32);
 ///     if d % 2 == 0 {
 ///         Ok((d, consumed))
@@ -60,7 +60,7 @@ pub struct FnParser<I, F>(F, PhantomData<fn(I) -> I>);
 pub fn parser<I, O, F>(f: F) -> FnParser<I, F>
 where
     I: Stream,
-    F: FnMut(&mut I) -> ParseResult<O, I>,
+    F: FnMut(&mut I) -> StdParseResult<O, I>,
 {
     FnParser(f, PhantomData)
 }
@@ -68,19 +68,19 @@ where
 impl<I, O, F> Parser for FnParser<I, F>
 where
     I: Stream,
-    F: FnMut(&mut I) -> ParseResult<O, I>,
+    F: FnMut(&mut I) -> StdParseResult<O, I>,
 {
     type Input = I;
     type Output = O;
     type PartialState = ();
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<O, I> {
+    fn parse_lazy(&mut self, input: &mut Self::Input) -> ParseResult<O, <I as StreamOnce>::Error> {
         (self.0)(input).into()
     }
 }
 
-impl<I, O> Parser for fn(&mut I) -> ParseResult<O, I>
+impl<I, O> Parser for fn(&mut I) -> StdParseResult<O, I>
 where
     I: Stream,
 {
@@ -89,7 +89,7 @@ where
     type PartialState = ();
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<O, I> {
+    fn parse_lazy(&mut self, input: &mut Self::Input) -> ParseResult<O, <I as StreamOnce>::Error> {
         self(input).into()
     }
 }
@@ -100,7 +100,7 @@ where
     I: Stream,
 {
     env: E,
-    parser: fn(E, &mut I) -> ParseResult<T, I>,
+    parser: fn(E, &mut I) -> StdParseResult<T, I>,
 }
 
 impl<E, I, T> Clone for EnvParser<E, I, T>
@@ -126,7 +126,7 @@ where
     type PartialState = ();
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<O, I> {
+    fn parse_lazy(&mut self, input: &mut Self::Input) -> ParseResult<O, <I as StreamOnce>::Error> {
         (self.parser)(self.env.clone(), input).into()
     }
 }
@@ -143,13 +143,14 @@ where
 /// # fn main() {
 /// struct Interner(HashMap<String, u32>);
 /// impl Interner {
-///     fn string<I>(&self, input: &mut I) -> ParseResult<u32, I>
+///     fn string<I>(&self, input: &mut I) -> StdParseResult<u32, I>
 ///         where I: Stream<Item=char>,
 ///               I::Error: ParseError<I::Item, I::Range, I::Position>,
 ///     {
 ///         many(letter())
 ///             .map(|s: String| self.0.get(&s).cloned().unwrap_or(0))
 ///             .parse_stream(input)
+///             .into_result()
 ///     }
 /// }
 ///
@@ -168,7 +169,10 @@ where
 /// # }
 /// ```
 #[inline(always)]
-pub fn env_parser<E, I, O>(env: E, parser: fn(E, &mut I) -> ParseResult<O, I>) -> EnvParser<E, I, O>
+pub fn env_parser<E, I, O>(
+    env: E,
+    parser: fn(E, &mut I) -> StdParseResult<O, I>,
+) -> EnvParser<E, I, O>
 where
     E: Clone,
     I: Stream,
diff --git a/src/parser/item.rs b/src/parser/item.rs
index 54959a5a..2828c0fe 100644
--- a/src/parser/item.rs
+++ b/src/parser/item.rs
@@ -1,12 +1,12 @@
 //! Parsers working with single stream items.
 
-use lib::marker::PhantomData;
+use crate::lib::marker::PhantomData;
 
-use error::{ConsumedResult, Info, ParseError, StreamError, Tracked};
-use stream::{uncons, Stream, StreamOnce};
-use Parser;
+use crate::error::{Info, ParseError, ParseResult, ResultExt, StreamError, Tracked};
+use crate::stream::{uncons, Stream, StreamOnce};
+use crate::Parser;
 
-use error::FastResult::*;
+use crate::error::ParseResult::*;
 
 #[doc(inline)]
 pub use self::token as item;
@@ -23,7 +23,10 @@ where
     type PartialState = ();
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<I::Item, I> {
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<I::Item, <I as StreamOnce>::Error> {
         uncons(input)
     }
 }
@@ -56,7 +59,10 @@ pub struct Satisfy<I, P> {
     _marker: PhantomData<I>,
 }
 
-fn satisfy_impl<I, P, R>(input: &mut I, mut predicate: P) -> ConsumedResult<R, I>
+fn satisfy_impl<I, P, R>(
+    input: &mut I,
+    mut predicate: P,
+) -> ParseResult<R, <I as StreamOnce>::Error>
 where
     I: Stream,
     P: FnMut(I::Item) -> Option<R>,
@@ -82,7 +88,10 @@ where
     type PartialState = ();
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
         satisfy_impl(input, |c| {
             if (self.predicate)(c.clone()) {
                 Some(c)
@@ -131,7 +140,10 @@ where
     type Output = R;
     type PartialState = ();
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
         satisfy_impl(input, &mut self.predicate)
     }
 }
@@ -192,7 +204,10 @@ where
     type PartialState = ();
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<I::Item, I> {
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<I::Item, <I as StreamOnce>::Error> {
         satisfy_impl(input, |c| if c == self.c { Some(c) } else { None })
     }
     fn add_error(&mut self, errors: &mut Tracked<<Self::Input as StreamOnce>::Error>) {
@@ -224,72 +239,6 @@ where
     }
 }
 
-#[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;
-    type PartialState = ();
-    #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<T, I> {
-        let start = input.position();
-        let mut consumed = false;
-        for c in self.tokens.clone() {
-            match ::stream::uncons(input) {
-                ConsumedOk(other) | EmptyOk(other) => {
-                    if !(self.cmp)(c, other.clone()) {
-                        return if consumed {
-                            let mut errors = <Self::Input as StreamOnce>::Error::from_error(
-                                start,
-                                StreamError::unexpected(Info::Token(other)),
-                            );
-                            errors.add_expected(self.expected.clone());
-                            ConsumedErr(errors)
-                        } else {
-                            EmptyErr(<Self::Input as StreamOnce>::Error::empty(start).into())
-                        };
-                    }
-                    consumed = true;
-                }
-                EmptyErr(mut error) => {
-                    error.error.set_position(start);
-                    return if consumed {
-                        ConsumedErr(error.error)
-                    } else {
-                        EmptyErr(error.into())
-                    };
-                }
-                ConsumedErr(mut error) => {
-                    error.set_position(start);
-                    return ConsumedErr(error);
-                }
-            }
-        }
-        if consumed {
-            ConsumedOk(self.tokens.clone())
-        } else {
-            EmptyOk(self.tokens.clone())
-        }
-    }
-    fn add_error(&mut self, errors: &mut Tracked<<Self::Input as StreamOnce>::Error>) {
-        errors.error.add_expected(self.expected.clone());
-    }
-}
-
 /// Parses multiple tokens.
 ///
 /// Consumes items from the input and compares them to the values from `tokens` using the
@@ -297,42 +246,26 @@ where
 /// stream and fails otherwise with `expected` used as part of the error.
 ///
 /// ```
-/// # extern crate combine;
 /// # use combine::*;
-/// # use combine::error::Info;
 /// # fn main() {
-/// use std::ascii::AsciiExt;
-/// let result = tokens(|l, r| l.eq_ignore_ascii_case(&r), "abc".into(), "abc".chars())
-///     .parse("AbC")
+/// let result = tokens("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>
+pub fn tokens<T, I>(tokens: T) -> impl Parser<Input = I, Output = T>
 where
-    C: FnMut(T::Item, I::Item) -> bool,
     T: Clone + IntoIterator,
     I: Stream,
+    T::Item: PartialEq<I::Item>,
 {
-    Tokens {
-        cmp: cmp,
-        expected: expected,
-        tokens: tokens,
-        _marker: PhantomData,
-    }
+    tokens_cmp(tokens, |l, r| l == r)
 }
 
 #[derive(Clone)]
-pub struct Tokens2<C, T, I>
+pub struct TokensCmp<C, T, I>
 where
     I: Stream,
 {
@@ -341,7 +274,7 @@ where
     _marker: PhantomData<I>,
 }
 
-impl<C, T, I> Parser for Tokens2<C, T, I>
+impl<C, T, I> Parser for TokensCmp<C, T, I>
 where
     C: FnMut(T::Item, I::Item) -> bool,
     T: Clone + IntoIterator,
@@ -352,11 +285,11 @@ where
     type PartialState = ();
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<T, I> {
+    fn parse_lazy(&mut self, input: &mut Self::Input) -> ParseResult<T, <I as StreamOnce>::Error> {
         let start = input.position();
         let mut consumed = false;
         for c in self.tokens.clone() {
-            match ::stream::uncons(input) {
+            match crate::stream::uncons(input) {
                 ConsumedOk(other) | EmptyOk(other) => {
                     if !(self.cmp)(c, other.clone()) {
                         return if consumed {
@@ -405,13 +338,13 @@ where
 /// # fn main() {
 /// # #[allow(deprecated)]
 /// # use std::ascii::AsciiExt;
-/// let result = tokens2(|l, r| l.eq_ignore_ascii_case(&r), "abc".chars())
+/// let result = tokens_cmp("abc".chars(), |l, r| l.eq_ignore_ascii_case(&r))
 ///     .parse("AbC")
 ///     .map(|x| x.0.as_str());
 /// assert_eq!(result, Ok("abc"));
-/// let result = tokens2(
+/// let result = tokens_cmp(
+///     &b"025"[..],
 ///     |&l, r| (if l < r { r - l } else { l - r }) <= 2,
-///     &b"025"[..]
 /// )
 ///     .parse(&b"123"[..])
 ///     .map(|x| x.0);
@@ -419,13 +352,13 @@ where
 /// # }
 /// ```
 #[inline(always)]
-pub fn tokens2<C, T, I>(cmp: C, tokens: T) -> Tokens2<C, T, I>
+pub fn tokens_cmp<C, T, I>(tokens: T, cmp: C) -> TokensCmp<C, T, I>
 where
     C: FnMut(T::Item, I::Item) -> bool,
     T: Clone + IntoIterator,
     I: Stream,
 {
-    Tokens2 {
+    TokensCmp {
         cmp: cmp,
         tokens: tokens,
         _marker: PhantomData,
@@ -449,7 +382,10 @@ where
     type PartialState = ();
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<I::Position, I> {
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<I::Position, <I as StreamOnce>::Error> {
         EmptyOk(input.position())
     }
 }
@@ -499,7 +435,10 @@ where
     type PartialState = ();
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<I::Item, I> {
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<I::Item, <I as StreamOnce>::Error> {
         satisfy(|c| self.tokens.clone().into_iter().any(|t| t == c)).parse_lazy(input)
     }
 
@@ -554,7 +493,10 @@ where
     type PartialState = ();
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<I::Item, I> {
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<I::Item, <I as StreamOnce>::Error> {
         satisfy(|c| self.tokens.clone().into_iter().all(|t| t != c)).parse_lazy(input)
     }
 }
@@ -605,7 +547,7 @@ where
     type Output = T;
     type PartialState = ();
     #[inline]
-    fn parse_lazy(&mut self, _: &mut Self::Input) -> ConsumedResult<T, I> {
+    fn parse_lazy(&mut self, _: &mut Self::Input) -> ParseResult<T, <I as StreamOnce>::Error> {
         EmptyOk(self.0.clone())
     }
 }
@@ -642,12 +584,12 @@ where
     type PartialState = ();
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<(), I> {
+    fn parse_lazy(&mut self, input: &mut Self::Input) -> ParseResult<(), <I as StreamOnce>::Error> {
         let before = input.checkpoint();
         match input.uncons() {
-            Err(ref err) if *err == StreamError::end_of_input() => EmptyOk(()),
+            Err(ref err) if err.is_unexpected_end_of_input() => EmptyOk(()),
             _ => {
-                input.reset(before);
+                ctry!(input.reset(before).consumed());
                 EmptyErr(<Self::Input as StreamOnce>::Error::empty(input.position()).into())
             }
         }
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index afc1783b..a93f38b7 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -4,15 +4,15 @@
 //! implementing all combine parsers.
 use either::Either;
 
-use combinator::{
+use crate::combinator::{
     and_then, expected, flat_map, map, message, then, then_partial, AndThen, Expected, FlatMap,
     Iter, Map, Message, Then, ThenPartial,
 };
-use error::FastResult::*;
-use error::{ConsumedResult, FastResult, Info, ParseError, ParseResult, Tracked};
-use parser::error::{silent, Silent};
-use stream::{Resetable, Stream, StreamOnce};
-use ErrorOffset;
+use crate::error::ParseResult::*;
+use crate::error::{Info, ParseError, ParseResult, ResultExt, Tracked};
+use crate::parser::error::{silent, Silent};
+use crate::stream::{ResetStream, Stream, StreamOnce};
+use crate::ErrorOffset;
 
 use self::choice::{or, Or};
 use self::sequence::{skip, with, Skip, With};
@@ -45,7 +45,7 @@ macro_rules! parse_mode {
             &mut self,
             input: &mut Self::Input,
             state: &mut Self::PartialState,
-        ) -> $crate::error::ConsumedResult<Self::Output, Self::Input> {
+        ) -> $crate::error::ParseResult<Self::Output, <Self::Input as $crate::StreamOnce>::Error> {
             self.parse_mode($crate::parser::PartialMode::default(), input, state)
         }
 
@@ -54,7 +54,7 @@ macro_rules! parse_mode {
             &mut self,
             input: &mut Self::Input,
             state: &mut Self::PartialState,
-        ) -> $crate::error::ConsumedResult<Self::Output, Self::Input> {
+        ) -> $crate::error::ParseResult<Self::Output, <Self::Input as $crate::StreamOnce>::Error> {
             self.parse_mode($crate::parser::FirstMode, input, state)
         }
     }
@@ -77,12 +77,12 @@ pub mod sequence;
 /// into the type `Output`.
 ///
 /// All methods have a default implementation but there needs to be at least an implementation of
-/// [`parse_stream`], [`parse_stream_consumed`], or [`parse_lazy`]. If the last is implemented, an
+/// [`parse_stream`], [`parse_stream`], or [`parse_lazy`]. If the last is implemented, an
 /// implementation of [`add_error`] may also be required. See the documentation for
 /// [`parse_lazy`] for details.
 ///
 /// [`parse_stream`]: trait.Parser.html#method.parse_stream
-/// [`parse_stream_consumed`]: trait.Parser.html#method.parse_stream_consumed
+/// [`parse_stream`]: trait.Parser.html#method.parse_stream
 /// [`parse_lazy`]: trait.Parser.html#method.parse_lazy
 /// [`add_error`]: trait.Parser.html#method.add_error
 pub trait Parser {
@@ -139,19 +139,21 @@ pub trait Parser {
     ///
     /// [`ParseError`]: struct.ParseError.html
     #[cfg(feature = "std")]
-    fn easy_parse<I>(&mut self, input: I) -> Result<(Self::Output, I), ::easy::ParseError<I>>
+    fn easy_parse<I>(&mut self, input: I) -> Result<(Self::Output, I), crate::easy::ParseError<I>>
     where
         I: Stream,
-        ::easy::Stream<I>: StreamOnce<
+        crate::easy::Stream<I>: StreamOnce<
             Item = I::Item,
             Range = I::Range,
-            Error = ::easy::ParseError<::easy::Stream<I>>,
+            Error = crate::easy::ParseError<crate::easy::Stream<I>>,
             Position = I::Position,
         >,
         I::Position: Default,
-        Self: Sized + Parser<Input = ::easy::Stream<I>>,
+        I::Item: PartialEq,
+        I::Range: PartialEq,
+        Self: Sized + Parser<Input = crate::easy::Stream<I>>,
     {
-        let input = ::easy::Stream(input);
+        let input = crate::easy::Stream(input);
         self.parse(input).map(|(v, input)| (v, input.0))
     }
 
@@ -171,7 +173,7 @@ pub trait Parser {
         &mut self,
         mut input: Self::Input,
     ) -> Result<(Self::Output, Self::Input), <Self::Input as StreamOnce>::Error> {
-        match self.parse_stream(&mut input) {
+        match self.parse_stream(&mut input).into() {
             Ok((v, _)) => Ok((v, input)),
             Err(error) => Err(error.into_inner().error),
         }
@@ -187,65 +189,33 @@ pub trait Parser {
         input: &mut Self::Input,
         state: &mut Self::PartialState,
     ) -> Result<Self::Output, <Self::Input as StreamOnce>::Error> {
-        match self.parse_stream_consumed_partial(input, state).into() {
+        match self.parse_stream_partial(input, state).into() {
             Ok((v, _)) => Ok(v),
             Err(error) => Err(error.into_inner().error),
         }
     }
 
-    /// Parses using the stream `input` by calling [`Stream::uncons`] one or more times.
-    ///
-    /// On success returns `Ok((value, new_state))`, and on failure returns `Err(error)`.
-    /// Furthermore `new_state` and `error` are wrapped in [`Consumed`], providing information on
-    /// whether this parser consumed any input data or not.
-    ///
-    /// [`Stream::uncons`]: trait.StreamOnce.html#tymethod.uncons
-    /// [`Consumed`]: enum.Consumed.html
-    #[inline(always)]
-    fn parse_stream(&mut self, input: &mut Self::Input) -> ParseResult<Self::Output, Self::Input> {
-        self.parse_stream_consumed(input).into()
-    }
-
     /// Parses using the stream `input` by calling [`Stream::uncons`] one or more times.
     ///
     /// Semantically equivalent to [`parse_stream`], except this method returns a flattened result
-    /// type, combining `Result` and [`Consumed`] into a single [`FastResult`].
+    /// type, combining `Result` and [`Consumed`] into a single [`ParseResult`].
     ///
     /// [`Stream::uncons`]: trait.StreamOnce.html#tymethod.uncons
     /// [`parse_stream`]: trait.Parser.html#method.parse_stream
     /// [`Consumed`]: enum.Consumed.html
-    /// [`FastResult`]: enum.FastResult.html
+    /// [`ParseResult`]: enum.ParseResult.html
     #[inline]
-    fn parse_stream_consumed(
+    fn parse_stream(
         &mut self,
         input: &mut Self::Input,
-    ) -> ConsumedResult<Self::Output, Self::Input> {
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
         let before = input.checkpoint();
         let mut state = Default::default();
         let mut result = self.parse_first(input, &mut state);
-        if let FastResult::EmptyErr(ref mut error) = result {
-            input.reset(before.clone());
-            if let Ok(t) = input.uncons() {
-                input.reset(before);
-                error.error.add_unexpected(Info::Token(t));
-            }
-            self.add_error(error);
-        }
-        result
-    }
-
-    #[inline]
-    fn parse_stream_consumed_partial(
-        &mut self,
-        input: &mut Self::Input,
-        state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input> {
-        let before = input.checkpoint();
-        let mut result = self.parse_partial(input, state);
-        if let FastResult::EmptyErr(ref mut error) = result {
-            input.reset(before.clone());
+        if let ParseResult::EmptyErr(ref mut error) = result {
+            ctry!(input.reset(before.clone()).consumed());
             if let Ok(t) = input.uncons() {
-                input.reset(before);
+                ctry!(input.reset(before).consumed());
                 error.error.add_unexpected(Info::Token(t));
             }
             self.add_error(error);
@@ -255,7 +225,7 @@ pub trait Parser {
 
     /// Parses using the stream `input` by calling [`Stream::uncons`] one or more times.
     ///
-    /// Specialized version of [`parse_stream_consumed`] which permits error value creation to be
+    /// Specialized version of [`parse_stream`] which permits error value creation to be
     /// skipped in the common case.
     ///
     /// When this parser returns `EmptyErr`, this method is allowed to return an empty
@@ -263,18 +233,19 @@ pub trait Parser {
     /// calling [`add_error`]. This allows a parent parser such as `choice` to skip the creation of
     /// an unnecessary error value, if an alternative parser succeeds.
     ///
-    /// External callers should never have to call this function directly.
-    ///
     /// Parsers should seek to implement this function instead of the above two if errors can be
     /// encountered before consuming input. The default implementation always returns all errors,
     /// with [`add_error`] being a no-op.
     ///
     /// [`Stream::uncons`]: trait.StreamOnce.html#tymethod.uncons
-    /// [`parse_stream_consumed`]: trait.Parser.html#method.parse_stream_consumed
+    /// [`parse_stream`]: trait.Parser.html#method.parse_stream
     /// [`Error`]: trait.StreamOnce.html#associatedtype.Error
     /// [`add_error`]: trait.Parser.html#method.add_error
     #[inline(always)]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
         if input.is_partial() {
             // If a partial parser were called from a non-partial parser (as it is here) we must
             // reset the input to before the partial parser were called on errors that consumed
@@ -283,7 +254,7 @@ pub trait Parser {
             let before = input.checkpoint();
             let result = self.parse_first(input, &mut Default::default());
             if let ConsumedErr(_) = result {
-                input.reset(before);
+                ctry!(input.reset(before).consumed());
             }
             result
         } else {
@@ -291,28 +262,64 @@ pub trait Parser {
         }
     }
 
+    /// Adds the first error that would normally be returned by this parser if it failed with an
+    /// `EmptyErr` result.
+    ///
+    /// See [`parse_lazy`] for details.
+    ///
+    /// [`parse_lazy`]: trait.Parser.html#method.parse_lazy
+    fn add_error(&mut self, _error: &mut Tracked<<Self::Input as StreamOnce>::Error>) {}
+
+    /// Like `parse_stream` but supports partial parsing.
+    #[inline]
+    fn parse_stream_partial(
+        &mut self,
+        input: &mut Self::Input,
+        state: &mut Self::PartialState,
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
+        let before = input.checkpoint();
+        let mut result = self.parse_partial(input, state);
+        if let ParseResult::EmptyErr(ref mut error) = result {
+            ctry!(input.reset(before.clone()).consumed());
+            if let Ok(t) = input.uncons() {
+                ctry!(input.reset(before).consumed());
+                error.error.add_unexpected(Info::Token(t));
+            }
+            self.add_error(error);
+        }
+        result
+    }
+
     /// Parses using the stream `input` and allows itself to be resumed at a later point using
     /// `parse_partial` by storing the necessary intermediate state in `state`.
     ///
     /// Unlike `parse_partial` function this is allowed to assume that there is no partial state to
     /// resume.
+    ///
+    /// Internal API. May break without a semver bump
+    /// Always overridden by the `parse_mode!` macro
     #[inline(always)]
+    #[doc(hidden)]
     fn parse_first(
         &mut self,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input> {
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
         self.parse_partial(input, state)
     }
 
     /// Parses using the stream `input` and allows itself to be resumed at a later point using
     /// `parse_partial` by storing the necessary intermediate state in `state`
+    ///
+    /// Internal API. May break without a semver bump
+    /// Always overridden by the `parse_mode!` macro
     #[inline(always)]
+    #[doc(hidden)]
     fn parse_partial(
         &mut self,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input> {
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
         let _ = state;
         self.parse_lazy(input)
     }
@@ -325,7 +332,7 @@ pub trait Parser {
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
         Self: Sized,
@@ -345,7 +352,7 @@ pub trait Parser {
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
         Self: Sized,
@@ -365,7 +372,7 @@ pub trait Parser {
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
         Self: Sized,
@@ -377,14 +384,6 @@ pub trait Parser {
         }
     }
 
-    /// Adds the first error that would normally be returned by this parser if it failed with an
-    /// `EmptyErr` result.
-    ///
-    /// See [`parse_lazy`] for details.
-    ///
-    /// [`parse_lazy`]: trait.Parser.html#method.parse_lazy
-    fn add_error(&mut self, _error: &mut Tracked<<Self::Input as StreamOnce>::Error>) {}
-
     /// Returns how many parsers this parser contains
     ///
     /// Internal API: This should not be implemented explicitly outside of combine.
@@ -410,10 +409,10 @@ pub trait Parser {
     /// # use combine::*;
     /// # use combine::error::Consumed;
     /// # use combine::parser::char::{digit, letter};
-    /// fn test(input: &mut &'static str) -> ParseResult<(char, char), &'static str> {
+    /// fn test(input: &mut &'static str) -> StdParseResult<(char, char), &'static str> {
     ///     let mut p = digit();
-    ///     let ((d, _), consumed) = try!((p.by_ref(), letter()).parse_stream(input));
-    ///     let (d2, consumed) = try!(consumed.combine(|_| p.parse_stream(input)));
+    ///     let ((d, _), consumed) = (p.by_ref(), letter()).parse_stream(input).into_result()?;
+    ///     let (d2, consumed) = consumed.combine(|_| p.parse_stream(input).into_result())?;
     ///     Ok(((d, d2), consumed))
     /// }
     ///
@@ -956,7 +955,7 @@ macro_rules! forward_deref {
             &mut self,
             input: &mut Self::Input,
             state: &mut Self::PartialState,
-        ) -> ConsumedResult<Self::Output, Self::Input> {
+        ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
             (**self).parse_first(input, state)
         }
 
@@ -965,7 +964,7 @@ macro_rules! forward_deref {
             &mut self,
             input: &mut Self::Input,
             state: &mut Self::PartialState,
-        ) -> ConsumedResult<Self::Output, Self::Input> {
+        ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
             (**self).parse_partial(input, state)
         }
 
@@ -1017,16 +1016,16 @@ pub trait ParseMode: Copy {
         parser: &mut P,
         input: &mut P::Input,
         state: &mut P::PartialState,
-    ) -> ConsumedResult<P::Output, P::Input>
+    ) -> ParseResult<P::Output, <P::Input as StreamOnce>::Error>
     where
         P: Parser,
     {
         let before = input.checkpoint();
         let mut result = parser.parse_mode_impl(self, input, state);
-        if let FastResult::EmptyErr(ref mut error) = result {
-            input.reset(before.clone());
+        if let ParseResult::EmptyErr(ref mut error) = result {
+            ctry!(input.reset(before.clone()).consumed());
             if let Ok(t) = input.uncons() {
-                input.reset(before);
+                ctry!(input.reset(before).consumed());
                 error.error.add_unexpected(Info::Token(t));
             }
             parser.add_error(error);
diff --git a/src/parser/range.rs b/src/parser/range.rs
index 6241295e..bb197b33 100644
--- a/src/parser/range.rs
+++ b/src/parser/range.rs
@@ -5,16 +5,16 @@
 //! [`RangeStream`]: ../../stream/trait.RangeStream.html
 //! [`Stream`]: ../../stream/trait.Stream.html
 
-use lib::marker::PhantomData;
+use crate::lib::marker::PhantomData;
 
-use error::FastResult::*;
-use error::{ConsumedResult, Info, ParseError, StreamError, Tracked};
-use parser::ParseMode;
-use stream::{
+use crate::error::ParseResult::*;
+use crate::error::{Info, ParseError, ParseResult, ResultExt, StreamError, Tracked};
+use crate::parser::ParseMode;
+use crate::stream::{
     uncons_range, uncons_while, uncons_while1, wrap_stream_error, FullRangeStream,
-    Range as StreamRange, RangeStream, RangeStreamOnce, Resetable, StreamOnce,
+    Range as StreamRange, RangeStream, RangeStreamOnce, ResetStream, StreamOnce,
 };
-use Parser;
+use crate::Parser;
 
 pub struct Range<I>(I::Range)
 where
@@ -23,15 +23,18 @@ where
 impl<I> Parser for Range<I>
 where
     I: RangeStream,
-    I::Range: PartialEq + ::stream::Range,
+    I::Range: PartialEq + crate::stream::Range,
 {
     type Input = I;
     type Output = I::Range;
     type PartialState = ();
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
-        use stream::Range;
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
+        use crate::stream::Range;
         let position = input.position();
         match input.uncons_range(self.0.len()) {
             Ok(other) => {
@@ -75,7 +78,7 @@ parser! {
     where [
         P: Parser,
         P::Input: RangeStream,
-        <P::Input as StreamOnce>::Range: ::stream::Range,
+        <P::Input as StreamOnce>::Range: crate::stream::Range,
     ]
     {
         recognize_with_value(parser).map(|(range, _)| range)
@@ -90,11 +93,11 @@ fn parse_partial_range<M, F, G, S, I>(
     state: S,
     first: F,
     resume: G,
-) -> ConsumedResult<I::Range, I>
+) -> ParseResult<I::Range, <I as StreamOnce>::Error>
 where
     M: ParseMode,
-    F: FnOnce(&mut I, S) -> ConsumedResult<I::Range, I>,
-    G: FnOnce(&mut I, S) -> ConsumedResult<I::Range, I>,
+    F: FnOnce(&mut I, S) -> ParseResult<I::Range, <I as StreamOnce>::Error>,
+    G: FnOnce(&mut I, S) -> ParseResult<I::Range, <I as StreamOnce>::Error>,
     I: RangeStream,
 {
     let before = input.checkpoint();
@@ -105,7 +108,7 @@ where
         let result = first(input, state);
         if let ConsumedErr(_) = result {
             *distance_state = input.distance(&before);
-            input.reset(before);
+            ctry!(input.reset(before).consumed());
         }
         result
     } else {
@@ -118,13 +121,13 @@ where
             EmptyErr(err) => return EmptyErr(err),
             ConsumedErr(err) => {
                 *distance_state = input.distance(&before);
-                input.reset(before);
+                ctry!(input.reset(before).consumed());
                 return ConsumedErr(err);
             }
         }
 
         let distance = input.distance(&before);
-        input.reset(before);
+        ctry!(input.reset(before).consumed());
         take(distance).parse_lazy(input).map(|range| {
             *distance_state = 0;
             range
@@ -139,7 +142,7 @@ impl<P> Parser for RecognizeWithValue<P>
 where
     P: Parser,
     P::Input: RangeStream,
-    <P::Input as StreamOnce>::Range: ::stream::Range,
+    <P::Input as StreamOnce>::Range: crate::stream::Range,
 {
     type Input = P::Input;
     type Output = (<P::Input as StreamOnce>::Range, P::Output);
@@ -152,7 +155,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -170,13 +173,13 @@ where
             EmptyErr(err) => return EmptyErr(err),
             ConsumedErr(err) => {
                 *distance_state = input.distance(&before);
-                input.reset(before);
+                ctry!(input.reset(before).consumed());
                 return ConsumedErr(err);
             }
         };
 
         let distance = input.distance(&before);
-        input.reset(before);
+        ctry!(input.reset(before).consumed());
         take(distance).parse_lazy(input).map(|range| {
             *distance_state = 0;
             (range, value)
@@ -215,7 +218,7 @@ pub fn recognize_with_value<P>(parser: P) -> RecognizeWithValue<P>
 where
     P: Parser,
     P::Input: RangeStream,
-    <P::Input as StreamOnce>::Range: ::stream::Range,
+    <P::Input as StreamOnce>::Range: crate::stream::Range,
 {
     RecognizeWithValue(parser)
 }
@@ -257,7 +260,10 @@ where
     type PartialState = ();
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
         uncons_range(input, self.0)
     }
 }
@@ -294,7 +300,7 @@ pub struct TakeWhile<I, F>(F, PhantomData<fn(I) -> I>);
 impl<I, F> Parser for TakeWhile<I, F>
 where
     I: RangeStream,
-    I::Range: ::stream::Range,
+    I::Range: crate::stream::Range,
     F: FnMut(I::Item) -> bool,
 {
     type Input = I;
@@ -308,7 +314,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -344,7 +350,7 @@ where
 pub fn take_while<I, F>(f: F) -> TakeWhile<I, F>
 where
     I: RangeStream,
-    I::Range: ::stream::Range,
+    I::Range: crate::stream::Range,
     F: FnMut(I::Item) -> bool,
 {
     TakeWhile(f, PhantomData)
@@ -354,7 +360,7 @@ pub struct TakeWhile1<I, F>(F, PhantomData<fn(I) -> I>);
 impl<I, F> Parser for TakeWhile1<I, F>
 where
     I: RangeStream,
-    I::Range: ::stream::Range,
+    I::Range: crate::stream::Range,
     F: FnMut(I::Item) -> bool,
 {
     type Input = I;
@@ -368,7 +374,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -404,7 +410,7 @@ where
 pub fn take_while1<I, F>(f: F) -> TakeWhile1<I, F>
 where
     I: RangeStream,
-    I::Range: ::stream::Range,
+    I::Range: crate::stream::Range,
     F: FnMut(I::Item) -> bool,
 {
     TakeWhile1(f, PhantomData)
@@ -416,7 +422,7 @@ where
 impl<I> Parser for TakeUntilRange<I>
 where
     I: RangeStream,
-    I::Range: PartialEq + ::stream::Range,
+    I::Range: PartialEq + crate::stream::Range,
 {
     type Input = I;
     type Output = I::Range;
@@ -427,8 +433,8 @@ where
         &mut self,
         input: &mut Self::Input,
         to_consume: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input> {
-        use stream::Range;
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
+        use crate::stream::Range;
 
         let len = self.0.len();
         let before = input.checkpoint();
@@ -444,7 +450,7 @@ where
                 Ok(xs) => {
                     if xs == self.0 {
                         let distance = input.distance(&before) - len;
-                        input.reset(before);
+                        ctry!(input.reset(before).consumed());
 
                         if let Ok(consumed) = input.uncons_range(distance) {
                             if distance == 0 {
@@ -460,7 +466,7 @@ where
                         unreachable!();
                     } else {
                         // Reset the stream back to where it was when we entered the top of the loop
-                        input.reset(look_ahead_input);
+                        ctry!(input.reset(look_ahead_input).consumed());
 
                         // Advance the stream by one item
                         if input.uncons().is_err() {
@@ -480,14 +486,14 @@ where
                     }
 
                     // Reset the stream back to where it was when we entered the top of the loop
-                    input.reset(look_ahead_input);
+                    ctry!(input.reset(look_ahead_input).consumed());
 
                     // See if we can advance anyway
                     if input.uncons().is_err() {
                         let (first_error, first_error_distance) = first_stream_error.unwrap();
 
                         // Reset the stream
-                        input.reset(before);
+                        ctry!(input.reset(before).consumed());
                         *to_consume = first_error_distance;
 
                         // Return the original error if uncons failed
@@ -554,7 +560,7 @@ where
     F: FnMut(I::Range) -> R,
     R: Into<TakeRange>,
     I: RangeStream + FullRangeStream,
-    I::Range: ::stream::Range,
+    I::Range: crate::stream::Range,
 {
     type Input = I;
     type Output = I::Range;
@@ -567,7 +573,7 @@ where
         mode: M,
         input: &mut Self::Input,
         offset: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -581,7 +587,7 @@ where
 
         match (self.searcher)(input.range()).into() {
             TakeRange::Found(i) => {
-                input.reset(checkpoint);
+                ctry!(input.reset(checkpoint).consumed());
                 let result = uncons_range(input, *offset + i);
                 if result.is_ok() {
                     *offset = 0;
@@ -594,7 +600,7 @@ where
                 let range = input.range();
                 let _ = input.uncons_range(range.len());
                 let position = input.position();
-                input.reset(checkpoint);
+                ctry!(input.reset(checkpoint).consumed());
 
                 let err = I::Error::from_error(position, StreamError::end_of_input());
                 if !input.is_partial() && range.is_empty() {
@@ -621,7 +627,7 @@ where
     F: FnMut(I::Range) -> R,
     R: Into<TakeRange>,
     I: FullRangeStream,
-    I::Range: ::stream::Range,
+    I::Range: crate::stream::Range,
 {
     TakeFn {
         searcher,
@@ -632,7 +638,7 @@ where
 #[cfg(test)]
 mod tests {
     use super::*;
-    use Parser;
+    use crate::Parser;
 
     #[test]
     fn take_while_test() {
diff --git a/src/parser/regex.rs b/src/parser/regex.rs
index 092cce6b..7081c631 100644
--- a/src/parser/regex.rs
+++ b/src/parser/regex.rs
@@ -37,11 +37,11 @@
 use std::iter::FromIterator;
 use std::marker::PhantomData;
 
-use error::FastResult::*;
-use error::{ConsumedResult, ParseError, StreamError, Tracked};
-use parser::range::take;
-use stream::{FullRangeStream, StreamOnce};
-use Parser;
+use crate::error::ParseResult::*;
+use crate::error::{ParseError, ParseResult, StreamError, Tracked};
+use crate::parser::range::take;
+use crate::stream::{FullRangeStream, StreamOnce};
+use crate::Parser;
 
 struct First<T>(Option<T>);
 
@@ -217,109 +217,6 @@ mod regex {
     }
 }
 
-#[cfg(feature = "regex-1")]
-mod regex_1 {
-    pub extern crate combine_regex_1 as regex_1;
-
-    use std::iter::FromIterator;
-
-    pub use self::regex_1::*;
-
-    use super::{find_iter, MatchFind, Regex};
-
-    impl<'t> MatchFind for regex_1::Match<'t> {
-        type Range = &'t str;
-        fn end(&self) -> usize {
-            regex_1::Match::end(self)
-        }
-        fn as_match(&self) -> Self::Range {
-            self.as_str()
-        }
-    }
-
-    impl<'t> MatchFind for regex_1::bytes::Match<'t> {
-        type Range = &'t [u8];
-        fn end(&self) -> usize {
-            regex_1::bytes::Match::end(self)
-        }
-        fn as_match(&self) -> Self::Range {
-            self.as_bytes()
-        }
-    }
-
-    impl<'a> Regex<&'a str> for regex_1::Regex {
-        fn is_match(&self, range: &'a str) -> bool {
-            regex_1::Regex::is_match(self, range)
-        }
-        fn find_iter<F>(&self, range: &'a str) -> (usize, F)
-        where
-            F: FromIterator<&'a str>,
-        {
-            find_iter(regex_1::Regex::find_iter(self, range))
-        }
-        fn captures<F, G>(&self, range: &'a str) -> (usize, G)
-        where
-            F: FromIterator<&'a str>,
-            G: FromIterator<F>,
-        {
-            let mut end = 0;
-            let value = regex_1::Regex::captures_iter(self, range)
-                .map(|captures| {
-                    let mut captures_iter = captures.iter();
-                    // The first group is the match on the entire regex
-                    let first_match = captures_iter.next().unwrap().unwrap();
-                    end = first_match.end();
-                    Some(Some(first_match))
-                        .into_iter()
-                        .chain(captures_iter)
-                        .filter_map(|match_| match_.map(|m| m.as_match()))
-                        .collect()
-                })
-                .collect();
-            (end, value)
-        }
-        fn as_str(&self) -> &str {
-            regex_1::Regex::as_str(self)
-        }
-    }
-
-    impl<'a> Regex<&'a [u8]> for regex_1::bytes::Regex {
-        fn is_match(&self, range: &'a [u8]) -> bool {
-            regex_1::bytes::Regex::is_match(self, range)
-        }
-        fn find_iter<F>(&self, range: &'a [u8]) -> (usize, F)
-        where
-            F: FromIterator<&'a [u8]>,
-        {
-            find_iter(regex_1::bytes::Regex::find_iter(self, range))
-        }
-        fn captures<F, G>(&self, range: &'a [u8]) -> (usize, G)
-        where
-            F: FromIterator<&'a [u8]>,
-            G: FromIterator<F>,
-        {
-            let mut end = 0;
-            let value = regex_1::bytes::Regex::captures_iter(self, range)
-                .map(|captures| {
-                    let mut captures_iter = captures.iter();
-                    // The first group is the match on the entire regex
-                    let first_match = captures_iter.next().unwrap().unwrap();
-                    end = first_match.end();
-                    Some(Some(first_match))
-                        .into_iter()
-                        .chain(captures_iter)
-                        .filter_map(|match_| match_.map(|m| m.as_match()))
-                        .collect()
-                })
-                .collect();
-            (end, value)
-        }
-        fn as_str(&self) -> &str {
-            regex_1::bytes::Regex::as_str(self)
-        }
-    }
-}
-
 pub struct Match<R, I>(R, PhantomData<I>);
 
 impl<'a, R, I> Parser for Match<R, I>
@@ -332,7 +229,10 @@ where
     type PartialState = ();
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
         if self.0.is_match(input.range()) {
             EmptyOk(input.range())
         } else {
@@ -380,14 +280,17 @@ impl<'a, R, I> Parser for Find<R, I>
 where
     R: Regex<I::Range>,
     I: FullRangeStream,
-    I::Range: ::stream::Range,
+    I::Range: crate::stream::Range,
 {
     type Input = I;
     type Output = I::Range;
     type PartialState = ();
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
         let (end, First(value)) = self.0.find_iter(input.range());
         match value {
             Some(value) => take(end).parse_lazy(input).map(|_| value),
@@ -427,7 +330,7 @@ pub fn find<R, I>(regex: R) -> Find<R, I>
 where
     R: Regex<I::Range>,
     I: FullRangeStream,
-    I::Range: ::stream::Range,
+    I::Range: crate::stream::Range,
 {
     Find(regex, PhantomData)
 }
@@ -440,14 +343,17 @@ where
     F: FromIterator<I::Range>,
     R: Regex<I::Range>,
     I: FullRangeStream,
-    I::Range: ::stream::Range,
+    I::Range: crate::stream::Range,
 {
     type Input = I;
     type Output = F;
     type PartialState = ();
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
         let (end, value) = self.0.find_iter(input.range());
         take(end).parse_lazy(input).map(|_| value)
     }
@@ -483,7 +389,7 @@ where
     F: FromIterator<I::Range>,
     R: Regex<I::Range>,
     I: FullRangeStream,
-    I::Range: ::stream::Range,
+    I::Range: crate::stream::Range,
 {
     FindMany(regex, PhantomData)
 }
@@ -496,14 +402,17 @@ where
     F: FromIterator<I::Range>,
     R: Regex<I::Range>,
     I: FullRangeStream,
-    I::Range: ::stream::Range,
+    I::Range: crate::stream::Range,
 {
     type Input = I;
     type Output = F;
     type PartialState = ();
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
         let (end, First(value)) = self.0.captures(input.range());
         match value {
             Some(value) => take(end).parse_lazy(input).map(|_| value),
@@ -549,7 +458,7 @@ where
     F: FromIterator<I::Range>,
     R: Regex<I::Range>,
     I: FullRangeStream,
-    I::Range: ::stream::Range,
+    I::Range: crate::stream::Range,
 {
     Captures(regex, PhantomData)
 }
@@ -563,14 +472,17 @@ where
     G: FromIterator<F>,
     R: Regex<I::Range>,
     I: FullRangeStream,
-    I::Range: ::stream::Range,
+    I::Range: crate::stream::Range,
 {
     type Input = I;
     type Output = G;
     type PartialState = ();
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
         let (end, value) = self.0.captures(input.range());
         take(end).parse_lazy(input).map(|_| value)
     }
@@ -616,17 +528,17 @@ where
     G: FromIterator<F>,
     R: Regex<I::Range>,
     I: FullRangeStream,
-    I::Range: ::stream::Range,
+    I::Range: crate::stream::Range,
 {
     CapturesMany(regex, PhantomData)
 }
 
-#[cfg(all(test, feature = "regex-1"))]
+#[cfg(test)]
 mod tests {
+    use regex::Regex;
 
-    use parser::regex::find;
-    use parser::regex::regex_1::regex_1::Regex;
-    use Parser;
+    use crate::parser::regex::find;
+    use crate::Parser;
 
     #[test]
     fn test() {
diff --git a/src/parser/repeat.rs b/src/parser/repeat.rs
index 7636e1a5..4cbca38e 100644
--- a/src/parser/repeat.rs
+++ b/src/parser/repeat.rs
@@ -1,20 +1,22 @@
 //! Combinators which take one or more parsers and applies them repeatedly.
 
-use lib::borrow::BorrowMut;
-use lib::marker::PhantomData;
-use lib::mem;
+use crate::lib::borrow::BorrowMut;
+use crate::lib::marker::PhantomData;
+use crate::lib::mem;
+
+use crate::combinator::{ignore, optional, parser, value, FnParser, Ignore, Optional, Value};
+use crate::error::{
+    Consumed, ParseError, ParseResult, ResultExt, StdParseResult, StreamError, Tracked,
+};
+use crate::parser::choice::Or;
+use crate::parser::sequence::With;
+use crate::parser::ParseMode;
+use crate::stream::{uncons, Positioned, ResetStream, Stream, StreamOnce};
+use crate::{ErrorOffset, Parser};
+
+use crate::error::ParseResult::*;
 
-use combinator::{ignore, optional, parser, value, FnParser, Ignore, Optional, Value};
-use error::{Consumed, ConsumedResult, ParseError, ParseResult, StreamError, Tracked};
-use parser::choice::Or;
-use parser::sequence::With;
-use parser::ParseMode;
-use stream::{uncons, Positioned, Resetable, Stream, StreamOnce};
-use {ErrorOffset, Parser};
-
-use error::FastResult::*;
-
-parser!{
+parser! {
 #[derive(Copy, Clone)]
 pub struct Count;
 
@@ -66,7 +68,7 @@ parser! {
         P: Parser
     ]
     {
-        ::combinator::count::<Sink, _>(*count, parser.map(|_| ())).with(value(()))
+        crate::combinator::count::<Sink, _>(*count, parser.map(|_| ())).with(value(()))
     }
 }
 
@@ -94,7 +96,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -188,7 +190,7 @@ parser! {
         P: Parser
     ]
     {
-        ::combinator::count_min_max::<Sink, _>(*min, *max, parser.map(|_| ())).with(value(()))
+        crate::combinator::count_min_max::<Sink, _>(*min, *max, parser.map(|_| ())).with(value(()))
     }
 }
 
@@ -224,13 +226,13 @@ where
             mode,
         }
     }
-    /// Converts the iterator to a `ParseResult`, returning `Ok` if the parsing so far has be done
+    /// Converts the iterator to a `StdParseResult`, 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> {
+    pub fn into_result<O>(self, value: O) -> StdParseResult<O, P::Input> {
         self.into_result_(value).into()
     }
 
-    fn into_result_<O>(self, value: O) -> ConsumedResult<O, P::Input> {
+    fn into_result_<O>(self, value: O) -> ParseResult<O, <P::Input as StreamOnce>::Error> {
         match self.state {
             State::Ok | State::EmptyErr => {
                 if self.consumed {
@@ -243,7 +245,7 @@ where
         }
     }
 
-    fn into_result_fast<O>(self, value: &mut O) -> ConsumedResult<O, P::Input>
+    fn into_result_fast<O>(self, value: &mut O) -> ParseResult<O, <P::Input as StreamOnce>::Error>
     where
         O: Default,
     {
@@ -267,7 +269,7 @@ where
             <P::Input as StreamOnce>::Range,
             <P::Input as StreamOnce>::Position,
         >>::StreamError,
-    ) -> ConsumedResult<T, P::Input> {
+    ) -> ParseResult<T, <P::Input as StreamOnce>::Error> {
         match self.state {
             State::Ok | State::EmptyErr => {
                 let err = <P::Input as StreamOnce>::Error::from_error(self.input.position(), err);
@@ -308,8 +310,10 @@ where
                 Some(v)
             }
             EmptyErr(_) => {
-                self.input.reset(before);
-                self.state = State::EmptyErr;
+                self.state = match self.input.reset(before) {
+                    Err(err) => State::ConsumedErr(err),
+                    Ok(_) => State::EmptyErr,
+                };
                 None
             }
             ConsumedErr(e) => {
@@ -339,7 +343,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -414,7 +418,7 @@ where
         mut mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<F, P::Input>
+    ) -> ParseResult<F, <P::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -573,7 +577,7 @@ where
     type Output = F;
     type PartialState = <Or<
         SepBy1<F, P, S>,
-        FnParser<P::Input, fn(&mut Self::Input) -> ParseResult<F, Self::Input>>,
+        FnParser<P::Input, fn(&mut Self::Input) -> StdParseResult<F, Self::Input>>,
     > as Parser>::PartialState;
 
     parse_mode!();
@@ -583,7 +587,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<F, P::Input>
+    ) -> ParseResult<F, <P::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -662,7 +666,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -762,7 +766,7 @@ where
     type Output = F;
     type PartialState = <Or<
         SepEndBy1<F, P, S>,
-        FnParser<P::Input, fn(&mut Self::Input) -> ParseResult<F, Self::Input>>,
+        FnParser<P::Input, fn(&mut Self::Input) -> StdParseResult<F, Self::Input>>,
     > as Parser>::PartialState;
 
     parse_mode!();
@@ -772,7 +776,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -847,7 +851,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -949,7 +953,7 @@ where
         mut mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -980,7 +984,7 @@ where
                     return ConsumedErr(err.error);
                 }
                 Err(Consumed::Empty(_)) => {
-                    input.reset(before);
+                    ctry!(input.reset(before).consumed());
                     break;
                 }
             }
@@ -1030,8 +1034,11 @@ where
     type Output = P::Output;
     type PartialState = ();
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<P::Output, I> {
-        // FIXME FastResult
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<P::Output, <I as StreamOnce>::Error> {
+        // FIXME ParseResult
         let (mut l, mut consumed) = ctry!(self.0.parse_lazy(input));
         loop {
             let before = input.checkpoint();
@@ -1042,7 +1049,7 @@ where
                 }
                 Err(Consumed::Consumed(err)) => return ConsumedErr(err.error),
                 Err(Consumed::Empty(_)) => {
-                    input.reset(before);
+                    ctry!(input.reset(before).consumed());
                     break;
                 }
             };
@@ -1054,7 +1061,7 @@ where
                 }
                 Err(Consumed::Consumed(err)) => return ConsumedErr(err.error),
                 Err(Consumed::Empty(_)) => {
-                    input.reset(before);
+                    ctry!(input.reset(before).consumed());
                     break;
                 }
             }
@@ -1111,7 +1118,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -1122,19 +1129,19 @@ where
             let before = input.checkpoint();
             match self.end.parse_mode(mode, input, end_state).into() {
                 Ok((_, rest)) => {
-                    input.reset(before);
+                    ctry!(input.reset(before).consumed());
                     return match consumed.merge(rest) {
                         Consumed::Consumed(()) => ConsumedOk(mem::replace(output, F::default())),
                         Consumed::Empty(()) => EmptyOk(mem::replace(output, F::default())),
                     };
                 }
                 Err(Consumed::Empty(_)) => {
-                    input.reset(before);
+                    ctry!(input.reset(before).consumed());
                     output.extend(Some(ctry!(uncons(input)).0));
                     consumed = Consumed::Consumed(());
                 }
                 Err(Consumed::Consumed(e)) => {
-                    input.reset(before);
+                    ctry!(input.reset(before).consumed());
                     return ConsumedErr(e.error);
                 }
             };
@@ -1234,7 +1241,10 @@ where
     type Output = ();
     type PartialState = EscapedState<P::PartialState, Q::PartialState>;
 
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
         let mut consumed = Consumed::Empty(());
         loop {
             match self.parser.parse_lazy(input) {
@@ -1246,7 +1256,7 @@ where
                     let checkpoint = input.checkpoint();
                     match uncons(input) {
                         ConsumedOk(ref c) | EmptyOk(ref c) if *c == self.escape => {
-                            match self.escape_parser.parse_stream_consumed(input) {
+                            match self.escape_parser.parse_stream(input) {
                                 EmptyOk(_) => {}
                                 ConsumedOk(_) => {
                                     consumed = Consumed::Consumed(());
@@ -1261,7 +1271,7 @@ where
                             return ConsumedErr(err);
                         }
                         _ => {
-                            input.reset(checkpoint);
+                            ctry!(input.reset(checkpoint).consumed());
                             return if consumed.is_empty() {
                                 EmptyOk(())
                             } else {
@@ -1276,7 +1286,7 @@ where
     }
 
     fn add_error(&mut self, errors: &mut Tracked<<Self::Input as StreamOnce>::Error>) {
-        use error::Info;
+        use crate::error::Info;
         self.parser.add_error(errors);
 
         errors.error.add_expected(Info::Token(self.escape.clone()));
diff --git a/src/parser/sequence.rs b/src/parser/sequence.rs
index 46548cc0..6adea069 100644
--- a/src/parser/sequence.rs
+++ b/src/parser/sequence.rs
@@ -1,11 +1,11 @@
 //! Combinators which take multiple parsers and applies them one after another.
-use lib::marker::PhantomData;
+use crate::lib::marker::PhantomData;
 
-use combinator::{ignore, Ignore, Map};
-use error::FastResult::*;
-use error::{ConsumedResult, ParseError, StreamError, Tracked};
-use parser::ParseMode;
-use {ErrorOffset, Parser, Stream, StreamOnce};
+use crate::combinator::{ignore, Ignore, Map};
+use crate::error::ParseResult::*;
+use crate::error::{ParseError, ParseResult, StreamError, Tracked};
+use crate::parser::ParseMode;
+use crate::{ErrorOffset, Parser, Stream, StreamOnce};
 
 macro_rules! dispatch_on {
     ($i: expr, $f: expr;) => {
@@ -87,7 +87,7 @@ macro_rules! tuple_parser {
                 first_empty_parser: usize,
                 offset: u8,
                 $h: &mut $h $(, $id : &mut $id )*
-            ) -> ConsumedResult<($h::Output, $($id::Output),*), Input>
+            ) -> ParseResult<($h::Output, $($id::Output),*), <Input as StreamOnce>::Error>
             {
                 let inner_offset = err.offset;
                 err.offset = ErrorOffset(offset);
@@ -117,7 +117,7 @@ macro_rules! tuple_parser {
                         true
                     }; $h $(, $id)*);
                     ConsumedErr(err.error)
-            } else {
+                } else {
                     EmptyErr(err)
                 }
             }
@@ -144,7 +144,7 @@ macro_rules! tuple_parser {
                 mut mode: M,
                 input: &mut Self::Input,
                 state: &mut Self::PartialState,
-            ) -> ConsumedResult<Self::Output, Self::Input>
+            ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
             where
                 M: ParseMode,
             {
@@ -192,7 +192,13 @@ macro_rules! tuple_parser {
                                 x
                             }
                             EmptyErr(err) => {
-                                input.reset(before);
+                                if let Err(err) = input.reset(before) {
+                                    return if first_empty_parser != 0 {
+                                        ConsumedErr(err.into())
+                                    } else {
+                                        EmptyErr(err.into())
+                                    };
+                                }
                                 return add_errors!(err, state.offset)
                             }
                             ConsumedErr(err) => return ConsumedErr(err),
@@ -418,7 +424,10 @@ where
     type PartialState = <(Ignore<P1>, P2) as Parser>::PartialState;
 
     #[inline]
-    fn parse_lazy(&mut self, input: &mut Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
+    fn parse_lazy(
+        &mut self,
+        input: &mut Self::Input,
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error> {
         self.0.parse_lazy(input).map(|(_, b)| b)
     }
 
@@ -429,7 +438,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -473,7 +482,7 @@ where
         mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -544,7 +553,7 @@ where
         mut mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -635,7 +644,7 @@ where
         mut mode: M,
         input: &mut Self::Input,
         state: &mut Self::PartialState,
-    ) -> ConsumedResult<Self::Output, Self::Input>
+    ) -> ParseResult<Self::Output, <Self::Input as StreamOnce>::Error>
     where
         M: ParseMode,
     {
@@ -707,7 +716,7 @@ where
 #[cfg(test)]
 mod tests {
     use super::*;
-    use parser::item::any;
+    use crate::parser::item::any;
 
     #[test]
     fn sequence_single_parser() {
diff --git a/src/stream/buffered.rs b/src/stream/buffered.rs
index 1ec906e5..acadb376 100644
--- a/src/stream/buffered.rs
+++ b/src/stream/buffered.rs
@@ -1,29 +1,29 @@
 use std::collections::VecDeque;
 
-use error::StreamError;
-use stream::{Positioned, Resetable, StreamErrorFor, StreamOnce};
+use crate::error::StreamError;
+use crate::stream::{ParseError, Positioned, ResetStream, StreamErrorFor, StreamOnce};
 
 /// `Stream` which buffers items from an instance of `StreamOnce` into a ring buffer.
-/// Instances of `StreamOnce` which is not able to implement `Resetable` (such as `ReadStream`) may
-/// use this as a way to implement `Resetable` and become a full `Stream` instance.
+/// Instances of `StreamOnce` which is not able to implement `ResetStream` (such as `ReadStream`) may
+/// use this as a way to implement `ResetStream` and become a full `Stream` instance.
 ///
 /// The drawback is that the buffer only stores a limited number of items which limits how many
-/// tokens that can be reset and replayed. If a `BufferedStream` is reset past this limit an error
+/// tokens that can be reset and replayed. If a `buffered::Stream` is reset past this limit an error
 /// will be returned when `uncons` is next called.
 ///
 /// NOTE: If this stream is used in conjunction with an error enhancing stream such as
-/// `easy::Stream` (also via the `easy_parser` method) it is recommended that the `BufferedStream`
+/// `easy::Stream` (also via the `easy_parser` method) it is recommended that the `buffered::Stream`
 /// instance wraps the `easy::Stream` instance instead of the other way around.
 ///
 /// ```ignore
 /// // DO
-/// BufferedStream::new(easy::Stream(..), ..)
+/// buffered::Stream::new(easy::Stream(..), ..)
 /// // DON'T
-/// easy::Stream(BufferedStream::new(.., ..))
-/// parser.easy_parse(BufferedStream::new(..));
+/// easy::Stream(buffered::Stream::new(.., ..))
+/// parser.easy_parse(buffered::Stream::new(..));
 /// ```
 #[derive(Debug, PartialEq)]
-pub struct BufferedStream<I>
+pub struct Stream<I>
 where
     I: StreamOnce + Positioned,
 {
@@ -33,29 +33,40 @@ where
     buffer: VecDeque<(I::Item, I::Position)>,
 }
 
-impl<I> Resetable for BufferedStream<I>
+impl<I> ResetStream for Stream<I>
 where
     I: Positioned,
 {
     type Checkpoint = usize;
+
     fn checkpoint(&self) -> Self::Checkpoint {
         self.offset
     }
-    fn reset(&mut self, checkpoint: Self::Checkpoint) {
-        self.offset = checkpoint;
+
+    fn reset(&mut self, checkpoint: Self::Checkpoint) -> Result<(), Self::Error> {
+        if checkpoint < self.buffer_offset - self.buffer.len() {
+            // We have backtracked to far
+            Err(Self::Error::from_error(
+                self.position(),
+                StreamErrorFor::<Self>::message_static_message("Backtracked to far".into()),
+            ))
+        } else {
+            self.offset = checkpoint;
+            Ok(())
+        }
     }
 }
 
-impl<I> BufferedStream<I>
+impl<I> Stream<I>
 where
     I: StreamOnce + Positioned,
     I::Position: Clone,
     I::Item: Clone,
 {
-    /// Constructs a new `BufferedStream` from a `StreamOnce` instance with a `lookahead`
+    /// Constructs a new `Stream` from a `StreamOnce` instance with a `lookahead`
     /// number of elements that can be stored in the buffer.
-    pub fn new(iter: I, lookahead: usize) -> BufferedStream<I> {
-        BufferedStream {
+    pub fn new(iter: I, lookahead: usize) -> Stream<I> {
+        Stream {
             offset: 0,
             iter: iter,
             buffer_offset: 0,
@@ -64,7 +75,7 @@ where
     }
 }
 
-impl<I> Positioned for BufferedStream<I>
+impl<I> Positioned for Stream<I>
 where
     I: StreamOnce + Positioned,
 {
@@ -86,10 +97,9 @@ where
     }
 }
 
-impl<I> StreamOnce for BufferedStream<I>
+impl<I> StreamOnce for Stream<I>
 where
     I: StreamOnce + Positioned,
-    I::Item: Clone + PartialEq,
 {
     type Item = I::Item;
     type Range = I::Range;
@@ -100,7 +110,7 @@ where
     fn uncons(&mut self) -> Result<I::Item, StreamErrorFor<Self>> {
         if self.offset >= self.buffer_offset {
             let position = self.iter.position();
-            let item = try!(self.iter.uncons());
+            let item = r#try!(self.iter.uncons());
             self.buffer_offset += 1;
             // We want the VecDeque to only keep the last .capacity() elements so we need to remove
             // an element if it gets to large
diff --git a/src/stream/easy.rs b/src/stream/easy.rs
index afed40d4..418e8a84 100644
--- a/src/stream/easy.rs
+++ b/src/stream/easy.rs
@@ -26,7 +26,9 @@
 //!                 I::Range,
 //!                 I::Position,
 //!                 StreamError = easy::Error<I::Item, I::Range>
-//!             >
+//!             >,
+//!             I::Item: PartialEq,
+//!             I::Range: PartialEq,
 //!         ]
 //!         {
 //!             many1(letter()).and_then(|word: String| {
@@ -82,9 +84,9 @@
 use std::error::Error as StdError;
 use std::fmt;
 
-use error::{FastResult, Info as PrimitiveInfo, StreamError, Tracked};
-use stream::{
-    FullRangeStream, Positioned, RangeStream, RangeStreamOnce, Resetable, StreamErrorFor,
+use crate::error::{ParseResult, Info as PrimitiveInfo, StreamError, Tracked};
+use crate::stream::{
+    FullRangeStream, Positioned, RangeStream, RangeStreamOnce, ResetStream, StreamErrorFor,
     StreamOnce,
 };
 
@@ -265,6 +267,10 @@ where
         Error::Message(Info::Range(token))
     }
 
+    fn is_unexpected_end_of_input(&self) -> bool {
+        *self == Self::end_of_input()
+    }
+
     #[inline]
     fn other<E>(err: E) -> Self
     where
@@ -302,7 +308,7 @@ where
     }
 }
 
-impl<Item, Range, Position> ::error::ParseError<Item, Range, Position> for Error<Item, Range>
+impl<Item, Range, Position> crate::error::ParseError<Item, Range, Position> for Error<Item, Range>
 where
     Item: PartialEq,
     Range: PartialEq,
@@ -342,13 +348,13 @@ where
     #[inline]
     fn into_other<T>(self) -> T
     where
-        T: ::error::ParseError<Item, Range, Position>,
+        T: crate::error::ParseError<Item, Range, Position>,
     {
         T::from_error(Position::default(), StreamError::into_other(self))
     }
 }
 
-impl<Item, Range, Position> ::error::ParseError<Item, Range, Position>
+impl<Item, Range, Position> crate::error::ParseError<Item, Range, Position>
     for Errors<Item, Range, Position>
 where
     Item: PartialEq,
@@ -412,13 +418,15 @@ where
     }
 
     fn is_unexpected_end_of_input(&self) -> bool {
-        self.errors.iter().any(|err| *err == Error::end_of_input())
+        self.errors
+            .iter()
+            .any(StreamError::is_unexpected_end_of_input)
     }
 
     #[inline]
     fn into_other<T>(mut self) -> T
     where
-        T: ::error::ParseError<Item, Range, Position>,
+        T: crate::error::ParseError<Item, Range, Position>,
     {
         match self.errors.pop() {
             Some(err) => T::from_error(self.position, StreamError::into_other(err)),
@@ -516,7 +524,7 @@ impl<T, R> Error<T, R> {
             _ => false,
         });
         for error in unexpected {
-            try!(writeln!(f, "{}", error));
+            r#try!(writeln!(f, "{}", error));
         }
 
         // Then we print out all the things that were expected in a comma separated list
@@ -535,10 +543,10 @@ impl<T, R> Error<T, R> {
                 // Last expected message to be written
                 _ => " or",
             };
-            try!(write!(f, "{} `{}`", s, message));
+            r#try!(write!(f, "{} `{}`", s, message));
         }
         if expected_count != 0 {
-            try!(writeln!(f, ""));
+            r#try!(writeln!(f, ""));
         }
         // If there are any generic messages we print them out last
         let messages = errors.iter().filter(|e| match **e {
@@ -546,7 +554,7 @@ impl<T, R> Error<T, R> {
             _ => false,
         });
         for error in messages {
-            try!(writeln!(f, "{}", error));
+            r#try!(writeln!(f, "{}", error));
         }
         Ok(())
     }
@@ -713,7 +721,7 @@ where
     R: fmt::Display,
 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(writeln!(f, "Parse error at {}", self.position));
+        r#try!(writeln!(f, "Parse error at {}", self.position));
         Error::fmt_errors(&self.errors, f)
     }
 }
@@ -732,23 +740,29 @@ impl<T: fmt::Display, R: fmt::Display> fmt::Display for Error<T, R> {
 #[derive(Copy, Clone, Debug)]
 pub struct Stream<S>(pub S);
 
-impl<S> Resetable for Stream<S>
+impl<S> ResetStream for Stream<S>
 where
-    S: Resetable,
+    S: ResetStream + Positioned,
+    S::Item: PartialEq,
+    S::Range: PartialEq,
 {
     type Checkpoint = S::Checkpoint;
 
     fn checkpoint(&self) -> Self::Checkpoint {
         self.0.checkpoint()
     }
-    fn reset(&mut self, checkpoint: Self::Checkpoint) {
-        self.0.reset(checkpoint);
+    fn reset(&mut self, checkpoint: Self::Checkpoint) -> Result<(), Self::Error> {
+        self.0
+            .reset(checkpoint)
+            .map_err(crate::error::ParseError::into_other)
     }
 }
 
 impl<S> StreamOnce for Stream<S>
 where
     S: StreamOnce + Positioned,
+    S::Item: PartialEq,
+    S::Range: PartialEq,
 {
     type Item = S::Item;
     type Range = S::Range;
@@ -768,6 +782,8 @@ where
 impl<S> RangeStreamOnce for Stream<S>
 where
     S: RangeStream,
+    S::Item: PartialEq,
+    S::Range: PartialEq,
 {
     #[inline]
     fn uncons_range(&mut self, size: usize) -> Result<Self::Range, StreamErrorFor<Self>> {
@@ -783,7 +799,7 @@ where
     }
 
     #[inline]
-    fn uncons_while1<F>(&mut self, f: F) -> FastResult<Self::Range, StreamErrorFor<Self>>
+    fn uncons_while1<F>(&mut self, f: F) -> ParseResult<Self::Range, StreamErrorFor<Self>>
     where
         F: FnMut(Self::Item) -> bool,
     {
@@ -799,6 +815,8 @@ where
 impl<S> Positioned for Stream<S>
 where
     S: StreamOnce + Positioned,
+    S::Item: PartialEq,
+    S::Range: PartialEq,
 {
     fn position(&self) -> S::Position {
         self.0.position()
@@ -808,6 +826,8 @@ where
 impl<S> FullRangeStream for Stream<S>
 where
     S: FullRangeStream,
+    S::Item: PartialEq,
+    S::Range: PartialEq,
 {
     fn range(&self) -> Self::Range {
         self.0.range()
diff --git a/src/stream/mod.rs b/src/stream/mod.rs
index 7a644fa4..13357693 100644
--- a/src/stream/mod.rs
+++ b/src/stream/mod.rs
@@ -7,40 +7,41 @@
 //!
 //! In addition to he functionality above, a proper `Stream` usable by a `Parser` must also have a
 //! position (marked by the `Positioned` trait) and must also be resetable (marked by the
-//! `Resetable` trait). The former is used to ensure that errors at different points in the stream
+//! `ResetStream` trait). The former is used to ensure that errors at different points in the stream
 //! aren't combined and the latter is used in parsers such as `or` to try multiple alternative
 //! parses.
 
-use lib::fmt;
-use lib::str::Chars;
+use crate::lib::{cmp::Ordering, fmt, marker::PhantomData, str::Chars};
 
 #[cfg(feature = "std")]
 use std::io::{Bytes, Read};
 
 #[cfg(feature = "std")]
-use stream::easy::Errors;
+use crate::stream::easy::Errors;
 
-use Parser;
+use crate::Parser;
 
-use error::FastResult::*;
-use error::{
-    ConsumedResult, FastResult, ParseError, StreamError, StringStreamError, Tracked,
-    UnexpectedParse,
+use crate::error::ParseResult::*;
+use crate::error::{
+    ParseError, ParseResult, StreamError, StringStreamError, Tracked, UnexpectedParse,
 };
 
 #[doc(hidden)]
 #[macro_export]
 macro_rules! clone_resetable {
     (( $($params: tt)* ) $ty: ty) => {
-        impl<$($params)*> Resetable for $ty
+        impl<$($params)*> ResetStream for $ty
+            where Self: StreamOnce
         {
             type Checkpoint = Self;
 
             fn checkpoint(&self) -> Self {
                 self.clone()
             }
-            fn reset(&mut self, checkpoint: Self) {
+            #[inline(always)]
+            fn reset(&mut self, checkpoint: Self) -> Result<(), Self::Error> {
                 *self = checkpoint;
+                Ok(())
             }
         }
     }
@@ -96,12 +97,12 @@ pub type StreamErrorFor<I> = <<I as StreamOnce>::Error as ParseError<
 /// `StreamOnce` represents a sequence of items that can be extracted one by one.
 pub trait StreamOnce {
     /// The type of items which is yielded from this stream.
-    type Item: Clone + PartialEq;
+    type Item: Clone;
 
     /// The type of a range of items yielded from this stream.
     /// Types which do not a have a way of yielding ranges of items should just use the
     /// `Self::Item` for this type.
-    type Range: Clone + PartialEq;
+    type Range: Clone;
 
     /// Type which represents the position in a stream.
     /// `Ord` is required to allow parsers to determine which of two positions are further ahead.
@@ -120,11 +121,15 @@ pub trait StreamOnce {
     }
 }
 
-pub trait Resetable {
+/// A `StreamOnce` which can create checkpoints which the stream can be reset to
+pub trait ResetStream: StreamOnce {
     type Checkpoint: Clone;
 
+    /// Creates a `Checkpoint` at the current position which can be used to reset the stream
+    /// later to the current position
     fn checkpoint(&self) -> Self::Checkpoint;
-    fn reset(&mut self, checkpoint: Self::Checkpoint);
+    /// Attempts to reset the stream to an earlier position.
+    fn reset(&mut self, checkpoint: Self::Checkpoint) -> Result<(), Self::Error>;
 }
 
 clone_resetable! {('a) &'a str}
@@ -133,17 +138,21 @@ clone_resetable! {('a, T) SliceStream<'a, T> }
 clone_resetable! {(T: Clone) IteratorStream<T>}
 
 /// A stream of tokens which can be duplicated
-pub trait Stream: StreamOnce + Resetable + Positioned {}
+///
+/// This is a trait over types which implement the `StreamOnce`, `ResetStream` and `Positioned`
+/// traits. If you need a custom `Stream` object then implement those traits and `Stream` is
+/// implemented automatically.
+pub trait Stream: StreamOnce + ResetStream + Positioned {}
 
 impl<I> Stream for I
 where
-    I: StreamOnce + Positioned + Resetable,
+    I: StreamOnce + Positioned + ResetStream,
     I::Error: ParseError<I::Item, I::Range, I::Position>,
 {
 }
 
 #[inline]
-pub fn uncons<I>(input: &mut I) -> ConsumedResult<I::Item, I>
+pub fn uncons<I>(input: &mut I) -> ParseResult<I::Item, <I as StreamOnce>::Error>
 where
     I: ?Sized + Stream,
 {
@@ -154,7 +163,7 @@ where
 }
 
 /// A `RangeStream` is an extension of `StreamOnce` which allows for zero copy parsing.
-pub trait RangeStreamOnce: StreamOnce + Resetable {
+pub trait RangeStreamOnce: StreamOnce + ResetStream {
     /// Takes `size` elements from the stream.
     /// Fails if the length of the stream is less than `size`.
     fn uncons_range(&mut self, size: usize) -> Result<Self::Range, StreamErrorFor<Self>>;
@@ -172,7 +181,7 @@ pub trait RangeStreamOnce: StreamOnce + Resetable {
     /// # Note
     ///
     /// This may not return `EmptyOk` as it should uncons at least one item.
-    fn uncons_while1<F>(&mut self, mut f: F) -> FastResult<Self::Range, StreamErrorFor<Self>>
+    fn uncons_while1<F>(&mut self, mut f: F) -> ParseResult<Self::Range, StreamErrorFor<Self>>
     where
         F: FnMut(Self::Item) -> bool,
     {
@@ -220,7 +229,7 @@ pub trait FullRangeStream: RangeStream {
 pub fn wrap_stream_error<T, I>(
     input: &I,
     err: <I::Error as ParseError<I::Item, I::Range, I::Position>>::StreamError,
-) -> ConsumedResult<T, I>
+) -> ParseResult<T, <I as StreamOnce>::Error>
 where
     I: ?Sized + StreamOnce + Positioned,
 {
@@ -233,7 +242,10 @@ where
 }
 
 #[inline]
-pub fn uncons_range<I>(input: &mut I, size: usize) -> ConsumedResult<I::Range, I>
+pub fn uncons_range<I>(
+    input: &mut I,
+    size: usize,
+) -> ParseResult<I::Range, <I as StreamOnce>::Error>
 where
     I: ?Sized + RangeStream,
 {
@@ -255,14 +267,19 @@ where
     I: ?Sized + Stream,
 {
     let before = input.checkpoint();
-    let x = input.uncons() == Err(StreamError::end_of_input());
-    input.reset(before);
-    x
+    let x = input
+        .uncons()
+        .err()
+        .map_or(false, |err| err.is_unexpected_end_of_input());
+    input.reset(before).is_ok() && x
 }
 
 /// Removes items from the input while `predicate` returns `true`.
 #[inline]
-pub fn uncons_while<I, F>(input: &mut I, predicate: F) -> ConsumedResult<I::Range, I>
+pub fn uncons_while<I, F>(
+    input: &mut I,
+    predicate: F,
+) -> ParseResult<I::Range, <I as StreamOnce>::Error>
 where
     F: FnMut(I::Item) -> bool,
     I: ?Sized + RangeStream,
@@ -294,7 +311,10 @@ where
 /// # Note
 ///
 /// This may not return `EmptyOk` as it should uncons at least one item.
-pub fn uncons_while1<I, F>(input: &mut I, predicate: F) -> ConsumedResult<I::Range, I>
+pub fn uncons_while1<I, F>(
+    input: &mut I,
+    predicate: F,
+) -> ParseResult<I::Range, <I as StreamOnce>::Error>
 where
     F: FnMut(I::Item) -> bool,
     I: ?Sized + RangeStream,
@@ -397,7 +417,7 @@ impl<'a> RangeStreamOnce for &'a str {
     }
 
     #[inline]
-    fn uncons_while1<F>(&mut self, mut f: F) -> FastResult<Self::Range, StreamErrorFor<Self>>
+    fn uncons_while1<F>(&mut self, mut f: F) -> ParseResult<Self::Range, StreamErrorFor<Self>>
     where
         F: FnMut(Self::Item) -> bool,
     {
@@ -531,7 +551,7 @@ where
     }
 
     #[inline]
-    fn uncons_while1<F>(&mut self, mut f: F) -> FastResult<Self::Range, StreamErrorFor<Self>>
+    fn uncons_while1<F>(&mut self, mut f: F) -> ParseResult<Self::Range, StreamErrorFor<Self>>
     where
         F: FnMut(Self::Item) -> bool,
     {
@@ -560,14 +580,14 @@ where
 impl<'a> Positioned for &'a str {
     #[inline(always)]
     fn position(&self) -> Self::Position {
-        self.as_bytes().position()
+        PointerOffset::new(self.as_bytes().position().0)
     }
 }
 
 impl<'a> StreamOnce for &'a str {
     type Item = char;
     type Range = &'a str;
-    type Position = PointerOffset;
+    type Position = PointerOffset<str>;
     type Error = StringStreamError;
 
     #[inline]
@@ -589,7 +609,7 @@ where
 {
     #[inline(always)]
     fn position(&self) -> Self::Position {
-        PointerOffset(self.as_ptr() as usize)
+        PointerOffset::new(self.as_ptr() as usize)
     }
 }
 
@@ -599,7 +619,7 @@ where
 {
     type Item = T;
     type Range = &'a [T];
-    type Position = PointerOffset;
+    type Position = PointerOffset<[T]>;
     type Error = UnexpectedParse;
 
     #[inline]
@@ -628,9 +648,9 @@ where
     }
 }
 
-impl<S> Resetable for PartialStream<S>
+impl<S> ResetStream for PartialStream<S>
 where
-    S: Resetable,
+    S: ResetStream,
 {
     type Checkpoint = S::Checkpoint;
 
@@ -640,8 +660,8 @@ where
     }
 
     #[inline(always)]
-    fn reset(&mut self, checkpoint: Self::Checkpoint) {
-        self.0.reset(checkpoint);
+    fn reset(&mut self, checkpoint: Self::Checkpoint) -> Result<(), S::Error> {
+        self.0.reset(checkpoint)
     }
 }
 
@@ -681,7 +701,7 @@ where
         self.0.uncons_while(f)
     }
 
-    fn uncons_while1<F>(&mut self, f: F) -> FastResult<Self::Range, StreamErrorFor<Self>>
+    fn uncons_while1<F>(&mut self, f: F) -> ParseResult<Self::Range, StreamErrorFor<Self>>
     where
         F: FnMut(Self::Item) -> bool,
     {
@@ -720,7 +740,7 @@ where
 {
     #[inline(always)]
     fn position(&self) -> Self::Position {
-        PointerOffset(self.0.as_ptr() as usize)
+        PointerOffset::new(self.0.as_ptr() as usize)
     }
 }
 
@@ -730,7 +750,7 @@ where
 {
     type Item = &'a T;
     type Range = &'a [T];
-    type Position = PointerOffset;
+    type Position = PointerOffset<[T]>;
     type Error = UnexpectedParse;
 
     #[inline]
@@ -811,7 +831,7 @@ where
     }
 
     #[inline]
-    fn uncons_while1<F>(&mut self, mut f: F) -> FastResult<Self::Range, StreamErrorFor<Self>>
+    fn uncons_while1<F>(&mut self, mut f: F) -> ParseResult<Self::Range, StreamErrorFor<Self>>
     where
         F: FnMut(Self::Item) -> bool,
     {
@@ -926,13 +946,13 @@ where
     /// use combine::*;
     /// use combine::parser::byte::*;
     /// use combine::stream::ReadStream;
-    /// use combine::stream::buffered::BufferedStream;
+    /// use combine::stream::buffered;
     /// use combine::stream::state::State;
     /// use std::io::Read;
     ///
     /// # fn main() {
     /// let input: &[u8] = b"123,";
-    /// let stream = BufferedStream::new(State::new(ReadStream::new(input)), 1);
+    /// let stream = buffered::Stream::new(State::new(ReadStream::new(input)), 1);
     /// let result = (many(digit()), byte(b','))
     ///     .parse(stream)
     ///     .map(|t| t.0);
@@ -947,16 +967,68 @@ where
 }
 
 /// Newtype around a pointer offset into a slice stream (`&[T]`/`&str`).
-#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
-pub struct PointerOffset(pub usize);
+pub struct PointerOffset<T: ?Sized>(pub usize, PhantomData<T>);
+
+impl<T: ?Sized> Clone for PointerOffset<T> {
+    fn clone(&self) -> Self {
+        PointerOffset::new(self.0)
+    }
+}
+
+impl<T: ?Sized> Copy for PointerOffset<T> {}
+
+impl<T: ?Sized> Default for PointerOffset<T> {
+    fn default() -> Self {
+        PointerOffset::new(0)
+    }
+}
+
+impl<T: ?Sized> PartialEq for PointerOffset<T> {
+    fn eq(&self, other: &Self) -> bool {
+        self.0 == other.0
+    }
+}
+
+impl<T: ?Sized> Eq for PointerOffset<T> {}
+
+impl<T: ?Sized> PartialOrd for PointerOffset<T> {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        self.0.partial_cmp(&other.0)
+    }
+}
+
+impl<T: ?Sized> Ord for PointerOffset<T> {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.0.cmp(&other.0)
+    }
+}
+
+impl<T> fmt::Debug for PointerOffset<T>
+where
+    T: ?Sized,
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", self)
+    }
+}
 
-impl fmt::Display for PointerOffset {
+impl<T> fmt::Display for PointerOffset<T>
+where
+    T: ?Sized,
+{
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{:?}", self.0 as *const ())
+        write!(f, "PointerOffset({:?})", self.0 as *const ())
     }
 }
 
-impl PointerOffset {
+impl<T> PointerOffset<T>
+where
+    T: ?Sized,
+{
+    pub fn new(offset: usize) -> Self {
+        PointerOffset(offset, PhantomData)
+    }
+
     /// Converts the pointer-based position into an indexed position.
     ///
     /// ```rust
@@ -969,11 +1041,8 @@ impl PointerOffset {
     /// assert_eq!(err.map_position(|p| p.translate_position(text)).position, 0);
     /// # }
     /// ```
-    pub fn translate_position<T>(mut self, initial_string: &T) -> usize
-    where
-        T: ?Sized,
-    {
-        self.0 -= initial_string as *const T as *const () as usize;
+    pub fn translate_position(mut self, initial_slice: &T) -> usize {
+        self.0 -= initial_slice as *const T as *const () as usize;
         self.0
     }
 }
@@ -1034,7 +1103,7 @@ mod tests {
         input.uncons().unwrap();
         assert_eq!(input.distance(&before), 2);
 
-        input.reset(before.clone());
+        input.reset(before.clone()).unwrap();
         assert_eq!(input.distance(&before), 0);
     }
 }
diff --git a/src/stream/state.rs b/src/stream/state.rs
index f704b806..9c8821df 100644
--- a/src/stream/state.rs
+++ b/src/stream/state.rs
@@ -1,13 +1,13 @@
-use lib::fmt;
+use crate::lib::fmt;
 
-use error::{FastResult, ParseError, StreamError};
-use stream::{
-    FullRangeStream, IteratorStream, Positioned, RangeStreamOnce, Resetable, SliceStream,
+use crate::error::{ParseError, ParseResult, StreamError};
+use crate::stream::{
+    FullRangeStream, IteratorStream, Positioned, RangeStreamOnce, ResetStream, SliceStream,
     StreamErrorFor, StreamOnce,
 };
 
 #[cfg(feature = "std")]
-use stream::ReadStream;
+use crate::stream::ReadStream;
 
 /// Trait for tracking the current position of a `Stream`.
 pub trait Positioner<Item> {
@@ -150,8 +150,6 @@ where
 #[derive(Clone, Debug, Default, PartialEq)]
 pub struct IndexPositioner(usize);
 
-clone_resetable! { () IndexPositioner }
-
 impl<Item> Positioner<Item> for IndexPositioner
 where
     Item: PartialEq + Clone,
@@ -182,7 +180,7 @@ impl IndexPositioner {
 impl<Item, Range> RangePositioner<Item, Range> for IndexPositioner
 where
     Item: PartialEq + Clone,
-    Range: PartialEq + Clone + ::stream::Range,
+    Range: PartialEq + Clone + crate::stream::Range,
 {
     fn update_range(&mut self, range: &Range) {
         self.0 += range.len()
@@ -198,8 +196,6 @@ pub struct SourcePosition {
     pub column: i32,
 }
 
-clone_resetable! { () SourcePosition }
-
 impl Default for SourcePosition {
     fn default() -> Self {
         SourcePosition { line: 1, column: 1 }
@@ -247,7 +243,8 @@ impl<'a> RangePositioner<char, &'a str> for SourcePosition {
 impl<I, X, S> RangeStreamOnce for State<I, X>
 where
     I: RangeStreamOnce,
-    X: Resetable + RangePositioner<I::Item, I::Range>,
+    I: ResetStream,
+    X: Clone + RangePositioner<I::Item, I::Range>,
     S: StreamError<I::Item, I::Range>,
     I::Error: ParseError<I::Item, I::Range, X::Position, StreamError = S>,
     I::Error: ParseError<I::Item, I::Range, I::Position, StreamError = S>,
@@ -281,7 +278,7 @@ where
     fn uncons_while1<F>(
         &mut self,
         mut predicate: F,
-    ) -> FastResult<Self::Range, StreamErrorFor<Self>>
+    ) -> ParseResult<Self::Range, StreamErrorFor<Self>>
     where
         F: FnMut(Self::Item) -> bool,
     {
@@ -302,32 +299,37 @@ where
     }
 }
 
-impl<I, X> Resetable for State<I, X>
+impl<I, X, S> ResetStream for State<I, X>
 where
-    I: Resetable,
-    X: Resetable,
+    I: ResetStream,
+    X: Clone + Positioner<I::Item>,
+    S: StreamError<I::Item, I::Range>,
+    I::Error: ParseError<I::Item, I::Range, X::Position, StreamError = S>,
+    I::Error: ParseError<I::Item, I::Range, I::Position, StreamError = S>,
 {
-    type Checkpoint = State<I::Checkpoint, X::Checkpoint>;
+    type Checkpoint = State<I::Checkpoint, X>;
+
     fn checkpoint(&self) -> Self::Checkpoint {
         State {
             input: self.input.checkpoint(),
-            positioner: self.positioner.checkpoint(),
+            positioner: self.positioner.clone(),
         }
     }
-    fn reset(&mut self, checkpoint: Self::Checkpoint) {
-        self.input.reset(checkpoint.input);
-        self.positioner.reset(checkpoint.positioner);
+    fn reset(&mut self, checkpoint: Self::Checkpoint) -> Result<(), Self::Error> {
+        self.input.reset(checkpoint.input)?;
+        self.positioner = checkpoint.positioner;
+        Ok(())
     }
 }
 
 impl<I, X, E> FullRangeStream for State<I, X>
 where
-    I: FullRangeStream + Resetable,
+    I: FullRangeStream + ResetStream,
     I::Position: Clone + Ord,
     E: StreamError<I::Item, I::Range>,
     I::Error: ParseError<I::Item, I::Range, X::Position, StreamError = E>,
     I::Error: ParseError<I::Item, I::Range, I::Position, StreamError = E>,
-    X: Resetable + RangePositioner<I::Item, I::Range>,
+    X: Clone + RangePositioner<I::Item, I::Range>,
 {
     fn range(&self) -> Self::Range {
         self.input.range()
@@ -337,12 +339,12 @@ where
 #[cfg(all(feature = "std", test))]
 mod tests {
     use super::*;
-    use Parser;
+    use crate::Parser;
 
     #[test]
     fn test_positioner() {
         let input = ["a".to_string(), "b".to_string()];
-        let mut parser = ::any();
+        let mut parser = crate::any();
         let result = parser.parse(State::new(&input[..]));
         assert_eq!(
             result,
@@ -359,7 +361,7 @@ mod tests {
     #[test]
     fn test_range_positioner() {
         let input = ["a".to_string(), "b".to_string(), "c".to_string()];
-        let mut parser = ::parser::range::take(2);
+        let mut parser = crate::parser::range::take(2);
         let result = parser.parse(State::new(&input[..]));
         assert_eq!(
             result,
diff --git a/travis.sh b/travis.sh
index 797b0a31..a4ca1fa0 100755
--- a/travis.sh
+++ b/travis.sh
@@ -13,8 +13,7 @@ else
     cargo test --features doc
     cargo test --features doc --examples
 
-    [ "$TRAVIS_RUST_VERSION" != "nightly" ] || cargo check --bench json
-
+    cargo check --bench json
     cargo check --bench http
     cargo check --bench mp4 --features mp4
 


Test patch:
diff --git a/tests/async.rs b/tests/async.rs
index 8545c2de..04a3473a 100644
--- a/tests/async.rs
+++ b/tests/async.rs
@@ -1,19 +1,5 @@
 #![allow(renamed_and_removed_lints)]
 
-#[macro_use]
-extern crate quick_error;
-#[macro_use]
-extern crate quickcheck;
-
-extern crate bytes;
-#[macro_use]
-extern crate combine;
-
-extern crate futures;
-extern crate partial_io;
-extern crate tokio_codec;
-extern crate tokio_io;
-
 use std::cell::Cell;
 use std::io::{self, Cursor};
 use std::rc::Rc;
@@ -22,22 +8,33 @@ use std::str;
 use bytes::BytesMut;
 
 use futures::{Future, Stream};
+use quick_error::quick_error;
+use quickcheck::quickcheck;
 use tokio_codec::{Decoder, FramedRead};
 
-use combine::combinator::{
-    any_partial_state, any_send_partial_state, attempt, from_str, no_partial, optional, recognize,
-    skip_many1, AnyPartialState, AnySendPartialState,
-};
-use combine::error::{ParseError, StreamError};
-use combine::parser::byte::take_until_bytes;
-use combine::parser::char::{char, digit, letter};
-use combine::parser::item::item;
-use combine::parser::range::{
-    self, range, recognize_with_value, take, take_fn, take_until_range, take_while, take_while1,
+use combine::{
+    any,
+    combinator::{
+        any_partial_state, any_send_partial_state, attempt, from_str, no_partial, optional,
+        recognize, skip_many1, AnyPartialState, AnySendPartialState,
+    },
+    count_min_max,
+    error::{ParseError, StreamError},
+    many1, parser,
+    parser::{
+        byte::take_until_bytes,
+        char::{char, digit, letter},
+        item::item,
+        range::{
+            self, range, recognize_with_value, take, take_fn, take_until_range, take_while,
+            take_while1,
+        },
+        repeat,
+    },
+    skip_many,
+    stream::{easy, RangeStream, StreamErrorFor},
+    Parser,
 };
-use combine::parser::repeat;
-use combine::stream::{easy, RangeStream, StreamErrorFor};
-use combine::{any, count_min_max, many1, skip_many, Parser};
 
 quick_error! {
     #[derive(Debug)]
@@ -107,7 +104,7 @@ macro_rules! impl_decoder {
                         // returning the error and before we call `split_to` to remove the input we
                         // just consumed
                         let err = err.map_range(|r| r.to_string())
-                            .map_position(|p| p.translate_position(&src[..]));
+                            .map_position(|p| p.translate_position(&str_src[..]));
                         format!("{}\nIn input: `{}`", err, str_src)
                     })?
                 };
diff --git a/tests/buffered_stream.rs b/tests/buffered_stream.rs
index 3f572e93..821d1178 100644
--- a/tests/buffered_stream.rs
+++ b/tests/buffered_stream.rs
@@ -1,7 +1,7 @@
 #![cfg(feature = "std")]
 extern crate combine;
 use combine::parser::char::{char, digit, spaces, string};
-use combine::stream::buffered::BufferedStream;
+use combine::stream::buffered;
 use combine::stream::easy::{self, Error};
 use combine::stream::state::State;
 use combine::stream::IteratorStream;
@@ -17,7 +17,7 @@ fn shared_stream_buffer() {
             c
         }
     });
-    let buffer = BufferedStream::new(State::new(IteratorStream::new(text)), 1);
+    let buffer = buffered::Stream::new(State::new(IteratorStream::new(text)), 1);
     let int: &mut Parser<Input = _, Output = _, PartialState = _> =
         &mut many(digit()).map(|s: String| s.parse::<i64>().unwrap());
     let result = sep_by(int, char(',')).parse(buffer).map(|t| t.0);
@@ -29,7 +29,7 @@ fn shared_stream_backtrack() {
     let text = "apple,apple,ananas,orangeblah";
     let mut iter = text.chars();
     // Iterator that can't be cloned
-    let stream = BufferedStream::new(State::new(IteratorStream::new(&mut iter)), 2);
+    let stream = buffered::Stream::new(State::new(IteratorStream::new(&mut iter)), 2);
 
     let value: &mut Parser<Input = _, Output = _, PartialState = _> = &mut choice([
         attempt(string("apple")),
@@ -46,7 +46,7 @@ fn shared_stream_insufficent_backtrack() {
     let text = "apple,apple,ananas,orangeblah";
     let mut iter = text.chars();
     // Iterator that can't be cloned
-    let stream = BufferedStream::new(easy::Stream(State::new(IteratorStream::new(&mut iter))), 1);
+    let stream = buffered::Stream::new(easy::Stream(State::new(IteratorStream::new(&mut iter))), 1);
 
     let value: &mut Parser<Input = _, Output = _, PartialState = _> = &mut choice([
         attempt(string("apple")),
@@ -73,7 +73,7 @@ fn shared_stream_insufficent_backtrack() {
 #[test]
 fn always_output_end_of_input_after_end_of_input() {
     let text = "10".chars();
-    let buffer = BufferedStream::new(State::new(IteratorStream::new(text)), 1);
+    let buffer = buffered::Stream::new(State::new(IteratorStream::new(text)), 1);
     let int = many1(digit()).map(|s: String| s.parse::<i64>().unwrap());
     let result = many(spaces().with(int)).parse(buffer).map(|t| t.0);
     assert_eq!(result, Ok(vec![10]));
@@ -82,7 +82,7 @@ fn always_output_end_of_input_after_end_of_input() {
 #[test]
 fn position() {
     let text = "10abc".chars();
-    let stream = BufferedStream::new(State::new(IteratorStream::new(text)), 3);
+    let stream = buffered::Stream::new(State::new(IteratorStream::new(text)), 3);
     assert_eq!(stream.position(), 0);
     let result = many1::<Vec<_>, _>(digit()).parse(stream);
     assert!(result.is_ok());
diff --git a/tests/parser.rs b/tests/parser.rs
index 78a6f8bd..eac9983a 100644
--- a/tests/parser.rs
+++ b/tests/parser.rs
@@ -1,6 +1,7 @@
 extern crate combine;
 
-use combine::parser::char::{digit, letter, string};
+use combine::parser::byte::bytes_cmp;
+use combine::parser::char::{digit, letter, string, string_cmp};
 use combine::parser::choice::{choice, optional};
 use combine::parser::combinator::{attempt, no_partial, not_followed_by};
 use combine::parser::error::unexpected;
@@ -573,6 +574,28 @@ mod tests_std {
         );
     }
 
+    #[test]
+    fn lifetime_inference() {
+        fn _string<'a>(source: &'a str) {
+            range::take(1).or(string("a")).parse(source).ok();
+            range::take(1)
+                .or(string_cmp("a", |x, y| x == y))
+                .parse(source)
+                .ok();
+            let _: &'static str = string("a").parse(source).unwrap().0;
+            let _: &'static str = string_cmp("a", |x, y| x == y).parse(source).unwrap().0;
+        }
+        fn _bytes<'a>(source: &'a [u8]) {
+            range::take(1).or(bytes(&[0u8])).parse(source).ok();
+            range::take(1)
+                .or(bytes_cmp(&[0u8], |x, y| x == y))
+                .parse(source)
+                .ok();
+            let _: &'static [u8] = bytes(&[0u8]).parse(source).unwrap().0;
+            let _: &'static [u8] = bytes_cmp(&[0u8], |x, y| x == y).parse(source).unwrap().0;
+        }
+    }
+
     #[test]
     fn test_nested_count_overflow() {
         let key = || count::<Vec<_>, _>(64, alpha_num());