ghee_lang/
relation.rs

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}
78/// E.g. `> 5`
79pub 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}