Add step parsing
parent
3c4d34e484
commit
9916389af9
106
src/lib.rs
106
src/lib.rs
|
@ -6,9 +6,9 @@ mod parse;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum CronSpecifier {
|
pub enum CronSpecifier {
|
||||||
Any,
|
Any(Option<u8>),
|
||||||
Specifically(u8),
|
Specifically(u8),
|
||||||
Range(u8, u8),
|
Range(u8, u8, Option<u8>),
|
||||||
Several(Vec<CronSpecifier>),
|
Several(Vec<CronSpecifier>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,59 +37,61 @@ mod tests {
|
||||||
use CronSpecifier::{Any, Range, Several, Specifically};
|
use CronSpecifier::{Any, Range, Several, Specifically};
|
||||||
|
|
||||||
// simple parse checks
|
// simple parse checks
|
||||||
#[test_case("* * * * *", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Any, day_of_week: Any})]
|
#[test_case("* * * * *", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Any(None), day_of_week: Any(None)})]
|
||||||
#[test_case("0 4 * * *", &CronEntry{minute: Specifically(0), hour: Specifically(4), day_of_month: Any, month: Any, day_of_week: Any})]
|
#[test_case("0 4 * * *", &CronEntry{minute: Specifically(0), hour: Specifically(4), day_of_month: Any(None), month: Any(None), day_of_week: Any(None)})]
|
||||||
#[test_case("0 4 10 5 4", &CronEntry{minute: Specifically(0), hour: Specifically(4), day_of_month: Specifically(10), month: Specifically(5), day_of_week: Specifically(4)})]
|
#[test_case("0 4 10 5 4", &CronEntry{minute: Specifically(0), hour: Specifically(4), day_of_month: Specifically(10), month: Specifically(5), day_of_week: Specifically(4)})]
|
||||||
#[test_case("* * 10 5 *", &CronEntry{minute: Any, hour: Any, day_of_month: Specifically(10), month: Specifically(5), day_of_week: Any})]
|
#[test_case("* * 10 5 *", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Specifically(10), month: Specifically(5), day_of_week: Any(None)})]
|
||||||
#[test_case("* * * * 7", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Any, day_of_week: Specifically(0)}; "sunday can be seven")]
|
#[test_case("* * * * 7", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Any(None), day_of_week: Specifically(0)}; "sunday can be seven")]
|
||||||
#[test_case("* 4-6 * * *", &CronEntry{minute: Any, hour: Range(4, 6), day_of_month: Any, month: Any, day_of_week: Any})]
|
#[test_case("* 4-6 * * *", &CronEntry{minute: Any(None), hour: Range(4, 6, None), day_of_month: Any(None), month: Any(None), day_of_week: Any(None)})]
|
||||||
#[test_case("* * * * mon-wed", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Any, day_of_week: Range(1, 3)})]
|
#[test_case("* * * * mon-wed", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Any(None), day_of_week: Range(1, 3, None)})]
|
||||||
#[test_case("* * * * mon-5", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Any, day_of_week: Range(1, 5)})]
|
#[test_case("* * * * mon-5", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Any(None), day_of_week: Range(1, 5, None)})]
|
||||||
#[test_case("* * * jan-jun *", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Range(1, 6), day_of_week: Any})]
|
#[test_case("* * * jan-jun *", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Range(1, 6, None), day_of_week: Any(None)})]
|
||||||
#[test_case("* * * 1,5 *", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Several(vec![Specifically(1), Specifically(5)]), day_of_week: Any})]
|
#[test_case("* * * 1,5 *", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Several(vec![Specifically(1), Specifically(5)]), day_of_week: Any(None)})]
|
||||||
#[test_case("* * * * 1,5", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Any, day_of_week: Several(vec![Specifically(1), Specifically(5)])})]
|
#[test_case("* * * * 1,5", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Any(None), day_of_week: Several(vec![Specifically(1), Specifically(5)])})]
|
||||||
#[test_case("* * * * mon-wed,1", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Any, day_of_week: Several(vec![Range(1, 3), Specifically(1)])})]
|
#[test_case("* * * * mon-wed,1", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Any(None), day_of_week: Several(vec![Range(1, 3, None), Specifically(1)])})]
|
||||||
#[test_case("* * * * mon-wed,1,3-5", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Any, day_of_week: Several(vec![Range(1, 3), Specifically(1), Range(3, 5)])})]
|
#[test_case("* * * * mon-wed,1,3-5", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Any(None), day_of_week: Several(vec![Range(1, 3, None), Specifically(1), Range(3, 5, None)])})]
|
||||||
|
#[test_case("*/10 * * * *", &CronEntry{minute: Any(Some(10)), hour: Any(None), day_of_month: Any(None), month: Any(None), day_of_week: Any(None)})]
|
||||||
|
#[test_case("* */2 * * SUN", &CronEntry{minute: Any(None), hour: Any(Some(2)), day_of_month: Any(None), month: Any(None), day_of_week: Specifically(0)})]
|
||||||
// days of week
|
// days of week
|
||||||
#[test_case("* * * 1 mon", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(1), day_of_week: Specifically(1)})]
|
#[test_case("* * * 1 mon", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(1), day_of_week: Specifically(1)})]
|
||||||
#[test_case("* * * 2 MON", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(2), day_of_week: Specifically(1)})]
|
#[test_case("* * * 2 MON", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(2), day_of_week: Specifically(1)})]
|
||||||
#[test_case("* * * 1 tue", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(1), day_of_week: Specifically(2)})]
|
#[test_case("* * * 1 tue", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(1), day_of_week: Specifically(2)})]
|
||||||
#[test_case("* * * 2 TUE", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(2), day_of_week: Specifically(2)})]
|
#[test_case("* * * 2 TUE", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(2), day_of_week: Specifically(2)})]
|
||||||
#[test_case("* * * 1 wed", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(1), day_of_week: Specifically(3)})]
|
#[test_case("* * * 1 wed", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(1), day_of_week: Specifically(3)})]
|
||||||
#[test_case("* * * 2 WED", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(2), day_of_week: Specifically(3)})]
|
#[test_case("* * * 2 WED", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(2), day_of_week: Specifically(3)})]
|
||||||
#[test_case("* * * 1 thu", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(1), day_of_week: Specifically(4)})]
|
#[test_case("* * * 1 thu", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(1), day_of_week: Specifically(4)})]
|
||||||
#[test_case("* * * 2 THU", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(2), day_of_week: Specifically(4)})]
|
#[test_case("* * * 2 THU", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(2), day_of_week: Specifically(4)})]
|
||||||
#[test_case("* * * 1 fri", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(1), day_of_week: Specifically(5)})]
|
#[test_case("* * * 1 fri", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(1), day_of_week: Specifically(5)})]
|
||||||
#[test_case("* * * 2 FRI", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(2), day_of_week: Specifically(5)})]
|
#[test_case("* * * 2 FRI", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(2), day_of_week: Specifically(5)})]
|
||||||
#[test_case("* * * 1 sat", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(1), day_of_week: Specifically(6)})]
|
#[test_case("* * * 1 sat", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(1), day_of_week: Specifically(6)})]
|
||||||
#[test_case("* * * 2 SAT", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(2), day_of_week: Specifically(6)})]
|
#[test_case("* * * 2 SAT", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(2), day_of_week: Specifically(6)})]
|
||||||
#[test_case("* * * 1 sun", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(1), day_of_week: Specifically(0)})]
|
#[test_case("* * * 1 sun", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(1), day_of_week: Specifically(0)})]
|
||||||
#[test_case("* * * 2 SUN", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(2), day_of_week: Specifically(0)})]
|
#[test_case("* * * 2 SUN", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(2), day_of_week: Specifically(0)})]
|
||||||
// months
|
// months
|
||||||
#[test_case("* * * jan 0", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(1), day_of_week: Specifically(0)})]
|
#[test_case("* * * jan 0", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(1), day_of_week: Specifically(0)})]
|
||||||
#[test_case("* * * JAN 1", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(1), day_of_week: Specifically(1)})]
|
#[test_case("* * * JAN 1", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(1), day_of_week: Specifically(1)})]
|
||||||
#[test_case("* * * feb 0", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(2), day_of_week: Specifically(0)})]
|
#[test_case("* * * feb 0", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(2), day_of_week: Specifically(0)})]
|
||||||
#[test_case("* * * FEB 1", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(2), day_of_week: Specifically(1)})]
|
#[test_case("* * * FEB 1", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(2), day_of_week: Specifically(1)})]
|
||||||
#[test_case("* * * mar 0", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(3), day_of_week: Specifically(0)})]
|
#[test_case("* * * mar 0", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(3), day_of_week: Specifically(0)})]
|
||||||
#[test_case("* * * MAR 1", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(3), day_of_week: Specifically(1)})]
|
#[test_case("* * * MAR 1", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(3), day_of_week: Specifically(1)})]
|
||||||
#[test_case("* * * apr 0", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(4), day_of_week: Specifically(0)})]
|
#[test_case("* * * apr 0", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(4), day_of_week: Specifically(0)})]
|
||||||
#[test_case("* * * APR 1", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(4), day_of_week: Specifically(1)})]
|
#[test_case("* * * APR 1", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(4), day_of_week: Specifically(1)})]
|
||||||
#[test_case("* * * may 0", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(5), day_of_week: Specifically(0)})]
|
#[test_case("* * * may 0", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(5), day_of_week: Specifically(0)})]
|
||||||
#[test_case("* * * MAY 1", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(5), day_of_week: Specifically(1)})]
|
#[test_case("* * * MAY 1", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(5), day_of_week: Specifically(1)})]
|
||||||
#[test_case("* * * jun 0", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(6), day_of_week: Specifically(0)})]
|
#[test_case("* * * jun 0", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(6), day_of_week: Specifically(0)})]
|
||||||
#[test_case("* * * JUN 1", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(6), day_of_week: Specifically(1)})]
|
#[test_case("* * * JUN 1", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(6), day_of_week: Specifically(1)})]
|
||||||
#[test_case("* * * jul 0", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(7), day_of_week: Specifically(0)})]
|
#[test_case("* * * jul 0", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(7), day_of_week: Specifically(0)})]
|
||||||
#[test_case("* * * JUL 1", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(7), day_of_week: Specifically(1)})]
|
#[test_case("* * * JUL 1", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(7), day_of_week: Specifically(1)})]
|
||||||
#[test_case("* * * aug 0", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(8), day_of_week: Specifically(0)})]
|
#[test_case("* * * aug 0", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(8), day_of_week: Specifically(0)})]
|
||||||
#[test_case("* * * AUG 1", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(8), day_of_week: Specifically(1)})]
|
#[test_case("* * * AUG 1", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(8), day_of_week: Specifically(1)})]
|
||||||
#[test_case("* * * sep 0", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(9), day_of_week: Specifically(0)})]
|
#[test_case("* * * sep 0", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(9), day_of_week: Specifically(0)})]
|
||||||
#[test_case("* * * SEP 1", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(9), day_of_week: Specifically(1)})]
|
#[test_case("* * * SEP 1", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(9), day_of_week: Specifically(1)})]
|
||||||
#[test_case("* * * oct 0", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(10), day_of_week: Specifically(0)})]
|
#[test_case("* * * oct 0", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(10), day_of_week: Specifically(0)})]
|
||||||
#[test_case("* * * OCT 1", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(10), day_of_week: Specifically(1)})]
|
#[test_case("* * * OCT 1", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(10), day_of_week: Specifically(1)})]
|
||||||
#[test_case("* * * nov 0", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(11), day_of_week: Specifically(0)})]
|
#[test_case("* * * nov 0", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(11), day_of_week: Specifically(0)})]
|
||||||
#[test_case("* * * NOV 1", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(11), day_of_week: Specifically(1)})]
|
#[test_case("* * * NOV 1", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(11), day_of_week: Specifically(1)})]
|
||||||
#[test_case("* * * dec 0", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(12), day_of_week: Specifically(0)})]
|
#[test_case("* * * dec 0", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(12), day_of_week: Specifically(0)})]
|
||||||
#[test_case("* * * DEC 1", &CronEntry{minute: Any, hour: Any, day_of_month: Any, month: Specifically(12), day_of_week: Specifically(1)})]
|
#[test_case("* * * DEC 1", &CronEntry{minute: Any(None), hour: Any(None), day_of_month: Any(None), month: Specifically(12), day_of_week: Specifically(1)})]
|
||||||
fn test_successful_parse(to_parse: &str, expected: &CronEntry) {
|
fn test_successful_parse(to_parse: &str, expected: &CronEntry) {
|
||||||
let parse_res = CronEntry::from_str(to_parse);
|
let parse_res = CronEntry::from_str(to_parse);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use nom::{branch::alt, character::complete::char, IResult, Parser};
|
use nom::{branch::alt, character::complete::char, error::FromExternalError, IResult, Parser};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::{CronEntry, CronSpecifier};
|
use crate::{CronEntry, CronSpecifier};
|
||||||
|
@ -163,7 +163,7 @@ fn list_or_single_specifier<'a, P, E>(
|
||||||
) -> impl FnMut(&'a str) -> IResult<&'a str, CronSpecifier, E>
|
) -> impl FnMut(&'a str) -> IResult<&'a str, CronSpecifier, E>
|
||||||
where
|
where
|
||||||
P: Parser<&'a str, CronSpecifier, E> + Copy,
|
P: Parser<&'a str, CronSpecifier, E> + Copy,
|
||||||
E: nom::error::ParseError<&'a str>,
|
E: nom::error::ParseError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError>,
|
||||||
{
|
{
|
||||||
alt((
|
alt((
|
||||||
compound::several_specifiers(list_element_parser),
|
compound::several_specifiers(list_element_parser),
|
||||||
|
|
|
@ -3,11 +3,12 @@
|
||||||
use crate::parse::{simple, word};
|
use crate::parse::{simple, word};
|
||||||
use crate::CronSpecifier;
|
use crate::CronSpecifier;
|
||||||
use nom::combinator::fail;
|
use nom::combinator::fail;
|
||||||
|
use nom::error::FromExternalError;
|
||||||
use nom::multi::separated_list1;
|
use nom::multi::separated_list1;
|
||||||
use nom::InputLength;
|
use nom::InputLength;
|
||||||
use nom::{
|
use nom::{
|
||||||
branch::alt, character::complete::char, sequence::separated_pair, AsChar, IResult, InputIter,
|
branch::alt, character::complete::char, combinator::opt, sequence::pair,
|
||||||
Parser, Slice,
|
sequence::separated_pair, AsChar, IResult, InputIter, Parser, Slice,
|
||||||
};
|
};
|
||||||
use std::ops::RangeFrom;
|
use std::ops::RangeFrom;
|
||||||
|
|
||||||
|
@ -101,20 +102,25 @@ where
|
||||||
/// Build a parser for a ranged specifier, with some kind of parser for the left/right of the range.
|
/// Build a parser for a ranged specifier, with some kind of parser for the left/right of the range.
|
||||||
/// This accepts strings of the form `<left>-<right>`. The left/right parsers must return the
|
/// This accepts strings of the form `<left>-<right>`. The left/right parsers must return the
|
||||||
/// raw components of a range, rather than the specifiers themselves
|
/// raw components of a range, rather than the specifiers themselves
|
||||||
fn build_range_parser<I, E, L, R>(
|
fn build_range_parser<'a, E, L, R>(
|
||||||
left_parser: L,
|
left_parser: L,
|
||||||
right_parser: R,
|
right_parser: R,
|
||||||
) -> impl FnMut(I) -> IResult<I, CronSpecifier, E>
|
) -> impl FnMut(&'a str) -> IResult<&'a str, CronSpecifier, E>
|
||||||
where
|
where
|
||||||
I: InputIter + Slice<RangeFrom<usize>>,
|
L: Parser<&'a str, u8, E> + Copy,
|
||||||
<I as InputIter>::Item: AsChar,
|
R: Parser<&'a str, u8, E> + Copy,
|
||||||
L: Parser<I, u8, E> + Copy,
|
E: nom::error::ParseError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError>,
|
||||||
R: Parser<I, u8, E> + Copy,
|
|
||||||
E: nom::error::ParseError<I>,
|
|
||||||
{
|
{
|
||||||
move |data: I| {
|
// I'd much prefer it if I could make this take a generic input, but I backed myself into a corner with
|
||||||
let (remaining, (start, end)) = separated_pair(left_parser, char('-'), right_parser)(data)?;
|
// `parse_number`.
|
||||||
let specifier = CronSpecifier::Range(start, end);
|
// TODO: make this take a generic input
|
||||||
|
move |data: &'a str| {
|
||||||
|
let (remaining, ((start, end), step)) = pair(
|
||||||
|
separated_pair(left_parser, char('-'), right_parser),
|
||||||
|
opt(simple::parse_step),
|
||||||
|
)(data)?;
|
||||||
|
|
||||||
|
let specifier = CronSpecifier::Range(start, end, step);
|
||||||
|
|
||||||
Ok((remaining, specifier))
|
Ok((remaining, specifier))
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,9 @@
|
||||||
|
|
||||||
use nom::{
|
use nom::{
|
||||||
character::complete::{char, digit1},
|
character::complete::{char, digit1},
|
||||||
combinator::map_res,
|
combinator::{map_res, opt},
|
||||||
error::FromExternalError,
|
error::FromExternalError,
|
||||||
|
sequence::{pair, preceded},
|
||||||
IResult,
|
IResult,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -27,9 +28,15 @@ where
|
||||||
|
|
||||||
pub(super) fn parse_star_specifier<'a, E>(chunk: &'a str) -> IResult<&'a str, CronSpecifier, E>
|
pub(super) fn parse_star_specifier<'a, E>(chunk: &'a str) -> IResult<&'a str, CronSpecifier, E>
|
||||||
where
|
where
|
||||||
E: nom::error::ParseError<&'a str>,
|
E: nom::error::ParseError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError>,
|
||||||
{
|
{
|
||||||
let (remaining, _) = char('*')(chunk)?;
|
let (remaining, (_, step)) = pair(char('*'), opt(parse_step))(chunk)?;
|
||||||
|
|
||||||
Ok((remaining, CronSpecifier::Any))
|
Ok((remaining, CronSpecifier::Any(step)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn parse_step<'a, E>(chunk: &'a str) -> IResult<&'a str, u8, E>
|
||||||
|
where
|
||||||
|
E: nom::error::ParseError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError> {
|
||||||
|
preceded(char('/'), parse_number)(chunk)
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ fn ensure_value_in_range(
|
||||||
construct_error: fn(u8) -> Error,
|
construct_error: fn(u8) -> Error,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
match *specifier {
|
match *specifier {
|
||||||
CronSpecifier::Any => Ok(()),
|
CronSpecifier::Any(_) => Ok(()),
|
||||||
CronSpecifier::Specifically(value) => {
|
CronSpecifier::Specifically(value) => {
|
||||||
if value >= min && value <= max {
|
if value >= min && value <= max {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -33,7 +33,8 @@ fn ensure_value_in_range(
|
||||||
Err(construct_error(value))
|
Err(construct_error(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CronSpecifier::Range(range_min, range_max) => {
|
// TODO: Handle steps
|
||||||
|
CronSpecifier::Range(range_min, range_max, _) => {
|
||||||
let min_ok = range_min >= min && range_min <= max;
|
let min_ok = range_min >= min && range_min <= max;
|
||||||
let max_ok = range_max >= min && range_max <= max;
|
let max_ok = range_max >= min && range_max <= max;
|
||||||
if max_ok && min_ok {
|
if max_ok && min_ok {
|
||||||
|
@ -54,7 +55,8 @@ fn ensure_value_in_range(
|
||||||
|
|
||||||
fn ensure_range_validity(specifier: &CronSpecifier) -> Result<(), Error> {
|
fn ensure_range_validity(specifier: &CronSpecifier) -> Result<(), Error> {
|
||||||
match *specifier {
|
match *specifier {
|
||||||
CronSpecifier::Range(min, max) => {
|
// TODO: Handle steps
|
||||||
|
CronSpecifier::Range(min, max, _) => {
|
||||||
if min <= max {
|
if min <= max {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue