-
Notifications
You must be signed in to change notification settings - Fork 807
/
target_validator.go
121 lines (102 loc) · 2.94 KB
/
target_validator.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
// Copyright 2020 Chaos Mesh Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package apivalidator
import (
"fmt"
"reflect"
"strconv"
"strings"
"github.com/go-playground/validator/v10"
)
// RequiredFieldEqualValid can be used to check the required field is not empty.
func RequiredFieldEqualValid(fl validator.FieldLevel) bool {
param := strings.Split(fl.Param(), `:`)
paramField := param[0]
paramValue := param[1]
if paramField == `` {
return true
}
var paramFieldValue reflect.Value
if fl.Parent().Kind() == reflect.Ptr {
paramFieldValue = fl.Parent().Elem().FieldByName(paramField)
} else {
paramFieldValue = fl.Parent().FieldByName(paramField)
}
if !isEq(paramFieldValue, paramValue) {
return true
}
return hasValue(fl)
}
// The following functions are copied from validator.v9 lib.
func hasValue(fl validator.FieldLevel) bool {
return requireCheckFieldKind(fl, "")
}
func requireCheckFieldKind(fl validator.FieldLevel, param string) bool {
field := fl.Field()
if len(param) > 0 {
if fl.Parent().Kind() == reflect.Ptr {
field = fl.Parent().Elem().FieldByName(param)
} else {
field = fl.Parent().FieldByName(param)
}
}
switch field.Kind() {
case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func:
return !field.IsNil()
default:
_, _, nullable := fl.ExtractType(field)
if nullable && field.Interface() != nil {
return true
}
return field.IsValid() && field.Interface() != reflect.Zero(field.Type()).Interface()
}
}
func isEq(field reflect.Value, value string) bool {
switch field.Kind() {
case reflect.String:
return field.String() == value
case reflect.Slice, reflect.Map, reflect.Array:
p := asInt(value)
return int64(field.Len()) == p
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
p := asInt(value)
return field.Int() == p
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
p := asUint(value)
return field.Uint() == p
case reflect.Float32, reflect.Float64:
p := asFloat(value)
return field.Float() == p
}
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
}
func asInt(param string) int64 {
i, err := strconv.ParseInt(param, 0, 64)
panicIf(err)
return i
}
func asUint(param string) uint64 {
i, err := strconv.ParseUint(param, 0, 64)
panicIf(err)
return i
}
func asFloat(param string) float64 {
i, err := strconv.ParseFloat(param, 64)
panicIf(err)
return i
}
func panicIf(err error) {
if err != nil {
panic(err.Error())
}
}