diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dc6595a77..8e8e6bee9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,22 +3,27 @@ name: CI on: [push, pull_request] env: - RUST_MINVERSION: 1.41.1 + RUST_MINVERSION: "1.50" CARGO_INCREMENTAL: 0 CARGO_NET_RETRY: 10 +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }} + cancel-in-progress: true + jobs: test: name: Test runs-on: ubuntu-latest strategy: + fail-fast: false matrix: rust: - stable - beta - nightly - - 1.48.0 + - 1.50.0 features: - '' @@ -41,7 +46,7 @@ jobs: steps: - name: Checkout sources - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install rust (${{ matrix.rust }}) uses: actions-rs/toolchain@v1 @@ -71,7 +76,7 @@ jobs: steps: - name: Checkout sources - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install rust (${{ env.RUST_MINVERSION }}) uses: actions-rs/toolchain@v1 @@ -95,7 +100,7 @@ jobs: steps: - name: Checkout sources - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install rust uses: actions-rs/toolchain@v1 @@ -125,7 +130,7 @@ jobs: steps: - name: Checkout sources - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install rust uses: actions-rs/toolchain@v1 @@ -145,7 +150,7 @@ jobs: steps: - name: Checkout sources - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install rust uses: actions-rs/toolchain@v1 @@ -162,13 +167,36 @@ jobs: command: fmt args: -- --check + clippy: + name: Check clippy + runs-on: ubuntu-latest + + steps: + - name: Checkout sources + uses: actions/checkout@v3 + + - name: Install rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + components: clippy + profile: minimal + override: true + + - name: cargo clippy -- -D warnings + continue-on-error: true + uses: actions-rs/cargo@v1 + with: + command: clippy + args: -- -D warnings + coverage: name: Coverage runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install rust uses: actions-rs/toolchain@v1 diff --git a/Cargo.toml b/Cargo.toml index 37066f63b..82e637695 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ edition = "2018" autoexamples = false # also update in README.md (badge and "Rust version requirements" section) -rust-version = "1.48" +rust-version = "1.50" include = [ "CHANGELOG.md", diff --git a/README.md b/README.md index f2c1b0528..1df50cc29 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![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=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-msrv) +[![Minimum rustc version](https://img.shields.io/badge/rustc-1.50.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 @@ -207,7 +207,7 @@ Some benchmarks are available on [Github](https://github.com/Geal/nom_benchmarks ## 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. +The 7.0 series of nom supports **Rustc version 1.50 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. The current policy is that this will only be updated in the next major nom release. diff --git a/src/bytes/complete.rs b/src/bytes/complete.rs index a5442b53f..43ff3ce35 100644 --- a/src/bytes/complete.rs +++ b/src/bytes/complete.rs @@ -327,6 +327,7 @@ where /// assert_eq!(till_colon("12345"), Ok(("", "12345"))); /// assert_eq!(till_colon(""), Ok(("", ""))); /// ``` +#[allow(clippy::redundant_closure)] pub fn take_till>( cond: F, ) -> impl Fn(Input) -> IResult @@ -358,6 +359,7 @@ where /// assert_eq!(till_colon("12345"), Ok(("", "12345"))); /// assert_eq!(till_colon(""), Err(Err::Error(Error::new("", ErrorKind::TakeTill1)))); /// ``` +#[allow(clippy::redundant_closure)] pub fn take_till1>( cond: F, ) -> impl Fn(Input) -> IResult diff --git a/src/bytes/streaming.rs b/src/bytes/streaming.rs index e972760e2..a8207a967 100644 --- a/src/bytes/streaming.rs +++ b/src/bytes/streaming.rs @@ -340,6 +340,7 @@ where /// assert_eq!(till_colon("12345"), Err(Err::Incomplete(Needed::new(1)))); /// assert_eq!(till_colon(""), Err(Err::Incomplete(Needed::new(1)))); /// ``` +#[allow(clippy::redundant_closure)] pub fn take_till>( cond: F, ) -> impl Fn(Input) -> IResult @@ -372,6 +373,7 @@ where /// assert_eq!(till_colon("12345"), Err(Err::Incomplete(Needed::new(1)))); /// assert_eq!(till_colon(""), Err(Err::Incomplete(Needed::new(1)))); /// ``` +#[allow(clippy::redundant_closure)] pub fn take_till1>( cond: F, ) -> impl Fn(Input) -> IResult diff --git a/src/character/complete.rs b/src/character/complete.rs index a98bafbb7..7cb760a68 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/character/mod.rs b/src/character/mod.rs index 2c5d3bc4a..e2637b1ea 100644 --- a/src/character/mod.rs +++ b/src/character/mod.rs @@ -19,7 +19,7 @@ pub mod streaming; /// ``` #[inline] pub fn is_alphabetic(chr: u8) -> bool { - (chr >= 0x41 && chr <= 0x5A) || (chr >= 0x61 && chr <= 0x7A) + (0x41..=0x5A).contains(&chr) || (0x61..=0x7A).contains(&chr) } /// Tests if byte is ASCII digit: 0-9 @@ -33,7 +33,7 @@ pub fn is_alphabetic(chr: u8) -> bool { /// ``` #[inline] pub fn is_digit(chr: u8) -> bool { - chr >= 0x30 && chr <= 0x39 + (0x30..=0x39).contains(&chr) } /// Tests if byte is ASCII hex digit: 0-9, A-F, a-f @@ -49,7 +49,7 @@ pub fn is_digit(chr: u8) -> bool { /// ``` #[inline] pub fn is_hex_digit(chr: u8) -> bool { - (chr >= 0x30 && chr <= 0x39) || (chr >= 0x41 && chr <= 0x46) || (chr >= 0x61 && chr <= 0x66) + (0x30..=0x39).contains(&chr) || (0x41..=0x46).contains(&chr) || (0x61..=0x66).contains(&chr) } /// Tests if byte is ASCII octal digit: 0-7 @@ -64,7 +64,7 @@ pub fn is_hex_digit(chr: u8) -> bool { /// ``` #[inline] pub fn is_oct_digit(chr: u8) -> bool { - chr >= 0x30 && chr <= 0x37 + (0x30..=0x37).contains(&chr) } /// Tests if byte is ASCII alphanumeric: A-Z, a-z, 0-9 diff --git a/src/error.rs b/src/error.rs index 498b5e135..5652d1ca4 100644 --- a/src/error.rs +++ b/src/error.rs @@ -54,6 +54,7 @@ pub trait FromExternalError { } /// default error type, only contains the error' location and code +#[allow(clippy::derive_partial_eq_without_eq)] #[derive(Debug, PartialEq)] pub struct Error { /// position of the error in the input data @@ -156,6 +157,7 @@ pub struct VerboseError { #[cfg(feature = "alloc")] #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] +#[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, Debug, PartialEq)] /// Error context for `VerboseError` pub enum VerboseErrorKind { diff --git a/src/internal.rs b/src/internal.rs index 8a3c6a14d..d6e41ae28 100644 --- a/src/internal.rs +++ b/src/internal.rs @@ -108,11 +108,7 @@ pub enum Err { impl Err { /// Tests if the result is Incomplete pub fn is_incomplete(&self) -> bool { - if let Err::Incomplete(_) = self { - true - } else { - false - } + matches!(self, Err::Incomplete(_)) } /// Applies the given function to the inner error @@ -344,7 +340,7 @@ pub struct Map { phantom: core::marker::PhantomData, } -impl<'a, I, O1, O2, E, F: Parser, G: Fn(O1) -> O2> Parser for Map { +impl, G: Fn(O1) -> O2> Parser for Map { fn parse(&mut self, i: I) -> IResult { match self.f.parse(i) { Err(e) => Err(e), @@ -361,7 +357,7 @@ pub struct FlatMap { phantom: core::marker::PhantomData, } -impl<'a, I, O1, O2, E, F: Parser, G: Fn(O1) -> H, H: Parser> Parser +impl, G: Fn(O1) -> H, H: Parser> Parser for FlatMap { fn parse(&mut self, i: I) -> IResult { @@ -378,7 +374,7 @@ pub struct AndThen { phantom: core::marker::PhantomData, } -impl<'a, I, O1, O2, E, F: Parser, G: Parser> Parser +impl, G: Parser> Parser for AndThen { fn parse(&mut self, i: I) -> IResult { @@ -395,9 +391,7 @@ pub struct And { g: G, } -impl<'a, I, O1, O2, E, F: Parser, G: Parser> Parser - for And -{ +impl, G: Parser> Parser for And { fn parse(&mut self, i: I) -> IResult { let (i, o1) = self.f.parse(i)?; let (i, o2) = self.g.parse(i)?; @@ -412,8 +406,8 @@ pub struct Or { g: G, } -impl<'a, I: Clone, O, E: crate::error::ParseError, F: Parser, G: Parser> - Parser for Or +impl, F: Parser, G: Parser> Parser + for Or { fn parse(&mut self, i: I) -> IResult { match self.f.parse(i.clone()) { @@ -436,15 +430,8 @@ pub struct Into, E1, E2: From> { phantom_err2: core::marker::PhantomData, } -impl< - 'a, - I: Clone, - O1, - O2: From, - E1, - E2: crate::error::ParseError + From, - F: Parser, - > Parser for Into +impl, E1, E2: error::ParseError + From, F: Parser> + Parser for Into { fn parse(&mut self, i: I) -> IResult { match self.f.parse(i) { diff --git a/src/number/complete.rs b/src/number/complete.rs index c9f87e689..5cc5d0783 100644 --- a/src/number/complete.rs +++ b/src/number/complete.rs @@ -1515,7 +1515,7 @@ where } } - let position = position.unwrap_or(i.input_len()); + let position = position.unwrap_or_else(|| i.input_len()); let index = if zero_count == 0 { position diff --git a/src/sequence/tests.rs b/src/sequence/tests.rs index ea662607d..30ad0d678 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, Error}; +use crate::error::{Error, ErrorKind}; use crate::internal::{Err, IResult, Needed}; use crate::number::streaming::be_u16; @@ -275,7 +275,16 @@ fn tuple_test() { #[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(("", ()))); + 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 f6a683cb0..3d8ec4ae4 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -148,24 +148,31 @@ as_bytes_array_impls! { } /// Transforms common types to a char for basic token parsing +#[allow(clippy::len_without_is_empty)] pub trait AsChar { /// makes a char from self + #[allow(clippy::wrong_self_convention)] fn as_char(self) -> char; /// Tests that self is an alphabetic character /// /// Warning: for `&str` it recognizes alphabetic /// characters outside of the 52 ASCII letters + #[allow(clippy::wrong_self_convention)] fn is_alpha(self) -> bool; /// Tests that self is an alphabetic character /// or a decimal digit + #[allow(clippy::wrong_self_convention)] fn is_alphanum(self) -> bool; /// Tests that self is a decimal digit + #[allow(clippy::wrong_self_convention)] fn is_dec_digit(self) -> bool; /// Tests that self is an hex digit + #[allow(clippy::wrong_self_convention)] fn is_hex_digit(self) -> bool; /// Tests that self is an octal digit + #[allow(clippy::wrong_self_convention)] fn is_oct_digit(self) -> bool; /// Gets the len in bytes for self fn len(self) -> usize; @@ -178,7 +185,7 @@ impl AsChar for u8 { } #[inline] fn is_alpha(self) -> bool { - (self >= 0x41 && self <= 0x5A) || (self >= 0x61 && self <= 0x7A) + (0x41..=0x5A).contains(&self) || (0x61..=0x7A).contains(&self) } #[inline] fn is_alphanum(self) -> bool { @@ -186,17 +193,15 @@ impl AsChar for u8 { } #[inline] fn is_dec_digit(self) -> bool { - self >= 0x30 && self <= 0x39 + (0x30..=0x39).contains(&self) } #[inline] fn is_hex_digit(self) -> bool { - (self >= 0x30 && self <= 0x39) - || (self >= 0x41 && self <= 0x46) - || (self >= 0x61 && self <= 0x66) + (0x30..=0x39).contains(&self) || (0x41..=0x46).contains(&self) || (0x61..=0x66).contains(&self) } #[inline] fn is_oct_digit(self) -> bool { - self >= 0x30 && self <= 0x37 + (0x30..=0x37).contains(&self) } #[inline] fn len(self) -> usize { @@ -703,6 +708,7 @@ impl<'a> InputTakeAtPosition for &'a str { /// Indicates whether a comparison was successful, an error, or /// if more data was needed +#[allow(clippy::derive_partial_eq_without_eq)] #[derive(Debug, PartialEq)] pub enum CompareResult { /// Comparison was successful @@ -1381,7 +1387,7 @@ impl HexDisplay for [u8] { v.push(b'\t'); for &byte in chunk { - if (byte >= 32 && byte <= 126) || byte >= 128 { + if (32..=126).contains(&byte) || byte >= 128 { v.push(byte); } else { v.push(b'.');