biscuit_parser/
parser.rs

1use crate::builder::{self, CheckKind};
2use nom::{
3    branch::alt,
4    bytes::complete::{escaped_transform, tag, tag_no_case, take_until, take_while, take_while1},
5    character::{
6        complete::{char, digit1, multispace0 as space0},
7        is_alphanumeric,
8    },
9    combinator::{consumed, cut, eof, map, map_res, opt, recognize, value},
10    error::{ErrorKind, FromExternalError, ParseError},
11    multi::{many0, separated_list0, separated_list1},
12    sequence::{delimited, pair, preceded, terminated, tuple},
13    IResult, Offset,
14};
15use std::{collections::BTreeSet, convert::TryInto};
16use thiserror::Error;
17
18/// parse a Datalog fact
19pub fn fact(i: &str) -> IResult<&str, builder::Fact, Error> {
20    let (i, fact) = fact_inner(i)?;
21
22    let (i, _) = error(
23        preceded(space0, eof),
24        |input| format!("unexpected trailing data after fact: '{}'", input),
25        " ,\n",
26    )(i)?;
27
28    Ok((i, fact))
29}
30
31pub fn fact_inner(i: &str) -> IResult<&str, builder::Fact, Error> {
32    let (i, _) = space0(i)?;
33    let (i, fact_name) = name(i)?;
34
35    let (i, _) = space0(i)?;
36    let (i, terms) = delimited(
37        char('('),
38        cut(separated_list1(
39            preceded(space0, char(',')),
40            cut(term_in_fact),
41        )),
42        preceded(space0, char(')')),
43    )(i)?;
44
45    Ok((i, builder::Fact::new(fact_name.to_string(), terms)))
46}
47
48/// parse a Datalog check
49pub fn check(i: &str) -> IResult<&str, builder::Check, Error> {
50    let (i, check) = check_inner(i)?;
51
52    let (i, _) = error(
53        preceded(space0, eof),
54        |input| {
55            match input.chars().next() {
56            Some(')') => "unexpected parens".to_string(),
57            _ => format!("expected either the next term after ',' or the next check variant after 'or', but got '{}'",
58                     input)
59        }
60        },
61        " ,\n",
62    )(i)?;
63
64    Ok((i, check))
65}
66
67fn check_inner(i: &str) -> IResult<&str, builder::Check, Error> {
68    let (i, _) = space0(i)?;
69
70    let (i, kind) = alt((
71        map(tag_no_case("check if"), |_| CheckKind::One),
72        map(tag_no_case("check all"), |_| CheckKind::All),
73    ))(i)?;
74
75    let (i, queries) = cut(check_body)(i)?;
76    Ok((i, builder::Check { queries, kind }))
77}
78
79/// parse an allow or deny rule
80pub fn policy(i: &str) -> IResult<&str, builder::Policy, Error> {
81    let (i, policy) = policy_inner(i)?;
82
83    let (i, _) = error(
84        preceded(space0, eof),
85        |input| {
86            match input.chars().next() {
87            Some(')') => "unexpected parens".to_string(),
88            _ => format!("expected either the next term after ',' or the next policy variant after 'or', but got '{}'",
89                     input)
90        }
91        },
92        " ,\n",
93    )(i)?;
94
95    Ok((i, policy))
96}
97
98fn policy_inner(i: &str) -> IResult<&str, builder::Policy, Error> {
99    alt((allow, deny))(i)
100}
101
102/// parse an allow rule
103pub fn allow(i: &str) -> IResult<&str, builder::Policy, Error> {
104    let (i, _) = space0(i)?;
105
106    let (i, _) = tag_no_case("allow if")(i)?;
107
108    let (i, queries) = cut(check_body)(i)?;
109    Ok((
110        i,
111        builder::Policy {
112            queries,
113            kind: builder::PolicyKind::Allow,
114        },
115    ))
116}
117
118/// parse a deny rule
119pub fn deny(i: &str) -> IResult<&str, builder::Policy, Error> {
120    let (i, _) = space0(i)?;
121
122    let (i, _) = tag_no_case("deny if")(i)?;
123
124    let (i, queries) = cut(check_body)(i)?;
125    Ok((
126        i,
127        builder::Policy {
128            queries,
129            kind: builder::PolicyKind::Deny,
130        },
131    ))
132}
133
134/// parse a Datalog check body
135pub fn check_body(i: &str) -> IResult<&str, Vec<builder::Rule>, Error> {
136    let (i, mut queries) = separated_list1(
137        preceded(space0, tag_no_case("or")),
138        preceded(space0, cut(rule_body)),
139    )(i)?;
140
141    let queries = queries
142        .drain(..)
143        .map(|(predicates, expressions, scopes)| {
144            builder::Rule::new(
145                builder::Predicate {
146                    name: "query".to_string(),
147                    terms: Vec::new(),
148                },
149                predicates,
150                expressions,
151                scopes,
152            )
153        })
154        .collect();
155    Ok((i, queries))
156}
157
158/// parse a Datalog rule
159pub fn rule(i: &str) -> IResult<&str, builder::Rule, Error> {
160    let (i, rule) = rule_inner(i)?;
161
162    let (i, _) = error(
163        preceded(space0, eof),
164        |input| match input.chars().next() {
165            Some(')') => "unexpected parens".to_string(),
166            _ => format!(
167                "expected the next term or expression after ',', but got '{}'",
168                input
169            ),
170        },
171        " ,\n",
172    )(i)?;
173
174    Ok((i, rule))
175}
176
177pub fn rule_inner(i: &str) -> IResult<&str, builder::Rule, Error> {
178    let (i, (head_input, head)) = consumed(rule_head)(i)?;
179    let (i, _) = space0(i)?;
180
181    let (i, _) = tag("<-")(i)?;
182
183    let (i, (body, expressions, scopes)) = cut(rule_body)(i)?;
184
185    let rule = builder::Rule::new(head, body, expressions, scopes);
186
187    if let Err(message) = rule.validate_variables() {
188        return Err(nom::Err::Failure(Error {
189            input: head_input,
190            code: ErrorKind::Satisfy,
191            message: Some(message),
192        }));
193    }
194
195    Ok((i, rule))
196}
197/*
198impl TryFrom<&str> for builder::Fact {
199    type Error = error::Token;
200
201    fn try_from(value: &str) -> Result<Self, Self::Error> {
202        Ok(fact(value).finish().map(|(_, o)| o)?)
203    }
204}
205
206impl TryFrom<&str> for builder::Rule {
207    type Error = error::Token;
208
209    fn try_from(value: &str) -> Result<Self, Self::Error> {
210        Ok(rule(value).finish().map(|(_, o)| o)?)
211    }
212}
213
214impl FromStr for builder::Fact {
215    type Err = error::Token;
216
217    fn from_str(s: &str) -> Result<Self, Self::Err> {
218        Ok(fact(s).finish().map(|(_, o)| o)?)
219    }
220}
221
222impl FromStr for builder::Rule {
223    type Err = error::Token;
224
225    fn from_str(s: &str) -> Result<Self, Self::Err> {
226        Ok(rule(s).finish().map(|(_, o)| o)?)
227    }
228}
229
230impl TryFrom<&str> for builder::Check {
231    type Error = error::Token;
232
233    fn try_from(value: &str) -> Result<Self, Self::Error> {
234        Ok(check(value).finish().map(|(_, o)| o)?)
235    }
236}
237
238impl FromStr for builder::Check {
239    type Err = error::Token;
240
241    fn from_str(s: &str) -> Result<Self, Self::Err> {
242        Ok(check(s).finish().map(|(_, o)| o)?)
243    }
244}
245
246impl TryFrom<&str> for builder::Policy {
247    type Error = error::Token;
248
249    fn try_from(value: &str) -> Result<Self, Self::Error> {
250        Ok(policy(value).finish().map(|(_, o)| o)?)
251    }
252}
253
254impl FromStr for builder::Policy {
255    type Err = error::Token;
256
257    fn from_str(s: &str) -> Result<Self, Self::Err> {
258        Ok(policy(s).finish().map(|(_, o)| o)?)
259    }
260}
261
262impl FromStr for builder::Predicate {
263    type Err = error::Token;
264
265    fn from_str(s: &str) -> Result<Self, Self::Err> {
266        Ok(predicate(s).finish().map(|(_, o)| o)?)
267    }
268}*/
269
270fn predicate(i: &str) -> IResult<&str, builder::Predicate, Error> {
271    let (i, _) = space0(i)?;
272    let (i, fact_name) = name(i)?;
273
274    let (i, _) = space0(i)?;
275    let (i, terms) = delimited(
276        char('('),
277        cut(separated_list1(preceded(space0, char(',')), cut(term))),
278        preceded(space0, char(')')),
279    )(i)?;
280
281    Ok((
282        i,
283        builder::Predicate {
284            name: fact_name.to_string(),
285            terms,
286        },
287    ))
288}
289
290fn rule_head(i: &str) -> IResult<&str, builder::Predicate, Error> {
291    let (i, _) = space0(i)?;
292    let (i, fact_name) = name(i)?;
293
294    let (i, _) = space0(i)?;
295    let (i, terms) = delimited(
296        char('('),
297        cut(separated_list0(preceded(space0, char(',')), cut(term))),
298        preceded(space0, char(')')),
299    )(i)?;
300
301    Ok((
302        i,
303        builder::Predicate {
304            name: fact_name.to_string(),
305            terms,
306        },
307    ))
308}
309
310/// parse a Datalog rule body
311pub fn rule_body(
312    i: &str,
313) -> IResult<
314    &str,
315    (
316        Vec<builder::Predicate>,
317        Vec<builder::Expression>,
318        Vec<builder::Scope>,
319    ),
320    Error,
321> {
322    let (i, mut elements) = separated_list1(
323        preceded(space0, char(',')),
324        preceded(space0, cut(predicate_or_expression)),
325    )(i)?;
326
327    let mut predicates = Vec::new();
328    let mut expressions = Vec::new();
329
330    for el in elements.drain(..) {
331        match el {
332            PredOrExpr::P(predicate) => predicates.push(predicate),
333            PredOrExpr::E(expression) => {
334                let ops = expression.opcodes();
335                let e = builder::Expression { ops };
336                expressions.push(e);
337            }
338        }
339    }
340
341    let (i, scopes) = scopes(i)?;
342
343    Ok((i, (predicates, expressions, scopes)))
344}
345
346enum PredOrExpr {
347    P(builder::Predicate),
348    E(Expr),
349}
350
351fn predicate_or_expression(i: &str) -> IResult<&str, PredOrExpr, Error> {
352    reduce(
353        alt((map(predicate, PredOrExpr::P), map(expr, PredOrExpr::E))),
354        ",;",
355    )(i)
356}
357
358fn scopes(i: &str) -> IResult<&str, Vec<builder::Scope>, Error> {
359    if let Ok((i, _)) = preceded(space0, tag::<_, _, ()>("trusting"))(i) {
360        separated_list1(preceded(space0, char(',')), preceded(space0, cut(scope)))(i)
361    } else {
362        Ok((i, vec![]))
363    }
364}
365
366fn scope(i: &str) -> IResult<&str, builder::Scope, Error> {
367    alt((
368        map(tag("authority"), |_| builder::Scope::Authority),
369        map(tag("previous"), |_| builder::Scope::Previous),
370        map(public_key, |bytes| builder::Scope::PublicKey(bytes)),
371        map(delimited(char('{'), name, char('}')), |n| {
372            builder::Scope::Parameter(n.to_string())
373        }),
374    ))(i)
375}
376
377pub fn public_key(i: &str) -> IResult<&str, builder::PublicKey, Error> {
378    preceded(tag("ed25519/"), parse_hex)(i)
379}
380
381#[derive(Debug, PartialEq)]
382pub enum Expr {
383    Value(builder::Term),
384    Unary(builder::Op, Box<Expr>),
385    Binary(builder::Op, Box<Expr>, Box<Expr>),
386}
387
388impl Expr {
389    pub fn opcodes(self) -> Vec<builder::Op> {
390        let mut v = Vec::new();
391        self.into_opcodes(&mut v);
392        v
393    }
394
395    fn into_opcodes(self, v: &mut Vec<builder::Op>) {
396        match self {
397            Expr::Value(t) => v.push(builder::Op::Value(t)),
398            Expr::Unary(op, expr) => {
399                expr.into_opcodes(v);
400                v.push(op);
401            }
402            Expr::Binary(op, left, right) => {
403                left.into_opcodes(v);
404                right.into_opcodes(v);
405                v.push(op);
406            }
407        }
408    }
409}
410
411fn unary_negate(i: &str) -> IResult<&str, Expr, Error> {
412    let (i, _) = space0(i)?;
413    let (i, _) = tag("!")(i)?;
414    let (i, _) = space0(i)?;
415    let (i, value) = expr6(i)?;
416
417    Ok((
418        i,
419        Expr::Unary(builder::Op::Unary(builder::Unary::Negate), Box::new(value)),
420    ))
421}
422
423fn unary_parens(i: &str) -> IResult<&str, Expr, Error> {
424    let (i, _) = space0(i)?;
425    let (i, _) = tag("(")(i)?;
426    let (i, _) = space0(i)?;
427    let (i, value) = expr(i)?;
428    let (i, _) = space0(i)?;
429    let (i, _) = tag(")")(i)?;
430
431    Ok((
432        i,
433        Expr::Unary(builder::Op::Unary(builder::Unary::Parens), Box::new(value)),
434    ))
435}
436
437fn binary_op_0(i: &str) -> IResult<&str, builder::Binary, Error> {
438    use builder::Binary;
439    value(Binary::Or, tag("||"))(i)
440}
441
442fn binary_op_1(i: &str) -> IResult<&str, builder::Binary, Error> {
443    use builder::Binary;
444    value(Binary::And, tag("&&"))(i)
445}
446
447fn binary_op_2(i: &str) -> IResult<&str, builder::Binary, Error> {
448    use builder::Binary;
449    alt((
450        value(Binary::LessOrEqual, tag("<=")),
451        value(Binary::GreaterOrEqual, tag(">=")),
452        value(Binary::LessThan, tag("<")),
453        value(Binary::GreaterThan, tag(">")),
454        value(Binary::Equal, tag("==")),
455        value(Binary::NotEqual, tag("!=")),
456    ))(i)
457}
458
459fn binary_op_3(i: &str) -> IResult<&str, builder::Binary, Error> {
460    use builder::Binary;
461    value(Binary::BitwiseXor, tag("^"))(i)
462}
463
464fn binary_op_4(i: &str) -> IResult<&str, builder::Binary, Error> {
465    use builder::Binary;
466    value(Binary::BitwiseOr, tag("|"))(i)
467}
468
469fn binary_op_5(i: &str) -> IResult<&str, builder::Binary, Error> {
470    use builder::Binary;
471    value(Binary::BitwiseAnd, tag("&"))(i)
472}
473
474fn binary_op_6(i: &str) -> IResult<&str, builder::Binary, Error> {
475    use builder::Binary;
476    alt((value(Binary::Add, tag("+")), value(Binary::Sub, tag("-"))))(i)
477}
478
479fn binary_op_7(i: &str) -> IResult<&str, builder::Binary, Error> {
480    use builder::Binary;
481    alt((value(Binary::Mul, tag("*")), value(Binary::Div, tag("/"))))(i)
482}
483
484fn binary_op_8(i: &str) -> IResult<&str, builder::Binary, Error> {
485    use builder::Binary;
486
487    alt((
488        value(Binary::Contains, tag("contains")),
489        value(Binary::Prefix, tag("starts_with")),
490        value(Binary::Suffix, tag("ends_with")),
491        value(Binary::Regex, tag("matches")),
492        value(Binary::Intersection, tag("intersection")),
493        value(Binary::Union, tag("union")),
494    ))(i)
495}
496
497/// Innermost parser for an expression: either a parenthesised expression,
498/// or a single term.
499fn expr_term(i: &str) -> IResult<&str, Expr, Error> {
500    alt((unary_parens, reduce(map(term, Expr::Value), " ,\n);")))(i)
501}
502
503fn fold_exprs(initial: Expr, remainder: Vec<(builder::Binary, Expr)>) -> Expr {
504    remainder.into_iter().fold(initial, |acc, pair| {
505        let (op, expr) = pair;
506        Expr::Binary(builder::Op::Binary(op), Box::new(acc), Box::new(expr))
507    })
508}
509
510/// Top-lever parser for an expression. Expression parsers are layered in
511/// order to support operator precedence (see https://en.wikipedia.org/wiki/Operator-precedence_parser).
512///
513/// See https://github.com/biscuit-auth/biscuit/blob/master/SPECIFICATIONS.md#grammar
514/// for the precedence order of operators in biscuit datalog.
515///
516/// The operators with the lowest precedence are parsed at the outer level,
517/// and their operands delegate to parsers that progressively handle more
518/// tightly binding operators.
519///
520/// This level handles the last operator in the precedence list: `||`
521/// `||` is left associative, so multiple `||` expressions can be combined:
522/// `a || b || c <=> (a || b) || c`
523pub fn expr(i: &str) -> IResult<&str, Expr, Error> {
524    let (i, initial) = expr1(i)?;
525
526    let (i, remainder) = many0(tuple((preceded(space0, binary_op_0), expr1)))(i)?;
527
528    Ok((i, fold_exprs(initial, remainder)))
529}
530
531/// This level handles `&&`
532/// `&&` is left associative, so multiple `&&` expressions can be combined:
533/// `a && b && c <=> (a && b) && c`
534fn expr1(i: &str) -> IResult<&str, Expr, Error> {
535    let (i, initial) = expr2(i)?;
536
537    let (i, remainder) = many0(tuple((preceded(space0, binary_op_1), expr2)))(i)?;
538
539    Ok((i, fold_exprs(initial, remainder)))
540}
541
542/// This level handles comparison operators (`==`, `>`, `>=`, `<`, `<=`).
543/// Those operators are _not_ associative and require explicit grouping
544/// with parentheses.
545fn expr2(i: &str) -> IResult<&str, Expr, Error> {
546    let (i, initial) = expr3(i)?;
547
548    if let Ok((i, (op, remainder))) = tuple((preceded(space0, binary_op_2), expr3))(i) {
549        Ok((
550            i,
551            Expr::Binary(
552                builder::Op::Binary(op),
553                Box::new(initial),
554                Box::new(remainder),
555            ),
556        ))
557    } else {
558        Ok((i, initial))
559    }
560}
561
562/// This level handles `|`.
563/// It is left associative, so multiple expressions can be combined:
564/// `a | b | c <=> (a | b) | c`
565fn expr3(i: &str) -> IResult<&str, Expr, Error> {
566    let (i, initial) = expr4(i)?;
567
568    let (i, remainder) = many0(tuple((preceded(space0, binary_op_3), expr4)))(i)?;
569
570    Ok((i, fold_exprs(initial, remainder)))
571}
572
573/// This level handles `^`.
574/// It is left associative, so multiple expressions can be combined:
575/// `a ^ b ^ c <=> (a ^ b) ^ c`
576fn expr4(i: &str) -> IResult<&str, Expr, Error> {
577    let (i, initial) = expr5(i)?;
578
579    let (i, remainder) = many0(tuple((preceded(space0, binary_op_4), expr5)))(i)?;
580
581    Ok((i, fold_exprs(initial, remainder)))
582}
583
584/// This level handles `&`.
585/// It is left associative, so multiple expressions can be combined:
586/// `a & b & c <=> (a & b) & c`
587fn expr5(i: &str) -> IResult<&str, Expr, Error> {
588    let (i, initial) = expr6(i)?;
589
590    let (i, remainder) = many0(tuple((preceded(space0, binary_op_5), expr6)))(i)?;
591
592    Ok((i, fold_exprs(initial, remainder)))
593}
594
595/// This level handles `+` and `-`.
596/// They are left associative, so multiple expressions can be combined:
597/// `a + b - c <=> (a + b) - c`
598fn expr6(i: &str) -> IResult<&str, Expr, Error> {
599    let (i, initial) = expr7(i)?;
600
601    let (i, remainder) = many0(tuple((preceded(space0, binary_op_6), expr7)))(i)?;
602
603    Ok((i, fold_exprs(initial, remainder)))
604}
605
606/// This level handles `*` and `/`.
607/// They are left associative, so multiple expressions can be combined:
608/// `a * b / c <=> (a * b) / c`
609fn expr7(i: &str) -> IResult<&str, Expr, Error> {
610    let (i, initial) = expr8(i)?;
611
612    let (i, remainder) = many0(tuple((preceded(space0, binary_op_7), expr8)))(i)?;
613
614    Ok((i, fold_exprs(initial, remainder)))
615}
616
617/// This level handles `!` (prefix negation)
618fn expr8(i: &str) -> IResult<&str, Expr, Error> {
619    alt((unary_negate, expr9))(i)
620}
621
622/// This level handles methods. Methods can take either zero or one
623/// argument in addition to the expression they are called on.
624/// The name of the method decides its arity.
625fn expr9(i: &str) -> IResult<&str, Expr, Error> {
626    let (mut input, mut initial) = expr_term(i)?;
627
628    loop {
629        if let Ok((i, _)) = char::<_, ()>('.')(input) {
630            let bin_result = binary_method(i);
631            let un_result = unary_method(i);
632            match (bin_result, un_result) {
633                (Ok((i, (op, arg))), _) => {
634                    input = i;
635                    initial =
636                        Expr::Binary(builder::Op::Binary(op), Box::new(initial), Box::new(arg));
637                }
638                (_, Ok((i, op))) => {
639                    input = i;
640
641                    initial = Expr::Unary(builder::Op::Unary(op), Box::new(initial));
642                }
643                (_, Err(e)) => return Err(e),
644            }
645        } else {
646            return Ok((input, initial));
647        }
648    }
649}
650
651fn binary_method(i: &str) -> IResult<&str, (builder::Binary, Expr), Error> {
652    let (i, op) = binary_op_8(i)?;
653
654    let (i, _) = char('(')(i)?;
655    let (i, _) = space0(i)?;
656    // we only support a single argument for now
657    let (i, arg) = expr(i)?;
658    let (i, _) = space0(i)?;
659    let (i, _) = char(')')(i)?;
660
661    Ok((i, (op, arg)))
662}
663
664fn unary_method(i: &str) -> IResult<&str, builder::Unary, Error> {
665    use builder::Unary;
666    let (i, op) = value(Unary::Length, tag("length"))(i)?;
667
668    let (i, _) = char('(')(i)?;
669    let (i, _) = space0(i)?;
670    let (i, _) = char(')')(i)?;
671
672    Ok((i, op))
673}
674
675fn name(i: &str) -> IResult<&str, &str, Error> {
676    let is_name_char = |c: char| is_alphanumeric(c as u8) || c == '_' || c == ':';
677
678    reduce(take_while1(is_name_char), " ,:(\n;")(i)
679}
680
681fn printable(i: &str) -> IResult<&str, &str, Error> {
682    take_while1(|c: char| c != '\\' && c != '"')(i)
683}
684
685fn parse_string_internal(i: &str) -> IResult<&str, String, Error> {
686    escaped_transform(
687        printable,
688        '\\',
689        alt((
690            map(char('\\'), |_| "\\"),
691            map(char('"'), |_| "\""),
692            map(char('n'), |_| "\n"),
693        )),
694    )(i)
695}
696
697fn parse_string(i: &str) -> IResult<&str, String, Error> {
698    alt((
699        value("".to_string(), tag("\"\"")),
700        delimited(char('"'), parse_string_internal, char('"')),
701    ))(i)
702}
703
704fn string(i: &str) -> IResult<&str, builder::Term, Error> {
705    parse_string(i).map(|(i, s)| (i, builder::Term::Str(s)))
706}
707
708fn parse_integer(i: &str) -> IResult<&str, i64, Error> {
709    map_res(recognize(pair(opt(char('-')), digit1)), |s: &str| s.parse())(i)
710}
711
712fn integer(i: &str) -> IResult<&str, builder::Term, Error> {
713    parse_integer(i).map(|(i, n)| (i, builder::int(n)))
714}
715
716fn parse_date(i: &str) -> IResult<&str, u64, Error> {
717    map_res(
718        map_res(
719            take_while1(|c: char| c != ',' && c != ' ' && c != ')' && c != ']' && c != ';'),
720            |s| time::OffsetDateTime::parse(s, &time::format_description::well_known::Rfc3339),
721        ),
722        |t| t.unix_timestamp().try_into(),
723    )(i)
724}
725
726fn date(i: &str) -> IResult<&str, builder::Term, Error> {
727    parse_date(i).map(|(i, t)| (i, builder::Term::Date(t)))
728}
729
730fn parse_bytes(i: &str) -> IResult<&str, Vec<u8>, Error> {
731    preceded(tag("hex:"), parse_hex)(i)
732}
733
734fn parse_hex(i: &str) -> IResult<&str, Vec<u8>, Error> {
735    map_res(
736        take_while1(|c| {
737            let c = c as u8;
738            (b'0'..=b'9').contains(&c) || (b'a'..=b'f').contains(&c) || (b'A'..=b'F').contains(&c)
739        }),
740        hex::decode,
741    )(i)
742}
743
744fn bytes(i: &str) -> IResult<&str, builder::Term, Error> {
745    parse_bytes(i).map(|(i, s)| (i, builder::Term::Bytes(s)))
746}
747
748fn variable(i: &str) -> IResult<&str, builder::Term, Error> {
749    map(preceded(char('$'), name), builder::variable)(i)
750}
751
752fn parameter(i: &str) -> IResult<&str, builder::Term, Error> {
753    map(delimited(char('{'), name, char('}')), builder::parameter)(i)
754}
755
756fn parse_bool(i: &str) -> IResult<&str, bool, Error> {
757    alt((value(true, tag("true")), value(false, tag("false"))))(i)
758}
759
760fn boolean(i: &str) -> IResult<&str, builder::Term, Error> {
761    parse_bool(i).map(|(i, b)| (i, builder::boolean(b)))
762}
763
764fn set(i: &str) -> IResult<&str, builder::Term, Error> {
765    //println!("set:\t{}", i);
766    let (i, _) = preceded(space0, char('['))(i)?;
767    let (i, mut list) = cut(separated_list0(preceded(space0, char(',')), term_in_set))(i)?;
768
769    let mut set = BTreeSet::new();
770
771    let mut kind: Option<u8> = None;
772    for term in list.drain(..) {
773        let index = match term {
774            builder::Term::Variable(_) => {
775                return Err(nom::Err::Failure(Error {
776                    input: i,
777                    code: ErrorKind::Fail,
778                    message: Some("variables are not permitted in sets".to_string()),
779                }))
780            }
781            builder::Term::Integer(_) => 2,
782            builder::Term::Str(_) => 3,
783            builder::Term::Date(_) => 4,
784            builder::Term::Bytes(_) => 5,
785            builder::Term::Bool(_) => 6,
786            builder::Term::Set(_) => {
787                return Err(nom::Err::Failure(Error {
788                    input: i,
789                    code: ErrorKind::Fail,
790                    message: Some("sets cannot contain other sets".to_string()),
791                }))
792            }
793            builder::Term::Parameter(_) => 7,
794        };
795
796        if let Some(k) = kind {
797            if k != index {
798                return Err(nom::Err::Failure(Error {
799                    input: i,
800                    code: ErrorKind::Fail,
801                    message: Some("set elements must have the same type".to_string()),
802                }));
803            }
804        } else {
805            kind = Some(index);
806        }
807
808        set.insert(term);
809    }
810
811    let (i, _) = preceded(space0, char(']'))(i)?;
812
813    Ok((i, builder::set(set)))
814}
815
816fn term(i: &str) -> IResult<&str, builder::Term, Error> {
817    preceded(
818        space0,
819        alt((
820            parameter, string, date, variable, integer, bytes, boolean, set,
821        )),
822    )(i)
823}
824
825fn term_in_fact(i: &str) -> IResult<&str, builder::Term, Error> {
826    preceded(
827        space0,
828        error(
829            alt((parameter, string, date, integer, bytes, boolean, set)),
830            |input| match input.chars().next() {
831                None | Some(',') | Some(')') => "missing term".to_string(),
832                Some('$') => "variables are not allowed in facts".to_string(),
833                _ => "expected a valid term".to_string(),
834            },
835            " ,)\n;",
836        ),
837    )(i)
838}
839
840fn term_in_set(i: &str) -> IResult<&str, builder::Term, Error> {
841    preceded(
842        space0,
843        error(
844            alt((parameter, string, date, integer, bytes, boolean)),
845            |input| match input.chars().next() {
846                None | Some(',') | Some(']') => "missing term".to_string(),
847                Some('$') => "variables are not allowed in sets".to_string(),
848                _ => "expected a valid term".to_string(),
849            },
850            " ,]\n;",
851        ),
852    )(i)
853}
854
855fn line_comment(i: &str) -> IResult<&str, (), Error> {
856    let (i, _) = space0(i)?;
857    let (i, _) = tag("//")(i)?;
858    let (i, _) = take_while(|c| c != '\r' && c != '\n')(i)?;
859    let (i, _) = alt((tag("\n"), tag("\r\n"), eof))(i)?;
860
861    Ok((i, ()))
862}
863
864fn multiline_comment(i: &str) -> IResult<&str, (), Error> {
865    let (i, _) = space0(i)?;
866    let (i, _) = tag("/*")(i)?;
867    let (i, _) = take_until("*/")(i)?;
868    let (i, _) = tag("*/")(i)?;
869
870    Ok((i, ()))
871}
872
873#[derive(Clone, Debug, PartialEq, Default)]
874pub struct SourceResult<'a> {
875    pub scopes: Vec<builder::Scope>,
876    pub facts: Vec<(&'a str, builder::Fact)>,
877    pub rules: Vec<(&'a str, builder::Rule)>,
878    pub checks: Vec<(&'a str, builder::Check)>,
879    pub policies: Vec<(&'a str, builder::Policy)>,
880}
881
882enum SourceElement<'a> {
883    Fact(&'a str, builder::Fact),
884    Rule(&'a str, builder::Rule),
885    Check(&'a str, builder::Check),
886    Policy(&'a str, builder::Policy),
887    Comment,
888}
889
890pub fn sep(i: &str) -> IResult<&str, &str, Error> {
891    let (i, _) = space0(i)?;
892    alt((tag(";"), eof))(i)
893}
894
895pub fn parse_source(mut i: &str) -> Result<SourceResult, Vec<Error>> {
896    let mut result = SourceResult::default();
897    let mut errors = Vec::new();
898
899    loop {
900        if i.is_empty() {
901            if errors.is_empty() {
902                return Ok(result);
903            } else {
904                return Err(errors);
905            }
906        }
907
908        match terminated(
909            alt((
910                map(terminated(consumed(rule_inner), sep), |(i, r)| {
911                    SourceElement::Rule(i, r)
912                }),
913                map(terminated(consumed(fact_inner), sep), |(i, f)| {
914                    SourceElement::Fact(i, f)
915                }),
916                map(terminated(consumed(check_inner), sep), |(i, c)| {
917                    SourceElement::Check(i, c)
918                }),
919                map(terminated(consumed(policy_inner), sep), |(i, p)| {
920                    SourceElement::Policy(i, p)
921                }),
922                map(line_comment, |_| SourceElement::Comment),
923                map(multiline_comment, |_| SourceElement::Comment),
924            )),
925            space0,
926        )(i)
927        {
928            Ok((i2, o)) => {
929                match o {
930                    SourceElement::Fact(i, f) => result.facts.push((i, f)),
931                    SourceElement::Rule(i, r) => result.rules.push((i, r)),
932                    SourceElement::Check(i, c) => result.checks.push((i, c)),
933                    SourceElement::Policy(i, p) => result.policies.push((i, p)),
934                    SourceElement::Comment => {}
935                }
936
937                i = i2;
938            }
939            Err(nom::Err::Incomplete(_)) => panic!(),
940            Err(nom::Err::Error(mut e)) => {
941                if let Some(index) = e.input.find(|c| c == ';') {
942                    e.input = &(e.input)[..index];
943                }
944
945                let offset = i.offset(e.input);
946                if let Some(index) = &i[offset..].find(|c| c == ';') {
947                    i = &i[offset + index + 1..];
948                } else {
949                    i = &i[i.len()..];
950                }
951
952                errors.push(e);
953            }
954            Err(nom::Err::Failure(mut e)) => {
955                if let Some(index) = e.input.find(|c| c == ';') {
956                    e.input = &(e.input)[..index];
957                }
958
959                let offset = i.offset(e.input);
960                if let Some(index) = &i[offset..].find(|c| c == ';') {
961                    i = &i[offset + index + 1..];
962                } else {
963                    i = &i[i.len()..];
964                }
965
966                errors.push(e);
967            }
968        }
969    }
970}
971
972pub fn parse_block_source(mut i: &str) -> Result<SourceResult, Vec<Error>> {
973    let mut result = SourceResult::default();
974    let mut errors = Vec::new();
975
976    match opt(terminated(consumed(scopes), sep))(i) {
977        Ok((i2, opt_scopes)) => {
978            if let Some((_, scopes)) = opt_scopes {
979                i = i2;
980                result.scopes = scopes;
981            }
982        }
983        Err(nom::Err::Incomplete(_)) => panic!(),
984        Err(nom::Err::Error(mut e)) => {
985            if let Some(index) = e.input.find(|c| c == ';') {
986                e.input = &(e.input)[..index];
987            }
988
989            let offset = i.offset(e.input);
990            if let Some(index) = &i[offset..].find(|c| c == ';') {
991                i = &i[offset + index + 1..];
992            } else {
993                i = &i[i.len()..];
994            }
995
996            errors.push(e);
997        }
998        Err(nom::Err::Failure(mut e)) => {
999            if let Some(index) = e.input.find(|c| c == ';') {
1000                e.input = &(e.input)[..index];
1001            }
1002
1003            let offset = i.offset(e.input);
1004            if let Some(index) = &i[offset..].find(|c| c == ';') {
1005                i = &i[offset + index + 1..];
1006            } else {
1007                i = &i[i.len()..];
1008            }
1009
1010            errors.push(e);
1011        }
1012    }
1013
1014    loop {
1015        if i.is_empty() {
1016            if errors.is_empty() {
1017                return Ok(result);
1018            } else {
1019                return Err(errors);
1020            }
1021        }
1022
1023        match terminated(
1024            alt((
1025                map(terminated(consumed(rule_inner), sep), |(i, r)| {
1026                    SourceElement::Rule(i, r)
1027                }),
1028                map(terminated(consumed(fact_inner), sep), |(i, f)| {
1029                    SourceElement::Fact(i, f)
1030                }),
1031                map(terminated(consumed(check_inner), sep), |(i, c)| {
1032                    SourceElement::Check(i, c)
1033                }),
1034                map(line_comment, |_| SourceElement::Comment),
1035                map(multiline_comment, |_| SourceElement::Comment),
1036            )),
1037            space0,
1038        )(i)
1039        {
1040            Ok((i2, o)) => {
1041                match o {
1042                    SourceElement::Fact(i, f) => result.facts.push((i, f)),
1043                    SourceElement::Rule(i, r) => result.rules.push((i, r)),
1044                    SourceElement::Check(i, c) => result.checks.push((i, c)),
1045                    SourceElement::Policy(_, _) => {}
1046                    SourceElement::Comment => {}
1047                }
1048
1049                i = i2;
1050            }
1051            Err(nom::Err::Incomplete(_)) => panic!(),
1052            Err(nom::Err::Error(mut e)) => {
1053                if let Some(index) = e.input.find(|c| c == ';') {
1054                    e.input = &(e.input)[..index];
1055                }
1056
1057                let offset = i.offset(e.input);
1058                if let Some(index) = &i[offset..].find(|c| c == ';') {
1059                    i = &i[offset + index + 1..];
1060                } else {
1061                    i = &i[i.len()..];
1062                }
1063
1064                errors.push(e);
1065            }
1066            Err(nom::Err::Failure(mut e)) => {
1067                if let Some(index) = e.input.find(|c| c == ';') {
1068                    e.input = &(e.input)[..index];
1069                }
1070
1071                let offset = i.offset(e.input);
1072                if let Some(index) = &i[offset..].find(|c| c == ';') {
1073                    i = &i[offset + index + 1..];
1074                } else {
1075                    i = &i[i.len()..];
1076                }
1077
1078                errors.push(e);
1079            }
1080        }
1081    }
1082}
1083
1084#[derive(Error, Debug, PartialEq, Eq)]
1085#[error("Parse error on input: {input}. Message: {message:?}")]
1086pub struct Error<'a> {
1087    pub input: &'a str,
1088    pub code: ErrorKind,
1089    pub message: Option<String>,
1090}
1091
1092impl<'a> ParseError<&'a str> for Error<'a> {
1093    fn from_error_kind(input: &'a str, kind: ErrorKind) -> Self {
1094        Self {
1095            input,
1096            code: kind,
1097            message: None,
1098        }
1099    }
1100
1101    fn append(_: &'a str, _: ErrorKind, other: Self) -> Self {
1102        other
1103    }
1104}
1105
1106//FIXME: properly handle other errors
1107impl<'a, E> FromExternalError<&'a str, E> for Error<'a> {
1108    fn from_external_error(input: &'a str, kind: ErrorKind, _e: E) -> Self {
1109        Self {
1110            input,
1111            code: kind,
1112            message: None,
1113        }
1114    }
1115}
1116
1117fn error<'a, F, O, P>(
1118    mut parser: P,
1119    context: F,
1120    reducer: &'static str,
1121) -> impl FnMut(&'a str) -> IResult<&'a str, O, Error<'a>>
1122where
1123    P: nom::Parser<&'a str, O, Error<'a>>,
1124    F: Fn(&'a str) -> String,
1125{
1126    move |i: &str| match parser.parse(i) {
1127        Ok(res) => Ok(res),
1128        Err(nom::Err::Incomplete(i)) => Err(nom::Err::Incomplete(i)),
1129        Err(nom::Err::Error(mut e)) => {
1130            if let Some(index) = e.input.find(|c| reducer.contains(c)) {
1131                e.input = &(e.input)[..index];
1132            }
1133
1134            if e.message.is_none() {
1135                e.message = Some(context(e.input));
1136            }
1137
1138            Err(nom::Err::Error(e))
1139        }
1140        Err(nom::Err::Failure(mut e)) => {
1141            if let Some(index) = e.input.find(|c| reducer.contains(c)) {
1142                e.input = &(e.input)[..index];
1143            }
1144
1145            if e.message.is_none() {
1146                e.message = Some(context(e.input));
1147            }
1148
1149            Err(nom::Err::Failure(e))
1150        }
1151    }
1152}
1153
1154fn reduce<'a, O, P>(
1155    mut parser: P,
1156    reducer: &'static str,
1157) -> impl FnMut(&'a str) -> IResult<&'a str, O, Error<'a>>
1158where
1159    P: nom::Parser<&'a str, O, Error<'a>>,
1160{
1161    move |i: &str| match parser.parse(i) {
1162        Ok(res) => Ok(res),
1163        Err(nom::Err::Incomplete(i)) => Err(nom::Err::Incomplete(i)),
1164        Err(nom::Err::Error(mut e)) => {
1165            if let Some(index) = e.input.find(|c| reducer.contains(c)) {
1166                e.input = &(e.input)[..index];
1167            }
1168
1169            Err(nom::Err::Error(e))
1170        }
1171        Err(nom::Err::Failure(mut e)) => {
1172            if let Some(index) = e.input.find(|c| reducer.contains(c)) {
1173                e.input = &(e.input)[..index];
1174            }
1175
1176            Err(nom::Err::Failure(e))
1177        }
1178    }
1179}
1180
1181#[cfg(test)]
1182mod tests {
1183    use crate::builder::{self, Unary};
1184
1185    #[test]
1186    fn name() {
1187        assert_eq!(
1188            super::name("operation(\"read\")"),
1189            Ok(("(\"read\")", "operation"))
1190        );
1191    }
1192
1193    #[test]
1194    fn string() {
1195        assert_eq!(
1196            super::string("\"file1 a hello - 123_\""),
1197            Ok(("", builder::string("file1 a hello - 123_")))
1198        );
1199    }
1200
1201    #[test]
1202    fn empty_string() {
1203        assert_eq!(super::string("\"\""), Ok(("", builder::string(""))));
1204    }
1205
1206    #[test]
1207    fn integer() {
1208        assert_eq!(super::integer("123"), Ok(("", builder::int(123))));
1209        assert_eq!(super::integer("-42"), Ok(("", builder::int(-42))));
1210    }
1211
1212    #[test]
1213    fn date() {
1214        assert_eq!(
1215            super::date("2019-12-02T13:49:53Z"),
1216            Ok(("", builder::Term::Date(1575294593)))
1217        );
1218    }
1219
1220    #[test]
1221    fn variable() {
1222        assert_eq!(super::variable("$1"), Ok(("", builder::variable("1"))));
1223    }
1224
1225    #[test]
1226    fn parameter() {
1227        assert_eq!(
1228            super::parameter("{param}"),
1229            Ok(("", builder::parameter("param")))
1230        );
1231    }
1232
1233    #[test]
1234    fn constraint() {
1235        use builder::{boolean, date, int, set, string, var, Binary, Op, Unary};
1236        use std::collections::BTreeSet;
1237        use std::time::{Duration, SystemTime};
1238
1239        assert_eq!(
1240            super::expr("$0 <= 2030-12-31T12:59:59+00:00").map(|(i, o)| (i, o.opcodes())),
1241            Ok((
1242                "",
1243                vec![
1244                    Op::Value(var("0")),
1245                    Op::Value(date(
1246                        &(SystemTime::UNIX_EPOCH + Duration::from_secs(1924952399))
1247                    )),
1248                    Op::Binary(Binary::LessOrEqual),
1249                ],
1250            ))
1251        );
1252
1253        assert_eq!(
1254            super::expr("$0 >= 2030-12-31T12:59:59+00:00").map(|(i, o)| (i, o.opcodes())),
1255            Ok((
1256                "",
1257                vec![
1258                    Op::Value(var("0")),
1259                    Op::Value(date(
1260                        &(SystemTime::UNIX_EPOCH + Duration::from_secs(1924952399))
1261                    )),
1262                    Op::Binary(Binary::GreaterOrEqual),
1263                ],
1264            ))
1265        );
1266
1267        assert_eq!(
1268            super::expr("$0 < 1234").map(|(i, o)| (i, o.opcodes())),
1269            Ok((
1270                "",
1271                vec![
1272                    Op::Value(var("0")),
1273                    Op::Value(int(1234)),
1274                    Op::Binary(Binary::LessThan),
1275                ],
1276            ))
1277        );
1278
1279        assert_eq!(
1280            super::expr("$0 > 1234").map(|(i, o)| (i, o.opcodes())),
1281            Ok((
1282                "",
1283                vec![
1284                    Op::Value(var("0")),
1285                    Op::Value(int(1234)),
1286                    Op::Binary(Binary::GreaterThan),
1287                ],
1288            ))
1289        );
1290
1291        assert_eq!(
1292            super::expr("$0 <= 1234").map(|(i, o)| (i, o.opcodes())),
1293            Ok((
1294                "",
1295                vec![
1296                    Op::Value(var("0")),
1297                    Op::Value(int(1234)),
1298                    Op::Binary(Binary::LessOrEqual),
1299                ],
1300            ))
1301        );
1302
1303        assert_eq!(
1304            super::expr("$0 >= -1234").map(|(i, o)| (i, o.opcodes())),
1305            Ok((
1306                "",
1307                vec![
1308                    Op::Value(var("0")),
1309                    Op::Value(int(-1234)),
1310                    Op::Binary(Binary::GreaterOrEqual),
1311                ],
1312            ))
1313        );
1314
1315        assert_eq!(
1316            super::expr("$0 == 1").map(|(i, o)| (i, o.opcodes())),
1317            Ok((
1318                "",
1319                vec![
1320                    Op::Value(var("0")),
1321                    Op::Value(int(1)),
1322                    Op::Binary(Binary::Equal),
1323                ],
1324            ))
1325        );
1326
1327        assert_eq!(
1328            super::expr("$0.length() == $1").map(|(i, o)| (i, o.opcodes())),
1329            Ok((
1330                "",
1331                vec![
1332                    Op::Value(var("0")),
1333                    Op::Unary(Unary::Length),
1334                    Op::Value(var("1")),
1335                    Op::Binary(Binary::Equal),
1336                ],
1337            ))
1338        );
1339
1340        assert_eq!(
1341            super::expr("!$0 == $1").map(|(i, o)| (i, o.opcodes())),
1342            Ok((
1343                "",
1344                vec![
1345                    Op::Value(var("0")),
1346                    Op::Unary(Unary::Negate),
1347                    Op::Value(var("1")),
1348                    Op::Binary(Binary::Equal),
1349                ],
1350            ))
1351        );
1352
1353        assert_eq!(
1354            super::expr("!false && true").map(|(i, o)| (i, o.opcodes())),
1355            Ok((
1356                "",
1357                vec![
1358                    Op::Value(boolean(false)),
1359                    Op::Unary(Unary::Negate),
1360                    Op::Value(boolean(true)),
1361                    Op::Binary(Binary::And),
1362                ],
1363            ))
1364        );
1365
1366        assert_eq!(
1367            super::expr("true || true && true").map(|(i, o)| (i, o.opcodes())),
1368            Ok((
1369                "",
1370                vec![
1371                    Op::Value(boolean(true)),
1372                    Op::Value(boolean(true)),
1373                    Op::Value(boolean(true)),
1374                    Op::Binary(Binary::And),
1375                    Op::Binary(Binary::Or),
1376                ],
1377            ))
1378        );
1379
1380        assert_eq!(
1381            super::expr("(1 > 2) == 3").map(|(i, o)| (i, o.opcodes())),
1382            Ok((
1383                "",
1384                vec![
1385                    Op::Value(int(1)),
1386                    Op::Value(int(2)),
1387                    Op::Binary(Binary::GreaterThan),
1388                    Op::Unary(Unary::Parens),
1389                    Op::Value(int(3)),
1390                    Op::Binary(Binary::Equal),
1391                ]
1392            ))
1393        );
1394
1395        assert_eq!(
1396            super::expr("1 > 2 + 3").map(|(i, o)| (i, o.opcodes())),
1397            Ok((
1398                "",
1399                vec![
1400                    Op::Value(int(1)),
1401                    Op::Value(int(2)),
1402                    Op::Value(int(3)),
1403                    Op::Binary(Binary::Add),
1404                    Op::Binary(Binary::GreaterThan),
1405                ]
1406            ))
1407        );
1408
1409        assert_eq!(
1410            super::expr("1 > 2 == 3").map(|(i, o)| (i, o.opcodes())),
1411            Ok((
1412                " == 3",
1413                vec![
1414                    Op::Value(int(1)),
1415                    Op::Value(int(2)),
1416                    Op::Binary(Binary::GreaterThan),
1417                ]
1418            ))
1419        );
1420
1421        let h = [int(1), int(2)].iter().cloned().collect::<BTreeSet<_>>();
1422        assert_eq!(
1423            super::expr("[1, 2].contains($0)").map(|(i, o)| (i, o.opcodes())),
1424            Ok((
1425                "",
1426                vec![
1427                    Op::Value(set(h.clone())),
1428                    Op::Value(var("0")),
1429                    Op::Binary(Binary::Contains),
1430                ],
1431            ))
1432        );
1433
1434        assert_eq!(
1435            super::expr("![1, 2].contains($0)").map(|(i, o)| (i, o.opcodes())),
1436            Ok((
1437                "",
1438                vec![
1439                    Op::Value(set(h)),
1440                    Op::Value(var("0")),
1441                    Op::Binary(Binary::Contains),
1442                    Op::Unary(Unary::Negate),
1443                ],
1444            ))
1445        );
1446
1447        assert_eq!(
1448            super::expr("$0 == \"abc\"").map(|(i, o)| (i, o.opcodes())),
1449            Ok((
1450                "",
1451                vec![
1452                    Op::Value(var("0")),
1453                    Op::Value(string("abc")),
1454                    Op::Binary(Binary::Equal),
1455                ],
1456            ))
1457        );
1458
1459        assert_eq!(
1460            super::expr("$0.ends_with(\"abc\")").map(|(i, o)| (i, o.opcodes())),
1461            Ok((
1462                "",
1463                vec![
1464                    Op::Value(var("0")),
1465                    Op::Value(string("abc")),
1466                    Op::Binary(Binary::Suffix),
1467                ],
1468            ))
1469        );
1470
1471        assert_eq!(
1472            super::expr("$0.starts_with(\"abc\")").map(|(i, o)| (i, o.opcodes())),
1473            Ok((
1474                "",
1475                vec![
1476                    Op::Value(var("0")),
1477                    Op::Value(string("abc")),
1478                    Op::Binary(Binary::Prefix),
1479                ],
1480            ))
1481        );
1482
1483        assert_eq!(
1484            super::expr("$0.matches(\"abc[0-9]+\")").map(|(i, o)| (i, o.opcodes())),
1485            Ok((
1486                "",
1487                vec![
1488                    Op::Value(var("0")),
1489                    Op::Value(string("abc[0-9]+")),
1490                    Op::Binary(Binary::Regex),
1491                ],
1492            ))
1493        );
1494
1495        let h = [string("abc"), string("def")]
1496            .iter()
1497            .cloned()
1498            .collect::<BTreeSet<_>>();
1499        assert_eq!(
1500            super::expr("[\"abc\", \"def\"].contains($0)").map(|(i, o)| (i, o.opcodes())),
1501            Ok((
1502                "",
1503                vec![
1504                    Op::Value(set(h.clone())),
1505                    Op::Value(var("0")),
1506                    Op::Binary(Binary::Contains),
1507                ],
1508            ))
1509        );
1510
1511        assert_eq!(
1512            super::expr("![\"abc\", \"def\"].contains($0)").map(|(i, o)| (i, o.opcodes())),
1513            Ok((
1514                "",
1515                vec![
1516                    Op::Value(set(h.clone())),
1517                    Op::Value(var("0")),
1518                    Op::Binary(Binary::Contains),
1519                    Op::Unary(Unary::Negate),
1520                ],
1521            ))
1522        );
1523
1524        let h = [string("abc"), string("def")]
1525            .iter()
1526            .cloned()
1527            .collect::<BTreeSet<_>>();
1528        assert_eq!(
1529            super::expr("[\"abc\", \"def\"].contains($0)").map(|(i, o)| (i, o.opcodes())),
1530            Ok((
1531                "",
1532                vec![
1533                    Op::Value(set(h.clone())),
1534                    Op::Value(var("0")),
1535                    Op::Binary(Binary::Contains),
1536                ],
1537            ))
1538        );
1539
1540        assert_eq!(
1541            super::expr("![\"abc\", \"def\"].contains($0)").map(|(i, o)| (i, o.opcodes())),
1542            Ok((
1543                "",
1544                vec![
1545                    Op::Value(set(h.clone())),
1546                    Op::Value(var("0")),
1547                    Op::Binary(Binary::Contains),
1548                    Op::Unary(Unary::Negate),
1549                ],
1550            ))
1551        );
1552
1553        assert_eq!(
1554            super::expr("1 + 2 | 4 * 3 & 4").map(|(i, o)| (i, o.opcodes())),
1555            Ok((
1556                "",
1557                vec![
1558                    Op::Value(int(1)),
1559                    Op::Value(int(2)),
1560                    Op::Binary(Binary::Add),
1561                    Op::Value(int(4)),
1562                    Op::Value(int(3)),
1563                    Op::Binary(Binary::Mul),
1564                    Op::Value(int(4)),
1565                    Op::Binary(Binary::BitwiseAnd),
1566                    Op::Binary(Binary::BitwiseOr),
1567                ],
1568            ))
1569        );
1570    }
1571
1572    #[test]
1573    fn fact() {
1574        assert_eq!(
1575            super::fact("right( \"file1\", \"read\" )"),
1576            Ok((
1577                "",
1578                builder::fact(
1579                    "right",
1580                    &[builder::string("file1"), builder::string("read")]
1581                )
1582            ))
1583        );
1584    }
1585
1586    #[test]
1587    fn fact_with_variable() {
1588        use nom::error::ErrorKind;
1589        assert_eq!(
1590            super::fact("right( \"file1\", $operation )"),
1591            Err(nom::Err::Failure(super::Error {
1592                code: ErrorKind::Char,
1593                input: "$operation",
1594                message: Some("variables are not allowed in facts".to_string()),
1595            }))
1596        );
1597    }
1598
1599    #[test]
1600    fn fact_with_date() {
1601        assert_eq!(
1602            super::fact("date(2019-12-02T13:49:53Z)"),
1603            Ok((
1604                "",
1605                builder::fact("date", &[builder::Term::Date(1575294593)])
1606            ))
1607        );
1608    }
1609    /*
1610    #[test]
1611    fn rule() {
1612        assert_eq!(
1613            super::rule("right($0, \"read\") <- resource( $0), operation(\"read\")"),
1614            Ok((
1615                "",
1616                builder::rule(
1617                    "right",
1618                    &[builder::variable("0"), builder::string("read"),],
1619                    &[
1620                        builder::pred("resource", &[builder::variable("0")]),
1621                        builder::pred("operation", &[builder::string("read")]),
1622                    ]
1623                )
1624            ))
1625        );
1626    }
1627
1628    #[test]
1629    fn constrained_rule() {
1630        use builder::{date, var, Binary, Expression, Op};
1631        use std::time::{Duration, SystemTime};
1632
1633        assert_eq!(
1634            super::rule("valid_date(\"file1\") <- time($0 ), resource(\"file1\"), $0 <= 2019-12-04T09:46:41+00:00"),
1635            Ok((
1636                "",
1637                builder::constrained_rule(
1638                    "valid_date",
1639                    &[
1640                        builder::string("file1"),
1641                    ],
1642                    &[
1643                        builder::pred("time", &[builder::variable("0")]),
1644                        builder::pred("resource", &[builder::string("file1")]),
1645                    ],
1646                    &[Expression {
1647                        ops: vec![
1648                            Op::Value(var("0")),
1649                            Op::Value(date(&(SystemTime::UNIX_EPOCH + Duration::from_secs(1575452801)))),
1650                            Op::Binary(Binary::LessOrEqual),
1651                        ]
1652                    }],
1653                )
1654            ))
1655        );
1656    }
1657
1658    #[test]
1659    fn constrained_rule_ordering() {
1660        use builder::{date, var, Binary, Expression, Op};
1661        use std::time::{Duration, SystemTime};
1662
1663        assert_eq!(
1664            super::rule("valid_date(\"file1\") <- time( $0 ), $0 <= 2019-12-04T09:46:41+00:00, resource(\"file1\")"),
1665            Ok((
1666                "",
1667                builder::constrained_rule(
1668                    "valid_date",
1669                    &[
1670                        builder::string("file1"),
1671                    ],
1672                    &[
1673                        builder::pred("time", &[builder::variable("0")]),
1674                        builder::pred("resource", &[builder::string("file1")]),
1675                    ],
1676                    &[Expression {
1677                        ops: vec![
1678                            Op::Value(var("0")),
1679                            Op::Value(date(&(SystemTime::UNIX_EPOCH + Duration::from_secs(1575452801)))),
1680                            Op::Binary(Binary::LessOrEqual),
1681                        ]
1682                    }],
1683                )
1684            ))
1685        );
1686    }
1687
1688    #[test]
1689    fn rule_with_unused_head_variables() {
1690        assert_eq!(
1691            super::rule("right($0, $test) <- resource($0), operation(\"read\")"),
1692            Err( nom::Err::Failure(Error {
1693                input: "right($0, $test)",
1694                code: ErrorKind::Satisfy,
1695                message: Some("rule head contains variables that are not used in predicates of the rule's body: $test".to_string()),
1696            }))
1697        );
1698    }
1699
1700    #[test]
1701    fn check() {
1702        let empty: &[builder::Term] = &[];
1703        assert_eq!(
1704            super::check("check if resource( $0), operation(\"read\") or admin(\"authority\")"),
1705            Ok((
1706                "",
1707                builder::Check {
1708                    queries: vec![
1709                        builder::rule(
1710                            "query",
1711                            empty,
1712                            &[
1713                                builder::pred("resource", &[builder::variable("0")]),
1714                                builder::pred("operation", &[builder::string("read")]),
1715                            ]
1716                        ),
1717                        builder::rule(
1718                            "query",
1719                            empty,
1720                            &[builder::pred("admin", &[builder::string("authority")]),]
1721                        ),
1722                    ]
1723                }
1724            ))
1725        );
1726    }
1727
1728    #[test]
1729    fn invalid_check() {
1730        assert_eq!(
1731            super::check(
1732                "check if resource($0) and operation(\"read\") or admin(\"authority\")"
1733            ),
1734            Err( nom::Err::Error(Error {
1735                input: "and",
1736                code: ErrorKind::Eof,
1737                message: Some("expected either the next term after ',' or the next check variant after 'or', but got 'and'".to_string()),
1738            }))
1739        );
1740
1741        assert_eq!(
1742            super::check("check if resource(\"{}\"), operation(\"write\")) or operation(\"read\")"),
1743            Err(nom::Err::Error(Error {
1744                input: ")",
1745                code: ErrorKind::Eof,
1746                message: Some("unexpected parens".to_string()),
1747            }))
1748        );
1749
1750        assert_eq!(
1751            super::check(
1752                "check if resource(\"{}\") && operation(\"write\")) || operation(\"read\")"
1753            ),
1754            Err( nom::Err::Error(Error {
1755                input: "&&",
1756                code: ErrorKind::Eof,
1757                message: Some("expected either the next term after ',' or the next check variant after 'or', but got '&&'".to_string()),
1758            }))
1759        );
1760    }
1761
1762    #[test]
1763    fn expression() {
1764        use super::Expr;
1765        use crate::datalog::SymbolTable;
1766        use builder::{date, int, string, var, Binary, Op, Term};
1767        use std::time::{Duration, SystemTime};
1768
1769        let mut syms = SymbolTable::new();
1770
1771        let input = " -1 ";
1772        println!("parsing: {}", input);
1773        let res = super::expr(input);
1774        assert_eq!(res, Ok((" ", Expr::Value(Term::Integer(-1)))));
1775
1776        let ops = res.unwrap().1.opcodes();
1777        println!("ops: {:#?}", ops);
1778        let e = builder::Expression { ops }.convert(&mut syms);
1779        println!("print: {}", e.print(&syms).unwrap());
1780
1781        let input = " $0 <= 2019-12-04T09:46:41+00:00";
1782        println!("parsing: {}", input);
1783        let res = super::expr(input);
1784        assert_eq!(
1785            res,
1786            Ok((
1787                "",
1788                Expr::Binary(
1789                    Op::Binary(Binary::LessOrEqual),
1790                    Box::new(Expr::Value(var("0"))),
1791                    Box::new(Expr::Value(date(
1792                        &(SystemTime::UNIX_EPOCH + Duration::from_secs(1575452801))
1793                    )))
1794                )
1795            ))
1796        );
1797
1798        let ops = res.unwrap().1.opcodes();
1799        println!("ops: {:#?}", ops);
1800        let e = builder::Expression { ops }.convert(&mut syms);
1801        println!("print: {}", e.print(&syms).unwrap());
1802
1803        let input = " 1 < $test + 2 ";
1804        println!("parsing: {}", input);
1805        let res = super::expr(input);
1806        assert_eq!(
1807            res,
1808            Ok((
1809                " ",
1810                Expr::Binary(
1811                    Op::Binary(Binary::LessThan),
1812                    Box::new(Expr::Value(int(1))),
1813                    Box::new(Expr::Binary(
1814                        Op::Binary(Binary::Add),
1815                        Box::new(Expr::Value(var("test"))),
1816                        Box::new(Expr::Value(int(2))),
1817                    ))
1818                )
1819            ))
1820        );
1821
1822        let ops = res.unwrap().1.opcodes();
1823        println!("ops: {:#?}", ops);
1824        let e = builder::Expression { ops }.convert(&mut syms);
1825        println!("print: {}", e.print(&syms).unwrap());
1826
1827        let input = " 2 < $test && $var2.starts_with(\"test\") && true ";
1828        println!("parsing: {}", input);
1829        let res = super::expr(input);
1830        assert_eq!(
1831            res,
1832            Ok((
1833                " ",
1834                Expr::Binary(
1835                    Op::Binary(Binary::And),
1836                    Box::new(Expr::Binary(
1837                        Op::Binary(Binary::And),
1838                        Box::new(Expr::Binary(
1839                            Op::Binary(Binary::LessThan),
1840                            Box::new(Expr::Value(int(2))),
1841                            Box::new(Expr::Value(var("test"))),
1842                        )),
1843                        Box::new(Expr::Binary(
1844                            Op::Binary(Binary::Prefix),
1845                            Box::new(Expr::Value(var("var2"))),
1846                            Box::new(Expr::Value(string("test"))),
1847                        )),
1848                    )),
1849                    Box::new(Expr::Value(Term::Bool(true))),
1850                )
1851            ))
1852        );
1853
1854        let ops = res.unwrap().1.opcodes();
1855        println!("ops: {:#?}", ops);
1856        let e = builder::Expression { ops }.convert(&mut syms);
1857        println!("print: {}", e.print(&syms).unwrap());
1858
1859        //panic!();
1860    }
1861
1862    #[test]
1863    fn parens() {
1864        use crate::datalog::{SymbolTable, TemporarySymbolTable};
1865        use builder::{int, Binary, Op, Unary};
1866        use std::collections::HashMap;
1867
1868        let mut syms = SymbolTable::new();
1869
1870        let input = " 1 + 2 * 3 ";
1871        println!("parsing: {}", input);
1872        let (_, res) = super::expr(input).unwrap();
1873
1874        let ops = res.opcodes();
1875        println!("ops: {:#?}", ops);
1876        let e = builder::Expression { ops: ops.clone() }.convert(&mut syms);
1877
1878        let printed = e.print(&syms).unwrap();
1879        println!("print: {}", e.print(&syms).unwrap());
1880        let h = HashMap::new();
1881        let result = e
1882            .evaluate(&h, &mut TemporarySymbolTable::new(&syms))
1883            .unwrap();
1884        println!("evaluates to: {:?}", result);
1885
1886        assert_eq!(
1887            ops,
1888            vec![
1889                Op::Value(int(1)),
1890                Op::Value(int(2)),
1891                Op::Value(int(3)),
1892                Op::Binary(Binary::Mul),
1893                Op::Binary(Binary::Add),
1894            ]
1895        );
1896        assert_eq!(&printed, "1 + 2 * 3");
1897        assert_eq!(result, datalog::Term::Integer(7));
1898
1899        let input = " (1 + 2) * 3 ";
1900        println!("parsing: {}", input);
1901        let (_, res) = super::expr(input).unwrap();
1902
1903        let ops = res.opcodes();
1904        println!("ops: {:#?}", ops);
1905        let e = builder::Expression { ops: ops.clone() }.convert(&mut syms);
1906
1907        let printed = e.print(&syms).unwrap();
1908        println!("print: {}", e.print(&syms).unwrap());
1909        let h = HashMap::new();
1910        let result = e
1911            .evaluate(&h, &mut TemporarySymbolTable::new(&syms))
1912            .unwrap();
1913        println!("evaluates to: {:?}", result);
1914
1915        assert_eq!(
1916            ops,
1917            vec![
1918                Op::Value(int(1)),
1919                Op::Value(int(2)),
1920                Op::Binary(Binary::Add),
1921                Op::Unary(Unary::Parens),
1922                Op::Value(int(3)),
1923                Op::Binary(Binary::Mul),
1924            ]
1925        );
1926        assert_eq!(&printed, "(1 + 2) * 3");
1927        assert_eq!(result, datalog::Term::Integer(9));
1928    }
1929
1930    #[test]
1931    fn source_file() {
1932        use builder::{
1933            boolean, constrained_rule, fact, int, pred, rule, string, var, Binary, Check,
1934            Expression, Op, Policy, PolicyKind,
1935        };
1936        use std::time::{Duration, SystemTime};
1937
1938        let input = r#"
1939          fact("string");
1940          fact2(1234);
1941
1942          rule_head($var0) <- fact($var0, $var1), 1 < 2;
1943
1944          // line comment
1945          check if 1 == 2;
1946
1947          allow if rule_head("string");
1948
1949          /*
1950           other comment
1951          */
1952    check if
1953              fact(5678)
1954              or fact(1234), "test".starts_with("abc");
1955
1956          check if 2021-01-01T00:00:00Z <= 2021-01-01T00:00:00Z;
1957
1958          deny if true;
1959        "#;
1960
1961        let res = super::parse_source(input);
1962        println!("parse_source res:\n{:#?}", res);
1963
1964        let empty_terms: &[builder::Term] = &[];
1965        let empty_preds: &[builder::Predicate] = &[];
1966
1967        let expected_facts = vec![
1968            fact("fact", &[string("string")]),
1969            fact("fact2", &[int(1234)]),
1970        ];
1971
1972        let expected_rules = vec![constrained_rule(
1973            "rule_head",
1974            &[var("var0")],
1975            &[pred("fact", &[var("var0"), var("var1")])],
1976            &[Expression {
1977                ops: vec![
1978                    Op::Value(int(1)),
1979                    Op::Value(int(2)),
1980                    Op::Binary(Binary::LessThan),
1981                ],
1982            }],
1983        )];
1984
1985        let expected_checks = vec![
1986            Check {
1987                queries: vec![constrained_rule(
1988                    "query",
1989                    empty_terms,
1990                    empty_preds,
1991                    &[Expression {
1992                        ops: vec![
1993                            Op::Value(int(1)),
1994                            Op::Value(int(2)),
1995                            Op::Binary(Binary::Equal),
1996                        ],
1997                    }],
1998                )],
1999            },
2000            Check {
2001                queries: vec![
2002                    rule("query", empty_terms, &[pred("fact", &[int(5678)])]),
2003                    constrained_rule(
2004                        "query",
2005                        empty_terms,
2006                        &[pred("fact", &[int(1234)])],
2007                        &[Expression {
2008                            ops: vec![
2009                                Op::Value(string("test")),
2010                                Op::Value(string("abc")),
2011                                Op::Binary(Binary::Prefix),
2012                            ],
2013                        }],
2014                    ),
2015                ],
2016            },
2017            Check {
2018                queries: vec![constrained_rule(
2019                    "query",
2020                    empty_terms,
2021                    empty_preds,
2022                    &[Expression {
2023                        ops: vec![
2024                            Op::Value(builder::date(
2025                                &(SystemTime::UNIX_EPOCH + Duration::from_secs(1609459200)),
2026                            )),
2027                            Op::Value(builder::date(
2028                                &(SystemTime::UNIX_EPOCH + Duration::from_secs(1609459200)),
2029                            )),
2030                            Op::Binary(Binary::LessOrEqual),
2031                        ],
2032                    }],
2033                )],
2034            },
2035        ];
2036
2037        let expected_policies = vec![
2038            Policy {
2039                kind: PolicyKind::Allow,
2040                queries: vec![rule(
2041                    "query",
2042                    empty_terms,
2043                    &[pred("rule_head", &[string("string")])],
2044                )],
2045            },
2046            Policy {
2047                kind: PolicyKind::Deny,
2048                queries: vec![constrained_rule(
2049                    "query",
2050                    empty_terms,
2051                    empty_preds,
2052                    &[Expression {
2053                        ops: vec![Op::Value(boolean(true))],
2054                    }],
2055                )],
2056            },
2057        ];
2058
2059        let mut result = res.unwrap();
2060        assert_eq!(
2061            result.facts.drain(..).map(|(_, r)| r).collect::<Vec<_>>(),
2062            expected_facts
2063        );
2064        assert_eq!(
2065            result.rules.drain(..).map(|(_, r)| r).collect::<Vec<_>>(),
2066            expected_rules
2067        );
2068        assert_eq!(
2069            result.checks.drain(..).map(|(_, r)| r).collect::<Vec<_>>(),
2070            expected_checks
2071        );
2072        assert_eq!(
2073            result
2074                .policies
2075                .drain(..)
2076                .map(|(_, r)| r)
2077                .collect::<Vec<_>>(),
2078            expected_policies
2079        );
2080    }
2081
2082    #[test]
2083    fn block_source_file() {
2084        use builder::{
2085            constrained_rule, fact, int, pred, rule, string, var, Binary, Check, Expression, Op,
2086        };
2087        use std::time::{Duration, SystemTime};
2088
2089        let input = r#"
2090          fact("string");
2091          fact2(1234);
2092
2093    rule_head($var0) <- fact($var0, $var1), 1 < 2; // line comment
2094    check if 1 == 2; /*
2095                      other comment
2096                     */
2097    check if
2098              fact(5678)
2099              or fact(1234), "test".starts_with("abc");
2100
2101          check if 2021-01-01T00:00:00Z <= 2021-01-01T00:00:00Z;
2102        "#;
2103
2104        let res = super::parse_block_source(input);
2105        println!("parse_block_source res:\n{:#?}", res);
2106
2107        let empty_terms: &[builder::Term] = &[];
2108        let empty_preds: &[builder::Predicate] = &[];
2109
2110        let expected_facts = vec![
2111            fact("fact", &[string("string")]),
2112            fact("fact2", &[int(1234)]),
2113        ];
2114
2115        let expected_rules = vec![constrained_rule(
2116            "rule_head",
2117            &[var("var0")],
2118            &[pred("fact", &[var("var0"), var("var1")])],
2119            &[Expression {
2120                ops: vec![
2121                    Op::Value(int(1)),
2122                    Op::Value(int(2)),
2123                    Op::Binary(Binary::LessThan),
2124                ],
2125            }],
2126        )];
2127
2128        let expected_checks = vec![
2129            Check {
2130                queries: vec![constrained_rule(
2131                    "query",
2132                    empty_terms,
2133                    empty_preds,
2134                    &[Expression {
2135                        ops: vec![
2136                            Op::Value(int(1)),
2137                            Op::Value(int(2)),
2138                            Op::Binary(Binary::Equal),
2139                        ],
2140                    }],
2141                )],
2142            },
2143            Check {
2144                queries: vec![
2145                    rule("query", empty_terms, &[pred("fact", &[int(5678)])]),
2146                    constrained_rule(
2147                        "query",
2148                        empty_terms,
2149                        &[pred("fact", &[int(1234)])],
2150                        &[Expression {
2151                            ops: vec![
2152                                Op::Value(string("test")),
2153                                Op::Value(string("abc")),
2154                                Op::Binary(Binary::Prefix),
2155                            ],
2156                        }],
2157                    ),
2158                ],
2159            },
2160            Check {
2161                queries: vec![constrained_rule(
2162                    "query",
2163                    empty_terms,
2164                    empty_preds,
2165                    &[Expression {
2166                        ops: vec![
2167                            Op::Value(builder::date(
2168                                &(SystemTime::UNIX_EPOCH + Duration::from_secs(1609459200)),
2169                            )),
2170                            Op::Value(builder::date(
2171                                &(SystemTime::UNIX_EPOCH + Duration::from_secs(1609459200)),
2172                            )),
2173                            Op::Binary(Binary::LessOrEqual),
2174                        ],
2175                    }],
2176                )],
2177            },
2178        ];
2179
2180        let mut result = res.unwrap();
2181        assert_eq!(
2182            result.facts.drain(..).map(|(_, r)| r).collect::<Vec<_>>(),
2183            expected_facts
2184        );
2185        assert_eq!(
2186            result.rules.drain(..).map(|(_, r)| r).collect::<Vec<_>>(),
2187            expected_rules
2188        );
2189        assert_eq!(
2190            result.checks.drain(..).map(|(_, r)| r).collect::<Vec<_>>(),
2191            expected_checks
2192        );
2193    }*/
2194
2195
2196    #[test]
2197    fn chained_calls() {
2198        use builder::{int, set, Binary, Op};
2199
2200        assert_eq!(
2201            super::expr("[1].intersection([2]).contains(3)").map(|(i, o)| (i, o.opcodes())),
2202            Ok((
2203                "",
2204                vec![
2205                    Op::Value(set([int(1)].into_iter().collect())),
2206                    Op::Value(set([int(2)].into_iter().collect())),
2207                    Op::Binary(Binary::Intersection),
2208                    Op::Value(int(3)),
2209                    Op::Binary(Binary::Contains)
2210                ],
2211            ))
2212        );
2213
2214        assert_eq!(
2215            super::expr("[1].intersection([2]).union([3]).length()").map(|(i, o)| (i, o.opcodes())),
2216            Ok((
2217                "",
2218                vec![
2219                    Op::Value(set([int(1)].into_iter().collect())),
2220                    Op::Value(set([int(2)].into_iter().collect())),
2221                    Op::Binary(Binary::Intersection),
2222                    Op::Value(set([int(3)].into_iter().collect())),
2223                    Op::Binary(Binary::Union),
2224                    Op::Unary(Unary::Length),
2225                ],
2226            ))
2227        );
2228
2229        assert_eq!(
2230            super::expr("[1].intersection([2]).length().union([3])").map(|(i, o)| (i, o.opcodes())),
2231            Ok((
2232                "",
2233                vec![
2234                    Op::Value(set([int(1)].into_iter().collect())),
2235                    Op::Value(set([int(2)].into_iter().collect())),
2236                    Op::Binary(Binary::Intersection),
2237                    Op::Unary(Unary::Length),
2238                    Op::Value(set([int(3)].into_iter().collect())),
2239                    Op::Binary(Binary::Union),
2240                ],
2241            ))
2242        );
2243    }
2244}