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
77
78
79
80
81
82
83
84
85
86
87
88
use crate::{
    is_whitespace,
    owner::{owner, Owner},
};
use nom::{char, named, tag, take_till1, types::CompleteStr, ws};
use std::path::PathBuf;

#[derive(Debug, PartialEq)]
pub enum Directive {
    NoParent,
    StarGlob,
    Owner(Owner),
    FilePath(PathBuf),
}

impl Directive {
    fn file_path<'a>(path: CompleteStr<'a>) -> Self {
        Directive::FilePath((*path).into())
    }
}

named!(pub(crate) directive<CompleteStr, Directive>, ws!(alt!(
        char!('*') => { |_| Directive::StarGlob } |
        pair!(tag!("set"), tag!("noparent")) => { |_| Directive::NoParent } |
        preceded!(tag!("file:"), take_till1!(is_whitespace)) => { Directive::file_path } |
        owner => { Directive::Owner }
)));

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn star() {
        let (rem, parsed) = directive(CompleteStr("*")).unwrap();

        assert_eq!(parsed, Directive::StarGlob);
        assert!(rem.is_empty());
    }

    #[test]
    fn no_parent() {
        let (rem, parsed) = directive(CompleteStr("set noparent")).unwrap();

        assert_eq!(parsed, Directive::NoParent);
        assert!(rem.is_empty());
    }

    #[test]
    fn no_parent_ws() {
        let (rem, parsed) = directive(CompleteStr("set   noparent")).unwrap();

        assert_eq!(parsed, Directive::NoParent);
        assert!(rem.is_empty());
    }

    #[test]
    fn filepath_absolute() {
        let (rem, parsed) = directive(CompleteStr("file: /absolute/path")).unwrap();

        assert_eq!(parsed, Directive::FilePath("/absolute/path".into()));
        assert!(rem.is_empty());
    }

    #[test]
    fn filepath_relative() {
        let (rem, parsed) = directive(CompleteStr("file: ../relative/path")).unwrap();

        assert_eq!(parsed, Directive::FilePath("../relative/path".into()));
        assert!(rem.is_empty());
    }

    #[test]
    fn filepath_ws() {
        let (rem, parsed) = directive(CompleteStr("file:   /absolute/path")).unwrap();

        assert_eq!(parsed, Directive::FilePath("/absolute/path".into()));
        assert!(rem.is_empty());
    }

    #[test]
    fn owner() {
        let (rem, parsed) = directive(CompleteStr("owner")).unwrap();

        assert_eq!(parsed, Directive::Owner(Owner::Text("owner".into())));
        assert!(rem.is_empty());
    }
}