proxmox-time: move common parse functions to parse_helpers

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
This commit is contained in:
Dominik Csapak 2021-11-30 13:11:57 +01:00 committed by Dietmar Maurer
parent 8e0fc66dfe
commit a104c8fc41
3 changed files with 78 additions and 55 deletions

View File

@ -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::*;

View File

@ -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<I, O, E = VerboseError<I>> = Result<(I, O), nom::Err<E>>;
pub(crate) fn parse_error<'a>(
i: &'a str,
context: &'static str,
) -> nom::Err<VerboseError<&'a str>> {
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<O, Error>
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 })),
}
}

View File

@ -15,38 +15,7 @@ use nom::{
multi::separated_nonempty_list,
};
type IResult<I, O, E = VerboseError<I>> = Result<(I, O), nom::Err<E>>;
fn parse_error<'a>(i: &'a str, context: &'static str) -> nom::Err<VerboseError<&'a str>> {
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<O, Error>
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<DateTimeValue>,
}
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})),
}
}