From 7262486428d1855080086a45cedf5f407bc563ee Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Thu, 26 May 2022 11:39:24 -0700 Subject: Update TEST_MAPPING Test: None Bug: 233924440 Change-Id: Icbf90fd0db657792f18d46bd1d9360cc43dd4786 --- TEST_MAPPING | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/TEST_MAPPING b/TEST_MAPPING index 0b9e785..3c77ea2 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -11,7 +11,30 @@ "path": "external/rust/crates/rusticata-macros" } ], + "postsubmit": [ + { + "name": "keystore2_legacy_blobs_test" + }, + { + "name": "keystore2_test" + }, + { + "name": "legacykeystore_test" + }, + { + "name": "libapkverify.integration_test" + }, + { + "name": "libapkverify.test" + }, + { + "name": "microdroid_manager_test" + } + ], "presubmit": [ + { + "name": "keystore2_legacy_blobs_test" + }, { "name": "keystore2_test" }, @@ -29,6 +52,9 @@ } ], "presubmit-rust": [ + { + "name": "keystore2_legacy_blobs_test" + }, { "name": "keystore2_test" }, -- cgit v1.2.3 From 44231575873b2df508aa89304be2519129e5e0e5 Mon Sep 17 00:00:00 2001 From: Andrew Scull Date: Wed, 1 Jun 2022 12:44:15 +0000 Subject: Make availble to com.android.virt Test: build Bug: 234564414 Change-Id: I5f9a685ae610e1ad7b5664aadf19461fb4d445ae --- Android.bp | 4 ++++ cargo2android.json | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Android.bp b/Android.bp index 6fd9d6f..6c36bec 100644 --- a/Android.bp +++ b/Android.bp @@ -35,4 +35,8 @@ rust_library { "libmemchr", "libminimal_lexical", ], + apex_available: [ + "//apex_available:platform", + "com.android.virt", + ], } 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 +} -- cgit v1.2.3 From 4cc414e9f6e9ef4709971130772d33fbf53cda2e Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Tue, 14 Jun 2022 16:31:35 -0700 Subject: Update TEST_MAPPING Test: None Bug: 236006683 Change-Id: Idef9a45c111c07e3cacded8bb43a67a421fbb278 --- TEST_MAPPING | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/TEST_MAPPING b/TEST_MAPPING index 3c77ea2..88c552c 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -11,7 +11,10 @@ "path": "external/rust/crates/rusticata-macros" } ], - "postsubmit": [ + "presubmit": [ + { + "name": "apkdmverity.test" + }, { "name": "keystore2_legacy_blobs_test" }, @@ -28,30 +31,19 @@ "name": "libapkverify.test" }, { - "name": "microdroid_manager_test" - } - ], - "presubmit": [ - { - "name": "keystore2_legacy_blobs_test" - }, - { - "name": "keystore2_test" + "name": "libidsig.test" }, { - "name": "legacykeystore_test" - }, - { - "name": "libapkverify.integration_test" - }, - { - "name": "libapkverify.test" + "name": "microdroid_manager_test" }, { - "name": "microdroid_manager_test" + "name": "virtualizationservice_device_test" } ], "presubmit-rust": [ + { + "name": "apkdmverity.test" + }, { "name": "keystore2_legacy_blobs_test" }, @@ -67,8 +59,14 @@ { "name": "libapkverify.test" }, + { + "name": "libidsig.test" + }, { "name": "microdroid_manager_test" + }, + { + "name": "virtualizationservice_device_test" } ] } -- cgit v1.2.3 From 3431aa22cd07266047da6be781d779cf282dba91 Mon Sep 17 00:00:00 2001 From: David LeGare Date: Mon, 27 Jun 2022 22:00:12 +0000 Subject: Upgrade rust/crates/nom to 7.1.1 Test: make Change-Id: I9bf288b3fcd5d99cf9c6a1652312764dd251d68c --- .cargo_vcs_info.json | 5 +++-- Android.bp | 3 +-- CHANGELOG.md | 2 +- Cargo.toml | 9 ++++----- Cargo.toml.orig | 11 +++++------ METADATA | 8 ++++---- README.md | 24 +++++++++++++----------- build.rs | 7 ------- doc/nom_recipes.md | 6 +++--- src/bytes/complete.rs | 12 ++++++++++++ src/character/complete.rs | 18 ++++++++++++++++++ src/lib.rs | 22 +++++++++------------- src/multi/tests.rs | 10 ---------- src/number/complete.rs | 13 ++++--------- src/number/streaming.rs | 13 ++++--------- src/sequence/mod.rs | 2 +- src/traits.rs | 12 ++++++++++++ tests/issues.rs | 8 ++++++++ 18 files changed, 102 insertions(+), 83 deletions(-) delete mode 100644 build.rs diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index d603d8a..80b8de4 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,5 +1,6 @@ { "git": { - "sha1": "b6f79c4d375ae55e1fd1a35032ebb47a52ea3389" - } + "sha1": "294ffb3d9e0ade2c3b7ddfff52484b6d643dcce1" + }, + "path_in_vcs": "" } \ No newline at end of file diff --git a/Android.bp b/Android.bp index 6c36bec..cbd679a 100644 --- a/Android.bp +++ b/Android.bp @@ -23,14 +23,13 @@ rust_library { host_supported: true, crate_name: "nom", cargo_env_compat: true, - cargo_pkg_version: "7.1.0", + cargo_pkg_version: "7.1.1", srcs: ["src/lib.rs"], edition: "2018", features: [ "alloc", "std", ], - cfgs: ["stable_i128"], rustlibs: [ "libmemchr", "libminimal_lexical", 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 6e38fa0..5096d4e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,10 +11,11 @@ [package] edition = "2018" +rust-version = "1.48" name = "nom" -version = "7.1.0" +version = "7.1.1" 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" @@ -110,8 +111,6 @@ version = "0.3" [dev-dependencies.proptest] version = "1.0.0" -[build-dependencies.version_check] -version = "0.9" [features] alloc = [] @@ -119,7 +118,7 @@ default = ["std"] docsrs = [] 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..37066f6 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,7 +1,7 @@ [package] name = "nom" -version = "7.1.0" +version = "7.1.1" authors = [ "contact@geoffroycouprie.com" ] description = "A byte-oriented, zero-copy, parser combinators library" license = "MIT" @@ -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/METADATA b/METADATA index 504894c..b5142c7 100644 --- a/METADATA +++ b/METADATA @@ -7,13 +7,13 @@ third_party { } 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.1.crate" } - version: "7.1.0" + version: "7.1.1" license_type: NOTICE last_upgrade_date { year: 2022 - month: 3 - day: 1 + month: 6 + day: 27 } } 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/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/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>( count: C, ) -> impl Fn(Input) -> IResult 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>(input: T) -> IResult 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`) //! - **`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/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/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>(input: I) -> IResult where I: Slice> + InputIter + 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>(input: I) -> IResult where I: Slice> + InputIter + 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>(input: I) -> IResult where I: Slice> + InputIter + 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>(input: I) -> IResult where I: Slice> + InputIter + 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>(endian: crate::number::Endianness) -> fn(I) -> IResult where I: Slice> + InputIter + 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>(endian: crate::number::Endianness) -> fn(I) -> IResult where I: Slice> + InputIter + 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>(input: I) -> IResult where I: Slice> + InputIter + 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>(input: I) -> IResult where I: Slice> + InputIter + 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>(input: I) -> IResult where I: Slice> + InputIter + 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>(input: I) -> IResult where I: Slice> + InputIter + 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>(endian: crate::number::Endianness) -> fn(I) -> IResult where I: Slice> + InputIter + 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>(endian: crate::number::Endianness) -> fn(I) -> IResult where I: Slice> + InputIter + 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 for &'a str { } } +impl<'a> FindToken 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 { /// Returns the byte position of the substring if it is found diff --git a/tests/issues.rs b/tests/issues.rs index 6df183b..f7e2799 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'][..]); + assert_eq!(parser("aaa"), Ok(("aa", 'a'))); +} -- cgit v1.2.3 From c0d4164f38ec9f334b015a1cda57b78170c45cb3 Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Mon, 23 Jan 2023 13:44:40 +0000 Subject: Update TEST_MAPPING Test: None Change-Id: I66514f2ae1f3d58ab117f1b9048cf8e89d3b1f7e --- TEST_MAPPING | 34 ++-------------------------------- 1 file changed, 2 insertions(+), 32 deletions(-) diff --git a/TEST_MAPPING b/TEST_MAPPING index 88c552c..60d2587 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -12,9 +12,6 @@ } ], "presubmit": [ - { - "name": "apkdmverity.test" - }, { "name": "keystore2_legacy_blobs_test" }, @@ -25,25 +22,10 @@ "name": "legacykeystore_test" }, { - "name": "libapkverify.integration_test" - }, - { - "name": "libapkverify.test" - }, - { - "name": "libidsig.test" - }, - { - "name": "microdroid_manager_test" - }, - { - "name": "virtualizationservice_device_test" + "name": "virtualizationmanager_device_test" } ], "presubmit-rust": [ - { - "name": "apkdmverity.test" - }, { "name": "keystore2_legacy_blobs_test" }, @@ -54,19 +36,7 @@ "name": "legacykeystore_test" }, { - "name": "libapkverify.integration_test" - }, - { - "name": "libapkverify.test" - }, - { - "name": "libidsig.test" - }, - { - "name": "microdroid_manager_test" - }, - { - "name": "virtualizationservice_device_test" + "name": "virtualizationmanager_device_test" } ] } -- cgit v1.2.3 From d8f05e58dfefd4afaca95111ed2f22a77f2c1065 Mon Sep 17 00:00:00 2001 From: Jeff Vander Stoep Date: Mon, 30 Jan 2023 12:16:22 +0100 Subject: Update TEST_MAPPING Test: atest Change-Id: Ic4365e260622ce6418fe7ac95ab4bbdf5bc685c6 --- TEST_MAPPING | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/TEST_MAPPING b/TEST_MAPPING index 60d2587..f441b9c 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -9,34 +9,15 @@ }, { "path": "external/rust/crates/rusticata-macros" - } - ], - "presubmit": [ - { - "name": "keystore2_legacy_blobs_test" - }, - { - "name": "keystore2_test" - }, - { - "name": "legacykeystore_test" - }, - { - "name": "virtualizationmanager_device_test" - } - ], - "presubmit-rust": [ - { - "name": "keystore2_legacy_blobs_test" }, { - "name": "keystore2_test" + "path": "packages/modules/Virtualization/virtualizationmanager" }, { - "name": "legacykeystore_test" + "path": "system/security/keystore2" }, { - "name": "virtualizationmanager_device_test" + "path": "system/security/keystore2/legacykeystore" } ] } -- cgit v1.2.3 From d9eac1939674a4ff3fd957b5b2e9707f3bab3da0 Mon Sep 17 00:00:00 2001 From: Jeff Vander Stoep Date: Fri, 3 Feb 2023 11:58:06 +0100 Subject: Upgrade nom to 7.1.3 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 Test: TreeHugger Change-Id: I16ad52f1f6b59146e1dc3458e5bae0b457410b76 --- .cargo_vcs_info.json | 2 +- Android.bp | 2 +- CHANGELOG.md | 71 +++++++++++++++++++++- Cargo.toml | 49 +++++++++++++-- Cargo.toml.orig | 12 +++- METADATA | 14 +++-- README.md | 22 ++++++- src/bits/complete.rs | 47 ++++++++++++++ src/bits/mod.rs | 10 +-- src/bits/streaming.rs | 41 +++++++++++++ src/branch/mod.rs | 24 -------- src/character/complete.rs | 8 +-- src/combinator/mod.rs | 53 ++++++++++++++-- src/internal.rs | 4 +- src/lib.rs | 7 ++- src/macros.rs | 23 +++++++ src/multi/mod.rs | 152 +++++++++++++++++++++++++++++++++------------- src/number/complete.rs | 78 ++++++++++-------------- src/number/streaming.rs | 76 ++++++++++------------- src/sequence/mod.rs | 9 +++ src/sequence/tests.rs | 18 +++++- src/traits.rs | 4 ++ tests/issues.rs | 26 ++++++++ 23 files changed, 562 insertions(+), 190 deletions(-) create mode 100644 src/macros.rs diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index 80b8de4..c356c32 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,6 +1,6 @@ { "git": { - "sha1": "294ffb3d9e0ade2c3b7ddfff52484b6d643dcce1" + "sha1": "869f8972a4383b13cf89574fda28cb7dbfd56517" }, "path_in_vcs": "" } \ No newline at end of file diff --git a/Android.bp b/Android.bp index cbd679a..809b68b 100644 --- a/Android.bp +++ b/Android.bp @@ -23,7 +23,7 @@ rust_library { host_supported: true, crate_name: "nom", cargo_env_compat: true, - cargo_pkg_version: "7.1.1", + cargo_pkg_version: "7.1.3", srcs: ["src/lib.rs"], edition: "2018", features: [ diff --git a/CHANGELOG.md b/CHANGELOG.md index 56709ea..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 @@ -1420,7 +1485,11 @@ Considering the number of changes since the last release, this version can conta ## 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 5096d4e..2388b4c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,30 +13,62 @@ edition = "2018" rust-version = "1.48" name = "nom" -version = "7.1.1" +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"] +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" @@ -99,6 +131,7 @@ name = "reborrow_fold" [[test]] name = "fnmut" required-features = ["alloc"] + [dependencies.memchr] version = "2.3" default-features = false @@ -106,6 +139,7 @@ default-features = false [dependencies.minimal-lexical] version = "0.2.0" default-features = false + [dev-dependencies.doc-comment] version = "0.3" @@ -116,7 +150,12 @@ version = "1.0.0" alloc = [] default = ["std"] docsrs = [] -std = ["alloc", "memchr/std", "minimal-lexical/std"] +std = [ + "alloc", + "memchr/std", + "minimal-lexical/std", +] + [badges.coveralls] branch = "main" repository = "Geal/nom" diff --git a/Cargo.toml.orig b/Cargo.toml.orig index 37066f6..c01eeba 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,7 +1,7 @@ [package] name = "nom" -version = "7.1.1" +version = "7.1.3" authors = [ "contact@geoffroycouprie.com" ] description = "A byte-oriented, zero-copy, parser combinators library" license = "MIT" @@ -104,11 +104,21 @@ name = "reborrow_fold" name = "fnmut" 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" diff --git a/METADATA b/METADATA index b5142c7..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 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/nom/nom-7.1.1.crate" + value: "https://static.crates.io/crates/nom/nom-7.1.3.crate" } - version: "7.1.1" + version: "7.1.3" license_type: NOTICE last_upgrade_date { - year: 2022 - month: 6 - day: 27 + year: 2023 + month: 2 + day: 3 } } diff --git a/README.md b/README.md index d429164..f2c1b05 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,25 @@ error prone plumbing. *nom will happily take a byte out of your files :)* + + +- [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) + + + ## Example [Hexadecimal color](https://developer.mozilla.org/en-US/docs/Web/CSS/color) parser: @@ -296,7 +315,8 @@ Here is a (non exhaustive) list of known projects using nom: [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/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 @@ where } } +/// 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>(input: (I, usize)) -> IResult<(I, usize), bool, E> +where + I: Slice> + InputIter + InputLength, +{ + let (res, bit): (_, u32) = take(1usize)(input)?; + Ok((res, bit != 0)) +} + #[cfg(test)] mod test { use super::*; @@ -147,4 +170,28 @@ mod test { 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 complete; 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 @@ where E1: ParseError<(I, usize)> + ErrorConvert, E2: ParseError, I: Slice>, - 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 @@ where E1: ParseError + ErrorConvert, E2: ParseError<(I, usize)>, I: Slice> + Clone, - P: FnMut(I) -> IResult, + P: Parser, { move |(input, offset): (I, usize)| { let inner = if offset % 8 != 0 { @@ -97,7 +97,7 @@ where 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 @@ where } } +/// 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>(input: (I, usize)) -> IResult<(I, usize), bool, E> +where + I: Slice> + InputIter + InputLength, +{ + let (res, bit): (_, u32) = take(1usize)(input)?; + Ok((res, bit != 0)) +} + #[cfg(test)] mod test { use super::*; @@ -126,4 +149,22 @@ mod test { })) ); } + + #[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/character/complete.rs b/src/character/complete.rs index a98bafb..7cb760a 100644 --- a/src/character/complete.rs +++ b/src/character/complete.rs @@ -414,10 +414,10 @@ 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; @@ -425,12 +425,12 @@ where /// 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>(input: T) -> IResult where 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 @@ where } } -/// 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 @@ where } } -/// 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::character::complete::{one_of, digit1}; +/// # use nom::combinator::rest; +/// # use nom::branch::alt; +/// # use nom::sequence::preceded; +/// # fn main() { +/// +/// fn parser(input: &str) -> IResult<&str, &str> { +/// alt(( +/// preceded(one_of("+-"), digit1), +/// rest +/// ))(input) +/// } +/// +/// 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; -/// use nom::character::complete::alpha1; /// # fn main() { /// -/// let mut parser = cut(alpha1); +/// fn parser(input: &str) -> IResult<&str, &str> { +/// alt(( +/// preceded(one_of("+-"), cut(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("+"), Err(Err::Failure(Error { input: "", code: ErrorKind::Digit }))); /// # } /// ``` pub fn cut, F>(mut parser: F) -> impl FnMut(I) -> IResult @@ -643,6 +682,8 @@ where /// 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 @@ mod tests { #[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, 16); assert_size!(ErrorKind, 1); diff --git a/src/lib.rs b/src/lib.rs index 9429467..3beb2f4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -438,16 +438,17 @@ pub use self::traits::*; 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::lib::std::vec::Vec; 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 @@ where } } -/// 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 @@ where } } -/// 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 @@ where } } -/// 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 @@ where } } -/// 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 @@ where } } -/// 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 @@ where 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::().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 @@ where } } -/// 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 @@ where } } -/// 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 @@ where } } -/// 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 @@ where { 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::().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 @@ where } } -/// 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 @@ where } } -/// 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 @@ where } } -/// 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 @@ where } } -/// 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 @@ where /// * `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/number/complete.rs b/src/number/complete.rs index 715da32..98b8b3a 100644 --- a/src/number/complete.rs +++ b/src/number/complete.rs @@ -13,26 +13,6 @@ use crate::traits::{ 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. @@ -248,7 +228,7 @@ pub fn be_i8>(input: I) -> IResult where I: Slice> + InputIter + 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. @@ -271,7 +251,7 @@ pub fn be_i16>(input: I) -> IResult where I: Slice> + InputIter + 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. @@ -295,16 +275,20 @@ where I: Slice> + InputIter + 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; @@ -322,7 +306,7 @@ pub fn be_i32>(input: I) -> IResult where I: Slice> + InputIter + 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. @@ -345,7 +329,7 @@ pub fn be_i64>(input: I) -> IResult where I: Slice> + InputIter + 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. @@ -368,7 +352,7 @@ pub fn be_i128>(input: I) -> IResult where I: Slice> + InputIter + InputLength, { - map!(input, be_u128, |x| x as i128) + be_u128.map(|x| x as i128).parse(input) } /// Recognizes an unsigned 1 byte integer. @@ -586,7 +570,7 @@ pub fn le_i8>(input: I) -> IResult where I: Slice> + InputIter + 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. @@ -609,7 +593,7 @@ pub fn le_i16>(input: I) -> IResult where I: Slice> + InputIter + 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. @@ -633,11 +617,15 @@ where I: Slice> + InputIter + 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. @@ -660,7 +648,7 @@ pub fn le_i32>(input: I) -> IResult where I: Slice> + InputIter + 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. @@ -683,7 +671,7 @@ pub fn le_i64>(input: I) -> IResult where I: Slice> + InputIter + 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. @@ -706,7 +694,7 @@ pub fn le_i128>(input: I) -> IResult where I: Slice> + InputIter + InputLength, { - map!(input, le_u128, |x| x as i128) + le_u128.map(|x| x as i128).parse(input) } /// Recognizes an unsigned 1 byte integer @@ -957,7 +945,7 @@ pub fn i8>(i: I) -> IResult where I: Slice> + InputIter + InputLength, { - map!(i, u8, |x| x as i8) + u8.map(|x| x as i8).parse(i) } /// Recognizes a signed 2 byte integer @@ -1595,7 +1583,7 @@ where */ 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, @@ -1648,7 +1636,7 @@ where */ 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, @@ -2111,7 +2099,7 @@ mod tests { #[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 9ee9f48..b4e856d 100644 --- a/src/number/streaming.rs +++ b/src/number/streaming.rs @@ -12,26 +12,6 @@ use crate::traits::{ 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. @@ -242,7 +222,7 @@ pub fn be_i8>(input: I) -> IResult where I: Slice> + InputIter + 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. @@ -262,7 +242,7 @@ pub fn be_i16>(input: I) -> IResult where I: Slice> + InputIter + 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. @@ -283,11 +263,15 @@ where I: Slice> + InputIter + 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. @@ -307,7 +291,7 @@ pub fn be_i32>(input: I) -> IResult where I: Slice> + InputIter + 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. @@ -328,7 +312,7 @@ pub fn be_i64>(input: I) -> IResult where I: Slice> + InputIter + 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. @@ -348,7 +332,7 @@ pub fn be_i128>(input: I) -> IResult where I: Slice> + InputIter + InputLength, { - map!(input, be_u128, |x| x as i128) + be_u128.map(|x| x as i128).parse(input) } /// Recognizes an unsigned 1 byte integer. @@ -560,7 +544,7 @@ pub fn le_i8>(input: I) -> IResult where I: Slice> + InputIter + 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. @@ -583,7 +567,7 @@ pub fn le_i16>(input: I) -> IResult where I: Slice> + InputIter + 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. @@ -607,11 +591,15 @@ where I: Slice> + InputIter + 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. @@ -634,7 +622,7 @@ pub fn le_i32>(input: I) -> IResult where I: Slice> + InputIter + 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. @@ -657,7 +645,7 @@ pub fn le_i64>(input: I) -> IResult where I: Slice> + InputIter + 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. @@ -680,7 +668,7 @@ pub fn le_i128>(input: I) -> IResult where I: Slice> + InputIter + InputLength, { - map!(input, le_u128, |x| x as i128) + le_u128.map(|x| x as i128).parse(input) } /// Recognizes an unsigned 1 byte integer @@ -931,7 +919,7 @@ pub fn i8>(i: I) -> IResult where I: Slice> + InputIter + InputLength, { - map!(i, u8, |x| x as i8) + u8.map(|x| x as i8).parse(i) } /// Recognizes a signed 2 byte integer @@ -1567,7 +1555,7 @@ where */ 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, @@ -1621,7 +1609,7 @@ where */ 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, @@ -2191,7 +2179,7 @@ mod tests { #[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 e09d413..735ab45 100644 --- a/src/sequence/mod.rs +++ b/src/sequence/mod.rs @@ -252,6 +252,15 @@ macro_rules! tuple_trait_inner( 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> Tuple for () { + fn parse(&mut self, input: I) -> IResult { + 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 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 @@ fn tuple_test() { 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 f6a683c..394e5bc 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1330,6 +1330,10 @@ impl ErrorConvert> for error::VerboseError } } +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 f7e2799..7985702 100644 --- a/tests/issues.rs +++ b/tests/issues.rs @@ -214,3 +214,29 @@ fn issue_1282_findtoken_char() { 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![(), (), ()])); +} -- cgit v1.2.3 From edeacd355eefd616177a1f6302760fc4dde24ffc Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Tue, 7 Mar 2023 17:24:18 -0800 Subject: Make nom available to product and vendor Bug: 270690570 Test: mma in external/rust/crates Change-Id: Ide59c7062ef44878c06eeb5f33414ce86aafe1f4 --- Android.bp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Android.bp b/Android.bp index 809b68b..f9f1cbb 100644 --- a/Android.bp +++ b/Android.bp @@ -38,4 +38,6 @@ rust_library { "//apex_available:platform", "com.android.virt", ], + product_available: true, + vendor_available: true, } -- cgit v1.2.3