-
Notifications
You must be signed in to change notification settings - Fork 18
/
operator.go
132 lines (107 loc) · 3.04 KB
/
operator.go
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package boolevator
import (
"context"
"regexp"
"strconv"
"strings"
)
func opNot(ctx context.Context, parameter interface{}) (interface{}, error) {
if err := handleError(parameter); err != nil {
return nil, err
}
val, err := strconv.ParseBool(parameter.(string))
if err != nil {
return "", err
}
return strconv.FormatBool(!val), nil
}
func opIn(a, b interface{}) (interface{}, error) {
if err := handleError(a, b); err != nil {
return nil, err
}
return strconv.FormatBool(strings.Contains(b.(string), a.(string))), nil
}
func opAnd(a, b interface{}) (interface{}, error) {
if err := handleError(a, b); err != nil {
return nil, err
}
left, err := strconv.ParseBool(a.(string))
if err != nil {
return false, err
}
right, err := strconv.ParseBool(b.(string))
if err != nil {
return false, err
}
return strconv.FormatBool(left && right), nil
}
func opOr(a, b interface{}) (interface{}, error) {
if err := handleError(a, b); err != nil {
return nil, err
}
left, err := strconv.ParseBool(a.(string))
if err != nil {
return false, err
}
right, err := strconv.ParseBool(b.(string))
if err != nil {
return false, err
}
return strconv.FormatBool(left || right), nil
}
func opEquals(a, b interface{}) (interface{}, error) {
if err := handleError(a, b); err != nil {
return nil, err
}
return strconv.FormatBool(a == b), nil
}
func opNotEquals(a, b interface{}) (interface{}, error) {
if err := handleError(a, b); err != nil {
return nil, err
}
return strconv.FormatBool(a != b), nil
}
func opRegexEquals(a, b interface{}) (interface{}, error) {
if err := handleError(a, b); err != nil {
return nil, err
}
matches, err := regexp.MatchString(PrepareRegexp(b.(string)), a.(string))
if err != nil {
return nil, err
}
return strconv.FormatBool(matches), nil
}
func opRegexNotEquals(a, b interface{}) (interface{}, error) {
if err := handleError(a, b); err != nil {
return nil, err
}
result, err := opRegexEquals(a, b)
if err != nil {
return "", nil
}
return strconv.FormatBool(result == "false"), nil
}
// handleError is a helper to catch and propagate errors from user-defined functions
// (see boolevator.WithFunctions option for more details).
func handleError(arguments ...interface{}) error {
for _, argument := range arguments {
if err, ok := argument.(error); ok {
return err
}
}
return nil
}
// PrepareRegexp ensures that:
//
// - we match the whole string to avoid partial match false positives (e.g. we don't want ".*smh.*" regular expression
// to match an empty string "")
// - enable Pattern.DOTALL[1] alternative in Go because otherwise simply adding ^ and $ will be too restricting,
// since we actually support multi-line matches
// - enable Pattern.CASE_INSENSITIVE alternative in Go to be compatible with the Cirrus Cloud parser
//
// [1]: https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#DOTALL
//
// [2]: https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#CASE_INSENSITIVE
func PrepareRegexp(r string) string {
return "(?s)(?i)^" + r + "$"
}