diff --git a/Cargo.lock b/Cargo.lock index 914bfd6d..fdc0eb72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,12 +28,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - [[package]] name = "async-broadcast" version = "0.4.0" @@ -1005,19 +999,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" -[[package]] -name = "lexical-core" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" -dependencies = [ - "arrayvec", - "bitflags", - "cfg-if 1.0.0", - "ryu", - "static_assertions", -] - [[package]] name = "libc" version = "0.2.125" @@ -1212,6 +1193,12 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.5.1" @@ -1320,13 +1307,12 @@ dependencies = [ [[package]] name = "nom" -version = "5.1.2" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" dependencies = [ - "lexical-core", "memchr", - "version_check", + "minimal-lexical", ] [[package]] diff --git a/melib/Cargo.toml b/melib/Cargo.toml index 07c632ce..02799f41 100644 --- a/melib/Cargo.toml +++ b/melib/Cargo.toml @@ -22,7 +22,7 @@ path = "src/lib.rs" bitflags = "1.0" data-encoding = "2.1.1" encoding = "0.2.33" -nom = { version = "5" } +nom = { version = "7" } indexmap = { version = "^1.5", features = ["serde-1", ] } notify = { version = "4.0.15", optional = true } diff --git a/melib/src/backends/imap/managesieve.rs b/melib/src/backends/imap/managesieve.rs index 4eb36955..56e3edd9 100644 --- a/melib/src/backends/imap/managesieve.rs +++ b/melib/src/backends/imap/managesieve.rs @@ -24,15 +24,15 @@ use crate::conf::AccountSettings; use crate::error::{MeliError, Result}; use crate::get_conf_val; use nom::{ - branch::alt, bytes::complete::tag, combinator::map, error::ErrorKind, - multi::separated_nonempty_list, sequence::separated_pair, IResult, + branch::alt, bytes::complete::tag, combinator::map, error::Error as NomError, error::ErrorKind, + multi::separated_list1, sequence::separated_pair, IResult, }; use std::str::FromStr; use std::sync::{Arc, Mutex}; use std::time::SystemTime; pub fn managesieve_capabilities(input: &[u8]) -> Result> { - let (_, ret) = separated_nonempty_list( + let (_, ret) = separated_list1( tag(b"\r\n"), alt(( separated_pair(quoted_raw, tag(b" "), quoted_raw), @@ -58,7 +58,10 @@ fn test_managesieve_capabilities() { // Return a byte sequence surrounded by "s and decoded if necessary pub fn quoted_raw(input: &[u8]) -> IResult<&[u8], &[u8]> { if input.is_empty() || input[0] != b'"' { - return Err(nom::Err::Error((input, ErrorKind::Tag))); + return Err(nom::Err::Error(NomError { + input, + code: ErrorKind::Tag, + })); } let mut i = 1; @@ -69,7 +72,10 @@ pub fn quoted_raw(input: &[u8]) -> IResult<&[u8], &[u8]> { i += 1; } - Err(nom::Err::Error((input, ErrorKind::Tag))) + Err(nom::Err::Error(NomError { + input, + code: ErrorKind::Tag, + })) } pub trait ManageSieve { diff --git a/melib/src/backends/imap/protocol_parser.rs b/melib/src/backends/imap/protocol_parser.rs index 465ce96a..6a5c8be8 100644 --- a/melib/src/backends/imap/protocol_parser.rs +++ b/melib/src/backends/imap/protocol_parser.rs @@ -33,7 +33,7 @@ use nom::{ character::complete::digit1, character::is_digit, combinator::{map, map_res, opt}, - multi::{fold_many1, length_data, many0, many1, separated_nonempty_list}, + multi::{fold_many1, length_data, many0, many1, separated_list1}, sequence::{delimited, preceded}, }; use std::convert::TryFrom; @@ -823,7 +823,7 @@ macro_rules! flags_to_imap_list { pub fn capabilities(input: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { let (input, _) = take_until("CAPABILITY ")(input)?; let (input, _) = tag("CAPABILITY ")(input)?; - let (input, ret) = separated_nonempty_list(tag(" "), is_not(" ]\r\n"))(input)?; + let (input, ret) = separated_list1(tag(" "), is_not(" ]\r\n"))(input)?; let (input, _) = take_until("\r\n")(input)?; let (input, _) = tag("\r\n")(input)?; Ok((input, ret)) @@ -981,7 +981,7 @@ pub fn search_results<'a>(input: &'a [u8]) -> IResult<&'a [u8], Vec> { alt(( |input: &'a [u8]| -> IResult<&'a [u8], Vec> { let (input, _) = tag("* SEARCH ")(input)?; - let (input, list) = separated_nonempty_list( + let (input, list) = separated_list1( tag(b" "), map_res(is_not(" \r\n"), |s: &[u8]| { ImapNum::from_str(unsafe { std::str::from_utf8_unchecked(s) }) @@ -1367,7 +1367,7 @@ pub fn envelope_addresses<'a>( let (input, _) = tag("(")(input)?; let (input, envelopes) = fold_many1( delimited(tag("("), envelope_address, tag(")")), - SmallVec::new(), + SmallVec::new, |mut acc, item| { acc.push(item); acc @@ -1472,11 +1472,11 @@ pub fn quoted_or_nil(input: &[u8]) -> IResult<&[u8], Option>> { alt((map(tag("NIL"), |_| None), map(quoted, Some)))(input.ltrim()) } -pub fn uid_fetch_envelopes_response( - input: &[u8], -) -> IResult<&[u8], Vec<(UID, Option<(Flag, Vec)>, Envelope)>> { +pub fn uid_fetch_envelopes_response<'a>( + input: &'a [u8], +) -> IResult<&'a [u8], Vec<(UID, Option<(Flag, Vec)>, Envelope)>> { many0( - |input: &[u8]| -> IResult<&[u8], (UID, Option<(Flag, Vec)>, Envelope)> { + |input: &'a [u8]| -> IResult<&'a [u8], (UID, Option<(Flag, Vec)>, Envelope)> { let (input, _) = tag("* ")(input)?; let (input, _) = take_while(is_digit)(input)?; let (input, _) = tag(" FETCH (")(input)?; diff --git a/melib/src/backends/mbox.rs b/melib/src/backends/mbox.rs index 5dad56fa..a5f55894 100644 --- a/melib/src/backends/mbox.rs +++ b/melib/src/backends/mbox.rs @@ -131,7 +131,7 @@ use crate::shellexpand::ShellExpandTrait; use nom::bytes::complete::tag; use nom::character::complete::digit1; use nom::combinator::map_res; -use nom::{self, error::ErrorKind, IResult}; +use nom::{self, error::Error as NomError, error::ErrorKind, IResult}; extern crate notify; use self::notify::{watcher, DebouncedEvent, RecursiveMode, Watcher}; @@ -491,7 +491,10 @@ impl MboxFormat { } Err(err) => { debug!("Could not parse mail {:?}", err); - Err(nom::Err::Error((input, ErrorKind::Tag))) + Err(nom::Err::Error(NomError { + input, + code: ErrorKind::Tag, + })) } } } else { @@ -535,7 +538,10 @@ impl MboxFormat { } Err(err) => { debug!("Could not parse mail at {:?}", err); - Err(nom::Err::Error((input, ErrorKind::Tag))) + Err(nom::Err::Error(NomError { + input, + code: ErrorKind::Tag, + })) } } } @@ -589,7 +595,10 @@ impl MboxFormat { } Err(err) => { debug!("Could not parse mail {:?}", err); - Err(nom::Err::Error((input, ErrorKind::Tag))) + Err(nom::Err::Error(NomError { + input, + code: ErrorKind::Tag, + })) } } } else { @@ -633,7 +642,10 @@ impl MboxFormat { } Err(err) => { debug!("Could not parse mail {:?}", err); - Err(nom::Err::Error((input, ErrorKind::Tag))) + Err(nom::Err::Error(NomError { + input, + code: ErrorKind::Tag, + })) } } } @@ -724,7 +736,10 @@ pub fn mbox_parse( format: Option, ) -> IResult<&[u8], Vec> { if input.is_empty() { - return Err(nom::Err::Error((input, ErrorKind::Tag))); + return Err(nom::Err::Error(NomError { + input, + code: ErrorKind::Tag, + })); } let mut offset = 0; let mut index = index.lock().unwrap(); diff --git a/melib/src/email/parser.rs b/melib/src/email/parser.rs index cf03a97f..6af3eb11 100644 --- a/melib/src/email/parser.rs +++ b/melib/src/email/parser.rs @@ -28,7 +28,7 @@ use nom::{ combinator::peek, combinator::{map, opt}, error::{context, ErrorKind}, - multi::{many0, many1, separated_nonempty_list}, + multi::{many0, many1, separated_list1}, number::complete::le_u8, sequence::{delimited, pair, preceded, separated_pair, terminated}, }; @@ -112,6 +112,17 @@ impl nom::error::ParseError for ParsingError { } } +impl nom::error::FromExternalError for ParsingError { + fn from_external_error(input: I, kind: ErrorKind, _e: E) -> Self { + Self { + input, + error: kind.description().to_string().into(), + } + } +} + +impl nom::error::ContextError for ParsingError {} + impl<'i> From> for MeliError { fn from(val: ParsingError<&'i [u8]>) -> MeliError { MeliError::new("Parsing error").set_summary(format!( @@ -155,6 +166,15 @@ impl<'i> From>> for MeliError { } } +impl From>> for MeliError { + fn from(val: nom::Err>) -> MeliError { + match val { + nom::Err::Incomplete(_) => MeliError::new("Parsing Error: Incomplete"), + nom::Err::Error(_) | nom::Err::Failure(_) => MeliError::new("Parsing Error"), + } + } +} + macro_rules! is_ctl_or_space { ($var:ident) => { /* */ @@ -1158,7 +1178,7 @@ pub mod mailing_lists { pub fn rfc_2369_list_headers_action_list(input: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { let (input, _) = opt(cfws)(input)?; let (input, ret) = alt(( - separated_nonempty_list( + separated_list1( delimited( map(opt(cfws), |_| ()), map(is_a(", "), |_| ()), @@ -1954,7 +1974,7 @@ pub mod encodings { } pub fn encoded_word_list(input: &[u8]) -> IResult<&[u8], SmallVec<[u8; 64]>> { - let (input, list) = separated_nonempty_list(space, encoded_word)(input)?; + let (input, list) = separated_list1(space, encoded_word)(input)?; let list_len = list.iter().fold(0, |mut acc, x| { acc += x.len(); acc diff --git a/src/command.rs b/src/command.rs index a2342e49..8f8cede5 100644 --- a/src/command.rs +++ b/src/command.rs @@ -28,7 +28,8 @@ use melib::nom::{ bytes::complete::{is_a, is_not, tag, take_until}, character::complete::{digit1, not_line_ending}, combinator::{map, map_res}, - multi::separated_list, + error::Error as NomError, + multi::separated_list1, sequence::{pair, preceded, separated_pair}, IResult, }; @@ -72,7 +73,10 @@ macro_rules! define_commands { pub fn quoted_argument(input: &[u8]) -> IResult<&[u8], &str> { if input.is_empty() { - return Err(nom::Err::Error((input, nom::error::ErrorKind::Tag))); + return Err(nom::Err::Error(NomError { + input, + code: nom::error::ErrorKind::Tag, + })); } if input[0] == b'"' { @@ -85,7 +89,10 @@ pub fn quoted_argument(input: &[u8]) -> IResult<&[u8], &str> { } i += 1; } - Err(nom::Err::Error((input, nom::error::ErrorKind::Tag))) + Err(nom::Err::Error(NomError { + input, + code: nom::error::ErrorKind::Tag, + })) } else { map_res(is_not(" "), std::str::from_utf8)(input) } @@ -243,7 +250,10 @@ fn eof(input: &[u8]) -> IResult<&[u8], ()> { if input.is_empty() { Ok((input, ())) } else { - Err(nom::Err::Error((input, nom::error::ErrorKind::Tag))) + Err(nom::Err::Error(NomError { + input, + code: nom::error::ErrorKind::Tag, + })) } } @@ -502,7 +512,7 @@ define_commands!([ let (input, _) = is_a(" ")(input)?; let (input, bin) = quoted_argument(input)?; let (input, _) = is_a(" ")(input)?; - let (input, args) = separated_list(is_a(" "), quoted_argument)(input)?; + let (input, args) = separated_list1(is_a(" "), quoted_argument)(input)?; let (input, _) = eof(input)?; Ok((input, { View(Pipe(bin.to_string(), args.into_iter().map(String::from).collect::>())) diff --git a/tools/src/mboxparse.rs b/tools/src/mboxparse.rs index 0c861936..100018f6 100644 --- a/tools/src/mboxparse.rs +++ b/tools/src/mboxparse.rs @@ -51,7 +51,7 @@ fn main() -> Result<()> { Err(melib::nom::Err::Error(err)) => { println!( "Error in parsing {:?}", - unsafe { std::str::from_utf8_unchecked(err.0) } + unsafe { std::str::from_utf8_unchecked(err.input) } .chars() .take(150) .collect::()