1use nom::{
2 branch::alt,
3 bytes::complete::tag,
4 combinator::map,
5 sequence::{pair, preceded},
6 IResult,
7};
8
9use super::{
10 array, space,
11 value::{parse_value, Value},
12};
13
14#[derive(Clone, Debug, PartialEq)]
15pub enum Relation {
16 Eq(Value),
17 Gt(Value),
18 Gte(Value),
19 Lt(Value),
20 Lte(Value),
21 In(Vec<Value>),
22}
23#[allow(dead_code)]
24impl Relation {
25 pub fn eq<V: Into<Value>>(x: V) -> Self {
26 Self::Eq(x.into())
27 }
28 pub fn gt<V: Into<Value>>(x: V) -> Self {
29 Self::Gt(x.into())
30 }
31 pub fn gte<V: Into<Value>>(x: V) -> Self {
32 Self::Gte(x.into())
33 }
34 pub fn lt<V: Into<Value>>(x: V) -> Self {
35 Self::Lt(x.into())
36 }
37 pub fn lte<V: Into<Value>>(x: V) -> Self {
38 Self::Lte(x.into())
39 }
40 pub fn in_<V: Into<Value>>(x: Vec<V>) -> Self {
41 Self::In(x.into_iter().map(|x| x.into()).collect())
42 }
43
44 pub fn satisfied_by<V: Into<Value>>(&self, x: V) -> bool {
45 let x: Value = x.into();
46 match self {
47 Self::Eq(v) => *v == x,
48 Self::Gt(v) => x > *v,
49 Self::Gte(v) => x >= *v,
50 Self::Lt(v) => x < *v,
51 Self::Lte(v) => x <= *v,
52 Self::In(v) => v.contains(&x),
53 }
54 }
55}
56
57#[test]
58fn test_satisfied_by() {
59 {
60 let r = parse_relation(b"< -2").unwrap().1;
61 assert!(r.satisfied_by(-3f64));
62 assert!(!r.satisfied_by(-2f64));
63 }
64 {
65 let r = parse_relation(b"=ABC").unwrap().1;
66 assert!(r.satisfied_by("ABC"));
67 assert!(!r.satisfied_by("ABCD"));
68 }
69 {
70 let r = parse_relation(b"in [1, 2, 3]").unwrap().1;
71 assert!(r.satisfied_by(1f64));
72 assert!(r.satisfied_by(2f64));
73 assert!(r.satisfied_by(3f64));
74 assert!(!r.satisfied_by(0f64));
75 assert!(!r.satisfied_by(1.1f64));
76 }
77}
78pub fn parse_relation(i: &[u8]) -> IResult<&[u8], Relation> {
80 alt((
81 preceded(pair(tag(">="), space), map(parse_value, Relation::Gte)),
82 preceded(pair(tag("<="), space), map(parse_value, Relation::Lte)),
83 preceded(pair(tag("in"), space), map(array, Relation::in_)),
84 preceded(pair(tag(">"), space), map(parse_value, Relation::Gt)),
85 preceded(pair(tag("<"), space), map(parse_value, Relation::Lt)),
86 preceded(pair(tag("="), space), map(parse_value, Relation::Eq)),
87 ))(i)
88}
89
90#[test]
91fn test_parse_relation() {
92 assert!(parse_relation(b"a + b").is_err());
93 assert_eq!(
94 parse_relation(b">=-2.4343").unwrap().1,
95 Relation::gte(-2.4343f64)
96 );
97 assert_eq!(parse_relation(b"<= -2").unwrap().1, Relation::lte(-2f64));
98 assert_eq!(
99 parse_relation(b"in [1,2,3]"),
100 Ok((b"".as_slice(), Relation::in_(vec![1f64, 2f64, 3f64])))
101 );
102 assert_eq!(
103 parse_relation(b"> 4"),
104 Ok((b"".as_slice(), Relation::gt(4f64)))
105 );
106 assert_eq!(
107 parse_relation(b"< 4"),
108 Ok((b"".as_slice(), Relation::lt(4f64)))
109 );
110}