1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
use nom::{
    branch::alt,
    bytes::complete::tag,
    character::complete::digit0,
    combinator::{map, map_res},
    multi::separated_list1,
    sequence::tuple,
    IResult,
};

#[derive(Debug, Clone)]
pub enum Types {
    Asterik,
    Digit(u8),
    AllXSteps(u8),
    List(Vec<Self>),
    Range { min: u8, max: u8 },
}

impl Types {
    pub fn parser(input: &str) -> IResult<&str, Self> {
        alt((
            Self::parser_all_x_minute,
            Self::parser_range,
            Self::parser_digit_as_list,
            Self::parser_digit,
            Self::parser_asterik,
        ))(input)
    }

    pub fn parser_asterik(input: &str) -> IResult<&str, Self> {
        map(tag("*"), |_| Types::Asterik)(input)
    }

    pub fn parser_digit(input: &str) -> IResult<&str, Self> {
        map(map_res(digit0, |s: &str| s.parse::<u8>()), |parsed| {
            Types::Digit(parsed)
        })(input)
    }

    pub fn parser_all_x_minute(input: &str) -> IResult<&str, Self> {
        map(
            tuple((
                tag("*"),
                tag("/"),
                map_res(digit0, |s: &str| s.parse::<u8>()),
            )),
            |(_, _, number)| Self::AllXSteps(number),
        )(input)
    }

    pub fn parser_range(input: &str) -> IResult<&str, Self> {
        map(
            tuple((
                map_res(digit0, |s: &str| s.parse::<u8>()),
                tag("-"),
                map_res(digit0, |s: &str| s.parse::<u8>()),
            )),
            |(min, _, max)| Self::Range { min, max },
        )(input)
    }

    pub fn parser_digit_as_list(input: &str) -> IResult<&str, Self> {
        map(
            separated_list1(
                tag(","),
                alt((
                    Self::parser_digit,
                    Self::parser_all_x_minute,
                    Self::parser_range,
                )),
            ),
            Self::List,
        )(input)
    }
}