New DailyDuration type with nom parser
We will use this to specify timesframes for network rate limits (only apply limite when inside the time frame). Note: This is not systemd related, but we can reuse some of the parser method. Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
This commit is contained in:
parent
b9d588ffde
commit
245e2aea23
92
proxmox-systemd/src/daily_duration.rs
Normal file
92
proxmox-systemd/src/daily_duration.rs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
use std::cmp::{Ordering, PartialOrd};
|
||||||
|
|
||||||
|
use super::time::{WeekDays};
|
||||||
|
|
||||||
|
pub use super::parse_time::parse_daily_duration;
|
||||||
|
|
||||||
|
/// Time of Day (hour with minute)
|
||||||
|
#[derive(Default, PartialEq, Clone, Debug)]
|
||||||
|
pub struct HmTime {
|
||||||
|
pub hour: u32,
|
||||||
|
pub minute: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for HmTime {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
let mut order = self.hour.cmp(&other.hour);
|
||||||
|
if order == Ordering::Equal {
|
||||||
|
order = self.minute.cmp(&other.minute);
|
||||||
|
}
|
||||||
|
Some(order)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone, Debug)]
|
||||||
|
pub struct DailyDuration {
|
||||||
|
/// the days in a week this duration should trigger
|
||||||
|
pub days: WeekDays,
|
||||||
|
pub start: HmTime,
|
||||||
|
pub end: HmTime,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
|
||||||
|
use anyhow::{bail, Error};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn test_parse(
|
||||||
|
duration_str: &str,
|
||||||
|
start_h: u32, start_m: u32,
|
||||||
|
end_h: u32, end_m: u32,
|
||||||
|
days: &[usize],
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let mut day_bits = 0;
|
||||||
|
for day in days { day_bits |= 1<<day; }
|
||||||
|
let expected_days = WeekDays::from_bits(day_bits).unwrap();
|
||||||
|
|
||||||
|
let duration = parse_daily_duration(duration_str)?;
|
||||||
|
|
||||||
|
if duration.start.hour != start_h {
|
||||||
|
bail!("start hour missmatch, extected {}, got {:?}", start_h, duration);
|
||||||
|
}
|
||||||
|
if duration.start.minute != start_m {
|
||||||
|
bail!("start minute missmatch, extected {}, got {:?}", start_m, duration);
|
||||||
|
}
|
||||||
|
if duration.end.hour != end_h {
|
||||||
|
bail!("end hour missmatch, extected {}, got {:?}", end_h, duration);
|
||||||
|
}
|
||||||
|
if duration.end.minute != end_m {
|
||||||
|
bail!("end minute missmatch, extected {}, got {:?}", end_m, duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
if duration.days != expected_days {
|
||||||
|
bail!("weekday missmatch, extected {:?}, got {:?}", expected_days, duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_daily_duration_parser() -> Result<(), Error> {
|
||||||
|
|
||||||
|
assert!(parse_daily_duration("").is_err());
|
||||||
|
assert!(parse_daily_duration(" 8-12").is_err());
|
||||||
|
assert!(parse_daily_duration("8:60-12").is_err());
|
||||||
|
assert!(parse_daily_duration("8-25").is_err());
|
||||||
|
assert!(parse_daily_duration("12-8").is_err());
|
||||||
|
|
||||||
|
test_parse("8-12", 8, 0, 12, 0, &[])?;
|
||||||
|
test_parse("8:0-12:0", 8, 0, 12, 0, &[])?;
|
||||||
|
test_parse("8:00-12:00", 8, 0, 12, 0, &[])?;
|
||||||
|
test_parse("8:05-12:20", 8, 5, 12, 20, &[])?;
|
||||||
|
test_parse("8:05 - 12:20", 8, 5, 12, 20, &[])?;
|
||||||
|
|
||||||
|
test_parse("mon 8-12", 8, 0, 12, 0, &[0])?;
|
||||||
|
test_parse("tue..fri 8-12", 8, 0, 12, 0, &[1,2,3,4])?;
|
||||||
|
test_parse("sat,tue..thu,fri 8-12", 8, 0, 12, 0, &[1,2,3,4,5])?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
pub mod time;
|
pub mod time;
|
||||||
|
pub mod daily_duration;
|
||||||
|
|
||||||
mod parse_time;
|
mod parse_time;
|
||||||
mod unit;
|
mod unit;
|
||||||
|
@ -4,6 +4,7 @@ use anyhow::{bail, Error};
|
|||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
use super::time::*;
|
use super::time::*;
|
||||||
|
use super::daily_duration::*;
|
||||||
|
|
||||||
use nom::{
|
use nom::{
|
||||||
error::{context, ParseError, VerboseError},
|
error::{context, ParseError, VerboseError},
|
||||||
@ -452,3 +453,58 @@ fn parse_time_span_incomplete(mut i: &str) -> IResult<&str, TimeSpan> {
|
|||||||
|
|
||||||
Ok((i, ts))
|
Ok((i, ts))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_daily_duration(i: &str) -> Result<DailyDuration, Error> {
|
||||||
|
parse_complete_line("daily duration", i, parse_daily_duration_incomplete)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_daily_duration_incomplete(mut i: &str) -> IResult<&str, DailyDuration> {
|
||||||
|
|
||||||
|
let mut duration = DailyDuration::default();
|
||||||
|
|
||||||
|
if i.starts_with(|c: char| char::is_ascii_alphabetic(&c)) {
|
||||||
|
|
||||||
|
let (n, range_list) = context(
|
||||||
|
"weekday range list",
|
||||||
|
separated_nonempty_list(tag(","), parse_weekdays_range)
|
||||||
|
)(i)?;
|
||||||
|
|
||||||
|
i = space0(n)?.0;
|
||||||
|
|
||||||
|
for range in range_list { duration.days.insert(range); }
|
||||||
|
}
|
||||||
|
|
||||||
|
let (i, start) = parse_hm_time(i)?;
|
||||||
|
|
||||||
|
let i = space0(i)?.0;
|
||||||
|
|
||||||
|
let (i, _) = tag("-")(i)?;
|
||||||
|
|
||||||
|
let i = space0(i)?.0;
|
||||||
|
|
||||||
|
let end_time_start = i;
|
||||||
|
|
||||||
|
let (i, end) = parse_hm_time(i)?;
|
||||||
|
|
||||||
|
if start > end {
|
||||||
|
return Err(parse_error(end_time_start, "end time before start time"));
|
||||||
|
}
|
||||||
|
|
||||||
|
duration.start = start;
|
||||||
|
duration.end = end;
|
||||||
|
|
||||||
|
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})),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -5,7 +5,7 @@ use bitflags::bitflags;
|
|||||||
|
|
||||||
use proxmox_time::TmEditor;
|
use proxmox_time::TmEditor;
|
||||||
|
|
||||||
pub use super::parse_time::*;
|
pub use super::parse_time::{parse_calendar_event, parse_time_span};
|
||||||
|
|
||||||
bitflags!{
|
bitflags!{
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
Loading…
Reference in New Issue
Block a user