diff --git a/Cargo.lock b/Cargo.lock index 3acf570..ce0f2c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "aetolia" @@ -12,6 +12,7 @@ dependencies = [ "hex", "lazy_static", "nom", + "nom-language", "similar-asserts", "test-case", "time", @@ -189,19 +190,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] -name = "minimal-lexical" -version = "0.2.1" +name = "nom" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] [[package]] -name = "nom" -version = "7.1.3" +name = "nom-language" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +checksum = "2de2bc5b451bfedaef92c90b8939a8fff5770bdcc1fafd6239d086aab8fa6b29" dependencies = [ - "memchr", - "minimal-lexical", + "nom", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 7d4e9d9..0118f08 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,8 @@ license = "MPL-2.0" repository = "https://github.com/EphyraSoftware/aetolia" [dependencies] -nom = "7.1" +nom = "8.0" +nom-language = "0.1.0" base64 = "0.22" hex = "0.4" lazy_static = "1.4" diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 1f8a30f..e522a74 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "1.80.0" +channel = "1.84.1" components = ["rustfmt", "clippy", "llvm-tools-preview"] profile = "minimal" diff --git a/src/lib.rs b/src/lib.rs index 25ac999..30dfcc8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,8 +4,7 @@ use crate::parser::Error; use nom::branch::alt; use nom::combinator::recognize; use nom::error::ParseError; -use nom::sequence::tuple; -use nom::{IResult, InputIter, InputLength, InputTake}; +use nom::{IResult, Input, Parser}; use std::num::NonZeroUsize; /// Common types. @@ -41,15 +40,15 @@ pub mod prelude { } /// Streaming, single character matching the predicate -pub(crate) fn single>( +pub(crate) fn single>( cond: F, -) -> impl Fn(Input) -> IResult +) -> impl Fn(In) -> IResult where - Input: InputIter + InputLength + InputTake, - F: Fn(::Item) -> bool, + In: Input, + F: Fn(::Item) -> bool, Output: Copy, { - move |i: Input| { + move |i: In| { match i.iter_elements().next() { Some(c) if cond(c) => { let (input, v) = i.take_split(1); @@ -73,55 +72,56 @@ where { let (input, seq) = alt(( // Utf-8 2-byte sequence - recognize(tuple(( + recognize(( single(|b| matches!(b, b'\xC2'..=b'\xDF')), single(|b| matches!(b, b'\x80'..=b'\xBF')), - ))), + )), // Utf-8 3-byte sequence alt(( - recognize(tuple(( + recognize(( single(|b| b == b'\xE0'), single(|b| matches!(b, b'\xA0'..=b'\xBF')), single(|b| matches!(b, b'\x80'..=b'\xBF')), - ))), - recognize(tuple(( + )), + recognize(( single(|b| matches!(b, b'\xE1'..=b'\xEC')), single(|b| matches!(b, b'\x80'..=b'\xBF')), single(|b| matches!(b, b'\x80'..=b'\xBF')), - ))), - recognize(tuple(( + )), + recognize(( single(|b| b == b'\xED'), single(|b| matches!(b, b'\x80'..=b'\x9F')), single(|b| matches!(b, b'\x80'..=b'\xBF')), - ))), - recognize(tuple(( + )), + recognize(( single(|b| matches!(b, b'\xEE'..=b'\xEF')), single(|b| matches!(b, b'\x80'..=b'\xBF')), single(|b| matches!(b, b'\x80'..=b'\xBF')), - ))), + )), )), // Utf-8 4-byte sequence alt(( - recognize(tuple(( + recognize(( single(|b| b == b'\xF0'), single(|b| matches!(b, b'\x90'..=b'\xBF')), single(|b| matches!(b, b'\x80'..=b'\xBF')), single(|b| matches!(b, b'\x80'..=b'\xBF')), - ))), - recognize(tuple(( + )), + recognize(( single(|b| matches!(b, b'\xF1'..=b'\xF3')), single(|b| matches!(b, b'\x80'..=b'\xBF')), single(|b| matches!(b, b'\x80'..=b'\xBF')), single(|b| matches!(b, b'\x80'..=b'\xBF')), - ))), - recognize(tuple(( + )), + recognize(( single(|b| b == b'\xF4'), single(|b| matches!(b, b'\x80'..=b'\x8F')), single(|b| matches!(b, b'\x80'..=b'\xBF')), single(|b| matches!(b, b'\x80'..=b'\xBF')), - ))), + )), )), - ))(input)?; + )) + .parse(input)?; Ok((input, seq)) } @@ -142,7 +142,7 @@ mod tests { fn invalid_utf8() { let mut input = "👍👌".as_bytes().to_vec(); input.extend_from_slice(&[1, 3, 4, 5, 2, 1]); - let (rem, seq) = many1(utf8_seq::)(input.as_slice()).unwrap(); + let (rem, seq) = many1(utf8_seq::).parse(input.as_slice()).unwrap(); test_utils::check_rem(rem, 6); assert_eq!( seq.into_iter().flatten().cloned().collect::>(), diff --git a/src/parser.rs b/src/parser.rs index d385e06..cb74561 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -5,10 +5,11 @@ use nom::bytes::complete::{take_while, take_while1, take_while_m_n}; use nom::bytes::streaming::tag_no_case; use nom::character::streaming::{char, crlf}; use nom::combinator::{cut, recognize}; -use nom::error::{ErrorKind, FromExternalError, ParseError, VerboseError, VerboseErrorKind}; +use nom::error::{ErrorKind, FromExternalError, ParseError}; use nom::multi::{fold_many0, many0, separated_list1}; -use nom::sequence::{separated_pair, tuple}; +use nom::sequence::separated_pair; use nom::{AsChar, IResult, Parser}; +use nom_language::error::{VerboseError, VerboseErrorKind}; use std::str::FromStr; use std::sync::Mutex; @@ -151,7 +152,7 @@ fn quoted_string<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], &'a [u8], E> where E: ParseError<&'a [u8]> + From>, { - let (input, (_, content, _)) = tuple((char('"'), cut(safe_char), char('"')))(input)?; + let (input, (_, content, _)) = (char('"'), cut(safe_char), char('"')).parse(input)?; Ok((input, content)) } @@ -160,7 +161,7 @@ fn param_value<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], &'a [u8], E> where E: ParseError<&'a [u8]> + From>, { - let (input, value) = alt((quoted_string, param_text))(input)?; + let (input, value) = alt((quoted_string, param_text)).parse(input)?; Ok((input, value)) } @@ -183,10 +184,11 @@ fn x_name<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], &'a [u8], E> where E: ParseError<&'a [u8]> + From>, { - let (input, x_name) = recognize(tuple(( + let (input, x_name) = recognize(( tag_no_case("X-"), cut(take_while1(|c: u8| c.is_alphanum() || c == b'-')), - )))(input)?; + )) + .parse(input)?; Ok((input, x_name)) } @@ -195,14 +197,14 @@ fn name<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], &'a [u8], E> where E: ParseError<&'a [u8]> + From>, { - alt((iana_token, x_name))(input) + alt((iana_token, x_name)).parse(input) } fn param_name<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], &'a [u8], E> where E: ParseError<&'a [u8]> + From>, { - alt((iana_token, x_name))(input) + alt((iana_token, x_name)).parse(input) } #[inline] @@ -259,7 +261,8 @@ where let (input, v) = fold_many0(value_char, Vec::new, |mut acc, item| { acc.extend_from_slice(&item); acc - })(input)?; + }) + .parse(input)?; Ok((input, v)) } @@ -271,7 +274,8 @@ where alt(( single(|b| matches!(b, b' ' | b'\t' | b'\x21'..=b'\x7E')).map(|c| vec![c]), utf8_seq.map(|c| c.to_vec()), - ))(input) + )) + .parse(input) } fn value<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Vec, E> @@ -281,7 +285,8 @@ where fold_many0(value_char, Vec::new, |mut acc, item| { acc.extend_from_slice(&item); acc - })(input) + }) + .parse(input) } fn param<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E> @@ -292,7 +297,8 @@ where param_name, char('='), cut(separated_list1(char(','), param_value)), - )(input)?; + ) + .parse(input)?; Ok(( input, @@ -311,13 +317,14 @@ fn content_line<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ContentLine<'a>, E> where E: ParseError<&'a [u8]> + From>, { - let (input, (property_name, params, _, value, _)) = tuple(( + let (input, (property_name, params, _, value, _)) = ( name, - many0(tuple((char(';'), cut(param))).map(|(_, p)| p)), + many0((char(';'), cut(param))).map(|v| v.into_iter().map(|(_, p)| p).collect()), char(':'), cut(line_value), crlf, - ))(input)?; + ) + .parse(input)?; Ok(( input, diff --git a/src/parser/component/alarm.rs b/src/parser/component/alarm.rs index 0dccd30..86d3563 100644 --- a/src/parser/component/alarm.rs +++ b/src/parser/component/alarm.rs @@ -9,7 +9,6 @@ use nom::branch::alt; use nom::bytes::streaming::tag; use nom::error::ParseError; use nom::multi::many0; -use nom::sequence::tuple; use nom::{IResult, Parser}; pub fn component_alarm<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], CalendarComponent<'a>, E> @@ -18,7 +17,7 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, properties, _)) = tuple(( + let (input, (_, properties, _)) = ( tag("BEGIN:VALARM\r\n"), many0(alt(( alt(( @@ -35,7 +34,8 @@ where prop_iana.map(ComponentProperty::IanaProperty), ))), tag("END:VALARM\r\n"), - ))(input)?; + ) + .parse(input)?; Ok((input, CalendarComponent::Alarm { properties })) } diff --git a/src/parser/component/event.rs b/src/parser/component/event.rs index 788e07c..abb147d 100644 --- a/src/parser/component/event.rs +++ b/src/parser/component/event.rs @@ -16,7 +16,6 @@ use nom::bytes::streaming::tag; use nom::combinator::cut; use nom::error::ParseError; use nom::multi::many0; -use nom::sequence::tuple; use nom::{IResult, Parser}; pub fn component_event<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], CalendarComponent<'a>, E> @@ -25,7 +24,7 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, properties, alarms, _)) = tuple(( + let (input, (_, properties, alarms, _)) = ( tag("BEGIN:VEVENT\r\n"), cut(many0(alt(( alt(( @@ -67,7 +66,8 @@ where )))), many0(component_alarm), tag("END:VEVENT\r\n"), - ))(input)?; + ) + .parse(input)?; Ok((input, CalendarComponent::Event { properties, alarms })) } diff --git a/src/parser/component/free_busy.rs b/src/parser/component/free_busy.rs index 80d9a89..5331975 100644 --- a/src/parser/component/free_busy.rs +++ b/src/parser/component/free_busy.rs @@ -11,7 +11,6 @@ use nom::bytes::streaming::tag; use nom::combinator::cut; use nom::error::ParseError; use nom::multi::many0; -use nom::sequence::tuple; use nom::IResult; use nom::Parser; @@ -21,7 +20,7 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, properties, _)) = tuple(( + let (input, (_, properties, _)) = ( tag("BEGIN:VFREEBUSY\r\n"), cut(many0(alt(( alt(( @@ -41,7 +40,8 @@ where prop_iana.map(ComponentProperty::IanaProperty), )))), tag("END:VFREEBUSY\r\n"), - ))(input)?; + ) + .parse(input)?; Ok((input, CalendarComponent::FreeBusy { properties })) } diff --git a/src/parser/component/journal.rs b/src/parser/component/journal.rs index ef7823a..d3e56fc 100644 --- a/src/parser/component/journal.rs +++ b/src/parser/component/journal.rs @@ -14,7 +14,6 @@ use nom::bytes::streaming::tag; use nom::combinator::cut; use nom::error::ParseError; use nom::multi::many0; -use nom::sequence::tuple; use nom::{IResult, Parser}; pub fn component_journal<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], CalendarComponent<'a>, E> @@ -23,7 +22,7 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, properties, _)) = tuple(( + let (input, (_, properties, _)) = ( tag("BEGIN:VJOURNAL\r\n"), cut(many0(alt(( alt(( @@ -57,7 +56,8 @@ where prop_iana.map(ComponentProperty::IanaProperty), )))), tag("END:VJOURNAL\r\n"), - ))(input)?; + ) + .parse(input)?; Ok((input, CalendarComponent::Journal { properties })) } diff --git a/src/parser/component/timezone.rs b/src/parser/component/timezone.rs index a4a8100..1a35762 100644 --- a/src/parser/component/timezone.rs +++ b/src/parser/component/timezone.rs @@ -11,7 +11,6 @@ use nom::bytes::streaming::tag; use nom::combinator::cut; use nom::error::ParseError; use nom::multi::many0; -use nom::sequence::tuple; use nom::IResult; use nom::Parser; @@ -27,7 +26,7 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, properties, _)) = tuple(( + let (input, (_, properties, _)) = ( tag("BEGIN:VTIMEZONE\r\n"), cut(many0(alt(( alt(( @@ -51,7 +50,8 @@ where .map(PropertyOrComponent::Property), )))), tag("END:VTIMEZONE\r\n"), - ))(input)?; + ) + .parse(input)?; let (properties, components): (Vec, Vec) = properties .into_iter() @@ -84,11 +84,12 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, properties, _)) = tuple(( + let (input, (_, properties, _)) = ( tag("BEGIN:STANDARD\r\n"), cut(tz_props), tag("END:STANDARD\r\n"), - ))(input)?; + ) + .parse(input)?; Ok((input, CalendarComponent::Standard { properties })) } @@ -99,11 +100,12 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, properties, _)) = tuple(( + let (input, (_, properties, _)) = ( tag("BEGIN:DAYLIGHT\r\n"), cut(tz_props), tag("END:DAYLIGHT\r\n"), - ))(input)?; + ) + .parse(input)?; Ok((input, CalendarComponent::Daylight { properties })) } @@ -126,7 +128,8 @@ where )), prop_x.map(ComponentProperty::XProperty), prop_iana.map(ComponentProperty::IanaProperty), - )))(input) + ))) + .parse(input) } #[cfg(test)] diff --git a/src/parser/component/todo.rs b/src/parser/component/todo.rs index a633271..37de867 100644 --- a/src/parser/component/todo.rs +++ b/src/parser/component/todo.rs @@ -16,7 +16,6 @@ use nom::bytes::streaming::tag; use nom::combinator::cut; use nom::error::ParseError; use nom::multi::many0; -use nom::sequence::tuple; use nom::IResult; use nom::Parser; @@ -26,7 +25,7 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, properties, alarms, _)) = tuple(( + let (input, (_, properties, alarms, _)) = ( tag("BEGIN:VTODO\r\n"), cut(many0(alt(( alt(( @@ -69,7 +68,8 @@ where )))), many0(component_alarm), tag("END:VTODO\r\n"), - ))(input)?; + ) + .parse(input)?; Ok((input, CalendarComponent::ToDo { properties, alarms })) } diff --git a/src/parser/first_pass.rs b/src/parser/first_pass.rs index c513af2..6de8a07 100644 --- a/src/parser/first_pass.rs +++ b/src/parser/first_pass.rs @@ -3,8 +3,8 @@ use nom::bytes::streaming::{tag, take_until}; use nom::character::streaming::one_of; use nom::combinator::opt; use nom::error::ParseError; -use nom::sequence::tuple; use nom::IResult; +use nom::Parser; /// Recognize a content line, collapsing folded lines. /// @@ -25,7 +25,7 @@ where break; } - match tuple((tag("\r\n"), opt(one_of(" \t"))))(input) { + match (tag("\r\n"), opt(one_of(" \t"))).parse(input) { Ok((i, (lb, sp))) => { if sp.is_none() { out.extend_from_slice(lb); diff --git a/src/parser/language_tag.rs b/src/parser/language_tag.rs index 968c4be..c3c2601 100644 --- a/src/parser/language_tag.rs +++ b/src/parser/language_tag.rs @@ -5,12 +5,10 @@ use crate::parser::Error; use nom::branch::alt; use nom::bytes::streaming::{tag, take_while_m_n}; use nom::character::streaming::char; -use nom::character::{is_alphabetic, is_alphanumeric, is_digit}; use nom::combinator::{opt, peek, recognize, verify}; use nom::error::ParseError; use nom::multi::{many0, many1, many_m_n}; -use nom::sequence::tuple; -use nom::{IResult, Parser}; +use nom::{AsChar, IResult, Parser}; #[inline] const fn is_singleton(b: u8) -> bool { @@ -21,10 +19,11 @@ fn private_use<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], &'a [u8], E> where E: ParseError<&'a [u8]> + From>, { - recognize(tuple(( + recognize(( char('x'), - many1(tuple((char('-'), take_while_m_n(1, 8, is_alphanumeric)))), - )))(input) + many1((char('-'), take_while_m_n(1, 8, AsChar::is_alphanum))), + )) + .parse(input) } pub fn language_tag<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], LanguageTag, E> @@ -49,7 +48,8 @@ where tag("sgn-BE-FR"), tag("sgn-BE-NL"), tag("sgn-CH-DE"), - )))(input)?; + ))) + .parse(input)?; if let Some(grandfathered_irregular) = grandfathered_irregular { let language_tag = LanguageTag { @@ -65,7 +65,7 @@ where return Ok((input, language_tag)); } - let (input, private_use) = opt(private_use)(input)?; + let (input, private_use) = opt(private_use).parse(input)?; if let Some(private_use) = private_use { let language_tag = LanguageTag { language: String::from_utf8_lossy(private_use).to_string(), @@ -93,9 +93,10 @@ where E: ParseError<&'a [u8]> + From>, { peek(verify( - take_while_m_n(0, 1, |c| c == b'-' || is_alphanumeric(c)), + take_while_m_n(0, 1, |c| c == b'-' || AsChar::is_alphanum(c)), |m: &[u8]| m == [b'-'] || m.is_empty(), - ))(input) + )) + .parse(input) } pub fn lang_tag<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], LanguageTag, E> @@ -103,24 +104,25 @@ where E: ParseError<&'a [u8]> + From>, { let (input, (language, ext_lang)) = alt(( - tuple(( - take_while_m_n(2, 3, is_alphabetic), - opt(tuple(( + ( + take_while_m_n(2, 3, AsChar::is_alpha), + opt(( char('-'), - recognize(tuple(( - take_while_m_n(3, 3, is_alphabetic), + recognize(( + take_while_m_n(3, 3, AsChar::is_alpha), many_m_n( 0, 2, - tuple((char('-'), take_while_m_n(3, 3, is_alphabetic), clip)), + (char('-'), take_while_m_n(3, 3, AsChar::is_alpha), clip), ), clip, - ))), - ))), - )), - take_while_m_n(4, 4, is_alphabetic).map(|l| (l, None)), - take_while_m_n(5, 8, is_alphabetic).map(|l| (l, None)), - ))(input)?; + )), + )), + ), + take_while_m_n(4, 4, AsChar::is_alpha).map(|l| (l, None)), + take_while_m_n(5, 8, AsChar::is_alpha).map(|l| (l, None)), + )) + .parse(input)?; let mut language_tag = LanguageTag { language: String::from_utf8_lossy(language).to_string(), @@ -133,40 +135,39 @@ where }; // Find the script, if present - let (input, script) = opt(tuple(( - char('-'), - take_while_m_n(4, 4, is_alphabetic), - clip, - )))(input)?; + let (input, script) = + opt((char('-'), take_while_m_n(4, 4, AsChar::is_alpha), clip)).parse(input)?; if let Some((_, script, _)) = script { language_tag.script = Some(String::from_utf8_lossy(script).to_string()); } // Find the region, if present - let (input, region) = opt(tuple(( + let (input, region) = opt(( char('-'), alt(( - tuple((take_while_m_n(2, 2, is_alphabetic), clip)), - tuple((take_while_m_n(3, 3, is_digit), clip)), + (take_while_m_n(2, 2, AsChar::is_alpha), clip), + (take_while_m_n(3, 3, AsChar::is_dec_digit), clip), )), - )))(input)?; + )) + .parse(input)?; if let Some((_, (region, _))) = region { language_tag.region = Some(String::from_utf8_lossy(region).to_string()); } // Find variants, is present - let (input, variants) = many0(tuple(( + let (input, variants) = many0(( char('-'), alt(( - take_while_m_n(5, 8, is_alphanumeric), - recognize(tuple(( - take_while_m_n(1, 1, is_digit), - take_while_m_n(3, 3, is_alphanumeric), - ))), + take_while_m_n(5, 8, AsChar::is_alphanum), + recognize(( + take_while_m_n(1, 1, AsChar::is_dec_digit), + take_while_m_n(3, 3, AsChar::is_alphanum), + )), )), - )))(input)?; + )) + .parse(input)?; if !variants.is_empty() { language_tag.variants = variants @@ -176,13 +177,14 @@ where } // Find extensions, if present - let (input, extensions) = many0(tuple(( + let (input, extensions) = many0(( char('-'), - recognize(tuple(( + recognize(( take_while_m_n(1, 1, is_singleton), - many1(tuple((char('-'), take_while_m_n(2, 8, is_alphanumeric)))), - ))), - )))(input)?; + many1((char('-'), take_while_m_n(2, 8, AsChar::is_alphanum))), + )), + )) + .parse(input)?; if !extensions.is_empty() { language_tag.extensions = extensions @@ -192,7 +194,7 @@ where } // Find private use, if present - let (input, private_use) = opt(tuple((char('-'), private_use)))(input)?; + let (input, private_use) = opt((char('-'), private_use)).parse(input)?; if let Some((_, private_use)) = private_use { language_tag.private_use = Some(String::from_utf8_lossy(private_use).to_string()); diff --git a/src/parser/object.rs b/src/parser/object.rs index 55c53e6..8475733 100644 --- a/src/parser/object.rs +++ b/src/parser/object.rs @@ -14,7 +14,6 @@ use nom::character::streaming::crlf; use nom::combinator::{cut, eof, verify}; use nom::error::ParseError; use nom::multi::{many0, many1}; -use nom::sequence::tuple; use nom::IResult; use nom::Parser; @@ -52,11 +51,12 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, body, _)) = tuple(( + let (input, (_, body, _)) = ( tag("BEGIN:VCALENDAR\r\n"), ical_body, tag("END:VCALENDAR\r\n"), - ))(input)?; + ) + .parse(input)?; Ok((input, body)) } @@ -67,7 +67,8 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (properties, components)) = tuple((many0(ical_cal_prop), many1(component)))(input)?; + let (input, (properties, components)) = + (many0(ical_cal_prop), many1(component)).parse(input)?; Ok(( input, @@ -109,14 +110,15 @@ where component_timezone, x_comp, iana_comp, - ))(input) + )) + .parse(input) } fn iana_comp<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], CalendarComponent<'a>, E> where E: ParseError<&'a [u8]> + From>, { - let (input, (_, name, _, lines, _, end_name, _)) = tuple(( + let (input, (_, name, _, lines, _, end_name, _)) = ( tag("BEGIN:"), iana_token, crlf, @@ -126,7 +128,8 @@ where tag("END:"), iana_token, tag("\r\n"), - ))(input)?; + ) + .parse(input)?; if name != end_name { return Err(nom::Err::Error( @@ -145,7 +148,7 @@ fn x_comp<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], CalendarComponent<'a>, E> where E: ParseError<&'a [u8]> + From>, { - let (input, (_, name, _, lines, _, end_name, _)) = tuple(( + let (input, (_, name, _, lines, _, end_name, _)) = ( tag("BEGIN:"), x_name, crlf, @@ -153,7 +156,8 @@ where tag("END:"), x_name, crlf, - ))(input)?; + ) + .parse(input)?; if name != end_name { return Err(nom::Err::Error( @@ -182,9 +186,9 @@ impl ReprStr for &[u8] { // Borrowed from `nom` and modified (somewhat poorly!) to work with byte arrays rather than strings. #[cfg(test)] -fn convert_error_mod(input: I, e: nom::error::VerboseError) -> String { - use nom::error::VerboseErrorKind; +fn convert_error_mod(input: I, e: nom_language::error::VerboseError) -> String { use nom::Offset; + use nom_language::error::VerboseErrorKind; use std::fmt::Write; let mut result = String::new(); @@ -306,7 +310,6 @@ mod tests { use crate::parser::types::VersionProperty; use crate::test_utils::check_rem; use nom::combinator::complete; - use nom::error::VerboseError; #[test] fn minimal_ical_stream_test() { @@ -334,7 +337,8 @@ mod tests { let (input, first) = content_line_first_pass::(input.as_bytes()).unwrap(); check_rem(input, 0); - let r = complete::<_, _, VerboseError<&[u8]>, _>(ical_stream).parse(&first); + let r = complete::<_, _, nom_language::error::VerboseError<&[u8]>, _>(ical_stream) + .parse(&first); match r { Err(nom::Err::Error(e) | nom::Err::Failure(e)) => { println!("fail:\n\n {}", convert_error_mod(first.as_slice(), e)); diff --git a/src/parser/param.rs b/src/parser/param.rs index 3ac156d..b7993b8 100644 --- a/src/parser/param.rs +++ b/src/parser/param.rs @@ -12,7 +12,7 @@ use nom::character::streaming::char; use nom::combinator::{cut, map_res, recognize}; use nom::error::ParseError; use nom::multi::{many0, separated_list1}; -use nom::sequence::{delimited, separated_pair, tuple}; +use nom::sequence::{delimited, separated_pair}; use nom::{IResult, Parser}; pub use value::*; @@ -23,7 +23,7 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - many0(tuple((char(';'), cut(property_param))).map(|(_, p)| p)).parse(input) + many0((char(';'), cut(property_param)).map(|(_, p)| p)).parse(input) } /// Recognize a single parameter. @@ -33,7 +33,7 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - alt((known_param, iana_param, x_param))(input) + alt((known_param, iana_param, x_param)).parse(input) } /// Parse an ALTREP param @@ -47,11 +47,12 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, _, uri)) = tuple(( + let (input, (_, _, uri)) = ( tag_no_case("ALTREP"), char('='), cut(delimited(char('"'), recognize(param_value_uri), char('"'))), - ))(input)?; + ) + .parse(input)?; Ok((input, ParamValue::AltRep { uri })) } @@ -63,7 +64,7 @@ fn param_common_name<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a> where E: ParseError<&'a [u8]> + From>, { - let (input, (_, _, value)) = tuple((tag_no_case("CN"), char('='), cut(param_value)))(input)?; + let (input, (_, _, value)) = (tag_no_case("CN"), char('='), cut(param_value)).parse(input)?; Ok(( input, @@ -82,11 +83,12 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, _, cu_type)) = tuple(( + let (input, (_, _, cu_type)) = ( tag_no_case("CUTYPE"), char('='), cut(param_value_calendar_user_type), - ))(input)?; + ) + .parse(input)?; Ok((input, ParamValue::CalendarUserType { cu_type })) } @@ -100,11 +102,12 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, _, delegators)) = tuple(( + let (input, (_, _, delegators)) = ( tag_no_case("DELEGATED-FROM"), char('='), cut(param_value_delegated_from), - ))(input)?; + ) + .parse(input)?; Ok((input, ParamValue::DelegatedFrom { delegators })) } @@ -120,7 +123,8 @@ where separated_list1( char(','), delimited(char('"'), recognize(param_value_uri), char('"')), - )(input) + ) + .parse(input) } /// Parse a DELEGATED-TO param @@ -132,14 +136,15 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, _, delegates)) = tuple(( + let (input, (_, _, delegates)) = ( tag_no_case("DELEGATED-TO"), char('='), cut(separated_list1( char(','), delimited(char('"'), recognize(param_value_uri), char('"')), )), - ))(input)?; + ) + .parse(input)?; Ok((input, ParamValue::DelegatedTo { delegates })) } @@ -153,11 +158,12 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, _, uri)) = tuple(( + let (input, (_, _, uri)) = ( tag_no_case("DIR"), char('='), cut(delimited(char('"'), recognize(param_value_uri), char('"'))), - ))(input)?; + ) + .parse(input)?; Ok((input, ParamValue::DirectoryEntryReference { uri })) } @@ -171,11 +177,12 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, _, encoding)) = tuple(( + let (input, (_, _, encoding)) = ( tag_no_case("ENCODING"), char('='), cut(param_value_encoding), - ))(input)?; + ) + .parse(input)?; Ok((input, ParamValue::Encoding { encoding })) } @@ -189,7 +196,7 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, _, (type_name, sub_type_name))) = tuple(( + let (input, (_, _, (type_name, sub_type_name))) = ( tag_no_case("FMTTYPE"), char('='), cut(separated_pair( @@ -197,7 +204,8 @@ where char('/'), map_res(reg_name, |t| read_string(t, "FMTTYPE subtype-name")), )), - ))(input)?; + ) + .parse(input)?; Ok(( input, @@ -217,11 +225,12 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, _, fb_type)) = tuple(( + let (input, (_, _, fb_type)) = ( tag_no_case("FBTYPE"), char('='), cut(param_value_free_busy_time_type), - ))(input)?; + ) + .parse(input)?; Ok((input, ParamValue::FreeBusyTimeType { fb_type })) } @@ -236,7 +245,7 @@ where + From>, { let (input, (_, _, language)) = - tuple((tag_no_case("LANGUAGE"), char('='), cut(language_tag)))(input)?; + (tag_no_case("LANGUAGE"), char('='), cut(language_tag)).parse(input)?; Ok((input, ParamValue::Language { language })) } @@ -250,14 +259,15 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, _, members)) = tuple(( + let (input, (_, _, members)) = ( tag_no_case("MEMBER"), char('='), cut(separated_list1( char(','), delimited(char('"'), recognize(param_value_uri), char('"')), )), - ))(input)?; + ) + .parse(input)?; Ok((input, ParamValue::Members { members })) } @@ -271,11 +281,12 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, _, status)) = tuple(( + let (input, (_, _, status)) = ( tag_no_case("PARTSTAT"), char('='), cut(param_value_participation_status), - ))(input)?; + ) + .parse(input)?; Ok((input, ParamValue::ParticipationStatus { status })) } @@ -290,7 +301,7 @@ where + From>, { let (input, (_, _, _)) = - tuple((tag_no_case("RANGE"), char('='), cut(tag("THISANDFUTURE"))))(input)?; + (tag_no_case("RANGE"), char('='), cut(tag("THISANDFUTURE"))).parse(input)?; Ok(( input, @@ -309,11 +320,12 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, _, related)) = tuple(( + let (input, (_, _, related)) = ( tag_no_case("RELATED"), char('='), cut(param_value_trigger_relationship), - ))(input)?; + ) + .parse(input)?; Ok((input, ParamValue::Related { related })) } @@ -327,11 +339,12 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, _, relationship)) = tuple(( + let (input, (_, _, relationship)) = ( tag_no_case("RELTYPE"), char('='), cut(param_value_relationship_type), - ))(input)?; + ) + .parse(input)?; Ok((input, ParamValue::RelationshipType { relationship })) } @@ -346,7 +359,7 @@ where + From>, { let (input, (_, _, role)) = - tuple((tag_no_case("ROLE"), char('='), cut(param_value_role)))(input)?; + (tag_no_case("ROLE"), char('='), cut(param_value_role)).parse(input)?; Ok((input, ParamValue::Role { role })) } @@ -361,7 +374,7 @@ where + From>, { let (input, (_, _, rsvp)) = - tuple((tag_no_case("RSVP"), char('='), cut(param_value_rsvp)))(input)?; + (tag_no_case("RSVP"), char('='), cut(param_value_rsvp)).parse(input)?; Ok((input, ParamValue::Rsvp { rsvp })) } @@ -375,11 +388,12 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, _, address)) = tuple(( + let (input, (_, _, address)) = ( tag_no_case("SENT-BY"), char('='), cut(delimited(char('"'), recognize(param_value_uri), char('"'))), - ))(input)?; + ) + .parse(input)?; Ok((input, ParamValue::SentBy { address })) } @@ -393,11 +407,12 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, _, (tz_id, unique))) = tuple(( + let (input, (_, _, (tz_id, unique))) = ( tag_no_case("TZID"), char('='), cut(param_value_time_zone_id), - ))(input)?; + ) + .parse(input)?; Ok((input, ParamValue::TimeZoneId { tz_id, unique })) } @@ -412,7 +427,7 @@ where + From>, { let (input, (_, _, value)) = - tuple((tag_no_case("VALUE"), char('='), cut(param_value_value_type)))(input)?; + (tag_no_case("VALUE"), char('='), cut(param_value_value_type)).parse(input)?; Ok((input, ParamValue::ValueType { value })) } @@ -444,7 +459,8 @@ where param_sent_by, param_time_zone_identifier, param_value_type, - ))(input)?; + )) + .parse(input)?; Ok((input, param_value)) } @@ -453,25 +469,28 @@ pub fn other_params<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Vec + From>, { - many0(tuple((char(';'), other_param)).map(|(_, p)| p)).parse(input) + many0((char(';'), other_param)) + .map(|v| v.into_iter().map(|(_, p)| p).collect()) + .parse(input) } pub fn other_param<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E> where E: ParseError<&'a [u8]> + From>, { - alt((iana_param, x_param))(input) + alt((iana_param, x_param)).parse(input) } fn iana_param<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E> where E: ParseError<&'a [u8]> + From>, { - let (input, (name, _, values)) = tuple(( + let (input, (name, _, values)) = ( param_name, char('='), separated_list1(char(','), param_value), - ))(input)?; + ) + .parse(input)?; Ok(( input, @@ -490,7 +509,7 @@ where E: ParseError<&'a [u8]> + From>, { let (input, (name, _, values)) = - tuple((x_name, char('='), separated_list1(char(','), param_value)))(input)?; + (x_name, char('='), separated_list1(char(','), param_value)).parse(input)?; Ok(( input, diff --git a/src/parser/param/value.rs b/src/parser/param/value.rs index 67fcbd4..05e37b4 100644 --- a/src/parser/param/value.rs +++ b/src/parser/param/value.rs @@ -9,7 +9,6 @@ use nom::bytes::complete::tag_no_case; use nom::character::streaming::char; use nom::combinator::{map_res, opt}; use nom::error::ParseError; -use nom::sequence::tuple; use nom::IResult; use nom::Parser; @@ -39,7 +38,8 @@ where "CUTYPE iana-token", )?)) }), - ))(input)?; + )) + .parse(input)?; Ok((input, cu_type)) } @@ -51,7 +51,8 @@ where let (input, encoding) = alt(( tag_no_case("8BIT").map(|_| Encoding::EightBit), tag_no_case("BASE64").map(|_| Encoding::Base64), - ))(input)?; + )) + .parse(input)?; Ok((input, encoding)) } @@ -81,7 +82,8 @@ where "FBTYPE iana-token", )?)) }), - ))(input)?; + )) + .parse(input)?; Ok((input, fb_type)) } @@ -114,7 +116,8 @@ where "PARTSTAT iana-token", )?)) }), - ))(input)?; + )) + .parse(input)?; Ok((input, part_stat)) } @@ -128,7 +131,8 @@ where let (input, related) = alt(( tag_no_case("START").map(|_| TriggerRelationship::Start), tag_no_case("END").map(|_| TriggerRelationship::End), - ))(input)?; + )) + .parse(input)?; Ok((input, related)) } @@ -157,7 +161,8 @@ where "RELTYPE iana-token", )?)) }), - ))(input)?; + )) + .parse(input)?; Ok((input, rel_type)) } @@ -179,7 +184,8 @@ where map_res(iana_token, |iana_token| { Ok(Role::IanaToken(read_string(iana_token, "ROLE iana-token")?)) }), - ))(input)?; + )) + .parse(input)?; Ok((input, role)) } @@ -191,7 +197,8 @@ where let (input, rsvp) = alt(( tag_no_case("TRUE").map(|_| true), tag_no_case("FALSE").map(|_| false), - ))(input)?; + )) + .parse(input)?; Ok((input, rsvp)) } @@ -200,7 +207,8 @@ pub fn param_value_time_zone_id<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], (St where E: ParseError<&'a [u8]> + From>, { - let (input, (unique, tz_id)) = tuple((opt(char('/')).map(|p| p.is_some()), param_text))(input)?; + let (input, (unique, tz_id)) = + (opt(char('/')).map(|p| p.is_some()), param_text).parse(input)?; Ok((input, (read_string(tz_id, "TZID")?, unique))) } @@ -235,7 +243,8 @@ where "VALUE iana-token", )?)) }), - ))(input)?; + )) + .parse(input)?; Ok((input, value)) } diff --git a/src/parser/property.rs b/src/parser/property.rs index b75d281..a20f436 100644 --- a/src/parser/property.rs +++ b/src/parser/property.rs @@ -14,24 +14,23 @@ pub use component::*; use nom::branch::alt; use nom::bytes::complete::tag_no_case; use nom::bytes::streaming::tag; -use nom::character::is_digit; use nom::character::streaming::char; use nom::combinator::{cut, recognize, verify}; use nom::error::ParseError; -use nom::sequence::tuple; -use nom::{IResult, Parser}; +use nom::{AsChar, IResult, Parser}; pub fn prop_product_id<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ProductIdProperty<'a>, E> where E: ParseError<&'a [u8]> + From>, { - let (input, (_, params, _, value, _)) = tuple(( + let (input, (_, params, _, value, _)) = ( tag_no_case("PRODID"), cut(other_params), char(':'), prop_value_text, tag("\r\n"), - ))(input)?; + ) + .parse(input)?; Ok(( input, @@ -46,22 +45,35 @@ pub fn prop_version<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], VersionProperty where E: ParseError<&'a [u8]> + From>, { - let (input, (_, params, _, (min_ver, max_ver), _)) = tuple(( + let (input, (_, params, _, (min_ver, max_ver), _)) = ( tag_no_case("VERSION"), cut(other_params), char(':'), alt(( - tuple(( - recognize(tuple((single(is_digit), char('.'), single(is_digit)))), + ( + recognize(( + single(AsChar::is_dec_digit), + char('.'), + single(AsChar::is_dec_digit), + )), char(';'), - recognize(tuple((single(is_digit), char('.'), single(is_digit)))), + recognize(( + single(AsChar::is_dec_digit), + char('.'), + single(AsChar::is_dec_digit), + )), + ) + .map(|(min_ver, _, max_ver)| (Some(min_ver), max_ver)), + recognize(( + single(AsChar::is_dec_digit), + char('.'), + single(AsChar::is_dec_digit), )) - .map(|(min_ver, _, max_ver)| (Some(min_ver), max_ver)), - recognize(tuple((single(is_digit), char('.'), single(is_digit)))) - .map(|v| (Option::<&[u8]>::None, v)), + .map(|v| (Option::<&[u8]>::None, v)), )), tag("\r\n"), - ))(input)?; + ) + .parse(input)?; Ok(( input, @@ -79,13 +91,14 @@ pub fn prop_calendar_scale<'a, E>( where E: ParseError<&'a [u8]> + From>, { - let (input, (_, params, _, value, _)) = tuple(( + let (input, (_, params, _, value, _)) = ( tag_no_case("CALSCALE"), cut(other_params), char(':'), prop_value_text, tag("\r\n"), - ))(input)?; + ) + .parse(input)?; Ok(( input, @@ -100,13 +113,14 @@ pub fn prop_method<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], MethodProperty<' where E: ParseError<&'a [u8]> + From>, { - let (input, (_, params, _, value, _)) = tuple(( + let (input, (_, params, _, value, _)) = ( tag_no_case("METHOD"), cut(other_params), char(':'), iana_token, tag("\r\n"), - ))(input)?; + ) + .parse(input)?; Ok(( input, @@ -124,7 +138,7 @@ where + From>, { let (input, (name, params, _, value, _)) = - tuple((x_name, cut(property_params), char(':'), value, tag("\r\n")))(input)?; + (x_name, cut(property_params), char(':'), value, tag("\r\n")).parse(input)?; Ok(( input, @@ -142,7 +156,7 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (name, params, _, value, _)) = tuple(( + let (input, (name, params, _, value, _)) = ( verify(iana_token, |t: &[u8]| { // Not ideal, but in order to avoid IANA names colliding with ical structure, filter these values out t != b"BEGIN" && t != b"END" @@ -151,7 +165,8 @@ where char(':'), value, tag("\r\n"), - ))(input)?; + ) + .parse(input)?; Ok(( input, diff --git a/src/parser/property/component.rs b/src/parser/property/component.rs index 1be592d..e13e5ce 100644 --- a/src/parser/property/component.rs +++ b/src/parser/property/component.rs @@ -25,13 +25,11 @@ use crate::parser::{ use nom::branch::alt; use nom::bytes::complete::{tag_no_case, take_while1}; use nom::bytes::streaming::tag; -use nom::character::is_digit; use nom::character::streaming::char; use nom::combinator::{cut, map_res, opt, recognize, verify}; use nom::error::ParseError; use nom::multi::{fold_many_m_n, separated_list1}; -use nom::sequence::tuple; -use nom::{IResult, Parser}; +use nom::{AsChar, IResult, Parser}; /// Parse an ATTACH property. /// @@ -43,7 +41,7 @@ where + From>, { let (input, (_, params, _)) = - tuple((tag_no_case("ATTACH"), cut(property_params), char(':')))(input)?; + (tag_no_case("ATTACH"), cut(property_params), char(':')).parse(input)?; let is_base_64 = params.iter().any(|p| { matches!( @@ -66,7 +64,7 @@ where // Use OR here rather than AND. It's not valid to set one of these and not the other so assume the // value is more likely to be binary if one is set and let the error happen later if so. if is_base_64 || is_binary { - let (input, (v, _)) = tuple((cut(prop_value_binary), tag("\r\n")))(input)?; + let (input, (v, _)) = (cut(prop_value_binary), tag("\r\n")).parse(input)?; Ok(( input, @@ -76,7 +74,7 @@ where }, )) } else { - let (input, (v, _)) = tuple((cut(recognize(param_value_uri)), tag("\r\n")))(input)?; + let (input, (v, _)) = (cut(recognize(param_value_uri)), tag("\r\n")).parse(input)?; Ok(( input, @@ -97,15 +95,16 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, (params, _, value, _))) = tuple(( + let (input, (_, (params, _, value, _))) = ( tag_no_case("CATEGORIES"), - cut(tuple(( + cut(( property_params, char(':'), separated_list1(char(','), prop_value_text), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok((input, CategoriesProperty { params, value })) } @@ -119,9 +118,9 @@ pub fn prop_classification<'a, E>( where E: ParseError<&'a [u8]> + From>, { - let (input, (_, (other_params, _, value, _))) = tuple(( + let (input, (_, (other_params, _, value, _))) = ( tag_no_case("CLASS"), - cut(tuple(( + cut(( other_params, char(':'), alt(( @@ -132,8 +131,9 @@ where iana_token.map(Classification::IanaToken), )), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok(( input, @@ -153,15 +153,11 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, (params, _, value, _))) = tuple(( + let (input, (_, (params, _, value, _))) = ( tag_no_case("COMMENT"), - cut(tuple(( - property_params, - char(':'), - prop_value_text, - tag("\r\n"), - ))), - ))(input)?; + cut((property_params, char(':'), prop_value_text, tag("\r\n"))), + ) + .parse(input)?; Ok((input, CommentProperty { params, value })) } @@ -175,15 +171,16 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, (params, _, value, _))) = tuple(( + let (input, (_, (params, _, value, _))) = ( tag_no_case("DESCRIPTION"), - cut(tuple(( + cut(( property_params, char(':'), prop_value_text.map(|v| v), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok((input, DescriptionProperty { params, value })) } @@ -197,15 +194,16 @@ pub fn prop_geographic_position<'a, E>( where E: ParseError<&'a [u8]> + From>, { - let (input, (_, (other_params, _, (latitude, _, longitude), _))) = tuple(( + let (input, (_, (other_params, _, (latitude, _, longitude), _))) = ( tag_no_case("GEO"), - cut(tuple(( + cut(( other_params, char(':'), - tuple((prop_value_float, char(';'), prop_value_float)), + (prop_value_float, char(';'), prop_value_float), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok(( input, @@ -226,15 +224,11 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, (params, _, value, _))) = tuple(( + let (input, (_, (params, _, value, _))) = ( tag_no_case("LOCATION"), - cut(tuple(( - property_params, - char(':'), - prop_value_text, - tag("\r\n"), - ))), - ))(input)?; + cut((property_params, char(':'), prop_value_text, tag("\r\n"))), + ) + .parse(input)?; Ok((input, LocationProperty { params, value })) } @@ -248,15 +242,16 @@ pub fn prop_percent_complete<'a, E>( where E: ParseError<&'a [u8]> + From>, { - let (input, (_, (other_params, _, value, _))) = tuple(( + let (input, (_, (other_params, _, value, _))) = ( tag_no_case("PERCENT-COMPLETE"), - cut(tuple(( + cut(( other_params, char(':'), verify(prop_value_integer, |v| 0 <= *v && *v <= 100).map(|v| v as u8), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok(( input, @@ -274,15 +269,16 @@ pub fn prop_priority<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], PriorityProper where E: ParseError<&'a [u8]> + From>, { - let (input, (_, (other_params, _, value, _))) = tuple(( + let (input, (_, (other_params, _, value, _))) = ( tag_no_case("PRIORITY"), - cut(tuple(( + cut(( other_params, char(':'), verify(prop_value_integer, |v| 0 <= *v && *v <= 9).map(|v| v as u8), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok(( input, @@ -302,15 +298,16 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, (params, _, value, _))) = tuple(( + let (input, (_, (params, _, value, _))) = ( tag_no_case("RESOURCES"), - cut(tuple(( + cut(( property_params, char(':'), separated_list1(char(','), prop_value_text), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok((input, ResourcesProperty { params, value })) } @@ -322,9 +319,9 @@ pub fn prop_status<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], StatusProperty<' where E: ParseError<&'a [u8]> + From>, { - let (input, (_, (other_params, _, value, _))) = tuple(( + let (input, (_, (other_params, _, value, _))) = ( tag_no_case("STATUS"), - cut(tuple(( + cut(( other_params, char(':'), alt(( @@ -338,8 +335,9 @@ where tag_no_case("FINAL").map(|_| Status::Final), )), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok(( input, @@ -359,15 +357,11 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, (params, _, value, _))) = tuple(( + let (input, (_, (params, _, value, _))) = ( tag_no_case("SUMMARY"), - cut(tuple(( - property_params, - char(':'), - prop_value_text, - tag("\r\n"), - ))), - ))(input)?; + cut((property_params, char(':'), prop_value_text, tag("\r\n"))), + ) + .parse(input)?; Ok((input, SummaryProperty { params, value })) } @@ -381,15 +375,11 @@ pub fn prop_date_time_completed<'a, E>( where E: ParseError<&'a [u8]> + From>, { - let (input, (_, (other_params, _, value, _))) = tuple(( + let (input, (_, (other_params, _, value, _))) = ( tag_no_case("COMPLETED"), - cut(tuple(( - other_params, - char(':'), - prop_value_date_time, - tag("\r\n"), - ))), - ))(input)?; + cut((other_params, char(':'), prop_value_date_time, tag("\r\n"))), + ) + .parse(input)?; Ok(( input, @@ -409,9 +399,9 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, (params, _, value, _))) = tuple(( + let (input, (_, (params, _, value, _))) = ( tag_no_case("DTEND"), - cut(tuple(( + cut(( property_params, char(':'), alt(( @@ -419,8 +409,9 @@ where prop_value_date.map(DateOrDateTime::Date), )), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok((input, DateTimeEndProperty { params, value })) } @@ -434,9 +425,9 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, (params, _, value, _))) = tuple(( + let (input, (_, (params, _, value, _))) = ( tag_no_case("DUE"), - cut(tuple(( + cut(( property_params, char(':'), alt(( @@ -444,8 +435,9 @@ where prop_value_date.map(DateOrDateTime::Date), )), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok((input, DateTimeDueProperty { params, value })) } @@ -461,9 +453,9 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, (params, _, value, _))) = tuple(( + let (input, (_, (params, _, value, _))) = ( tag_no_case("DTSTART"), - cut(tuple(( + cut(( property_params, char(':'), alt(( @@ -471,8 +463,9 @@ where prop_value_date.map(DateOrDateTime::Date), )), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok((input, DateTimeStartProperty { params, value })) } @@ -484,15 +477,11 @@ pub fn prop_duration<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], DurationProper where E: ParseError<&'a [u8]> + From>, { - let (input, (_, (other_params, _, value, _))) = tuple(( + let (input, (_, (other_params, _, value, _))) = ( tag_no_case("DURATION"), - cut(tuple(( - other_params, - char(':'), - prop_value_duration, - tag("\r\n"), - ))), - ))(input)?; + cut((other_params, char(':'), prop_value_duration, tag("\r\n"))), + ) + .parse(input)?; Ok(( input, @@ -512,15 +501,16 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, (params, _, value, _))) = tuple(( + let (input, (_, (params, _, value, _))) = ( tag_no_case("FREEBUSY"), - cut(tuple(( + cut(( property_params, char(':'), separated_list1(char(','), prop_value_period), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok((input, FreeBusyTimeProperty { params, value })) } @@ -534,9 +524,9 @@ pub fn prop_time_transparency<'a, E>( where E: ParseError<&'a [u8]> + From>, { - let (input, (_, (other_params, _, value, _))) = tuple(( + let (input, (_, (other_params, _, value, _))) = ( tag_no_case("TRANSP"), - cut(tuple(( + cut(( other_params, char(':'), alt(( @@ -544,8 +534,9 @@ where tag_no_case("TRANSPARENT").map(|_| TimeTransparency::Transparent), )), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok(( input, @@ -563,15 +554,16 @@ pub fn prop_time_zone_id<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], TimeZoneId where E: ParseError<&'a [u8]> + From>, { - let (input, (_, (other_params, _, (unique, value), _))) = tuple(( + let (input, (_, (other_params, _, (unique, value), _))) = ( tag_no_case("TZID"), - cut(tuple(( + cut(( other_params, char(':'), - tuple((opt(char('/')), prop_value_text)), + (opt(char('/')), prop_value_text), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok(( input, @@ -592,15 +584,11 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, (params, _, value, _))) = tuple(( + let (input, (_, (params, _, value, _))) = ( tag_no_case("TZNAME"), - cut(tuple(( - property_params, - char(':'), - prop_value_text, - tag("\r\n"), - ))), - ))(input)?; + cut((property_params, char(':'), prop_value_text, tag("\r\n"))), + ) + .parse(input)?; Ok((input, TimeZoneNameProperty { params, value })) } @@ -614,15 +602,11 @@ pub fn prop_time_zone_offset_from<'a, E>( where E: ParseError<&'a [u8]> + From>, { - let (input, (_, (other_params, _, value, _))) = tuple(( + let (input, (_, (other_params, _, value, _))) = ( tag_no_case("TZOFFSETFROM"), - cut(tuple(( - other_params, - char(':'), - prop_value_utc_offset, - tag("\r\n"), - ))), - ))(input)?; + cut((other_params, char(':'), prop_value_utc_offset, tag("\r\n"))), + ) + .parse(input)?; Ok(( input, @@ -642,15 +626,11 @@ pub fn prop_time_zone_offset_to<'a, E>( where E: ParseError<&'a [u8]> + From>, { - let (input, (_, (other_params, _, value, _))) = tuple(( + let (input, (_, (other_params, _, value, _))) = ( tag_no_case("TZOFFSETTO"), - cut(tuple(( - other_params, - char(':'), - prop_value_utc_offset, - tag("\r\n"), - ))), - ))(input)?; + cut((other_params, char(':'), prop_value_utc_offset, tag("\r\n"))), + ) + .parse(input)?; Ok(( input, @@ -670,15 +650,16 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, (other_params, _, value, _))) = tuple(( + let (input, (_, (other_params, _, value, _))) = ( tag_no_case("TZURL"), - cut(tuple(( + cut(( other_params, char(':'), cut(recognize(param_value_uri)), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok(( input, @@ -698,15 +679,16 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, (params, _, uri, _))) = tuple(( + let (input, (_, (params, _, uri, _))) = ( tag_no_case("ATTENDEE"), - cut(tuple(( + cut(( property_params, char(':'), cut(recognize(prop_value_calendar_user_address)), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok((input, AttendeeProperty { params, value: uri })) } @@ -720,15 +702,11 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, (params, _, value, _))) = tuple(( + let (input, (_, (params, _, value, _))) = ( tag_no_case("CONTACT"), - cut(tuple(( - property_params, - char(':'), - prop_value_text, - tag("\r\n"), - ))), - ))(input)?; + cut((property_params, char(':'), prop_value_text, tag("\r\n"))), + ) + .parse(input)?; Ok((input, ContactProperty { params, value })) } @@ -742,15 +720,16 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, (params, _, uri, _))) = tuple(( + let (input, (_, (params, _, uri, _))) = ( tag_no_case("ORGANIZER"), - cut(tuple(( + cut(( property_params, char(':'), recognize(prop_value_calendar_user_address), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok((input, OrganizerProperty { params, value: uri })) } @@ -764,9 +743,9 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, (params, _, value, _))) = tuple(( + let (input, (_, (params, _, value, _))) = ( tag_no_case("RECURRENCE-ID"), - cut(tuple(( + cut(( property_params, char(':'), alt(( @@ -774,8 +753,9 @@ where prop_value_date.map(DateOrDateTime::Date), )), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok((input, RecurrenceIdProperty { params, value })) } @@ -789,15 +769,11 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, (params, _, value, _))) = tuple(( + let (input, (_, (params, _, value, _))) = ( tag_no_case("RELATED-TO"), - cut(tuple(( - property_params, - char(':'), - prop_value_text, - tag("\r\n"), - ))), - ))(input)?; + cut((property_params, char(':'), prop_value_text, tag("\r\n"))), + ) + .parse(input)?; Ok((input, RelatedToProperty { params, value })) } @@ -811,15 +787,11 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, (other_params, _, value, _))) = tuple(( + let (input, (_, (other_params, _, value, _))) = ( tag_no_case("URL"), - cut(tuple(( - other_params, - char(':'), - param_value_uri, - tag("\r\n"), - ))), - ))(input)?; + cut((other_params, char(':'), param_value_uri, tag("\r\n"))), + ) + .parse(input)?; Ok(( input, @@ -839,15 +811,11 @@ pub fn prop_unique_identifier<'a, E>( where E: ParseError<&'a [u8]> + From>, { - let (input, (_, (other_params, _, value, _))) = tuple(( + let (input, (_, (other_params, _, value, _))) = ( tag_no_case("UID"), - cut(tuple(( - other_params, - char(':'), - prop_value_text, - tag("\r\n"), - ))), - ))(input)?; + cut((other_params, char(':'), prop_value_text, tag("\r\n"))), + ) + .parse(input)?; Ok(( input, @@ -869,9 +837,9 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, (params, _, value, _))) = tuple(( + let (input, (_, (params, _, value, _))) = ( tag_no_case("EXDATE"), - cut(tuple(( + cut(( property_params, char(':'), separated_list1( @@ -882,8 +850,9 @@ where )), ), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok((input, ExceptionDateTimesProperty { params, value })) } @@ -899,9 +868,9 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, (params, _, value, _))) = tuple(( + let (input, (_, (params, _, value, _))) = ( tag_no_case("RDATE"), - cut(tuple(( + cut(( property_params, char(':'), separated_list1( @@ -913,8 +882,9 @@ where )), ), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok((input, RecurrenceDateTimesProperty { params, value })) } @@ -930,15 +900,11 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, (other_params, _, value, _))) = tuple(( + let (input, (_, (other_params, _, value, _))) = ( tag_no_case("RRULE"), - cut(tuple(( - other_params, - char(':'), - prop_value_recur, - tag("\r\n"), - ))), - ))(input)?; + cut((other_params, char(':'), prop_value_recur, tag("\r\n"))), + ) + .parse(input)?; Ok(( input, @@ -956,9 +922,9 @@ pub fn prop_action<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ActionProperty<' where E: ParseError<&'a [u8]> + From>, { - let (input, (_, (other_params, _, value, _))) = tuple(( + let (input, (_, (other_params, _, value, _))) = ( tag_no_case("ACTION"), - cut(tuple(( + cut(( other_params, char(':'), alt(( @@ -969,8 +935,9 @@ where iana_token.map(Action::IanaToken), )), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok(( input, @@ -988,15 +955,16 @@ pub fn prop_repeat<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], RepeatProperty<' where E: ParseError<&'a [u8]> + From>, { - let (input, (_, (other_params, _, value, _))) = tuple(( + let (input, (_, (other_params, _, value, _))) = ( tag_no_case("REPEAT"), - cut(tuple(( + cut(( other_params, char(':'), prop_value_integer.map(|v| v as u32), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok(( input, @@ -1016,10 +984,8 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (_, (params, _))) = tuple(( - tag_no_case("TRIGGER"), - cut(tuple((property_params, char(':')))), - ))(input)?; + let (input, (_, (params, _))) = + (tag_no_case("TRIGGER"), cut((property_params, char(':')))).parse(input)?; let value_choice = params .iter() @@ -1048,7 +1014,7 @@ where } }?; - let (input, _) = cut(tag("\r\n"))(input)?; + let (input, _) = cut(tag("\r\n")).parse(input)?; Ok((input, TriggerProperty { params, value })) } @@ -1062,15 +1028,11 @@ pub fn prop_date_time_created<'a, E>( where E: ParseError<&'a [u8]> + From>, { - let (input, (_, (other_params, _, value, _))) = tuple(( + let (input, (_, (other_params, _, value, _))) = ( tag_no_case("CREATED"), - cut(tuple(( - other_params, - char(':'), - prop_value_date_time, - tag("\r\n"), - ))), - ))(input)?; + cut((other_params, char(':'), prop_value_date_time, tag("\r\n"))), + ) + .parse(input)?; Ok(( input, @@ -1090,15 +1052,11 @@ pub fn prop_date_time_stamp<'a, E>( where E: ParseError<&'a [u8]> + From>, { - let (input, (_, (other_params, _, value, _))) = tuple(( + let (input, (_, (other_params, _, value, _))) = ( tag_no_case("DTSTAMP"), - cut(tuple(( - other_params, - char(':'), - prop_value_date_time, - tag("\r\n"), - ))), - ))(input)?; + cut((other_params, char(':'), prop_value_date_time, tag("\r\n"))), + ) + .parse(input)?; Ok(( input, @@ -1116,15 +1074,11 @@ pub fn prop_last_modified<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], LastModif where E: ParseError<&'a [u8]> + From>, { - let (input, (_, (other_params, _, value, _))) = tuple(( + let (input, (_, (other_params, _, value, _))) = ( tag_no_case("LAST-MODIFIED"), - cut(tuple(( - other_params, - char(':'), - prop_value_date_time, - tag("\r\n"), - ))), - ))(input)?; + cut((other_params, char(':'), prop_value_date_time, tag("\r\n"))), + ) + .parse(input)?; Ok(( input, @@ -1142,15 +1096,16 @@ pub fn prop_sequence<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], SequenceProper where E: ParseError<&'a [u8]> + From>, { - let (input, (_, (other_params, _, value, _))) = tuple(( + let (input, (_, (other_params, _, value, _))) = ( tag_no_case("SEQUENCE"), - cut(tuple(( + cut(( other_params, char(':'), prop_value_integer.map(|v| v as u32), tag("\r\n"), - ))), - ))(input)?; + )), + ) + .parse(input)?; Ok(( input, @@ -1178,15 +1133,15 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (num, mut nums)) = tuple(( + let (input, (num, mut nums)) = ( map_res( - verify(take_while1(is_digit), |v: &[u8]| v.len() == 1), + verify(take_while1(AsChar::is_dec_digit), |v: &[u8]| v.len() == 1), |v| read_int::(v), ), fold_many_m_n( 1, 2, - map_res(tuple((char('.'), take_while1(is_digit))), |(_, v)| { + map_res((char('.'), take_while1(AsChar::is_dec_digit)), |(_, v)| { read_int::(v) }), Vec::new, @@ -1195,25 +1150,26 @@ where acc }, ), - ))(input)?; + ) + .parse(input)?; nums.insert(0, num); Ok((input, nums)) } - let (input, (_, (params, _, status_code, _, status_description, extra_data, _))) = - tuple(( - tag_no_case("REQUEST-STATUS"), - cut(tuple(( - property_params, - char(':'), - status_code, - char(';'), - prop_value_text, - opt(tuple((char(';'), prop_value_text)).map(|(_, v)| v)), - tag("\r\n"), - ))), - ))(input)?; + let (input, (_, (params, _, status_code, _, status_description, extra_data, _))) = ( + tag_no_case("REQUEST-STATUS"), + cut(( + property_params, + char(':'), + status_code, + char(';'), + prop_value_text, + opt((char(';'), prop_value_text).map(|(_, v)| v)), + tag("\r\n"), + )), + ) + .parse(input)?; Ok(( input, diff --git a/src/parser/property/recur.rs b/src/parser/property/recur.rs index 887d676..3398a99 100644 --- a/src/parser/property/recur.rs +++ b/src/parser/property/recur.rs @@ -6,12 +6,10 @@ use nom::branch::alt; use nom::bytes::complete::{take_while1, take_while_m_n}; use nom::bytes::streaming::tag; use nom::character::streaming::char; -use nom::character::{is_alphabetic, is_digit}; use nom::combinator::{map_res, opt}; use nom::error::ParseError; use nom::multi::separated_list1; -use nom::sequence::tuple; -use nom::{IResult, Parser}; +use nom::{AsChar, IResult, Parser}; pub fn prop_value_recur<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Vec, E> where @@ -19,7 +17,7 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - separated_list1(char(';'), recur_rule_part)(input) + separated_list1(char(';'), recur_rule_part).parse(input) } fn recur_rule_part<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], RecurRulePart, E> @@ -28,7 +26,7 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (name, _)) = tuple((take_while1(is_alphabetic), char('=')))(input)?; + let (input, (name, _)) = (take_while1(AsChar::is_alpha), char('=')).parse(input)?; match std::str::from_utf8(name).map_err(|e| { nom::Err::Error( @@ -79,7 +77,8 @@ where tag("WEEKLY").map(|_| RecurFreq::Weekly), tag("MONTHLY").map(|_| RecurFreq::Monthly), tag("YEARLY").map(|_| RecurFreq::Yearly), - ))(input)?; + )) + .parse(input)?; Ok((input, freq)) } @@ -89,7 +88,7 @@ where E: ParseError<&'a [u8]> + From>, { let (input, (date, opt_time)) = - tuple((prop_value_date, opt(tuple((char('T'), prop_value_time)))))(input)?; + (prop_value_date, opt((char('T'), prop_value_time))).parse(input)?; let time = opt_time.map(|(_, time)| time); @@ -106,7 +105,7 @@ fn read_num<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], u64, E> where E: ParseError<&'a [u8]> + From>, { - let (input, c) = take_while1(is_digit)(input)?; + let (input, c) = take_while1(AsChar::is_dec_digit)(input)?; let v = std::str::from_utf8(c).map_err(|e| { nom::Err::Error( @@ -129,7 +128,7 @@ where { separated_list1( char(','), - map_res(take_while_m_n(1, 2, is_digit), |s| { + map_res(take_while_m_n(1, 2, AsChar::is_dec_digit), |s| { std::str::from_utf8(s) .map_err(|e| { nom::Err::Error( @@ -143,7 +142,8 @@ where .parse() .map_err(|_| nom::Err::Error(Error::new(input, InnerError::InvalidRecurNum).into())) }), - )(input) + ) + .parse(input) } fn weekday<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Weekday, E> @@ -158,7 +158,8 @@ where tag("FR").map(|_| Weekday::Friday), tag("SA").map(|_| Weekday::Saturday), tag("SU").map(|_| Weekday::Sunday), - ))(input) + )) + .parse(input) } fn recur_by_weekday_list<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Vec, E> @@ -169,9 +170,9 @@ where { separated_list1( char(','), - tuple(( + ( opt(map_res( - tuple(( + ( opt(alt((char('+'), char('-')))).map(|opt_sign| { if let Some('-') = opt_sign { -1i8 @@ -179,8 +180,8 @@ where 1 } }), - take_while_m_n(1, 2, is_digit), - )), + take_while_m_n(1, 2, AsChar::is_dec_digit), + ), |(sign, num)| { std::str::from_utf8(num) .map_err(|e| { @@ -200,7 +201,7 @@ where }, )), weekday, - )), + ), ) .map(|values| { values @@ -223,11 +224,11 @@ where separated_list1( char(','), map_res( - tuple(( + ( opt(alt((char('+'), char('-')))) .map(|sign| if let Some('-') = sign { -1i8 } else { 1 }), - take_while_m_n(1, 2, is_digit), - )), + take_while_m_n(1, 2, AsChar::is_dec_digit), + ), |(sign, num)| { std::str::from_utf8(num) .map_err(|e| { @@ -246,7 +247,8 @@ where .map(|num| sign * num) }, ), - )(input) + ) + .parse(input) } fn recur_by_year_day_list<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Vec, E> @@ -258,11 +260,11 @@ where separated_list1( char(','), map_res( - tuple(( + ( opt(alt((char('+'), char('-')))) .map(|sign| if let Some('-') = sign { -1i16 } else { 1 }), - take_while_m_n(1, 3, is_digit), - )), + take_while_m_n(1, 3, AsChar::is_dec_digit), + ), |(sign, num)| { std::str::from_utf8(num) .map_err(|e| { @@ -281,7 +283,8 @@ where .map(|num| sign * num) }, ), - )(input) + ) + .parse(input) } fn recur_by_week_number<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Vec, E> @@ -293,11 +296,11 @@ where separated_list1( char(','), map_res( - tuple(( + ( opt(alt((char('+'), char('-')))) .map(|sign| if let Some('-') = sign { -1i8 } else { 1 }), - take_while_m_n(1, 2, is_digit), - )), + take_while_m_n(1, 2, AsChar::is_dec_digit), + ), |(sign, num)| { std::str::from_utf8(num) .map_err(|e| { @@ -316,7 +319,8 @@ where .map(|num| sign * num) }, ), - )(input) + ) + .parse(input) } fn recur_by_month_list<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Vec, E> @@ -327,7 +331,7 @@ where { separated_list1( char(','), - map_res(take_while_m_n(1, 2, is_digit), |num| { + map_res(take_while_m_n(1, 2, AsChar::is_dec_digit), |num| { std::str::from_utf8(num) .map_err(|e| { nom::Err::Error( @@ -341,7 +345,8 @@ where .parse::() .map_err(|_| nom::Err::Error(Error::new(input, InnerError::InvalidRecurNum).into())) }), - )(input) + ) + .parse(input) } #[cfg(test)] diff --git a/src/parser/property/uri.rs b/src/parser/property/uri.rs index 3b7960c..478477f 100644 --- a/src/parser/property/uri.rs +++ b/src/parser/property/uri.rs @@ -4,12 +4,10 @@ use crate::single; use nom::branch::alt; use nom::bytes::streaming::{tag, take_while, take_while1, take_while_m_n}; use nom::character::streaming::char; -use nom::character::{is_alphabetic, is_digit}; use nom::combinator::{map_res, opt, recognize, verify}; use nom::error::ParseError; use nom::multi::{fold_many0, fold_many1, many0, many1, separated_list0}; -use nom::sequence::tuple; -use nom::{IResult, Parser}; +use nom::{AsChar, IResult, Parser}; use std::fmt::{Display, Formatter, Write}; use std::net::{Ipv4Addr, Ipv6Addr}; @@ -20,17 +18,18 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, (scheme, _, (authority, path), query, fragment)) = tuple(( + let (input, (scheme, _, (authority, path), query, fragment)) = ( scheme, char(':'), alt(( - tuple((tag("//"), authority, opt(path_absolute_empty))).map(|(_, a, b)| (Some(a), b)), + (tag("//"), authority, opt(path_absolute_empty)).map(|(_, a, b)| (Some(a), b)), path_absolute.map(|p| (None, Some(p))), path_rootless.map(|p| (None, Some(p))), )), - opt(tuple((char('?'), query_or_fragment)).map(|(_, v)| v)), - opt(tuple((char('#'), query_or_fragment)).map(|(_, v)| v)), - ))(input)?; + opt((char('?'), query_or_fragment).map(|(_, v)| v)), + opt((char('#'), query_or_fragment).map(|(_, v)| v)), + ) + .parse(input)?; Ok(( input, @@ -54,8 +53,9 @@ where E: ParseError<&'a [u8]> + From>, { verify(take_while1(is_scheme_char), |sch: &[u8]| { - is_alphabetic(sch[0]) - })(input) + AsChar::is_alpha(sch[0]) + }) + .parse(input) } #[inline] @@ -77,15 +77,15 @@ fn pct_encoded<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Vec, E> where E: ParseError<&'a [u8]> + From>, { - tuple(( + ( char('%'), take_while_m_n(2, 2, is_hex_digit_upper).map(|v| { // TODO do without a dep here? hex::decode(v).unwrap() }), - )) - .map(|(_, v)| v) - .parse(input) + ) + .map(|(_, v)| v) + .parse(input) } #[inline] @@ -102,17 +102,17 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - tuple(( - opt(tuple((user_info, char('@'))).map(|(u, _)| u)), + ( + opt((user_info, char('@')).map(|(u, _)| u)), host, - opt(tuple((char(':'), port)).map(|(_, p)| p)), - )) - .map(|(user_info, host, port)| Authority { - user_info, - host, - port, - }) - .parse(input) + opt((char(':'), port).map(|(_, p)| p)), + ) + .map(|(user_info, host, port)| Authority { + user_info, + host, + port, + }) + .parse(input) } fn port<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], u16, E> @@ -121,7 +121,7 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - map_res(take_while(is_digit), |c| { + map_res(take_while(AsChar::is_dec_digit), |c| { std::str::from_utf8(c) .map_err(|e| { nom::Err::Error( @@ -154,7 +154,8 @@ where acc.extend(item); acc }, - )(input) + ) + .parse(input) } fn host<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Host, E> @@ -169,7 +170,8 @@ where .map(|ip| IpAddr::V4(Ipv4Addr::from(ip))) .map(Host::IpAddr), reg_name.map(Host::RegName), - ))(input) + )) + .parse(input) } fn ip_literal<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], IpAddr, E> @@ -178,23 +180,23 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - tuple(( + ( tag("["), alt(( ip_v6_addr.map(IpAddr::V6), ip_v_future_addr.map(|ip| IpAddr::VFuture(ip.to_vec())), )), tag("]"), - )) - .map(|(_, v, _)| v) - .parse(input) + ) + .map(|(_, v, _)| v) + .parse(input) } -fn ip_v_future_addr<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], &[u8], E> +fn ip_v_future_addr<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], &'a [u8], E> where E: ParseError<&'a [u8]> + From>, { - recognize(tuple(( + recognize(( char('v').map(|a| a as u8), take_while1(is_hex_digit), char('.'), @@ -203,7 +205,8 @@ where single(is_sub_delim), char(':').map(|c| c as u8), ))), - )))(input) + )) + .parse(input) } fn ip_v6_addr<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Ipv6Addr, E> @@ -212,7 +215,7 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - let (input, prefix_parts) = separated_list0(char(':'), h_16)(input)?; + let (input, prefix_parts) = separated_list0(char(':'), h_16).parse(input)?; if prefix_parts.len() > 7 { return Err(nom::Err::Error( @@ -220,10 +223,10 @@ where )); } - let (input, found_collapse) = opt(tag("::"))(input)?; + let (input, found_collapse) = opt(tag("::")).parse(input)?; let fill_zeroes = found_collapse.is_some(); - let (input, suffix_parts) = separated_list0(char(':'), h_16)(input)?; + let (input, suffix_parts) = separated_list0(char(':'), h_16).parse(input)?; if suffix_parts.len() > 8 { return Err(nom::Err::Error( @@ -231,7 +234,7 @@ where )); } - let (input, ipv4_post) = opt(tuple((char(':'), ip_v4_addr)))(input)?; + let (input, ipv4_post) = opt((char(':'), ip_v4_addr)).parse(input)?; let mut content = [0u8; 16]; @@ -295,7 +298,7 @@ where + nom::error::FromExternalError<&'a [u8], nom::Err> + From>, { - tuple(( + ( dec_octet, char('.'), dec_octet, @@ -303,9 +306,9 @@ where dec_octet, char('.'), dec_octet, - )) - .map(|(a, _, b, _, c, _, d)| [a, b, c, d]) - .parse(input) + ) + .map(|(a, _, b, _, c, _, d)| [a, b, c, d]) + .parse(input) } fn dec_octet<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], u8, E> @@ -315,7 +318,7 @@ where + From>, { map_res( - verify(take_while_m_n(1, 3, is_digit), |b: &[u8]| { + verify(take_while_m_n(1, 3, AsChar::is_dec_digit), |b: &[u8]| { // May not have a 0 prefix if b.len() == 2 { b[0] != b'0' @@ -335,7 +338,8 @@ where .parse::() .map_err(|_| nom::Err::Error(Error::new(input, InnerError::InvalidOctet).into())) }, - )(input) + ) + .parse(input) } fn reg_name<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Vec, E> @@ -353,28 +357,29 @@ where acc.extend(item); acc }, - )(input) + ) + .parse(input) } fn path_absolute_empty<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], &'a [u8], E> where E: ParseError<&'a [u8]> + From>, { - recognize(many0(tuple((char('/'), segment))))(input) + recognize(many0((char('/'), segment))).parse(input) } fn path_absolute<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], &'a [u8], E> where E: ParseError<&'a [u8]> + From>, { - recognize(tuple((segment_nz, path_absolute_empty)))(input) + recognize((segment_nz, path_absolute_empty)).parse(input) } fn path_rootless<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], &'a [u8], E> where E: ParseError<&'a [u8]> + From>, { - recognize(tuple((segment_nz, many0(tuple((char('/'), segment))))))(input) + recognize((segment_nz, many0((char('/'), segment)))).parse(input) } fn segment<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Vec, E> @@ -384,7 +389,8 @@ where fold_many0(p_char, Vec::new, |mut acc, item| { acc.extend(item); acc - })(input) + }) + .parse(input) } fn segment_nz<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Vec, E> @@ -394,10 +400,11 @@ where fold_many1(p_char, Vec::new, |mut acc, item| { acc.extend(item); acc - })(input) + }) + .parse(input) } -fn query_or_fragment<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], &[u8], E> +fn query_or_fragment<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], &'a [u8], E> where E: ParseError<&'a [u8]> + From>, { @@ -405,7 +412,8 @@ where p_char, tag("/").map(|c: &[u8]| c.to_vec()), tag("?").map(|c: &[u8]| c.to_vec()), - ))))(input) + )))) + .parse(input) } fn p_char<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Vec, E> @@ -418,7 +426,8 @@ where single(is_sub_delim).map(|c| vec![c]), tag(":").map(|c: &[u8]| c.to_vec()), tag("@").map(|c: &[u8]| c.to_vec()), - ))(input) + )) + .parse(input) } impl Display for Uri<'_> { diff --git a/src/parser/property/value.rs b/src/parser/property/value.rs index 36eaf89..93a1724 100644 --- a/src/parser/property/value.rs +++ b/src/parser/property/value.rs @@ -5,14 +5,12 @@ use crate::utf8_seq; use nom::branch::alt; use nom::bytes::complete::take_while1; use nom::bytes::streaming::{tag, tag_no_case, take_while_m_n}; -use nom::character::is_digit; use nom::character::streaming::{char, one_of}; use nom::combinator::{opt, recognize}; use nom::error::ParseError; use nom::multi::{fold_many0, many0}; -use nom::sequence::tuple; -use nom::IResult; use nom::Parser; +use nom::{AsChar, IResult}; #[inline] const fn is_base64(c: u8) -> bool { @@ -23,13 +21,14 @@ pub fn prop_value_binary<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], &'a [u8], where E: ParseError<&'a [u8]> + From>, { - let (input, content) = recognize(tuple(( + let (input, content) = recognize(( many0(take_while_m_n(4, 4, is_base64)), opt(alt(( - tuple((take_while_m_n(2, 2, is_base64), tag("=="))), - tuple((take_while_m_n(3, 3, is_base64), tag("="))), + (take_while_m_n(2, 2, is_base64), tag("==")), + (take_while_m_n(3, 3, is_base64), tag("=")), ))), - )))(input)?; + )) + .parse(input)?; Ok((input, content)) } @@ -49,11 +48,12 @@ pub fn prop_value_date<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Date, E> where E: ParseError<&'a [u8]> + From>, { - let (input, (year, month, day)) = tuple(( - take_while_m_n(4, 4, is_digit), - take_while_m_n(2, 2, is_digit), - take_while_m_n(2, 2, is_digit), - ))(input)?; + let (input, (year, month, day)) = ( + take_while_m_n(4, 4, AsChar::is_dec_digit), + take_while_m_n(2, 2, AsChar::is_dec_digit), + take_while_m_n(2, 2, AsChar::is_dec_digit), + ) + .parse(input)?; let year = std::str::from_utf8(year) .map_err(|e| { @@ -101,12 +101,13 @@ pub fn prop_value_time<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Time, E> where E: ParseError<&'a [u8]> + From>, { - let (input, (h, m, s, is_utc)) = tuple(( - take_while_m_n(2, 2, is_digit), - take_while_m_n(2, 2, is_digit), - take_while_m_n(2, 2, is_digit), + let (input, (h, m, s, is_utc)) = ( + take_while_m_n(2, 2, AsChar::is_dec_digit), + take_while_m_n(2, 2, AsChar::is_dec_digit), + take_while_m_n(2, 2, AsChar::is_dec_digit), opt(char('Z')).map(|x| x.is_some()), - ))(input)?; + ) + .parse(input)?; let read_time = |s: &[u8]| -> Result { std::str::from_utf8(s) @@ -135,7 +136,7 @@ pub fn prop_value_date_time<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], DateTim where E: ParseError<&'a [u8]> + From>, { - let (input, (date, _, time)) = tuple((prop_value_date, char('T'), prop_value_time))(input)?; + let (input, (date, _, time)) = (prop_value_date, char('T'), prop_value_time).parse(input)?; Ok((input, DateTime { date, time })) } @@ -144,7 +145,7 @@ fn duration_num<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], u64, E> where E: ParseError<&'a [u8]> + From>, { - let (input, v) = take_while1(is_digit)(input)?; + let (input, v) = take_while1(AsChar::is_dec_digit)(input)?; let s = std::str::from_utf8(v).map_err(|e| { nom::Err::Error( @@ -176,15 +177,16 @@ where match time_branch { 'H' => { - let (input, (min, sec)) = tuple(( - opt(tuple((duration_num, char('M'))).map(|(min, _)| min)), - opt(tuple((duration_num, char('S'))).map(|(sec, _)| sec)), - ))(input)?; + let (input, (min, sec)) = ( + opt((duration_num, char('M')).map(|(min, _)| min)), + opt((duration_num, char('S')).map(|(sec, _)| sec)), + ) + .parse(input)?; Ok((input, (Some(num), min, sec))) } 'M' => { - let (input, sec) = opt(tuple((duration_num, char('S'))).map(|(sec, _)| sec))(input)?; + let (input, sec) = opt((duration_num, char('S')).map(|(sec, _)| sec)).parse(input)?; Ok((input, (None, Some(num), sec))) } @@ -214,9 +216,9 @@ pub fn prop_value_duration<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Duration where E: ParseError<&'a [u8]> + From>, { - let (input, (sign, _)) = tuple((opt_sign, char('P')))(input)?; + let (input, (sign, _)) = (opt_sign, char('P')).parse(input)?; - let (input, t) = opt(char('T'))(input)?; + let (input, t) = opt(char('T')).parse(input)?; if t.is_some() { let (input, (hours, minutes, seconds)) = duration_time(input)?; @@ -239,7 +241,9 @@ where match date_branch { 'D' => { - let (input, time) = opt(tuple((char('T'), duration_time)).map(|(_, t)| t))(input)?; + let (input, time) = opt((char('T'), duration_time)) + .map(|opt| opt.map(|(_, t)| t)) + .parse(input)?; let (hours, minutes, seconds) = time.unwrap_or((None, None, None)); @@ -272,13 +276,14 @@ pub fn prop_value_float<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], f64, E> where E: ParseError<&'a [u8]> + From>, { - let (input, (sign, num)) = tuple(( + let (input, (sign, num)) = ( opt_sign, - recognize(tuple(( - take_while1(is_digit), - opt(tuple((char('.'), take_while1(is_digit)))), - ))), - ))(input)?; + recognize(( + take_while1(AsChar::is_dec_digit), + opt((char('.'), take_while1(AsChar::is_dec_digit))), + )), + ) + .parse(input)?; let num: f64 = std::str::from_utf8(num) .map_err(|e| { @@ -300,7 +305,7 @@ pub fn prop_value_integer<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], i32, E> where E: ParseError<&'a [u8]> + From>, { - let (input, (sign, num)) = tuple((opt_sign, take_while1(is_digit)))(input)?; + let (input, (sign, num)) = (opt_sign, take_while1(AsChar::is_dec_digit)).parse(input)?; let num: i32 = read_int(num)?; @@ -311,14 +316,15 @@ pub fn prop_value_period<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Period, E> where E: ParseError<&'a [u8]> + From>, { - let (input, (start, _, end)) = tuple(( + let (input, (start, _, end)) = ( prop_value_date_time, char('/'), alt(( prop_value_duration.map(PeriodEnd::Duration), prop_value_date_time.map(PeriodEnd::DateTime), )), - ))(input)?; + ) + .parse(input)?; Ok((input, Period { start, end })) } @@ -335,15 +341,15 @@ where let (input, r) = fold_many0( alt(( // Escaped characters - tuple(( + ( char('\\'), alt((tag_no_case("n").map(|_| b'\n' as char), one_of(r#"\;,"#))), - )) - .map(|(_, c)| vec![c as u8]), + ) + .map(|(_, c)| vec![c as u8]), // Allowed raw characters one_of(r#":""#).map(|c: char| vec![c as u8]), // Text split over multiple lines - tuple((tag("\r\n"), alt((char(' '), char('\t'))))).map(|_| Vec::with_capacity(0)), + (tag("\r\n"), alt((char(' '), char('\t')))).map(|_| Vec::with_capacity(0)), // UTF-8 sequence utf8_seq.map(|seq| seq.to_vec()), // Other text safe characters @@ -354,7 +360,8 @@ where acc.extend_from_slice(&item); acc }, - )(input)?; + ) + .parse(input)?; Ok((input, r)) } @@ -363,12 +370,13 @@ pub fn prop_value_utc_offset<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], UtcOff where E: ParseError<&'a [u8]> + From>, { - let (input, (sign, h, m, s)) = tuple(( + let (input, (sign, h, m, s)) = ( one_of("+-"), - take_while_m_n(2, 2, is_digit), - take_while_m_n(2, 2, is_digit), - opt(take_while_m_n(2, 2, is_digit)), - ))(input)?; + take_while_m_n(2, 2, AsChar::is_dec_digit), + take_while_m_n(2, 2, AsChar::is_dec_digit), + opt(take_while_m_n(2, 2, AsChar::is_dec_digit)), + ) + .parse(input)?; Ok(( input, diff --git a/src/serialize/value.rs b/src/serialize/value.rs index 066063a..77cfb8f 100644 --- a/src/serialize/value.rs +++ b/src/serialize/value.rs @@ -762,7 +762,7 @@ impl WriteModel for String { if matches!(c as u8, b';' | b'\\' | b',') { out.extend_from_slice(&[b'\\', c as u8]); } else if c == '\n' { - out.extend_from_slice(&[b'\\', b'n']); + out.extend_from_slice(b"\\n"); } else { out.push(c as u8); } diff --git a/src/validate/value.rs b/src/validate/value.rs index a5a440d..3cffeb0 100644 --- a/src/validate/value.rs +++ b/src/validate/value.rs @@ -25,6 +25,7 @@ use anyhow::Context; use nom::character::streaming::char; use nom::multi::separated_list1; use nom::AsBytes; +use nom::Parser; pub(super) fn check_declared_value( errors: &mut Vec, @@ -1026,7 +1027,7 @@ fn is_date_valued(property_value: &String) -> bool { let mut content = property_value.as_bytes().to_vec(); content.push(b';'); - let result = separated_list1(char(','), prop_value_date::)(content.as_bytes()); + let result = separated_list1(char(','), prop_value_date::).parse(content.as_bytes()); match result { Ok((rest, _)) => rest.len() == 1, _ => false, @@ -1037,7 +1038,8 @@ fn is_date_time_valued(property_value: &String) -> bool { let mut content = property_value.as_bytes().to_vec(); content.push(b';'); - let result = separated_list1(char(','), prop_value_date_time::)(content.as_bytes()); + let result = + separated_list1(char(','), prop_value_date_time::).parse(content.as_bytes()); match result { Ok((rest, _)) => rest.len() == 1, _ => false, @@ -1048,7 +1050,7 @@ fn is_duration_valued(property_value: &String) -> bool { let mut content = property_value.as_bytes().to_vec(); content.push(b';'); - let result = separated_list1(char(','), prop_value_duration::)(content.as_bytes()); + let result = separated_list1(char(','), prop_value_duration::).parse(content.as_bytes()); match result { Ok((rest, _)) => rest.len() == 1, _ => false, @@ -1059,7 +1061,7 @@ fn is_float_valued(property_value: &String) -> bool { let mut content = property_value.as_bytes().to_vec(); content.push(b';'); - let result = separated_list1(char(','), prop_value_float::)(content.as_bytes()); + let result = separated_list1(char(','), prop_value_float::).parse(content.as_bytes()); match result { Ok((rest, _)) => rest.len() == 1, _ => false, @@ -1070,7 +1072,7 @@ fn is_integer_valued(property_value: &String) -> bool { let mut content = property_value.as_bytes().to_vec(); content.push(b';'); - let result = separated_list1(char(','), prop_value_integer::)(content.as_bytes()); + let result = separated_list1(char(','), prop_value_integer::).parse(content.as_bytes()); match result { Ok((rest, _)) => rest.len() == 1, _ => false, @@ -1106,7 +1108,7 @@ fn is_text_valued(property_value: &String) -> bool { content.push(b'\r'); content.push(b'\n'); - let result = separated_list1(char(','), prop_value_text::)(content.as_bytes()); + let result = separated_list1(char(','), prop_value_text::).parse(content.as_bytes()); match result { Ok((rest, _)) => rest.len() == 1, _ => false, @@ -1117,7 +1119,7 @@ fn is_time_valued(property_value: &String) -> anyhow::Result)(content.as_bytes()); + let result = separated_list1(char(','), prop_value_time::).parse(content.as_bytes()); match result { Ok((rest, times)) if rest.len() == 1 => Ok(times), _ => anyhow::bail!("Not a valid time"),