-
Notifications
You must be signed in to change notification settings - Fork 1
/
regexpr.go
139 lines (131 loc) · 3.53 KB
/
regexpr.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
137
138
139
package govalidator
import (
"context"
"fmt"
"reflect"
"regexp"
"strings"
)
type RegExprCheck struct {
expr *regexp.Regexp
minLength *int
}
func (r *RegExprCheck) IsValidStringPtr(ctx context.Context, value interface{}) (bool, error) {
if value == nil {
return false, nil
}
actual, ok := value.(*string)
if !ok {
return false, fmt.Errorf("expected: %T, but had: %T", actual, value)
}
if actual == nil {
return false, nil
}
if r.minLength != nil {
if len(*actual) < *r.minLength {
return false, nil
}
}
return r.expr.MatchString(*actual), nil
}
func (r *RegExprCheck) IsValidString(ctx context.Context, value interface{}) (bool, error) {
actual, ok := value.(string)
if !ok {
return false, fmt.Errorf("expected: %T, but had: %T", actual, value)
}
if r.minLength != nil {
if len(actual) < *r.minLength {
return false, nil
}
}
return r.expr.MatchString(actual), nil
}
func NewNotRegExprCheck(expr *regexp.Regexp) func(field *Field, check *Check) (IsValid, error) {
fn := NewRegExprCheck(expr)
return func(field *Field, check *Check) (IsValid, error) {
isValid, err := fn(field, check)
if err != nil {
return nil, err
}
return func(ctx context.Context, value interface{}) (bool, error) {
ret, err := isValid(ctx, value)
if err != nil {
return false, err
}
return !ret, nil
}, nil
}
}
//NewRegExprCheck creates a regexpr based validation check
func NewRegExprCheck(expr *regexp.Regexp) func(field *Field, check *Check) (IsValid, error) {
ret := &RegExprCheck{expr: expr}
return func(field *Field, check *Check) (IsValid, error) {
switch field.Kind() {
case reflect.String:
return ret.IsValidString, nil
case reflect.Ptr:
if field.Type.Elem().Kind() == reflect.String {
return ret.IsValidStringPtr, nil
}
}
return nil, fmt.Errorf("unsupported regexpr based %v check type: %s", field.Tag, field.Type.String())
}
}
func NewRepeatedRegExprCheck(expr *regexp.Regexp, separator string) func(field *Field, check *Check) (IsValid, error) {
fn := NewRegExprCheck(expr)
return func(field *Field, check *Check) (IsValid, error) {
isValid, err := fn(field, check)
if err != nil {
return nil, err
}
isPtr := false
return func(ctx context.Context, value interface{}) (bool, error) {
fragment := ""
switch actual := value.(type) {
case string:
fragment = actual
case []byte:
fragment = string(actual)
case *string:
isPtr = true
if actual != nil {
fragment = *actual
}
default:
return false, fmt.Errorf("invalid input type: expected: %T, but had: %T", fragment, value)
}
if len(fragment) == 0 {
return false, nil
}
for _, item := range strings.Split(fragment, separator) {
var value interface{} = item
if isPtr {
value = &item
}
ret, err := isValid(ctx, value)
if err != nil {
return false, err
}
if !ret {
return false, nil
}
}
return true, nil
}, nil
}
}
//NewRegExprCheckWithMinLength creates a regexpr based validation check with min Length
func NewRegExprCheckWithMinLength(expr *regexp.Regexp, minLen int) func(field *Field, check *Check) (IsValid, error) {
ret := &RegExprCheck{expr: expr, minLength: &minLen}
return func(field *Field, check *Check) (IsValid, error) {
switch field.Kind() {
case reflect.String:
return ret.IsValidString, nil
case reflect.Ptr:
if field.Type.Elem().Kind() == reflect.String {
return ret.IsValidStringPtr, nil
}
}
return nil, fmt.Errorf("unsupported regexpr based %v check type: %s", field.Tag, field.Type.String())
}
}