forked from proxmox-mirrors/proxmox
		
	proxmox-time: move common parse functions to parse_helpers
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
This commit is contained in:
		
							parent
							
								
									8e0fc66dfe
								
							
						
					
					
						commit
						a104c8fc41
					
				@ -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::*;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										75
									
								
								proxmox-time/src/parse_helpers.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								proxmox-time/src/parse_helpers.rs
									
									
									
									
									
										Normal 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 })),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -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})),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user