fapolicy_rules/parser/
parse.rs1use nom::bytes::complete::{is_not, tag, take_until};
10
11use nom::character::complete::digit1;
12use nom::character::complete::space0;
13use nom::character::is_alphanumeric;
14use nom::combinator::rest;
15use nom::error::ErrorKind;
16
17use nom::sequence::tuple;
18
19use crate::parser::error::RuleParseError;
20use crate::parser::error::RuleParseError::*;
21use crate::parser::object;
22use crate::parser::subject;
23use crate::parser::trace::Trace;
24
25use crate::{Object, Rvalue, Subject};
26use nom::IResult;
27
28pub type StrTrace<'a> = Trace<&'a str>;
31pub(crate) type TraceError<'a> = RuleParseError<StrTrace<'a>>;
32pub(crate) type NomTraceError<'a> = nom::error::Error<StrTrace<'a>>;
33pub(crate) type TraceResult<'a, O> = IResult<StrTrace<'a>, O, TraceError<'a>>;
34
35#[derive(Debug)]
36pub(crate) struct SubObj {
37 pub subject: Subject,
38 pub object: Object,
39}
40
41pub(crate) fn filepath(i: StrTrace) -> TraceResult<StrTrace> {
43 nom::bytes::complete::is_not(" \t\n")(i)
44}
45
46pub(crate) fn filetype(i: StrTrace) -> TraceResult<Rvalue> {
48 nom::bytes::complete::is_not(" \t\n")(i)
49 .map(|(r, v)| (r, Rvalue::Literal(v.current.to_string())))
50}
51
52pub(crate) fn pattern(i: StrTrace) -> IResult<StrTrace, StrTrace, TraceError> {
53 nom::bytes::complete::take_while1(|x| is_alphanumeric(x as u8) || x == '_')(i)
54}
55
56pub(crate) fn trust_flag(i: StrTrace) -> TraceResult<bool> {
57 match digit1(i) {
58 Ok((r, v)) if v.current == "1" => Ok((r, true)),
59 Ok((r, v)) if v.current == "0" => Ok((r, false)),
60 Ok((_, _)) => Err(nom::Err::Failure(Nom(i, ErrorKind::Digit))),
61 Err(e) => Err(e),
62 }
63}
64
65pub(crate) fn subject_object_parts(i: StrTrace) -> TraceResult<SubObj> {
66 if !i.current.contains(':') {
67 return Err(nom::Err::Error(MissingSeparator(i)));
68 }
69
70 let (_, ss) = take_until(" :")(i)?;
71 let (_, s) = subject::parse(ss)?;
72
73 let (_, (_, _, _, oo)) = tuple((is_not(":"), tag(":"), space0, rest))(i)?;
74 let (ii, o) = object::parse(oo)?;
75
76 Ok((
77 ii,
78 SubObj {
79 subject: s,
80 object: o,
81 },
82 ))
83}
84
85pub(crate) fn end_of_rule(i: StrTrace) -> nom::IResult<StrTrace, (), RuleParseError<StrTrace>> {
86 match rest(i) {
87 Ok((rem, v)) if v.current.is_empty() => Ok((rem, ())),
88 Ok((_, v)) => Err(nom::Err::Error(ExpectedEndOfInput(v))),
89 res => res.map(|(rem, _)| (rem, ())),
90 }
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96
97 #[test]
98 fn parse_trust_flag() {
99 assert!(trust_flag("1".into()).ok().unwrap().1);
100 assert!(!trust_flag("0".into()).ok().unwrap().1);
101 assert_eq!(None, trust_flag("2".into()).ok());
102 assert_eq!(None, trust_flag("foo".into()).ok());
103 }
104}