Snap for 10453563 from 003ed36b64cfdce15292751127a0dc944fb44fd8 to mainline-os-statsd-release

Change-Id: Icc6ec1e3c589ccd1469f16fd9f3dda460e048e59
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index d603d8a..c356c32 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
 {
   "git": {
-    "sha1": "b6f79c4d375ae55e1fd1a35032ebb47a52ea3389"
-  }
+    "sha1": "869f8972a4383b13cf89574fda28cb7dbfd56517"
+  },
+  "path_in_vcs": ""
 }
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 6fd9d6f..f9f1cbb 100644
--- a/Android.bp
+++ b/Android.bp
@@ -23,16 +23,21 @@
     host_supported: true,
     crate_name: "nom",
     cargo_env_compat: true,
-    cargo_pkg_version: "7.1.0",
+    cargo_pkg_version: "7.1.3",
     srcs: ["src/lib.rs"],
     edition: "2018",
     features: [
         "alloc",
         "std",
     ],
-    cfgs: ["stable_i128"],
     rustlibs: [
         "libmemchr",
         "libminimal_lexical",
     ],
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.virt",
+    ],
+    product_available: true,
+    vendor_available: true,
 }
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a1bff5c..a8f4c02 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,71 @@
 
 ### Changed
 
+## 7.1.3 - 2023-01-15
+
+### Thanks
+
+- @Shadow53
+
+### Fixed
+
+- panic in `many` and `count` combinators when the output type is zero sized
+
+## 7.1.2 - 2023-01-01
+
+### Thanks
+
+- @joubs
+- @Fyko
+- @LoganDark
+- @darnuria
+- @jkugelman
+- @barower
+- @puzzlewolf
+- @epage
+- @cky
+- @wolthom
+- @w1ll-i-code
+
+### Changed
+
+- documentation fixes
+- tests fixes
+- limit the initial capacity of the result vector of `many_m_n` to 64kiB
+- bits parser now accept `Parser` implementors instead of only functions
+
+### Added
+
+- implement `Tuple` parsing for the unit type as a special case
+- implement `ErrorConvert` on the unit type to make it usable as error type for bits parsers
+- bool parser for bits input
+
+## 7.1.1 - 2022-03-14
+
+### Thanks
+
+- @ThomasdenH
+- @@SphinxKnight
+- @irevoire
+- @doehyunbaek
+- @pxeger
+- @punkeel
+- @max-sixty
+- @Xiretza
+- @5c077m4n
+- @erihsu
+- @TheNeikos
+- @LoganDark
+- @nickelc
+- @chotchki
+- @ctrlcctrlv
+
+
+### Changed
+
+- documentation fixes
+- more examples
+
 ## 7.1.0 - 2021-11-04
 
 ### Thanks
@@ -851,7 +916,7 @@
 
 The 2.0 release is one of the biggest yet. It was a good opportunity to clean up some badly named combinators and fix invalid behaviours.
 
-Since this version introduces a few breaking changes, an [upgrade documentation](https://github.com/Geal/nom/blob/master/doc/upgrading_to_nom_2.md) is available, detailing the steps to fix the most common migration issues. After testing on a set of 30 crates, most of them will build directly, a large part will just need to activate the "verbose-errors" compilation feature. The remaining fixes are documented.
+Since this version introduces a few breaking changes, an [upgrade documentation](https://github.com/Geal/nom/blob/main/doc/upgrading_to_nom_2.md) is available, detailing the steps to fix the most common migration issues. After testing on a set of 30 crates, most of them will build directly, a large part will just need to activate the "verbose-errors" compilation feature. The remaining fixes are documented.
 
 This version also adds a lot of interesting features, like the permutation combinator or whitespace separated formats support.
 
@@ -1420,7 +1485,11 @@
 
 ## Compare code
 
-* [unreleased](https://github.com/Geal/nom/compare/7.0.0...HEAD)
+* [unreleased](https://github.com/Geal/nom/compare/7.1.3...HEAD)
+* [7.1.2](https://github.com/Geal/nom/compare/7.1.2...7.1.3)
+* [7.1.2](https://github.com/Geal/nom/compare/7.1.1...7.1.2)
+* [7.1.1](https://github.com/Geal/nom/compare/7.1.0...7.1.1)
+* [7.1.0](https://github.com/Geal/nom/compare/7.0.0...7.1.0)
 * [7.0.0](https://github.com/Geal/nom/compare/6.2.1...7.0.0)
 * [6.2.1](https://github.com/Geal/nom/compare/6.2.0...6.2.1)
 * [6.2.0](https://github.com/Geal/nom/compare/6.1.2...6.2.0)
diff --git a/Cargo.toml b/Cargo.toml
index 6e38fa0..2388b4c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,32 +11,65 @@
 
 [package]
 edition = "2018"
+rust-version = "1.48"
 name = "nom"
-version = "7.1.0"
+version = "7.1.3"
 authors = ["contact@geoffroycouprie.com"]
-include = ["CHANGELOG.md", "LICENSE", "README.md", ".gitignore", "Cargo.toml", "src/*.rs", "src/*/*.rs", "tests/*.rs", "doc/nom_recipes.md", "build.rs"]
+include = [
+    "CHANGELOG.md",
+    "LICENSE",
+    "README.md",
+    ".gitignore",
+    "Cargo.toml",
+    "src/*.rs",
+    "src/*/*.rs",
+    "tests/*.rs",
+    "doc/nom_recipes.md",
+]
 autoexamples = false
 description = "A byte-oriented, zero-copy, parser combinators library"
 documentation = "https://docs.rs/nom"
 readme = "README.md"
-keywords = ["parser", "parser-combinators", "parsing", "streaming", "bit"]
+keywords = [
+    "parser",
+    "parser-combinators",
+    "parsing",
+    "streaming",
+    "bit",
+]
 categories = ["parsing"]
 license = "MIT"
 repository = "https://github.com/Geal/nom"
+
 [package.metadata.docs.rs]
+features = [
+    "alloc",
+    "std",
+    "docsrs",
+]
 all-features = true
-features = ["alloc", "std", "docsrs"]
+
 [profile.bench]
 lto = true
 codegen-units = 1
 debug = true
 
 [[example]]
+name = "custom_error"
+path = "examples/custom_error.rs"
+required-features = ["alloc"]
+
+[[example]]
 name = "json"
 path = "examples/json.rs"
 required-features = ["alloc"]
 
 [[example]]
+name = "json_iterator"
+path = "examples/json_iterator.rs"
+required-features = ["alloc"]
+
+[[example]]
 name = "iterator"
 path = "examples/iterator.rs"
 
@@ -98,6 +131,7 @@
 [[test]]
 name = "fnmut"
 required-features = ["alloc"]
+
 [dependencies.memchr]
 version = "2.3"
 default-features = false
@@ -105,21 +139,25 @@
 [dependencies.minimal-lexical]
 version = "0.2.0"
 default-features = false
+
 [dev-dependencies.doc-comment]
 version = "0.3"
 
 [dev-dependencies.proptest]
 version = "1.0.0"
-[build-dependencies.version_check]
-version = "0.9"
 
 [features]
 alloc = []
 default = ["std"]
 docsrs = []
-std = ["alloc", "memchr/std", "minimal-lexical/std"]
+std = [
+    "alloc",
+    "memchr/std",
+    "minimal-lexical/std",
+]
+
 [badges.coveralls]
-branch = "master"
+branch = "main"
 repository = "Geal/nom"
 service = "github"
 
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 4e5b011..c01eeba 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,7 +1,7 @@
 [package]
 
 name = "nom"
-version = "7.1.0"
+version = "7.1.3"
 authors = [ "contact@geoffroycouprie.com" ]
 description = "A byte-oriented, zero-copy, parser combinators library"
 license = "MIT"
@@ -13,6 +13,9 @@
 edition = "2018"
 autoexamples = false
 
+# also update in README.md (badge and "Rust version requirements" section)
+rust-version = "1.48"
+
 include = [
   "CHANGELOG.md",
   "LICENSE",
@@ -23,7 +26,6 @@
   "src/*/*.rs",
   "tests/*.rs",
   "doc/nom_recipes.md",
-  "build.rs"
 ]
 
 [features]
@@ -44,9 +46,6 @@
 doc-comment = "0.3"
 proptest = "1.0.0"
 
-[build-dependencies]
-version_check = "0.9"
-
 [package.metadata.docs.rs]
 features = ["alloc", "std", "docsrs"]
 all-features = true
@@ -106,11 +105,21 @@
 required-features = ["alloc"]
 
 [[example]]
+name = "custom_error"
+required-features = ["alloc"]
+path = "examples/custom_error.rs"
+
+[[example]]
 name = "json"
 required-features = ["alloc"]
 path = "examples/json.rs"
 
 [[example]]
+name = "json_iterator"
+required-features = ["alloc"]
+path = "examples/json_iterator.rs"
+
+[[example]]
 name = "iterator"
 path = "examples/iterator.rs"
 
@@ -126,7 +135,7 @@
 
 [badges]
 travis-ci = { repository = "Geal/nom" }
-coveralls = { repository = "Geal/nom", branch = "master", service = "github" }
+coveralls = { repository = "Geal/nom", branch = "main", service = "github" }
 maintenance = { status = "actively-developed" }
 
 [workspace]
diff --git a/METADATA b/METADATA
index 504894c..e948955 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,7 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update rust/crates/nom
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+
 name: "nom"
 description: "A byte-oriented, zero-copy, parser combinators library"
 third_party {
@@ -7,13 +11,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/nom/nom-7.1.0.crate"
+    value: "https://static.crates.io/crates/nom/nom-7.1.3.crate"
   }
-  version: "7.1.0"
+  version: "7.1.3"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2022
-    month: 3
-    day: 1
+    year: 2023
+    month: 2
+    day: 3
   }
 }
diff --git a/README.md b/README.md
index 1a95f96..f2c1b05 100644
--- a/README.md
+++ b/README.md
@@ -3,9 +3,9 @@
 [![LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
 [![Join the chat at https://gitter.im/Geal/nom](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Geal/nom?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 [![Build Status](https://github.com/Geal/nom/actions/workflows/ci.yml/badge.svg)](https://github.com/Geal/nom/actions/workflows/ci.yml)
-[![Coverage Status](https://coveralls.io/repos/github/Geal/nom/badge.svg?branch=master)](https://coveralls.io/github/Geal/nom?branch=master)
+[![Coverage Status](https://coveralls.io/repos/github/Geal/nom/badge.svg?branch=main)](https://coveralls.io/github/Geal/nom?branch=main)
 [![Crates.io Version](https://img.shields.io/crates/v/nom.svg)](https://crates.io/crates/nom)
-[![Minimum rustc version](https://img.shields.io/badge/rustc-1.48.0+-lightgray.svg)](#rust-version-requirements)
+[![Minimum rustc version](https://img.shields.io/badge/rustc-1.48.0+-lightgray.svg)](#rust-version-requirements-msrv)
 
 nom is a parser combinators library written in Rust. Its goal is to provide tools
 to build safe parsers without compromising the speed or memory consumption. To
@@ -13,10 +13,29 @@
 fast and correct parsers, and provides functions, macros and traits to abstract most of the
 error prone plumbing.
 
-![nom logo in CC0 license, by Ange Albertini](https://raw.githubusercontent.com/Geal/nom/master/assets/nom.png)
+![nom logo in CC0 license, by Ange Albertini](https://raw.githubusercontent.com/Geal/nom/main/assets/nom.png)
 
 *nom will happily take a byte out of your files :)*
 
+<!-- toc -->
+
+- [Example](#example)
+- [Documentation](#documentation)
+- [Why use nom?](#why-use-nom)
+    - [Binary format parsers](#binary-format-parsers)
+    - [Text format parsers](#text-format-parsers)
+    - [Programming language parsers](#programming-language-parsers)
+    - [Streaming formats](#streaming-formats)
+- [Parser combinators](#parser-combinators)
+- [Technical features](#technical-features)
+- [Rust version requirements](#rust-version-requirements-msrv)
+- [Installation](#installation)
+- [Related projects](#related-projects)
+- [Parsers written with nom](#parsers-written-with-nom)
+- [Contributors](#contributors)
+
+<!-- tocstop -->
+
 ## Example
 
 [Hexadecimal color](https://developer.mozilla.org/en-US/docs/Web/CSS/color) parser:
@@ -74,8 +93,8 @@
 ## Documentation
 
 - [Reference documentation](https://docs.rs/nom)
-- [Various design documents and tutorials](https://github.com/Geal/nom/tree/master/doc)
-- [List of combinators and their behaviour](https://github.com/Geal/nom/blob/master/doc/choosing_a_combinator.md)
+- [Various design documents and tutorials](https://github.com/Geal/nom/tree/main/doc)
+- [List of combinators and their behaviour](https://github.com/Geal/nom/blob/main/doc/choosing_a_combinator.md)
 
 If you need any help developing your parsers, please ping `geal` on IRC (libera, geeknode, oftc), go to `#nom-parsers` on Libera IRC, or on the [Gitter chat room](https://gitter.im/Geal/nom).
 
@@ -113,7 +132,7 @@
 
 Example projects:
 
-- [HTTP proxy](https://github.com/sozu-proxy/sozu/blob/master/lib/src/protocol/http/parser.rs)
+- [HTTP proxy](https://github.com/sozu-proxy/sozu/tree/main/lib/src/protocol/http/parser)
 - [TOML parser](https://github.com/joelself/tomllib)
 
 ### Programming language parsers
@@ -148,7 +167,7 @@
 
 Example projects:
 
-- [HTTP proxy](https://github.com/sozu-proxy/sozu/blob/master/lib/src/protocol/http/parser.rs)
+- [HTTP proxy](https://github.com/sozu-proxy/sozu/tree/main/lib/src/protocol/http/parser)
 - [Using nom with generators](https://github.com/Geal/generator_nom)
 
 ## Parser combinators
@@ -186,7 +205,7 @@
 
 Some benchmarks are available on [Github](https://github.com/Geal/nom_benchmarks).
 
-## Rust version requirements
+## Rust version requirements (MSRV)
 
 The 7.0 series of nom supports **Rustc version 1.48 or greater**. It is known to work properly on Rust 1.41.1 but there is no guarantee it will stay the case through this major release.
 
@@ -230,7 +249,7 @@
 [CSV](https://github.com/GuillaumeGomez/csv-parser),
 [FASTA](https://github.com/TianyiShi2001/nom-fasta),
 [FASTQ](https://github.com/elij/fastq.rs),
-[INI](https://github.com/Geal/nom/blob/master/tests/ini.rs),
+[INI](https://github.com/Geal/nom/blob/main/tests/ini.rs),
 [ISO 8601 dates](https://github.com/badboy/iso8601),
 [libconfig-like configuration file format](https://github.com/filipegoncalves/rust-config),
 [Web archive](https://github.com/sbeckeriv/warc_nom_parser),
@@ -251,6 +270,7 @@
 [CSML](https://github.com/CSML-by-Clevy/csml-interpreter),
 [Wasm](https://github.com/Strytyp/wasm-nom),
 [Pseudocode](https://github.com/Gungy2/pseudocode)
+[Filter for MeiliSearch](https://github.com/meilisearch/meilisearch)
 - Interface definition formats: [Thrift](https://github.com/thehydroimpulse/thrust)
 - Audio, video and image formats:
 [GIF](https://github.com/Geal/gif.rs),
@@ -261,14 +281,15 @@
 [Matroska (MKV)](https://github.com/rust-av/matroska)
 - Document formats:
 [TAR](https://github.com/Keruspe/tar-parser.rs),
-[GZ](https://github.com/nharward/nom-gzip)
+[GZ](https://github.com/nharward/nom-gzip),
+[GDSII](https://github.com/erihsu/gds2-io)
 - Cryptographic formats:
 [X.509](https://github.com/rusticata/x509-parser)
 - Network protocol formats:
 [Bencode](https://github.com/jbaum98/bencode.rs),
 [D-Bus](https://github.com/toshokan/misato),
 [DHCP](https://github.com/rusticata/dhcp-parser),
-[HTTP](https://github.com/sozu-proxy/sozu/tree/master/lib/src/protocol/http),
+[HTTP](https://github.com/sozu-proxy/sozu/tree/main/lib/src/protocol/http),
 [URI](https://github.com/santifa/rrp/blob/master/src/uri.rs),
 [IMAP](https://github.com/djc/tokio-imap),
 [IRC](https://github.com/Detegr/RBot-parser),
@@ -294,7 +315,8 @@
 [Telcordia/Bellcore SR-4731 SOR OTDR files](https://github.com/JamesHarrison/otdrs),
 [MySQL binary log](https://github.com/PrivateRookie/boxercrab),
 [URI](https://github.com/Skasselbard/nom-uri),
-[Furigana](https://github.com/sachaarbonel/furigana.rs)
+[Furigana](https://github.com/sachaarbonel/furigana.rs),
+[Wordle Result](https://github.com/Fyko/wordle-stats/tree/main/parser)
 
 Want to create a new parser using `nom`? A list of not yet implemented formats is available [here](https://github.com/Geal/nom/issues/14).
 
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 0b9e785..f441b9c 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -9,40 +9,15 @@
     },
     {
       "path": "external/rust/crates/rusticata-macros"
-    }
-  ],
-  "presubmit": [
-    {
-      "name": "keystore2_test"
     },
     {
-      "name": "legacykeystore_test"
+      "path": "packages/modules/Virtualization/virtualizationmanager"
     },
     {
-      "name": "libapkverify.integration_test"
+      "path": "system/security/keystore2"
     },
     {
-      "name": "libapkverify.test"
-    },
-    {
-      "name": "microdroid_manager_test"
-    }
-  ],
-  "presubmit-rust": [
-    {
-      "name": "keystore2_test"
-    },
-    {
-      "name": "legacykeystore_test"
-    },
-    {
-      "name": "libapkverify.integration_test"
-    },
-    {
-      "name": "libapkverify.test"
-    },
-    {
-      "name": "microdroid_manager_test"
+      "path": "system/security/keystore2/legacykeystore"
     }
   ]
 }
diff --git a/build.rs b/build.rs
deleted file mode 100644
index 0fb5784..0000000
--- a/build.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-extern crate version_check;
-
-fn main() {
-  if version_check::is_min_version("1.44.0").unwrap_or(true) {
-    println!("cargo:rustc-cfg=stable_i128");
-  }
-}
diff --git a/cargo2android.json b/cargo2android.json
index 5fb7e33..73b74df 100644
--- a/cargo2android.json
+++ b/cargo2android.json
@@ -1,5 +1,9 @@
 {
+  "apex-available": [
+    "//apex_available:platform",
+    "com.android.virt"
+  ],
   "device": true,
   "features": "alloc,std",
   "run": true
-}
\ No newline at end of file
+}
diff --git a/doc/nom_recipes.md b/doc/nom_recipes.md
index 8899485..e862634 100644
--- a/doc/nom_recipes.md
+++ b/doc/nom_recipes.md
@@ -115,7 +115,7 @@
 use nom::{
   IResult,
   branch::alt,
-  multi::many0,
+  multi::many0_count,
   combinator::recognize,
   sequence::pair,
   character::complete::{alpha1, alphanumeric1},
@@ -126,7 +126,7 @@
   recognize(
     pair(
       alt((alpha1, tag("_"))),
-      many0(alt((alphanumeric1, tag("_"))))
+      many0_count(alt((alphanumeric1, tag("_"))))
     )
   )(input)
 }
@@ -142,7 +142,7 @@
 
 ### Escaped Strings
 
-This is [one of the examples](https://github.com/Geal/nom/blob/master/examples/string.rs) in the
+This is [one of the examples](https://github.com/Geal/nom/blob/main/examples/string.rs) in the
 examples directory.
 
 ### Integers
diff --git a/src/bits/complete.rs b/src/bits/complete.rs
index b46bc7a..bf36dcc 100644
--- a/src/bits/complete.rs
+++ b/src/bits/complete.rs
@@ -105,6 +105,29 @@
   }
 }
 
+/// Parses one specific bit as a bool.
+///
+/// # Example
+/// ```rust
+/// # use nom::bits::complete::bool;
+/// # use nom::IResult;
+/// # use nom::error::{Error, ErrorKind};
+///
+/// fn parse(input: (&[u8], usize)) -> IResult<(&[u8], usize), bool> {
+///     bool(input)
+/// }
+///
+/// assert_eq!(parse(([0b10000000].as_ref(), 0)), Ok((([0b10000000].as_ref(), 1), true)));
+/// assert_eq!(parse(([0b10000000].as_ref(), 1)), Ok((([0b10000000].as_ref(), 2), false)));
+/// ```
+pub fn bool<I, E: ParseError<(I, usize)>>(input: (I, usize)) -> IResult<(I, usize), bool, E>
+where
+  I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+  let (res, bit): (_, u32) = take(1usize)(input)?;
+  Ok((res, bit != 0))
+}
+
 #[cfg(test)]
 mod test {
   use super::*;
@@ -147,4 +170,28 @@
       Ok((([0b11111111].as_ref(), 4), 0b1000110100111111111111))
     );
   }
+
+  #[test]
+  fn test_bool_0() {
+    let input = [0b10000000].as_ref();
+
+    let result: crate::IResult<(&[u8], usize), bool> = bool((input, 0));
+
+    assert_eq!(result, Ok(((input, 1), true)));
+  }
+
+  #[test]
+  fn test_bool_eof() {
+    let input = [0b10000000].as_ref();
+
+    let result: crate::IResult<(&[u8], usize), bool> = bool((input, 8));
+
+    assert_eq!(
+      result,
+      Err(crate::Err::Error(crate::error::Error {
+        input: (input, 8),
+        code: ErrorKind::Eof
+      }))
+    );
+  }
 }
diff --git a/src/bits/mod.rs b/src/bits/mod.rs
index 235b797..0d3f73d 100644
--- a/src/bits/mod.rs
+++ b/src/bits/mod.rs
@@ -5,7 +5,7 @@
 pub mod streaming;
 
 use crate::error::{ErrorKind, ParseError};
-use crate::internal::{Err, IResult, Needed};
+use crate::internal::{Err, IResult, Needed, Parser};
 use crate::lib::std::ops::RangeFrom;
 use crate::traits::{ErrorConvert, Slice};
 
@@ -42,9 +42,9 @@
   E1: ParseError<(I, usize)> + ErrorConvert<E2>,
   E2: ParseError<I>,
   I: Slice<RangeFrom<usize>>,
-  P: FnMut((I, usize)) -> IResult<(I, usize), O, E1>,
+  P: Parser<(I, usize), O, E1>,
 {
-  move |input: I| match parser((input, 0)) {
+  move |input: I| match parser.parse((input, 0)) {
     Ok(((rest, offset), result)) => {
       // If the next byte has been partially read, it will be sliced away as well.
       // The parser functions might already slice away all fully read bytes.
@@ -88,7 +88,7 @@
   E1: ParseError<I> + ErrorConvert<E2>,
   E2: ParseError<(I, usize)>,
   I: Slice<RangeFrom<usize>> + Clone,
-  P: FnMut(I) -> IResult<I, O, E1>,
+  P: Parser<I, O, E1>,
 {
   move |(input, offset): (I, usize)| {
     let inner = if offset % 8 != 0 {
@@ -97,7 +97,7 @@
       input.slice((offset / 8)..)
     };
     let i = (input, offset);
-    match parser(inner) {
+    match parser.parse(inner) {
       Ok((rest, res)) => Ok(((rest, 0), res)),
       Err(Err::Incomplete(Needed::Unknown)) => Err(Err::Incomplete(Needed::Unknown)),
       Err(Err::Incomplete(Needed::Size(sz))) => Err(match sz.get().checked_mul(8) {
diff --git a/src/bits/streaming.rs b/src/bits/streaming.rs
index e8adc1c..a7c8d0a 100644
--- a/src/bits/streaming.rs
+++ b/src/bits/streaming.rs
@@ -79,6 +79,29 @@
   }
 }
 
+/// Parses one specific bit as a bool.
+///
+/// # Example
+/// ```rust
+/// # use nom::bits::complete::bool;
+/// # use nom::IResult;
+/// # use nom::error::{Error, ErrorKind};
+///
+/// fn parse(input: (&[u8], usize)) -> IResult<(&[u8], usize), bool> {
+///     bool(input)
+/// }
+///
+/// assert_eq!(parse(([0b10000000].as_ref(), 0)), Ok((([0b10000000].as_ref(), 1), true)));
+/// assert_eq!(parse(([0b10000000].as_ref(), 1)), Ok((([0b10000000].as_ref(), 2), false)));
+/// ```
+pub fn bool<I, E: ParseError<(I, usize)>>(input: (I, usize)) -> IResult<(I, usize), bool, E>
+where
+  I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+  let (res, bit): (_, u32) = take(1usize)(input)?;
+  Ok((res, bit != 0))
+}
+
 #[cfg(test)]
 mod test {
   use super::*;
@@ -126,4 +149,22 @@
       }))
     );
   }
+
+  #[test]
+  fn test_bool_0() {
+    let input = [0b10000000].as_ref();
+
+    let result: crate::IResult<(&[u8], usize), bool> = bool((input, 0));
+
+    assert_eq!(result, Ok(((input, 1), true)));
+  }
+
+  #[test]
+  fn test_bool_eof() {
+    let input = [0b10000000].as_ref();
+
+    let result: crate::IResult<(&[u8], usize), bool> = bool((input, 8));
+
+    assert_eq!(result, Err(crate::Err::Incomplete(Needed::new(1))));
+  }
 }
diff --git a/src/branch/mod.rs b/src/branch/mod.rs
index 9df5a29..e03622c 100644
--- a/src/branch/mod.rs
+++ b/src/branch/mod.rs
@@ -1,29 +1,5 @@
 //! Choice combinators
 
-macro_rules! succ (
-  (0, $submac:ident ! ($($rest:tt)*)) => ($submac!(1, $($rest)*));
-  (1, $submac:ident ! ($($rest:tt)*)) => ($submac!(2, $($rest)*));
-  (2, $submac:ident ! ($($rest:tt)*)) => ($submac!(3, $($rest)*));
-  (3, $submac:ident ! ($($rest:tt)*)) => ($submac!(4, $($rest)*));
-  (4, $submac:ident ! ($($rest:tt)*)) => ($submac!(5, $($rest)*));
-  (5, $submac:ident ! ($($rest:tt)*)) => ($submac!(6, $($rest)*));
-  (6, $submac:ident ! ($($rest:tt)*)) => ($submac!(7, $($rest)*));
-  (7, $submac:ident ! ($($rest:tt)*)) => ($submac!(8, $($rest)*));
-  (8, $submac:ident ! ($($rest:tt)*)) => ($submac!(9, $($rest)*));
-  (9, $submac:ident ! ($($rest:tt)*)) => ($submac!(10, $($rest)*));
-  (10, $submac:ident ! ($($rest:tt)*)) => ($submac!(11, $($rest)*));
-  (11, $submac:ident ! ($($rest:tt)*)) => ($submac!(12, $($rest)*));
-  (12, $submac:ident ! ($($rest:tt)*)) => ($submac!(13, $($rest)*));
-  (13, $submac:ident ! ($($rest:tt)*)) => ($submac!(14, $($rest)*));
-  (14, $submac:ident ! ($($rest:tt)*)) => ($submac!(15, $($rest)*));
-  (15, $submac:ident ! ($($rest:tt)*)) => ($submac!(16, $($rest)*));
-  (16, $submac:ident ! ($($rest:tt)*)) => ($submac!(17, $($rest)*));
-  (17, $submac:ident ! ($($rest:tt)*)) => ($submac!(18, $($rest)*));
-  (18, $submac:ident ! ($($rest:tt)*)) => ($submac!(19, $($rest)*));
-  (19, $submac:ident ! ($($rest:tt)*)) => ($submac!(20, $($rest)*));
-  (20, $submac:ident ! ($($rest:tt)*)) => ($submac!(21, $($rest)*));
-);
-
 #[cfg(test)]
 mod tests;
 
diff --git a/src/bytes/complete.rs b/src/bytes/complete.rs
index 9375b1f..a5442b5 100644
--- a/src/bytes/complete.rs
+++ b/src/bytes/complete.rs
@@ -388,6 +388,18 @@
 /// assert_eq!(take6("short"), Err(Err::Error(Error::new("short", ErrorKind::Eof))));
 /// assert_eq!(take6(""), Err(Err::Error(Error::new("", ErrorKind::Eof))));
 /// ```
+///
+/// The units that are taken will depend on the input type. For example, for a
+/// `&str` it will take a number of `char`'s, whereas for a `&[u8]` it will
+/// take that many `u8`'s:
+///
+/// ```rust
+/// use nom::error::Error;
+/// use nom::bytes::complete::take;
+///
+/// assert_eq!(take::<_, _, Error<_>>(1usize)("💙"), Ok(("", "💙")));
+/// assert_eq!(take::<_, _, Error<_>>(1usize)("💙".as_bytes()), Ok((b"\x9F\x92\x99".as_ref(), b"\xF0".as_ref())));
+/// ```
 pub fn take<C, Input, Error: ParseError<Input>>(
   count: C,
 ) -> impl Fn(Input) -> IResult<Input, Input, Error>
diff --git a/src/character/complete.rs b/src/character/complete.rs
index 5b73c14..7cb760a 100644
--- a/src/character/complete.rs
+++ b/src/character/complete.rs
@@ -414,6 +414,24 @@
 /// assert_eq!(parser("c1"), Err(Err::Error(Error::new("c1", ErrorKind::Digit))));
 /// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Digit))));
 /// ```
+///
+/// ## Parsing an integer
+/// You can use `digit1` in combination with [`map_res`] to parse an integer:
+///
+/// ```
+/// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom::combinator::map_res;
+/// # use nom::character::complete::digit1;
+/// fn parser(input: &str) -> IResult<&str, u32> {
+///   map_res(digit1, str::parse)(input)
+/// }
+///
+/// assert_eq!(parser("416"), Ok(("", 416)));
+/// assert_eq!(parser("12b"), Ok(("b", 12)));
+/// assert!(parser("b").is_err());
+/// ```
+///
+/// [`map_res`]: crate::combinator::map_res
 pub fn digit1<T, E: ParseError<T>>(input: T) -> IResult<T, T, E>
 where
   T: InputTakeAtPosition,
diff --git a/src/combinator/mod.rs b/src/combinator/mod.rs
index 7071cc7..fe08d4a 100644
--- a/src/combinator/mod.rs
+++ b/src/combinator/mod.rs
@@ -218,7 +218,9 @@
   }
 }
 
-/// Optional parser: Will return `None` if not successful.
+/// Optional parser, will return `None` on [`Err::Error`].
+///
+/// To chain an error up, see [`cut`].
 ///
 /// ```rust
 /// # use nom::{Err,error::ErrorKind, IResult};
@@ -575,18 +577,55 @@
   }
 }
 
-/// transforms an error to failure
+/// Transforms an [`Err::Error`] (recoverable) to [`Err::Failure`] (unrecoverable)
 ///
+/// This commits the parse result, preventing alternative branch paths like with
+/// [`nom::branch::alt`][crate::branch::alt].
+///
+/// # Example
+///
+/// Without `cut`:
 /// ```rust
 /// # use nom::{Err,error::ErrorKind, IResult};
-/// use nom::combinator::cut;
-/// use nom::character::complete::alpha1;
+/// # use nom::character::complete::{one_of, digit1};
+/// # use nom::combinator::rest;
+/// # use nom::branch::alt;
+/// # use nom::sequence::preceded;
 /// # fn main() {
 ///
-/// let mut parser = cut(alpha1);
+/// fn parser(input: &str) -> IResult<&str, &str> {
+///   alt((
+///     preceded(one_of("+-"), digit1),
+///     rest
+///   ))(input)
+/// }
 ///
-/// assert_eq!(parser("abcd;"), Ok((";", "abcd")));
-/// assert_eq!(parser("123;"), Err(Err::Failure(("123;", ErrorKind::Alpha))));
+/// assert_eq!(parser("+10 ab"), Ok((" ab", "10")));
+/// assert_eq!(parser("ab"), Ok(("", "ab")));
+/// assert_eq!(parser("+"), Ok(("", "+")));
+/// # }
+/// ```
+///
+/// With `cut`:
+/// ```rust
+/// # use nom::{Err,error::ErrorKind, IResult, error::Error};
+/// # use nom::character::complete::{one_of, digit1};
+/// # use nom::combinator::rest;
+/// # use nom::branch::alt;
+/// # use nom::sequence::preceded;
+/// use nom::combinator::cut;
+/// # fn main() {
+///
+/// fn parser(input: &str) -> IResult<&str, &str> {
+///   alt((
+///     preceded(one_of("+-"), cut(digit1)),
+///     rest
+///   ))(input)
+/// }
+///
+/// assert_eq!(parser("+10 ab"), Ok((" ab", "10")));
+/// assert_eq!(parser("ab"), Ok(("", "ab")));
+/// assert_eq!(parser("+"), Err(Err::Failure(Error { input: "", code: ErrorKind::Digit })));
 /// # }
 /// ```
 pub fn cut<I, O, E: ParseError<I>, F>(mut parser: F) -> impl FnMut(I) -> IResult<I, O, E>
@@ -643,6 +682,8 @@
 /// Call the iterator's [ParserIterator::finish] method to get the remaining input if successful,
 /// or the error value if we encountered an error.
 ///
+/// On [`Err::Error`], iteration will stop. To instead chain an error up, see [`cut`].
+///
 /// ```rust
 /// use nom::{combinator::iterator, IResult, bytes::complete::tag, character::complete::alpha1, sequence::terminated};
 /// use std::collections::HashMap;
diff --git a/src/internal.rs b/src/internal.rs
index 8a3c6a1..b7572fb 100644
--- a/src/internal.rs
+++ b/src/internal.rs
@@ -473,7 +473,9 @@
   #[cfg(target_pointer_width = "64")]
   fn size_test() {
     assert_size!(IResult<&[u8], &[u8], (&[u8], u32)>, 40);
-    assert_size!(IResult<&str, &str, u32>, 40);
+    //FIXME: since rust 1.65, this is now 32 bytes, likely thanks to https://github.com/rust-lang/rust/pull/94075
+    // deactivating that test for now because it'll have different values depending on the rust version
+    // assert_size!(IResult<&str, &str, u32>, 40);
     assert_size!(Needed, 8);
     assert_size!(Err<u32>, 16);
     assert_size!(ErrorKind, 1);
diff --git a/src/lib.rs b/src/lib.rs
index 1ce115a..3beb2f4 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -52,16 +52,16 @@
 //!
 //! The code is available on [Github](https://github.com/Geal/nom)
 //!
-//! There are a few [guides](https://github.com/Geal/nom/tree/master/doc) with more details
-//! about [how to write parsers](https://github.com/Geal/nom/blob/master/doc/making_a_new_parser_from_scratch.md),
-//! or the [error management system](https://github.com/Geal/nom/blob/master/doc/error_management.md).
+//! There are a few [guides](https://github.com/Geal/nom/tree/main/doc) with more details
+//! about [how to write parsers](https://github.com/Geal/nom/blob/main/doc/making_a_new_parser_from_scratch.md),
+//! or the [error management system](https://github.com/Geal/nom/blob/main/doc/error_management.md).
 //! You can also check out the [recipes] module that contains examples of common patterns.
 //!
 //! **Looking for a specific combinator? Read the
-//! ["choose a combinator" guide](https://github.com/Geal/nom/blob/master/doc/choosing_a_combinator.md)**
+//! ["choose a combinator" guide](https://github.com/Geal/nom/blob/main/doc/choosing_a_combinator.md)**
 //!
 //! If you are upgrading to nom 5.0, please read the
-//! [migration document](https://github.com/Geal/nom/blob/master/doc/upgrading_to_nom_5.md).
+//! [migration document](https://github.com/Geal/nom/blob/main/doc/upgrading_to_nom_5.md).
 //!
 //! ## Parser combinators
 //!
@@ -167,8 +167,8 @@
 //! - An error `Err(Err::Incomplete(Needed))` indicating that more input is necessary. `Needed` can indicate how much data is needed
 //! - An error `Err(Err::Failure(c))`. It works like the `Error` case, except it indicates an unrecoverable error: We cannot backtrack and test another parser
 //!
-//! Please refer to the ["choose a combinator" guide](https://github.com/Geal/nom/blob/master/doc/choosing_a_combinator.md) for an exhaustive list of parsers.
-//! See also the rest of the documentation [here](https://github.com/Geal/nom/blob/master/doc).
+//! Please refer to the ["choose a combinator" guide](https://github.com/Geal/nom/blob/main/doc/choosing_a_combinator.md) for an exhaustive list of parsers.
+//! See also the rest of the documentation [here](https://github.com/Geal/nom/blob/main/doc).
 //!
 //! ## Making new parsers with function combinators
 //!
@@ -253,7 +253,7 @@
 //! - **`many0`**: Will apply the parser 0 or more times (if it returns the `O` type, the new parser returns `Vec<O>`)
 //! - **`many1`**: Will apply the parser 1 or more times
 //!
-//! There are more complex (and more useful) parsers like `tuple!`, which is
+//! There are more complex (and more useful) parsers like `tuple`, which is
 //! used to apply a series of parsers then assemble their results.
 //!
 //! Example with `tuple`:
@@ -369,11 +369,10 @@
 //! // while the complete version knows that all of the data is there
 //! assert_eq!(alpha0_complete("abcd"), Ok(("", "abcd")));
 //! ```
-//! **Going further:** Read the [guides](https://github.com/Geal/nom/tree/master/doc),
+//! **Going further:** Read the [guides](https://github.com/Geal/nom/tree/main/doc),
 //! check out the [recipes]!
 #![cfg_attr(not(feature = "std"), no_std)]
 #![cfg_attr(feature = "cargo-clippy", allow(clippy::doc_markdown))]
-#![cfg_attr(nightly, feature(test))]
 #![cfg_attr(feature = "docsrs", feature(doc_cfg))]
 #![cfg_attr(feature = "docsrs", feature(extended_key_value_attributes))]
 #![deny(missing_docs)]
@@ -384,9 +383,6 @@
 #[cfg(doctest)]
 extern crate doc_comment;
 
-#[cfg(nightly)]
-extern crate test;
-
 #[cfg(doctest)]
 doc_comment::doctest!("../README.md");
 
@@ -443,15 +439,16 @@
 pub use self::str::*;
 
 #[macro_use]
+mod macros;
+#[macro_use]
 pub mod error;
 
+pub mod branch;
 pub mod combinator;
 mod internal;
-mod traits;
-#[macro_use]
-pub mod branch;
 pub mod multi;
 pub mod sequence;
+mod traits;
 
 pub mod bits;
 pub mod bytes;
diff --git a/src/macros.rs b/src/macros.rs
new file mode 100644
index 0000000..980d2d9
--- /dev/null
+++ b/src/macros.rs
@@ -0,0 +1,23 @@
+macro_rules! succ (
+  (0, $submac:ident ! ($($rest:tt)*)) => ($submac!(1, $($rest)*));
+  (1, $submac:ident ! ($($rest:tt)*)) => ($submac!(2, $($rest)*));
+  (2, $submac:ident ! ($($rest:tt)*)) => ($submac!(3, $($rest)*));
+  (3, $submac:ident ! ($($rest:tt)*)) => ($submac!(4, $($rest)*));
+  (4, $submac:ident ! ($($rest:tt)*)) => ($submac!(5, $($rest)*));
+  (5, $submac:ident ! ($($rest:tt)*)) => ($submac!(6, $($rest)*));
+  (6, $submac:ident ! ($($rest:tt)*)) => ($submac!(7, $($rest)*));
+  (7, $submac:ident ! ($($rest:tt)*)) => ($submac!(8, $($rest)*));
+  (8, $submac:ident ! ($($rest:tt)*)) => ($submac!(9, $($rest)*));
+  (9, $submac:ident ! ($($rest:tt)*)) => ($submac!(10, $($rest)*));
+  (10, $submac:ident ! ($($rest:tt)*)) => ($submac!(11, $($rest)*));
+  (11, $submac:ident ! ($($rest:tt)*)) => ($submac!(12, $($rest)*));
+  (12, $submac:ident ! ($($rest:tt)*)) => ($submac!(13, $($rest)*));
+  (13, $submac:ident ! ($($rest:tt)*)) => ($submac!(14, $($rest)*));
+  (14, $submac:ident ! ($($rest:tt)*)) => ($submac!(15, $($rest)*));
+  (15, $submac:ident ! ($($rest:tt)*)) => ($submac!(16, $($rest)*));
+  (16, $submac:ident ! ($($rest:tt)*)) => ($submac!(17, $($rest)*));
+  (17, $submac:ident ! ($($rest:tt)*)) => ($submac!(18, $($rest)*));
+  (18, $submac:ident ! ($($rest:tt)*)) => ($submac!(19, $($rest)*));
+  (19, $submac:ident ! ($($rest:tt)*)) => ($submac!(20, $($rest)*));
+  (20, $submac:ident ! ($($rest:tt)*)) => ($submac!(21, $($rest)*));
+);
diff --git a/src/multi/mod.rs b/src/multi/mod.rs
index a119134..7312908 100644
--- a/src/multi/mod.rs
+++ b/src/multi/mod.rs
@@ -11,15 +11,28 @@
 use crate::traits::{InputLength, InputTake, ToUsize};
 use core::num::NonZeroUsize;
 
-/// Repeats the embedded parser until it fails
-/// and returns the results in a `Vec`.
+/// Don't pre-allocate more than 64KiB when calling `Vec::with_capacity`.
+///
+/// Pre-allocating memory is a nice optimization but count fields can't
+/// always be trusted. We should clamp initial capacities to some reasonable
+/// amount. This reduces the risk of a bogus count value triggering a panic
+/// due to an OOM error.
+///
+/// This does not affect correctness. Nom will always read the full number
+/// of elements regardless of the capacity cap.
+#[cfg(feature = "alloc")]
+const MAX_INITIAL_CAPACITY_BYTES: usize = 65536;
+
+/// Repeats the embedded parser, gathering the results in a `Vec`.
+///
+/// This stops on [`Err::Error`] and returns the results that were accumulated. To instead chain an error up, see
+/// [`cut`][crate::combinator::cut].
 ///
 /// # Arguments
 /// * `f` The parser to apply.
 ///
-/// *Note*: if the parser passed to `many0` accepts empty inputs
-/// (like `alpha0` or `digit0`), `many0` will return an error,
-/// to prevent going into an infinite loop
+/// *Note*: if the parser passed in accepts empty inputs (like `alpha0` or `digit0`), `many0` will
+/// return an error, to prevent going into an infinite loop
 ///
 /// ```rust
 /// # use nom::{Err, error::ErrorKind, Needed, IResult};
@@ -64,10 +77,10 @@
   }
 }
 
-/// Runs the embedded parser until it fails and
-/// returns the results in a `Vec`. Fails if
-/// the embedded parser does not produce at least
-/// one result.
+/// Runs the embedded parser, gathering the results in a `Vec`.
+///
+/// This stops on [`Err::Error`] if there is at least one result,  and returns the results that were accumulated. To instead chain an error up,
+/// see [`cut`][crate::combinator::cut].
 ///
 /// # Arguments
 /// * `f` The parser to apply.
@@ -126,9 +139,12 @@
   }
 }
 
-/// Applies the parser `f` until the parser `g` produces
-/// a result. Returns a pair consisting of the results of
-/// `f` in a `Vec` and the result of `g`.
+/// Applies the parser `f` until the parser `g` produces a result.
+///
+/// Returns a tuple of the results of `f` in a `Vec` and the result of `g`.
+///
+/// `f` keeps going so long as `g` produces [`Err::Error`]. To instead chain an error up, see [`cut`][crate::combinator::cut].
+///
 /// ```rust
 /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
 /// use nom::multi::many_till;
@@ -183,8 +199,11 @@
   }
 }
 
-/// Alternates between two parsers to produce
-/// a list of elements.
+/// Alternates between two parsers to produce a list of elements.
+///
+/// This stops when either parser returns [`Err::Error`]  and returns the results that were accumulated. To instead chain an error up, see
+/// [`cut`][crate::combinator::cut].
+///
 /// # Arguments
 /// * `sep` Parses the separator between list elements.
 /// * `f` Parses the elements of the list.
@@ -253,9 +272,13 @@
   }
 }
 
-/// Alternates between two parsers to produce
-/// a list of elements. Fails if the element
-/// parser does not produce at least one element.
+/// Alternates between two parsers to produce a list of elements until [`Err::Error`].
+///
+/// Fails if the element parser does not produce at least one element.$
+///
+/// This stops when either parser returns [`Err::Error`]  and returns the results that were accumulated. To instead chain an error up, see
+/// [`cut`][crate::combinator::cut].
+///
 /// # Arguments
 /// * `sep` Parses the separator between list elements.
 /// * `f` Parses the elements of the list.
@@ -323,13 +346,20 @@
   }
 }
 
-/// Repeats the embedded parser `n` times or until it fails
-/// and returns the results in a `Vec`. Fails if the
-/// embedded parser does not succeed at least `m` times.
+/// Repeats the embedded parser `m..=n` times
+///
+/// This stops before `n` when the parser returns [`Err::Error`]  and returns the results that were accumulated. To instead chain an error up, see
+/// [`cut`][crate::combinator::cut].
+///
 /// # Arguments
 /// * `m` The minimum number of iterations.
 /// * `n` The maximum number of iterations.
 /// * `f` The parser to apply.
+///
+/// *Note*: If the parser passed to `many1` accepts empty inputs
+/// (like `alpha0` or `digit0`), `many1` will return an error,
+/// to prevent going into an infinite loop.
+///
 /// ```rust
 /// # use nom::{Err, error::ErrorKind, Needed, IResult};
 /// use nom::multi::many_m_n;
@@ -362,7 +392,9 @@
       return Err(Err::Failure(E::from_error_kind(input, ErrorKind::ManyMN)));
     }
 
-    let mut res = crate::lib::std::vec::Vec::with_capacity(min);
+    let max_initial_capacity =
+      MAX_INITIAL_CAPACITY_BYTES / crate::lib::std::mem::size_of::<O>().max(1);
+    let mut res = crate::lib::std::vec::Vec::with_capacity(min.min(max_initial_capacity));
     for count in 0..max {
       let len = input.input_len();
       match parse.parse(input.clone()) {
@@ -392,10 +424,17 @@
   }
 }
 
-/// Repeats the embedded parser until it fails
-/// and returns the number of successful iterations.
+/// Repeats the embedded parser, counting the results
+///
+/// This stops on [`Err::Error`]. To instead chain an error up, see
+/// [`cut`][crate::combinator::cut].
+///
 /// # Arguments
 /// * `f` The parser to apply.
+///
+/// *Note*: if the parser passed in accepts empty inputs (like `alpha0` or `digit0`), `many0` will
+/// return an error, to prevent going into an infinite loop
+///
 /// ```rust
 /// # use nom::{Err, error::ErrorKind, Needed, IResult};
 /// use nom::multi::many0_count;
@@ -442,12 +481,18 @@
   }
 }
 
-/// Repeats the embedded parser until it fails
-/// and returns the number of successful iterations.
-/// Fails if the embedded parser does not succeed
-/// at least once.
+/// Runs the embedded parser, counting the results.
+///
+/// This stops on [`Err::Error`] if there is at least one result. To instead chain an error up,
+/// see [`cut`][crate::combinator::cut].
+///
 /// # Arguments
 /// * `f` The parser to apply.
+///
+/// *Note*: If the parser passed to `many1` accepts empty inputs
+/// (like `alpha0` or `digit0`), `many1` will return an error,
+/// to prevent going into an infinite loop.
+///
 /// ```rust
 /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
 /// use nom::multi::many1_count;
@@ -499,8 +544,8 @@
   }
 }
 
-/// Runs the embedded parser a specified number
-/// of times. Returns the results in a `Vec`.
+/// Runs the embedded parser `count` times, gathering the results in a `Vec`
+///
 /// # Arguments
 /// * `f` The parser to apply.
 /// * `count` How often to apply the parser.
@@ -529,7 +574,9 @@
 {
   move |i: I| {
     let mut input = i.clone();
-    let mut res = crate::lib::std::vec::Vec::with_capacity(count);
+    let max_initial_capacity =
+      MAX_INITIAL_CAPACITY_BYTES / crate::lib::std::mem::size_of::<O>().max(1);
+    let mut res = crate::lib::std::vec::Vec::with_capacity(count.min(max_initial_capacity));
 
     for _ in 0..count {
       let input_ = input.clone();
@@ -551,8 +598,10 @@
   }
 }
 
-/// Runs the embedded parser repeatedly, filling the given slice with results. This parser fails if
-/// the input runs out before the given slice is full.
+/// Runs the embedded parser repeatedly, filling the given slice with results.
+///
+/// This parser fails if the input runs out before the given slice is full.
+///
 /// # Arguments
 /// * `f` The parser to apply.
 /// * `buf` The slice to fill
@@ -602,13 +651,20 @@
   }
 }
 
-/// Applies a parser until it fails and accumulates
-/// the results using a given function and initial value.
+/// Repeats the embedded parser, calling `g` to gather the results.
+///
+/// This stops on [`Err::Error`]. To instead chain an error up, see
+/// [`cut`][crate::combinator::cut].
+///
 /// # Arguments
 /// * `f` The parser to apply.
 /// * `init` A function returning the initial value.
 /// * `g` The function that combines a result of `f` with
 ///       the current accumulator.
+///
+/// *Note*: if the parser passed in accepts empty inputs (like `alpha0` or `digit0`), `many0` will
+/// return an error, to prevent going into an infinite loop
+///
 /// ```rust
 /// # use nom::{Err, error::ErrorKind, Needed, IResult};
 /// use nom::multi::fold_many0;
@@ -670,15 +726,21 @@
   }
 }
 
-/// Applies a parser until it fails and accumulates
-/// the results using a given function and initial value.
-/// Fails if the embedded parser does not succeed at least
-/// once.
+/// Repeats the embedded parser, calling `g` to gather the results.
+///
+/// This stops on [`Err::Error`] if there is at least one result. To instead chain an error up,
+/// see [`cut`][crate::combinator::cut].
+///
 /// # Arguments
 /// * `f` The parser to apply.
 /// * `init` A function returning the initial value.
 /// * `g` The function that combines a result of `f` with
 ///       the current accumulator.
+///
+/// *Note*: If the parser passed to `many1` accepts empty inputs
+/// (like `alpha0` or `digit0`), `many1` will return an error,
+/// to prevent going into an infinite loop.
+///
 /// ```rust
 /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
 /// use nom::multi::fold_many1;
@@ -748,10 +810,11 @@
   }
 }
 
-/// Applies a parser `n` times or until it fails and accumulates
-/// the results using a given function and initial value.
-/// Fails if the embedded parser does not succeed at least `m`
-/// times.
+/// Repeats the embedded parser `m..=n` times, calling `g` to gather the results
+///
+/// This stops before `n` when the parser returns [`Err::Error`]. To instead chain an error up, see
+/// [`cut`][crate::combinator::cut].
+///
 /// # Arguments
 /// * `m` The minimum number of iterations.
 /// * `n` The maximum number of iterations.
@@ -759,6 +822,11 @@
 /// * `init` A function returning the initial value.
 /// * `g` The function that combines a result of `f` with
 ///       the current accumulator.
+///
+/// *Note*: If the parser passed to `many1` accepts empty inputs
+/// (like `alpha0` or `digit0`), `many1` will return an error,
+/// to prevent going into an infinite loop.
+///
 /// ```rust
 /// # use nom::{Err, error::ErrorKind, Needed, IResult};
 /// use nom::multi::fold_many_m_n;
diff --git a/src/multi/tests.rs b/src/multi/tests.rs
index 2a96f84..96a6518 100644
--- a/src/multi/tests.rs
+++ b/src/multi/tests.rs
@@ -129,16 +129,6 @@
   );
 }
 
-#[cfg(nightly)]
-use test::Bencher;
-
-#[cfg(nightly)]
-#[bench]
-fn many0_bench(b: &mut Bencher) {
-  named!(multi<&[u8],Vec<&[u8]> >, many0!(tag!("abcd")));
-  b.iter(|| multi(&b"abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"[..]));
-}
-
 #[test]
 #[cfg(feature = "alloc")]
 fn many1_test() {
diff --git a/src/number/complete.rs b/src/number/complete.rs
index d23079e..98b8b3a 100644
--- a/src/number/complete.rs
+++ b/src/number/complete.rs
@@ -13,26 +13,6 @@
   AsBytes, AsChar, Compare, InputIter, InputLength, InputTake, InputTakeAtPosition, Offset, Slice,
 };
 
-#[doc(hidden)]
-macro_rules! map(
-  // Internal parser, do not use directly
-  (__impl $i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => (
-    $crate::combinator::map(move |i| {$submac!(i, $($args)*)}, $g).parse($i)
-  );
-  ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => (
-    map!(__impl $i, $submac!($($args)*), $g)
-  );
-  ($i:expr, $f:expr, $g:expr) => (
-    map!(__impl $i, call!($f), $g)
-  );
-);
-
-#[doc(hidden)]
-macro_rules! call (
-  ($i:expr, $fun:expr) => ( $fun( $i ) );
-  ($i:expr, $fun:expr, $($args:expr),* ) => ( $fun( $i, $($args),* ) );
-);
-
 /// Recognizes an unsigned 1 byte integer.
 ///
 /// *Complete version*: Returns an error if there is not enough input data.
@@ -211,7 +191,6 @@
 /// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
 /// ```
 #[inline]
-#[cfg(stable_i128)]
 pub fn be_u128<I, E: ParseError<I>>(input: I) -> IResult<I, u128, E>
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
@@ -249,7 +228,7 @@
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
-  map!(input, be_u8, |x| x as i8)
+  be_u8.map(|x| x as i8).parse(input)
 }
 
 /// Recognizes a big endian signed 2 bytes integer.
@@ -272,7 +251,7 @@
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
-  map!(input, be_u16, |x| x as i16)
+  be_u16.map(|x| x as i16).parse(input)
 }
 
 /// Recognizes a big endian signed 3 bytes integer.
@@ -296,16 +275,20 @@
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
   // Same as the unsigned version but we need to sign-extend manually here
-  map!(input, be_u24, |x| if x & 0x80_00_00 != 0 {
-    (x | 0xff_00_00_00) as i32
-  } else {
-    x as i32
-  })
+  be_u24
+    .map(|x| {
+      if x & 0x80_00_00 != 0 {
+        (x | 0xff_00_00_00) as i32
+      } else {
+        x as i32
+      }
+    })
+    .parse(input)
 }
 
 /// Recognizes a big endian signed 4 bytes integer.
 ///
-/// *Complete version*: Teturns an error if there is not enough input data.
+/// *Complete version*: Returns an error if there is not enough input data.
 /// ```rust
 /// # use nom::{Err, error::ErrorKind, Needed};
 /// # use nom::Needed::Size;
@@ -323,7 +306,7 @@
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
-  map!(input, be_u32, |x| x as i32)
+  be_u32.map(|x| x as i32).parse(input)
 }
 
 /// Recognizes a big endian signed 8 bytes integer.
@@ -346,7 +329,7 @@
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
-  map!(input, be_u64, |x| x as i64)
+  be_u64.map(|x| x as i64).parse(input)
 }
 
 /// Recognizes a big endian signed 16 bytes integer.
@@ -365,12 +348,11 @@
 /// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
 /// ```
 #[inline]
-#[cfg(stable_i128)]
 pub fn be_i128<I, E: ParseError<I>>(input: I) -> IResult<I, i128, E>
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
-  map!(input, be_u128, |x| x as i128)
+  be_u128.map(|x| x as i128).parse(input)
 }
 
 /// Recognizes an unsigned 1 byte integer.
@@ -551,7 +533,6 @@
 /// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
 /// ```
 #[inline]
-#[cfg(stable_i128)]
 pub fn le_u128<I, E: ParseError<I>>(input: I) -> IResult<I, u128, E>
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
@@ -589,7 +570,7 @@
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
-  map!(input, be_u8, |x| x as i8)
+  be_u8.map(|x| x as i8).parse(input)
 }
 
 /// Recognizes a little endian signed 2 bytes integer.
@@ -612,7 +593,7 @@
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
-  map!(input, le_u16, |x| x as i16)
+  le_u16.map(|x| x as i16).parse(input)
 }
 
 /// Recognizes a little endian signed 3 bytes integer.
@@ -636,11 +617,15 @@
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
   // Same as the unsigned version but we need to sign-extend manually here
-  map!(input, le_u24, |x| if x & 0x80_00_00 != 0 {
-    (x | 0xff_00_00_00) as i32
-  } else {
-    x as i32
-  })
+  le_u24
+    .map(|x| {
+      if x & 0x80_00_00 != 0 {
+        (x | 0xff_00_00_00) as i32
+      } else {
+        x as i32
+      }
+    })
+    .parse(input)
 }
 
 /// Recognizes a little endian signed 4 bytes integer.
@@ -663,7 +648,7 @@
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
-  map!(input, le_u32, |x| x as i32)
+  le_u32.map(|x| x as i32).parse(input)
 }
 
 /// Recognizes a little endian signed 8 bytes integer.
@@ -686,7 +671,7 @@
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
-  map!(input, le_u64, |x| x as i64)
+  le_u64.map(|x| x as i64).parse(input)
 }
 
 /// Recognizes a little endian signed 16 bytes integer.
@@ -705,12 +690,11 @@
 /// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
 /// ```
 #[inline]
-#[cfg(stable_i128)]
 pub fn le_i128<I, E: ParseError<I>>(input: I) -> IResult<I, i128, E>
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
-  map!(input, le_u128, |x| x as i128)
+  le_u128.map(|x| x as i128).parse(input)
 }
 
 /// Recognizes an unsigned 1 byte integer
@@ -926,7 +910,6 @@
 /// assert_eq!(le_u128(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
 /// ```
 #[inline]
-#[cfg(stable_i128)]
 pub fn u128<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, u128, E>
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
@@ -962,7 +945,7 @@
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
-  map!(i, u8, |x| x as i8)
+  u8.map(|x| x as i8).parse(i)
 }
 
 /// Recognizes a signed 2 byte integer
@@ -1146,7 +1129,6 @@
 /// assert_eq!(le_i128(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
 /// ```
 #[inline]
-#[cfg(stable_i128)]
 pub fn i128<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, i128, E>
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
@@ -1460,7 +1442,10 @@
   ))(input)
 }
 
-/// Recognizes a floating point number in text format and returns the integer, fraction and exponent parts of the input data
+/// Recognizes a floating point number in text format
+///
+/// It returns a tuple of (`sign`, `integer part`, `fraction part` and `exponent`) of the input
+/// data.
 ///
 /// *Complete version*: Can parse until the end of input.
 ///
@@ -1598,7 +1583,7 @@
       */
   let (i, s) = recognize_float_or_exceptions(input)?;
   match s.parse_to() {
-    Some(f) => (Ok((i, f))),
+    Some(f) => Ok((i, f)),
     None => Err(crate::Err::Error(E::from_error_kind(
       i,
       crate::error::ErrorKind::Float,
@@ -1651,7 +1636,7 @@
       */
   let (i, s) = recognize_float_or_exceptions(input)?;
   match s.parse_to() {
-    Some(f) => (Ok((i, f))),
+    Some(f) => Ok((i, f)),
     None => Err(crate::Err::Error(E::from_error_kind(
       i,
       crate::error::ErrorKind::Float,
@@ -1752,7 +1737,6 @@
   }
 
   #[test]
-  #[cfg(stable_i128)]
   fn be_i128_tests() {
     assert_parse!(
       be_i128(
@@ -1869,7 +1853,6 @@
   }
 
   #[test]
-  #[cfg(stable_i128)]
   fn le_i128_tests() {
     assert_parse!(
       le_i128(
@@ -2116,7 +2099,7 @@
 
   #[cfg(feature = "std")]
   fn parse_f64(i: &str) -> IResult<&str, f64, ()> {
-    match recognize_float(i) {
+    match recognize_float_or_exceptions(i) {
       Err(e) => Err(e),
       Ok((i, s)) => {
         if s.is_empty() {
diff --git a/src/number/streaming.rs b/src/number/streaming.rs
index 7c53ccc..b4e856d 100644
--- a/src/number/streaming.rs
+++ b/src/number/streaming.rs
@@ -12,26 +12,6 @@
   AsBytes, AsChar, Compare, InputIter, InputLength, InputTake, InputTakeAtPosition, Offset, Slice,
 };
 
-#[doc(hidden)]
-macro_rules! map(
-  // Internal parser, do not use directly
-  (__impl $i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => (
-    $crate::combinator::map(move |i| {$submac!(i, $($args)*)}, $g).parse($i)
-  );
-  ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => (
-    map!(__impl $i, $submac!($($args)*), $g)
-  );
-  ($i:expr, $f:expr, $g:expr) => (
-    map!(__impl $i, call!($f), $g)
-  );
-);
-
-#[doc(hidden)]
-macro_rules! call (
-  ($i:expr, $fun:expr) => ( $fun( $i ) );
-  ($i:expr, $fun:expr, $($args:expr),* ) => ( $fun( $i, $($args),* ) );
-);
-
 /// Recognizes an unsigned 1 byte integer.
 ///
 /// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data.
@@ -208,7 +188,6 @@
 /// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15))));
 /// ```
 #[inline]
-#[cfg(stable_i128)]
 pub fn be_u128<I, E: ParseError<I>>(input: I) -> IResult<I, u128, E>
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
@@ -243,7 +222,7 @@
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
-  map!(input, be_u8, |x| x as i8)
+  be_u8.map(|x| x as i8).parse(input)
 }
 
 /// Recognizes a big endian signed 2 bytes integer.
@@ -263,7 +242,7 @@
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
-  map!(input, be_u16, |x| x as i16)
+  be_u16.map(|x| x as i16).parse(input)
 }
 
 /// Recognizes a big endian signed 3 bytes integer.
@@ -284,11 +263,15 @@
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
   // Same as the unsigned version but we need to sign-extend manually here
-  map!(input, be_u24, |x| if x & 0x80_00_00 != 0 {
-    (x | 0xff_00_00_00) as i32
-  } else {
-    x as i32
-  })
+  be_u24
+    .map(|x| {
+      if x & 0x80_00_00 != 0 {
+        (x | 0xff_00_00_00) as i32
+      } else {
+        x as i32
+      }
+    })
+    .parse(input)
 }
 
 /// Recognizes a big endian signed 4 bytes integer.
@@ -308,7 +291,7 @@
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
-  map!(input, be_u32, |x| x as i32)
+  be_u32.map(|x| x as i32).parse(input)
 }
 
 /// Recognizes a big endian signed 8 bytes integer.
@@ -329,7 +312,7 @@
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
-  map!(input, be_u64, |x| x as i64)
+  be_u64.map(|x| x as i64).parse(input)
 }
 
 /// Recognizes a big endian signed 16 bytes integer.
@@ -345,12 +328,11 @@
 /// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15))));
 /// ```
 #[inline]
-#[cfg(stable_i128)]
 pub fn be_i128<I, E: ParseError<I>>(input: I) -> IResult<I, i128, E>
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
-  map!(input, be_u128, |x| x as i128)
+  be_u128.map(|x| x as i128).parse(input)
 }
 
 /// Recognizes an unsigned 1 byte integer.
@@ -528,7 +510,6 @@
 /// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15))));
 /// ```
 #[inline]
-#[cfg(stable_i128)]
 pub fn le_u128<I, E: ParseError<I>>(input: I) -> IResult<I, u128, E>
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
@@ -563,7 +544,7 @@
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
-  map!(input, le_u8, |x| x as i8)
+  le_u8.map(|x| x as i8).parse(input)
 }
 
 /// Recognizes a little endian signed 2 bytes integer.
@@ -586,7 +567,7 @@
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
-  map!(input, le_u16, |x| x as i16)
+  le_u16.map(|x| x as i16).parse(input)
 }
 
 /// Recognizes a little endian signed 3 bytes integer.
@@ -610,11 +591,15 @@
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
   // Same as the unsigned version but we need to sign-extend manually here
-  map!(input, le_u24, |x| if x & 0x80_00_00 != 0 {
-    (x | 0xff_00_00_00) as i32
-  } else {
-    x as i32
-  })
+  le_u24
+    .map(|x| {
+      if x & 0x80_00_00 != 0 {
+        (x | 0xff_00_00_00) as i32
+      } else {
+        x as i32
+      }
+    })
+    .parse(input)
 }
 
 /// Recognizes a little endian signed 4 bytes integer.
@@ -637,7 +622,7 @@
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
-  map!(input, le_u32, |x| x as i32)
+  le_u32.map(|x| x as i32).parse(input)
 }
 
 /// Recognizes a little endian signed 8 bytes integer.
@@ -660,7 +645,7 @@
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
-  map!(input, le_u64, |x| x as i64)
+  le_u64.map(|x| x as i64).parse(input)
 }
 
 /// Recognizes a little endian signed 16 bytes integer.
@@ -679,12 +664,11 @@
 /// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15))));
 /// ```
 #[inline]
-#[cfg(stable_i128)]
 pub fn le_i128<I, E: ParseError<I>>(input: I) -> IResult<I, i128, E>
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
-  map!(input, le_u128, |x| x as i128)
+  le_u128.map(|x| x as i128).parse(input)
 }
 
 /// Recognizes an unsigned 1 byte integer
@@ -900,7 +884,6 @@
 /// assert_eq!(le_u128(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15))));
 /// ```
 #[inline]
-#[cfg(stable_i128)]
 pub fn u128<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, u128, E>
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
@@ -936,7 +919,7 @@
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
 {
-  map!(i, u8, |x| x as i8)
+  u8.map(|x| x as i8).parse(i)
 }
 
 /// Recognizes a signed 2 byte integer
@@ -1120,7 +1103,6 @@
 /// assert_eq!(le_i128(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15))));
 /// ```
 #[inline]
-#[cfg(stable_i128)]
 pub fn i128<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, i128, E>
 where
   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
@@ -1429,7 +1411,10 @@
   ))(input)
 }
 
-/// Recognizes a floating point number in text format and returns the integer, fraction and exponent parts of the input data
+/// Recognizes a floating point number in text format
+///
+/// It returns a tuple of (`sign`, `integer part`, `fraction part` and `exponent`) of the input
+/// data.
 ///
 /// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there is not enough data.
 ///
@@ -1570,7 +1555,7 @@
   */
   let (i, s) = recognize_float_or_exceptions(input)?;
   match s.parse_to() {
-    Some(f) => (Ok((i, f))),
+    Some(f) => Ok((i, f)),
     None => Err(crate::Err::Error(E::from_error_kind(
       i,
       crate::error::ErrorKind::Float,
@@ -1624,7 +1609,7 @@
   */
   let (i, s) = recognize_float_or_exceptions(input)?;
   match s.parse_to() {
-    Some(f) => (Ok((i, f))),
+    Some(f) => Ok((i, f)),
     None => Err(crate::Err::Error(E::from_error_kind(
       i,
       crate::error::ErrorKind::Float,
@@ -1768,7 +1753,6 @@
   }
 
   #[test]
-  #[cfg(stable_i128)]
   fn i128_tests() {
     assert_parse!(
       be_i128(
@@ -1948,7 +1932,6 @@
   }
 
   #[test]
-  #[cfg(stable_i128)]
   fn le_i128_tests() {
     assert_parse!(
       le_i128(
@@ -2196,7 +2179,7 @@
   #[cfg(feature = "std")]
   fn parse_f64(i: &str) -> IResult<&str, f64, ()> {
     use crate::traits::ParseTo;
-    match recognize_float(i) {
+    match recognize_float_or_exceptions(i) {
       Err(e) => Err(e),
       Ok((i, s)) => {
         if s.is_empty() {
diff --git a/src/sequence/mod.rs b/src/sequence/mod.rs
index 100c63f..735ab45 100644
--- a/src/sequence/mod.rs
+++ b/src/sequence/mod.rs
@@ -252,8 +252,17 @@
 tuple_trait!(FnA A, FnB B, FnC C, FnD D, FnE E, FnF F, FnG G, FnH H, FnI I, FnJ J, FnK K, FnL L,
   FnM M, FnN N, FnO O, FnP P, FnQ Q, FnR R, FnS S, FnT T, FnU U);
 
+// Special case: implement `Tuple` for `()`, the unit type.
+// This can come up in macros which accept a variable number of arguments.
+// Literally, `()` is an empty tuple, so it should simply parse nothing.
+impl<I, E: ParseError<I>> Tuple<I, (), E> for () {
+  fn parse(&mut self, input: I) -> IResult<I, (), E> {
+    Ok((input, ()))
+  }
+}
+
 ///Applies a tuple of parsers one by one and returns their results as a tuple.
-///
+///There is a maximum of 21 parsers
 /// ```rust
 /// # use nom::{Err, error::ErrorKind};
 /// use nom::sequence::tuple;
diff --git a/src/sequence/tests.rs b/src/sequence/tests.rs
index 201579b..30ad0d6 100644
--- a/src/sequence/tests.rs
+++ b/src/sequence/tests.rs
@@ -1,6 +1,6 @@
 use super::*;
 use crate::bytes::streaming::{tag, take};
-use crate::error::ErrorKind;
+use crate::error::{Error, ErrorKind};
 use crate::internal::{Err, IResult, Needed};
 use crate::number::streaming::be_u16;
 
@@ -272,3 +272,19 @@
     Err(Err::Error(error_position!(&b"jk"[..], ErrorKind::Tag)))
   );
 }
+
+#[test]
+fn unit_type() {
+  assert_eq!(
+    tuple::<&'static str, (), Error<&'static str>, ()>(())("abxsbsh"),
+    Ok(("abxsbsh", ()))
+  );
+  assert_eq!(
+    tuple::<&'static str, (), Error<&'static str>, ()>(())("sdfjakdsas"),
+    Ok(("sdfjakdsas", ()))
+  );
+  assert_eq!(
+    tuple::<&'static str, (), Error<&'static str>, ()>(())(""),
+    Ok(("", ()))
+  );
+}
diff --git a/src/traits.rs b/src/traits.rs
index 3c3053e..394e5bc 100644
--- a/src/traits.rs
+++ b/src/traits.rs
@@ -914,6 +914,18 @@
   }
 }
 
+impl<'a> FindToken<char> for &'a [char] {
+  fn find_token(&self, token: char) -> bool {
+    self.iter().any(|i| *i == token)
+  }
+}
+
+impl<'a, 'b> FindToken<&'a char> for &'b [char] {
+  fn find_token(&self, token: &char) -> bool {
+    self.find_token(*token)
+  }
+}
+
 /// Look for a substring in self
 pub trait FindSubstring<T> {
   /// Returns the byte position of the substring if it is found
@@ -1318,6 +1330,10 @@
   }
 }
 
+impl ErrorConvert<()> for () {
+  fn convert(self) {}
+}
+
 #[cfg(feature = "std")]
 #[cfg_attr(feature = "docsrs", doc(cfg(feature = "std")))]
 /// Helper trait to show a byte slice as a hex dump
diff --git a/tests/issues.rs b/tests/issues.rs
index 6df183b..7985702 100644
--- a/tests/issues.rs
+++ b/tests/issues.rs
@@ -206,3 +206,37 @@
   }
   assert_eq!(example(&[0xff]), Ok((&b""[..], (1, 1))));
 }
+
+#[test]
+fn issue_1282_findtoken_char() {
+  use nom::character::complete::one_of;
+  use nom::error::Error;
+  let parser = one_of::<_, _, Error<_>>(&['a', 'b', 'c'][..]);
+  assert_eq!(parser("aaa"), Ok(("aa", 'a')));
+}
+
+#[test]
+fn issue_1459_clamp_capacity() {
+  use nom::character::complete::char;
+
+  // shouldn't panic
+  use nom::multi::many_m_n;
+  let mut parser = many_m_n::<_, _, (), _>(usize::MAX, usize::MAX, char('a'));
+  assert_eq!(parser("a"), Err(nom::Err::Error(())));
+
+  // shouldn't panic
+  use nom::multi::count;
+  let mut parser = count::<_, _, (), _>(char('a'), usize::MAX);
+  assert_eq!(parser("a"), Err(nom::Err::Error(())));
+}
+
+#[test]
+fn issue_1617_count_parser_returning_zero_size() {
+  use nom::{bytes::complete::tag, combinator::map, error::Error, multi::count};
+
+  // previously, `count()` panicked if the parser had type `O = ()`
+  let parser = map(tag::<_, _, Error<&str>>("abc"), |_| ());
+  // shouldn't panic
+  let result = count(parser, 3)("abcabcabcdef").expect("parsing should succeed");
+  assert_eq!(result, ("def", vec![(), (), ()]));
+}