1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use phreak_facts::Value;

trait Predicate<T> {
    fn eval(&self, left: &T, right: &T) -> bool;
}

/// An enum is faster than a dyn Trait dispatch
#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq)]
pub enum TestCondition {
    Equal(Eq),
    NotEqual(Ne),
    GreaterEqual(Ge),
    LessEqual(Le),
    GreaterThan(Gt),
    LessThan(Lt),
}

impl TestCondition {
    pub fn eval(&self, left: &Value, right: &Value) -> bool {
        match self {
            TestCondition::Equal(p) => p.eval(left, right),
            TestCondition::NotEqual(p) => p.eval(left, right),
            TestCondition::GreaterEqual(p) => p.eval(left, right),
            TestCondition::LessEqual(p) => p.eval(left, right),
            TestCondition::GreaterThan(p) => p.eval(left, right),
            TestCondition::LessThan(p) => p.eval(left, right),
        }
    }
}

/// The predicate Eq is used to test for equality
#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq)]
pub struct Eq;

impl<T: PartialEq> Predicate<T> for Eq {
    fn eval(&self, left: &T, right: &T) -> bool {
        left == right
    }
}

/// The predicate Ne is used to test for inequality
#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq)]
pub struct Ne;

impl<T: PartialEq> Predicate<T> for Ne {
    fn eval(&self, left: &T, right: &T) -> bool {
        left != right
    }
}

#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq)]
pub struct Ge;

impl<T: PartialOrd> Predicate<T> for Ge {
    fn eval(&self, left: &T, right: &T) -> bool {
        left >= right
    }
}

#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq)]
pub struct Le;

impl<T: PartialOrd> Predicate<T> for Le {
    fn eval(&self, left: &T, right: &T) -> bool {
        left <= right
    }
}

#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq)]
pub struct Gt;

impl<T: PartialOrd> Predicate<T> for Gt {
    fn eval(&self, left: &T, right: &T) -> bool {
        left > right
    }
}

#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq)]
pub struct Lt;

impl<T: PartialOrd> Predicate<T> for Lt {
    fn eval(&self, left: &T, right: &T) -> bool {
        left < right
    }
}