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
18pub 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
48pub 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
79pub 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
102pub 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
118pub 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
134pub 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
158pub 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}
197fn 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
310pub 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
497fn 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
510pub 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
531fn 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
542fn 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
562fn 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
573fn 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
584fn 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
595fn 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
606fn 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
617fn expr8(i: &str) -> IResult<&str, Expr, Error> {
619 alt((unary_negate, expr9))(i)
620}
621
622fn 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 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 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
1106impl<'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 #[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}