Repository: Geal/nom
Pull request #1463 (2021-11-14 16:26:17)

`impl<'a> FindToken<char> for &'a [char]`
Closes Geal/nom#1282. Test case added to `tests/`. Useful for me.

<!--
Hello, and thank you for submitting a pull request to nom!

First, please note that, for family reasons, I have limited time to work on
nom, so following the advice here will make sure I will quickly understand
your work and be able to merge it early.
Second, if I don't get to work on your PR quickly, that does not mean I won't
include it later. Major version releases happen once a year, and a lot of
interesting work is merged for the occasion. So I will get back to you :)

## Prerequisites

Please provide the following information with this pull request:

- related issue number (I need some context to understand a PR with a lot of
code, except for documentation typos)
- a test case reproducing the issue. You can write it in [issues.rs](https://github.com/Geal/nom/blob/master/tests/issues.rs)
- if adding a new combinator, please add code documentation and some unit tests
in the same file. Also, please update the [combinator list](https://github.com/Geal/nom/blob/master/doc/choosing_a_combinator.md)

## Code style

This project follows a [code style](https://github.com/Geal/nom/blob/master/rustfmt.toml)
checked by [rustfmt][https://github.com/rust-lang-nursery/rustfmt].

Please avoid cosmetic fixes unrelated to the pull request. Keeping the changes
as small as possible increase your chances of getting this merged quickly.

## Rebasing

To make sure the changes will work properly once merged into the master branch
(which might have changed while you were working on your PR), please
[rebase your PR on master](https://git-scm.com/book/en/v2/Git-Branching-Rebasing).

## Squashing the commits

If the pull request include a lot of small commits used for testing, debugging,
or correcting previous work, it might be useful to
[squash the commits](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History)
to make the code easier to merge.
-->



Patch:
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 97a320a..932a2a5 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -14,13 +14,13 @@ Please provide the following information with this pull request:
 
 - related issue number (I need some context to understand a PR with a lot of
 code, except for documentation typos)
-- a test case reproducing the issue. You can write it in [issues.rs](https://github.com/Geal/nom/blob/master/tests/issues.rs)
+- a test case reproducing the issue. You can write it in [issues.rs](https://github.com/Geal/nom/blob/main/tests/issues.rs)
 - if adding a new combinator, please add code documentation and some unit tests
-in the same file. Also, please update the [combinator list](https://github.com/Geal/nom/blob/master/doc/choosing_a_combinator.md)
+in the same file. Also, please update the [combinator list](https://github.com/Geal/nom/blob/main/doc/choosing_a_combinator.md)
 
 ## Code style
 
-This project follows a [code style](https://github.com/Geal/nom/blob/master/rustfmt.toml)
+This project follows a [code style](https://github.com/Geal/nom/blob/main/rustfmt.toml)
 checked by [rustfmt][https://github.com/rust-lang-nursery/rustfmt].
 
 Please avoid cosmetic fixes unrelated to the pull request. Keeping the changes
@@ -28,9 +28,9 @@ as small as possible increase your chances of getting this merged quickly.
 
 ## Rebasing
 
-To make sure the changes will work properly once merged into the master branch
+To make sure the changes will work properly once merged into the main branch
 (which might have changed while you were working on your PR), please
-[rebase your PR on master](https://git-scm.com/book/en/v2/Git-Branching-Rebasing).
+[rebase your PR on main](https://git-scm.com/book/en/v2/Git-Branching-Rebasing).
 
 ## Squashing the commits
 
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a1bff5c..56709ea 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -851,7 +851,7 @@ Bugfix release
 
 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.
 
diff --git a/Cargo.toml b/Cargo.toml
index 4e5b011..663697c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,6 +13,9 @@ categories = ["parsing"]
 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 @@ include = [
   "src/*/*.rs",
   "tests/*.rs",
   "doc/nom_recipes.md",
-  "build.rs"
 ]
 
 [features]
@@ -44,9 +46,6 @@ default-features = false
 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
@@ -126,7 +125,7 @@ path = "examples/string.rs"
 
 [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/README.md b/README.md
index 1a95f96..d429164 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,7 +13,7 @@ that end, it uses extensively Rust's *strong typing* and *memory safety* to prod
 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 :)*
 
@@ -74,8 +74,8 @@ fn parse_color() {
 ## 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 +113,7 @@ formats such as JSON, nom can manage it, and provides you with useful tools:
 
 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 +148,7 @@ It allows you to build powerful, deterministic state machines for your protocols
 
 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 +186,7 @@ nom parsers are for:
 
 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 +230,7 @@ Here is a (non exhaustive) list of known projects using nom:
 [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 +251,7 @@ Here is a (non exhaustive) list of known projects using nom:
 [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 +262,15 @@ Here is a (non exhaustive) list of known projects using nom:
 [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),
diff --git a/benchmarks/benches/arithmetic.rs b/benchmarks/benches/arithmetic.rs
index 136aca5..cab1222 100644
--- a/benchmarks/benches/arithmetic.rs
+++ b/benchmarks/benches/arithmetic.rs
@@ -65,6 +65,7 @@ fn expr(input: &[u8]) -> IResult<&[u8], i64> {
   )(input)
 }
 
+#[allow(clippy::eq_op, clippy::erasing_op)]
 fn arithmetic(c: &mut Criterion) {
   let data = b"  2*2 / ( 5 - 1) + 3 / 4 * (2 - 7 + 567 *12 /2) + 3*(1+2*( 45 /2));";
 
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/doc/archive/FAQ.md b/doc/archive/FAQ.md
index 9b02ee9..eb39788 100644
--- a/doc/archive/FAQ.md
+++ b/doc/archive/FAQ.md
@@ -12,7 +12,7 @@ If you got the following error when compiling your nom parser:
 error[E0425]: cannot find value `INVALID_NOM_SYNTAX_PLEASE_SEE_FAQ` in this scope
    --> src/lib.rs:111:7
     |
-111 |         INVALID_NOM_SYNTAX_PLEASE_SEE_FAQ //https://github.com/Geal/nom/blob/master/doc/FAQ.md#using-nightly-to-get-better-error-messages
+111 |         INVALID_NOM_SYNTAX_PLEASE_SEE_FAQ //https://github.com/Geal/nom/blob/main/doc/archive/FAQ.md#using-nightly-to-get-better-error-messages
     |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
 ```
 
diff --git a/doc/archive/upgrading_to_nom_1.md b/doc/archive/upgrading_to_nom_1.md
index b59cb4a..f54a0bf 100644
--- a/doc/archive/upgrading_to_nom_1.md
+++ b/doc/archive/upgrading_to_nom_1.md
@@ -51,7 +51,7 @@ fn parse_status(i: &[u8]) -> IResult<&[u8], Status>
 
 # Producers and consumers
 
-The old implementation was not flexible, and a bit slow (because of allocations). The new implementation can be driven more precisely outside of the consumer, step by step if needed, can return a result, has custom error types, and can combine consumers. You can see [an example in the repository](https://github.com/Geal/nom/blob/master/tests/omnom.rs#).
+The old implementation was not flexible, and a bit slow (because of allocations). The new implementation can be driven more precisely outside of the consumer, step by step if needed, can return a result, has custom error types, and can combine consumers. You can see [an example in the repository](https://github.com/Geal/nom/blob/1.0/tests/omnom.rs#).
 
 # Changes around `Incomplete`
 
diff --git a/doc/choosing_a_combinator.md b/doc/choosing_a_combinator.md
index c004b5b..d7cb4d1 100644
--- a/doc/choosing_a_combinator.md
+++ b/doc/choosing_a_combinator.md
@@ -38,7 +38,7 @@ Those are used to recognize the lowest level elements of your grammar, like, "he
 | [terminated](https://docs.rs/nom/latest/nom/sequence/fn.terminated.html) | `terminated(tag("ab"), tag("XY"))` | `"abXYZ"` | `Ok(("Z", "ab"))` ||
 | [pair](https://docs.rs/nom/latest/nom/sequence/fn.pair.html) | `pair(tag("ab"), tag("XY"))` | `"abXYZ"` | `Ok(("Z", ("ab", "XY")))` ||
 | [separated_pair](https://docs.rs/nom/latest/nom/sequence/fn.separated_pair.html) | `separated_pair(tag("hello"), char(','), tag("world"))` | `"hello,world!"` | `Ok(("!", ("hello", "world")))` ||
-| [tuple](https://docs.rs/nom/latest/nom/sequence/fn.tuple.html) | `tuple(tag("ab"), tag("XY"), take(1))` | `"abXYZ!"` | `Ok(("!", ("ab", "XY", "Z")))` |Chains parsers and assemble the sub results in a tuple. You can use as many child parsers as you can put elements in a tuple|
+| [tuple](https://docs.rs/nom/latest/nom/sequence/fn.tuple.html) | `tuple((tag("ab"), tag("XY"), take(1)))` | `"abXYZ!"` | `Ok(("!", ("ab", "XY", "Z")))` |Chains parsers and assemble the sub results in a tuple. You can use as many child parsers as you can put elements in a tuple|
 
 ## Applying a parser multiple times
 
@@ -125,7 +125,7 @@ Use these functions with a combinator like `take_while`:
 - [`is_space`](https://docs.rs/nom/latest/nom/character/fn.is_space.html): Tests if byte is ASCII space or tab: `[ \t]`
 - [`is_newline`](https://docs.rs/nom/latest/nom/character/fn.is_newline.html): Tests if byte is ASCII newline: `[\n]`
 
-Alternatively there are ready to use function:
+Alternatively there are ready to use functions:
 
 - [`alpha0`](https://docs.rs/nom/latest/nom/character/complete/fn.alpha0.html): Recognizes zero or more lowercase and uppercase alphabetic characters: `[a-zA-Z]`. [`alpha1`](https://docs.rs/nom/latest/nom/character/complete/fn.alpha1.html) does the same but returns at least one character
 - [`alphanumeric0`](https://docs.rs/nom/latest/nom/character/complete/fn.alphanumeric0.html): Recognizes zero or more numerical and alphabetic characters: `[0-9a-zA-Z]`. [`alphanumeric1`](https://docs.rs/nom/latest/nom/character/complete/fn.alphanumeric1.html) does the same but returns at least one character
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 @@ letters and numbers may be parsed like this:
 use nom::{
   IResult,
   branch::alt,
-  multi::many0,
+  multi::many0_count,
   combinator::recognize,
   sequence::pair,
   character::complete::{alpha1, alphanumeric1},
@@ -126,7 +126,7 @@ pub fn identifier(input: &str) -> IResult<&str, &str> {
   recognize(
     pair(
       alt((alpha1, tag("_"))),
-      many0(alt((alphanumeric1, tag("_"))))
+      many0_count(alt((alphanumeric1, tag("_"))))
     )
   )(input)
 }
@@ -142,7 +142,7 @@ input text that was parsed, which in this case is the entire `&str` `hello_world
 
 ### 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/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 @@ where
 /// 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..a98bafb 100644
--- a/src/character/complete.rs
+++ b/src/character/complete.rs
@@ -414,6 +414,24 @@ where
 /// 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/lib.rs b/src/lib.rs
index 1ce115a..9429467 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 @@ extern crate alloc;
 #[cfg(doctest)]
 extern crate doc_comment;
 
-#[cfg(nightly)]
-extern crate test;
-
 #[cfg(doctest)]
 doc_comment::doctest!("../README.md");
 
diff --git a/src/number/complete.rs b/src/number/complete.rs
index d23079e..715da32 100644
--- a/src/number/complete.rs
+++ b/src/number/complete.rs
@@ -211,7 +211,6 @@ where
 /// 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,
@@ -365,7 +364,6 @@ where
 /// 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,
@@ -551,7 +549,6 @@ where
 /// 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,
@@ -705,7 +702,6 @@ where
 /// 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,
@@ -926,7 +922,6 @@ where
 /// 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,
@@ -1146,7 +1141,6 @@ where
 /// 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 +1454,10 @@ where
   ))(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.
 ///
@@ -1752,7 +1749,6 @@ mod tests {
   }
 
   #[test]
-  #[cfg(stable_i128)]
   fn be_i128_tests() {
     assert_parse!(
       be_i128(
@@ -1869,7 +1865,6 @@ mod tests {
   }
 
   #[test]
-  #[cfg(stable_i128)]
   fn le_i128_tests() {
     assert_parse!(
       le_i128(
diff --git a/src/number/streaming.rs b/src/number/streaming.rs
index 7c53ccc..9ee9f48 100644
--- a/src/number/streaming.rs
+++ b/src/number/streaming.rs
@@ -208,7 +208,6 @@ where
 /// 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,
@@ -345,7 +344,6 @@ where
 /// 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,
@@ -528,7 +526,6 @@ where
 /// 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,
@@ -679,7 +676,6 @@ where
 /// 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,
@@ -900,7 +896,6 @@ where
 /// 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,
@@ -1120,7 +1115,6 @@ where
 /// 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 +1423,10 @@ where
   ))(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.
 ///
@@ -1768,7 +1765,6 @@ mod tests {
   }
 
   #[test]
-  #[cfg(stable_i128)]
   fn i128_tests() {
     assert_parse!(
       be_i128(
@@ -1948,7 +1944,6 @@ mod tests {
   }
 
   #[test]
-  #[cfg(stable_i128)]
   fn le_i128_tests() {
     assert_parse!(
       le_i128(
diff --git a/src/sequence/mod.rs b/src/sequence/mod.rs
index 100c63f..e09d413 100644
--- a/src/sequence/mod.rs
+++ b/src/sequence/mod.rs
@@ -253,7 +253,7 @@ tuple_trait!(FnA A, FnB B, FnC C, FnD D, FnE E, FnF F, FnG G, FnH H, FnI I, FnJ
   FnM M, FnN N, FnO O, FnP P, FnQ Q, FnR R, FnS S, FnT T, FnU U);
 
 ///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/traits.rs b/src/traits.rs
index 3c3053e..f6a683c 100644
--- a/src/traits.rs
+++ b/src/traits.rs
@@ -914,6 +914,18 @@ impl<'a> FindToken<char> for &'a str {
   }
 }
 
+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


Test patch:
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 @@ fn many0_test() {
   );
 }
 
-#[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/tests/issues.rs b/tests/issues.rs
index 6df183b..24f7050 100644
--- a/tests/issues.rs
+++ b/tests/issues.rs
@@ -206,3 +206,11 @@ fn issue_1231_bits_expect_fn_closure() {
   }
   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'].as_slice());
+  assert_eq!(parser("aaa"), Ok(("aa", 'a')));
+}