1use crate::{
2 error::NomResult,
3 is_whitespace,
4 owner::{owner, Owner},
5};
6use nom::{
7 branch::alt,
8 bytes::complete::{tag, take_till1},
9 character::complete::{char, multispace0, multispace1},
10 combinator::map,
11 error::context,
12 sequence::{pair, preceded, separated_pair},
13};
14use std::path::PathBuf;
15
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub enum Directive {
18 NoParent,
19 StarGlob,
20 FilePath(PathBuf),
21 Owner(Owner),
22}
23
24pub(crate) fn directive(input: &str) -> NomResult<Directive> {
25 let star_glob = char('*');
26 let no_parent = separated_pair(tag("set"), multispace1, tag("noparent"));
27 let file_path = preceded(pair(tag("file:"), multispace0), take_till1(is_whitespace));
28
29 context(
30 "directive",
31 alt((
32 map(star_glob, |_| Directive::StarGlob),
33 map(no_parent, |_| Directive::NoParent),
34 map(file_path, |path: &str| Directive::FilePath(path.into())),
35 map(owner, Directive::Owner),
36 )),
37 )(input)
38}
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43
44 #[test]
45 fn star() {
46 let (rem, parsed) = directive("*").unwrap();
47
48 assert_eq!(parsed, Directive::StarGlob);
49 assert!(rem.is_empty());
50 }
51
52 #[test]
53 fn no_parent() {
54 let (rem, parsed) = directive("set noparent").unwrap();
55
56 assert_eq!(parsed, Directive::NoParent);
57 assert!(rem.is_empty());
58 }
59
60 #[test]
61 fn no_parent_ws() {
62 let (rem, parsed) = directive("set noparent").unwrap();
63
64 assert_eq!(parsed, Directive::NoParent);
65 assert!(rem.is_empty());
66 }
67
68 #[test]
69 fn filepath_absolute() {
70 let (rem, parsed) = directive("file: /absolute/path").unwrap();
71
72 assert_eq!(parsed, Directive::FilePath("/absolute/path".into()));
73 assert!(rem.is_empty());
74 }
75
76 #[test]
77 fn filepath_relative() {
78 let (rem, parsed) = directive("file: ../relative/path").unwrap();
79
80 assert_eq!(parsed, Directive::FilePath("../relative/path".into()));
81 assert!(rem.is_empty());
82 }
83
84 #[test]
85 fn filepath_ws() {
86 let (rem, parsed) = directive("file: /absolute/path").unwrap();
87
88 assert_eq!(parsed, Directive::FilePath("/absolute/path".into()));
89 assert!(rem.is_empty());
90 }
91
92 #[test]
93 fn owner() {
94 let (rem, parsed) = directive("owner").unwrap();
95
96 assert_eq!(parsed, Directive::Owner(Owner::Text("owner".into())));
97 assert!(rem.is_empty());
98 }
99}