-
Notifications
You must be signed in to change notification settings - Fork 23
/
expression.go
136 lines (116 loc) · 3.79 KB
/
expression.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
133
134
135
136
package expression
import (
"fmt"
"regexp"
"strconv"
)
// Type is the type of the filter (i.e. const, regex, etc)
type Type string
const (
// EqualTo a filter that applies numerical and string equal to operations
EqualTo Type = "equal"
// Regex a filter that applies regex rules to the matching
Regex Type = "regex"
// LessThan a filter that applies numerical less than operation
LessThan Type = "less-than"
// LessThanEqual a filter that applies numerical less than or equal operation
LessThanEqual Type = "less-than-equal"
// GreaterThan a filter that applies numerical greater than operation
GreaterThan Type = "greater-than"
// GreaterThanEqual a filter that applies numerical greater than or equal operation
GreaterThanEqual Type = "greater-than-equal"
// NotEqualTo a filter that applies numerical NOT equal to operation
NotEqualTo Type = "not-equal"
)
// TypeMap contains all the expression types for validation.
var TypeMap = map[Type]interface{}{
Regex: struct{}{},
LessThan: struct{}{},
LessThanEqual: struct{}{},
GreaterThan: struct{}{},
GreaterThanEqual: struct{}{},
EqualTo: struct{}{},
NotEqualTo: struct{}{},
}
// Expression the expression interface
type Expression interface {
Match(input interface{}) (bool, error)
}
type regexExpression struct {
Regex *regexp.Regexp
}
func (e *regexExpression) Match(input interface{}) (bool, error) {
switch v := input.(type) {
case string:
return e.Regex.MatchString(v), nil
default:
return false, fmt.Errorf("unexpected regex search input type (%T)", v)
}
}
type stringEqualExpression struct {
Str string
}
func (e *stringEqualExpression) Match(input interface{}) (bool, error) {
switch v := input.(type) {
case string:
return e.Str == v, nil
default:
return false, fmt.Errorf("unexpected regex search input type (%T)", v)
}
}
func makeRegexExpression(searchStr string) (Expression, error) {
r, err := regexp.Compile(searchStr)
if err != nil {
return nil, err
}
return ®exExpression{Regex: r}, nil
}
func makeSignedExpression(searchStr string, expressionType Type) (Expression, error) {
if expressionType == Regex {
return nil, fmt.Errorf("target type (numeric) does not support %s filters", expressionType)
}
v, err := strconv.ParseInt(searchStr, 10, 64)
if err != nil {
return nil, fmt.Errorf("search string \"%s\" is not a valid int64: %w", searchStr, err)
}
return &int64NumericalExpression{
FilterValue: v,
Op: expressionType,
}, nil
}
func makeUnsignedExpression(searchStr string, expressionType Type) (Expression, error) {
if expressionType == Regex {
return nil, fmt.Errorf("target type (numeric) does not support %s filters", expressionType)
}
v, err := strconv.ParseUint(searchStr, 10, 64)
if err != nil {
return nil, fmt.Errorf("search string \"%s\" is not a valid uint64: %w", searchStr, err)
}
return &uint64NumericalExpression{
FilterValue: v,
Op: expressionType,
}, nil
}
// MakeExpression creates an expression based on an expression type
func MakeExpression(expressionType Type, expressionSearchStr string, target interface{}) (exp Expression, err error) {
if _, ok := TypeMap[expressionType]; !ok {
return nil, fmt.Errorf("expression type (%s) is not supported", expressionType)
}
switch t := target.(type) {
case uint64:
return makeUnsignedExpression(expressionSearchStr, expressionType)
case int64:
return makeSignedExpression(expressionSearchStr, expressionType)
case string:
switch expressionType {
case EqualTo:
return &stringEqualExpression{Str: expressionSearchStr}, nil
case Regex:
return makeRegexExpression(expressionSearchStr)
default:
return nil, fmt.Errorf("target type (string) does not support %s filters", expressionType)
}
default:
return nil, fmt.Errorf("unknown expression type: %T", t)
}
}