-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
validate.go
160 lines (147 loc) · 4.01 KB
/
validate.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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// Copyright © 2019 Developer Network, LLC
//
// This file is subject to the terms and conditions defined in
// file 'LICENSE', which is part of this source code package.
// Package validator sets up several methods for simple validation as well
// as setting up an interface which when implemented allows for custom validation
// logic by the implementor. `Valid()` returns a boolean indicating if the value(s)
// passed into it are valid based on the different types. `Assert()` returns an error
// indicating `nil` if the values are valid. Otherwise `Assert()` returns an error
// indicating the index of the value(s) passed into it as to which was determined
// to be invalid.
package validator
import (
"reflect"
"strconv"
)
// validator interface for checking to see if the struct has a Validate method assigned to it
// NOTE: This implementation should not use a pointer receiver, otherwise it will not work for non-pointer instances
// of structs
type validator interface {
Validate() (valid bool)
}
// Assert determines the validity of each value passed in to determine
// if the inputs are valid. A non-nil error return indicates an invalid
// assertion and a nil error returns indicates validity
func Assert(objs ...interface{}) error {
if len(objs) == 0 {
return ValidationError{
Message: "empty argument list passed to assert",
Index: 0,
}
}
for i, obj := range objs {
switch v := obj.(type) {
case nil:
return ValidationError{
Message: "nil value",
Index: i,
Type: reflect.TypeOf(i),
}
case validator:
if !v.Validate() {
return ValidationError{
Message: "nil value",
Index: i,
Type: reflect.TypeOf(obj),
ValidatorFailure: true,
}
}
case string:
if v == "" {
return ValidationError{
Message: "empty string",
Index: i,
Type: reflect.TypeOf(obj),
}
}
case []byte:
if len(v) == 0 {
return ValidationError{
Message: "empty slice",
Index: i,
Type: reflect.TypeOf(obj),
}
}
case []string:
for j, s := range v {
if s == "" {
return ValidationError{
Message: "empty string in slice at index " + strconv.Itoa(j),
Index: i,
Type: reflect.TypeOf(obj),
}
}
}
case int, int8, int16, int32, int64, uint, uint8,
uint16, uint32, uint64, uintptr, bool,
float32, float64, complex128, complex64:
continue
default:
if !valid(obj) { // TODO: return index of error
return ValidationError{
Message: "invalid at reflection check",
Index: i,
Type: reflect.TypeOf(obj),
}
}
}
}
return nil
}
// IsValid is DEPRECATED, replaced by Valid. This method will be available until version 1.1.0
func IsValid(objs ...interface{}) bool {
return Valid(objs...)
}
// Valid reads in an object, and checks to see if the object implements the validator interface
// if the object does then it executes the objects validate method and returns that
func Valid(objs ...interface{}) bool {
if len(objs) == 0 {
return false
}
for _, obj := range objs {
switch v := obj.(type) {
case nil:
return false
case validator:
if !v.Validate() {
return false
}
case string:
if v == "" {
return false
}
case []byte:
if len(v) == 0 {
return false
}
case []string:
for _, s := range v {
if s == "" {
return false
}
}
case int, int8, int16, int32, int64, uint, uint8,
uint16, uint32, uint64, uintptr, bool,
float32, float64, complex128, complex64:
continue
default:
if !valid(v) {
return false
}
}
}
return true
}
func valid(obj interface{}) (valid bool) {
// Using reflection pull the type associated with the object that is passed in. nil types are invalid.
var tp reflect.Type
if tp = reflect.TypeOf(obj); tp != nil {
val := reflect.ValueOf(obj)
// determine if the value is a pointer or not and whether it's nil if it is a pointer
if val.Kind() != reflect.Ptr || (val.Kind() == reflect.Ptr && !val.IsNil()) {
valid = true
}
}
return valid
}