From a104c8fc41c4a5de257b1194776c25d9cb282d2c Mon Sep 17 00:00:00 2001 From: Dominik Csapak Date: Tue, 30 Nov 2021 13:11:57 +0100 Subject: [PATCH] proxmox-time: move common parse functions to parse_helpers Signed-off-by: Dominik Csapak --- proxmox-time/src/lib.rs | 2 + proxmox-time/src/parse_helpers.rs | 75 +++++++++++++++++++++++++++++++ proxmox-time/src/parse_time.rs | 56 +---------------------- 3 files changed, 78 insertions(+), 55 deletions(-) create mode 100644 proxmox-time/src/parse_helpers.rs diff --git a/proxmox-time/src/lib.rs b/proxmox-time/src/lib.rs index d72509fb..d2a4cb79 100644 --- a/proxmox-time/src/lib.rs +++ b/proxmox-time/src/lib.rs @@ -13,6 +13,8 @@ pub use parse_time::*; mod time; pub use time::*; +pub(crate) mod parse_helpers; + mod daily_duration; pub use daily_duration::*; diff --git a/proxmox-time/src/parse_helpers.rs b/proxmox-time/src/parse_helpers.rs new file mode 100644 index 00000000..4890b2f2 --- /dev/null +++ b/proxmox-time/src/parse_helpers.rs @@ -0,0 +1,75 @@ +use anyhow::{bail, Error}; + +use super::daily_duration::*; + +use nom::{ + bytes::complete::tag, + character::complete::digit1, + combinator::{all_consuming, map_res, opt, recognize}, + error::{ParseError, VerboseError}, + sequence::{preceded, tuple}, +}; + +pub(crate) type IResult> = Result<(I, O), nom::Err>; + +pub(crate) fn parse_error<'a>( + i: &'a str, + context: &'static str, +) -> nom::Err> { + let err = VerboseError { errors: Vec::new() }; + let err = VerboseError::add_context(i, context, err); + nom::Err::Error(err) +} + +// Parse a 64 bit unsigned integer +pub(crate) fn parse_u64(i: &str) -> IResult<&str, u64> { + map_res(recognize(digit1), str::parse)(i) +} + +// Parse complete input, generate simple error message (use this for sinple line input). +pub(crate) fn parse_complete_line<'a, F, O>(what: &str, i: &'a str, parser: F) -> Result +where + F: Fn(&'a str) -> IResult<&'a str, O>, +{ + match all_consuming(parser)(i) { + Err(nom::Err::Error(VerboseError { errors })) + | Err(nom::Err::Failure(VerboseError { errors })) => { + if errors.is_empty() { + bail!("unable to parse {}", what); + } else { + bail!( + "unable to parse {} at '{}' - {:?}", + what, + errors[0].0, + errors[0].1 + ); + } + } + Err(err) => { + bail!("unable to parse {} - {}", what, err); + } + Ok((_, data)) => Ok(data), + } +} + +pub(crate) fn parse_time_comp(max: usize) -> impl Fn(&str) -> IResult<&str, u32> { + move |i: &str| { + let (i, v) = map_res(recognize(digit1), str::parse)(i)?; + if (v as usize) >= max { + return Err(parse_error(i, "time value too large")); + } + Ok((i, v)) + } +} + +pub(crate) fn parse_hm_time(i: &str) -> IResult<&str, HmTime> { + let (i, (hour, opt_minute)) = tuple(( + parse_time_comp(24), + opt(preceded(tag(":"), parse_time_comp(60))), + ))(i)?; + + match opt_minute { + Some(minute) => Ok((i, HmTime { hour, minute })), + None => Ok((i, HmTime { hour, minute: 0 })), + } +} diff --git a/proxmox-time/src/parse_time.rs b/proxmox-time/src/parse_time.rs index aa1c58e8..7b0e168b 100644 --- a/proxmox-time/src/parse_time.rs +++ b/proxmox-time/src/parse_time.rs @@ -15,38 +15,7 @@ use nom::{ multi::separated_nonempty_list, }; -type IResult> = Result<(I, O), nom::Err>; - -fn parse_error<'a>(i: &'a str, context: &'static str) -> nom::Err> { - let err = VerboseError { errors: Vec::new() }; - let err = VerboseError::add_context(i, context, err); - nom::Err::Error(err) -} - -// Parse a 64 bit unsigned integer -fn parse_u64(i: &str) -> IResult<&str, u64> { - map_res(recognize(digit1), str::parse)(i) -} - -// Parse complete input, generate simple error message (use this for sinple line input). -fn parse_complete_line<'a, F, O>(what: &str, i: &'a str, parser: F) -> Result - where F: Fn(&'a str) -> IResult<&'a str, O>, -{ - match all_consuming(parser)(i) { - Err(nom::Err::Error(VerboseError { errors })) | - Err(nom::Err::Failure(VerboseError { errors })) => { - if errors.is_empty() { - bail!("unable to parse {}", what); - } else { - bail!("unable to parse {} at '{}' - {:?}", what, errors[0].0, errors[0].1); - } - } - Err(err) => { - bail!("unable to parse {} - {}", what, err); - } - Ok((_, data)) => Ok(data), - } -} +use crate::parse_helpers::{parse_complete_line, parse_error, parse_hm_time, parse_time_comp, parse_u64, IResult}; lazy_static! { static ref TIME_SPAN_UNITS: HashMap<&'static str, f64> = { @@ -129,16 +98,6 @@ struct DateSpec { day: Vec, } -fn parse_time_comp(max: usize) -> impl Fn(&str) -> IResult<&str, u32> { - move |i: &str| { - let (i, v) = map_res(recognize(digit1), str::parse)(i)?; - if (v as usize) >= max { - return Err(parse_error(i, "time value too large")); - } - Ok((i, v)) - } -} - fn parse_weekday(i: &str) -> IResult<&str, WeekDays> { let (i, text) = alpha1(i)?; @@ -501,16 +460,3 @@ fn parse_daily_duration_incomplete(mut i: &str) -> IResult<&str, DailyDuration> Ok((i, duration)) } - -fn parse_hm_time(i: &str) -> IResult<&str, HmTime> { - - let (i, (hour, opt_minute)) = tuple(( - parse_time_comp(24), - opt(preceded(tag(":"), parse_time_comp(60))), - ))(i)?; - - match opt_minute { - Some(minute) => Ok((i, HmTime { hour, minute })), - None => Ok((i, HmTime { hour, minute: 0})), - } -}