-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcel_utils.go
More file actions
116 lines (100 loc) · 3.48 KB
/
cel_utils.go
File metadata and controls
116 lines (100 loc) · 3.48 KB
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
package celUtils
import (
"fmt"
"strings"
)
// In generates a CEL expression that checks for `field` membership in `vals`.
func In(field string, vals []string) string {
if len(vals) == 0 {
return ""
}
quotedVals := make([]string, len(vals))
for i, val := range vals {
quotedVals[i] = fmt.Sprintf(`'%s'`, val)
}
return fmt.Sprintf("%s in [%s]", field, strings.Join(quotedVals, ","))
}
// Equals generates a CEL expression that checks for equality.
func Equals(key string, value interface{}) string {
switch v := value.(type) {
case string:
return fmt.Sprintf(`%s == '%s'`, key, v)
case nil:
return fmt.Sprintf("%s == null", key)
default:
return fmt.Sprintf("%s == %v", key, v)
}
}
// EqualsAll generates a CEL expression that checks for equality of all key-value pairs.
func EqualsAll(values map[string]interface{}) string {
var clauses []string
for key, value := range values {
clauses = append(clauses, Equals(key, value))
}
return strings.Join(clauses, " && ")
}
// EqualsDouble generates a CEL expression that checks for equality with a double value.
func EqualsDouble(key string, value interface{}) string {
if value == nil {
return fmt.Sprintf("%s == null", key)
}
return fmt.Sprintf("%s == double(%v)", key, value)
}
// And generates a CEL expression that joins all clauses with an AND operator.
func And(clauses ...string) string {
if len(clauses) == 0 {
return ""
}
if len(clauses) == 1 {
return clauses[0]
}
return strings.Join(clauses, " && ")
}
func AndWithParentheses(clauses ...string) string {
return fmt.Sprintf("(%s)", strings.Join(clauses, " && "))
}
// Or generates a CEL expression that joins all clauses with an OR operator.
func Or(clauses ...string) string {
if len(clauses) == 0 {
return ""
}
if len(clauses) == 1 {
return clauses[0]
}
return strings.Join(clauses, " || ")
}
func OrWithParentheses(clauses ...string) string {
return fmt.Sprintf("(%s)", strings.Join(clauses, " || "))
}
// Not generates a CEL expression that negates the given clause.
func Not(clause string) string {
return fmt.Sprintf("!(%s)", clause)
}
// GreaterThan generates a CEL expression that checks whether a field is greater than a given value.
func GreaterThan(field string, value float64) string {
return fmt.Sprintf("%s > %v", field, value)
}
// GreaterThanOrEqual generates a CEL expression that checks whether a field is greater than or equal to a given string value.
func GreaterThanOrEqual(field string, value string) string {
return fmt.Sprintf(`%s >= %s`, field, value)
}
// LessThanOrEqual generates a CEL expression that checks whether a field is less than or equal to a given string value.
func LessThanOrEqual(field string, value string) string {
return fmt.Sprintf(`%s <= %s`, field, value)
}
// Contains generates a CEL expression that checks whether a string field contains a given value.
func Contains(field, value string) string {
return fmt.Sprintf(`%s.contains('%s')`, field, value)
}
// Match generates a CEL expression that checks for a match
// on the specified field.
func Match(field, query string) string {
return fmt.Sprintf(`%s.matches('%s')`, field, query)
}
// MatchRegex is like Match but properly escapes backslashes in regex patterns for CEL
// It adds an extra backslash before any existing backslash in the pattern
func MatchRegex(field, regex string) string {
// Double-escape any backslashes that already exist in the regex
escapedRegex := strings.ReplaceAll(regex, "\\", "\\\\")
return fmt.Sprintf(`%s.matches('%s')`, field, escapedRegex)
}