OSDN Git Service

new repo
[bytom/vapor.git] / vendor / gopkg.in / go-playground / validator.v9 / util.go
1 package validator
2
3 import (
4         "reflect"
5         "strconv"
6         "strings"
7 )
8
9 // extractTypeInternal gets the actual underlying type of field value.
10 // It will dive into pointers, customTypes and return you the
11 // underlying value and it's kind.
12 func (v *validate) extractTypeInternal(current reflect.Value, nullable bool) (reflect.Value, reflect.Kind, bool) {
13
14 BEGIN:
15         switch current.Kind() {
16         case reflect.Ptr:
17
18                 nullable = true
19
20                 if current.IsNil() {
21                         return current, reflect.Ptr, nullable
22                 }
23
24                 current = current.Elem()
25                 goto BEGIN
26
27         case reflect.Interface:
28
29                 nullable = true
30
31                 if current.IsNil() {
32                         return current, reflect.Interface, nullable
33                 }
34
35                 current = current.Elem()
36                 goto BEGIN
37
38         case reflect.Invalid:
39                 return current, reflect.Invalid, nullable
40
41         default:
42
43                 if v.v.hasCustomFuncs {
44
45                         if fn, ok := v.v.customFuncs[current.Type()]; ok {
46                                 current = reflect.ValueOf(fn(current))
47                                 goto BEGIN
48                         }
49                 }
50
51                 return current, current.Kind(), nullable
52         }
53 }
54
55 // getStructFieldOKInternal traverses a struct to retrieve a specific field denoted by the provided namespace and
56 // returns the field, field kind and whether is was successful in retrieving the field at all.
57 //
58 // NOTE: when not successful ok will be false, this can happen when a nested struct is nil and so the field
59 // could not be retrieved because it didn't exist.
60 func (v *validate) getStructFieldOKInternal(val reflect.Value, namespace string) (current reflect.Value, kind reflect.Kind, found bool) {
61
62 BEGIN:
63         current, kind, _ = v.ExtractType(val)
64
65         if kind == reflect.Invalid {
66                 return
67         }
68
69         if namespace == "" {
70                 found = true
71                 return
72         }
73
74         switch kind {
75
76         case reflect.Ptr, reflect.Interface:
77                 return
78
79         case reflect.Struct:
80
81                 typ := current.Type()
82                 fld := namespace
83                 ns := namespace
84
85                 if typ != timeType {
86
87                         idx := strings.Index(namespace, namespaceSeparator)
88
89                         if idx != -1 {
90                                 fld = namespace[:idx]
91                                 ns = namespace[idx+1:]
92                         } else {
93                                 ns = ""
94                         }
95
96                         bracketIdx := strings.Index(fld, leftBracket)
97                         if bracketIdx != -1 {
98                                 fld = fld[:bracketIdx]
99
100                                 ns = namespace[bracketIdx:]
101                         }
102
103                         val = current.FieldByName(fld)
104                         namespace = ns
105                         goto BEGIN
106                 }
107
108         case reflect.Array, reflect.Slice:
109                 idx := strings.Index(namespace, leftBracket)
110                 idx2 := strings.Index(namespace, rightBracket)
111
112                 arrIdx, _ := strconv.Atoi(namespace[idx+1 : idx2])
113
114                 if arrIdx >= current.Len() {
115                         return current, kind, false
116                 }
117
118                 startIdx := idx2 + 1
119
120                 if startIdx < len(namespace) {
121                         if namespace[startIdx:startIdx+1] == namespaceSeparator {
122                                 startIdx++
123                         }
124                 }
125
126                 val = current.Index(arrIdx)
127                 namespace = namespace[startIdx:]
128                 goto BEGIN
129
130         case reflect.Map:
131                 idx := strings.Index(namespace, leftBracket) + 1
132                 idx2 := strings.Index(namespace, rightBracket)
133
134                 endIdx := idx2
135
136                 if endIdx+1 < len(namespace) {
137                         if namespace[endIdx+1:endIdx+2] == namespaceSeparator {
138                                 endIdx++
139                         }
140                 }
141
142                 key := namespace[idx:idx2]
143
144                 switch current.Type().Key().Kind() {
145                 case reflect.Int:
146                         i, _ := strconv.Atoi(key)
147                         val = current.MapIndex(reflect.ValueOf(i))
148                         namespace = namespace[endIdx+1:]
149
150                 case reflect.Int8:
151                         i, _ := strconv.ParseInt(key, 10, 8)
152                         val = current.MapIndex(reflect.ValueOf(int8(i)))
153                         namespace = namespace[endIdx+1:]
154
155                 case reflect.Int16:
156                         i, _ := strconv.ParseInt(key, 10, 16)
157                         val = current.MapIndex(reflect.ValueOf(int16(i)))
158                         namespace = namespace[endIdx+1:]
159
160                 case reflect.Int32:
161                         i, _ := strconv.ParseInt(key, 10, 32)
162                         val = current.MapIndex(reflect.ValueOf(int32(i)))
163                         namespace = namespace[endIdx+1:]
164
165                 case reflect.Int64:
166                         i, _ := strconv.ParseInt(key, 10, 64)
167                         val = current.MapIndex(reflect.ValueOf(i))
168                         namespace = namespace[endIdx+1:]
169
170                 case reflect.Uint:
171                         i, _ := strconv.ParseUint(key, 10, 0)
172                         val = current.MapIndex(reflect.ValueOf(uint(i)))
173                         namespace = namespace[endIdx+1:]
174
175                 case reflect.Uint8:
176                         i, _ := strconv.ParseUint(key, 10, 8)
177                         val = current.MapIndex(reflect.ValueOf(uint8(i)))
178                         namespace = namespace[endIdx+1:]
179
180                 case reflect.Uint16:
181                         i, _ := strconv.ParseUint(key, 10, 16)
182                         val = current.MapIndex(reflect.ValueOf(uint16(i)))
183                         namespace = namespace[endIdx+1:]
184
185                 case reflect.Uint32:
186                         i, _ := strconv.ParseUint(key, 10, 32)
187                         val = current.MapIndex(reflect.ValueOf(uint32(i)))
188                         namespace = namespace[endIdx+1:]
189
190                 case reflect.Uint64:
191                         i, _ := strconv.ParseUint(key, 10, 64)
192                         val = current.MapIndex(reflect.ValueOf(i))
193                         namespace = namespace[endIdx+1:]
194
195                 case reflect.Float32:
196                         f, _ := strconv.ParseFloat(key, 32)
197                         val = current.MapIndex(reflect.ValueOf(float32(f)))
198                         namespace = namespace[endIdx+1:]
199
200                 case reflect.Float64:
201                         f, _ := strconv.ParseFloat(key, 64)
202                         val = current.MapIndex(reflect.ValueOf(f))
203                         namespace = namespace[endIdx+1:]
204
205                 case reflect.Bool:
206                         b, _ := strconv.ParseBool(key)
207                         val = current.MapIndex(reflect.ValueOf(b))
208                         namespace = namespace[endIdx+1:]
209
210                 // reflect.Type = string
211                 default:
212                         val = current.MapIndex(reflect.ValueOf(key))
213                         namespace = namespace[endIdx+1:]
214                 }
215
216                 goto BEGIN
217         }
218
219         // if got here there was more namespace, cannot go any deeper
220         panic("Invalid field namespace")
221 }
222
223 // asInt returns the parameter as a int64
224 // or panics if it can't convert
225 func asInt(param string) int64 {
226
227         i, err := strconv.ParseInt(param, 0, 64)
228         panicIf(err)
229
230         return i
231 }
232
233 // asUint returns the parameter as a uint64
234 // or panics if it can't convert
235 func asUint(param string) uint64 {
236
237         i, err := strconv.ParseUint(param, 0, 64)
238         panicIf(err)
239
240         return i
241 }
242
243 // asFloat returns the parameter as a float64
244 // or panics if it can't convert
245 func asFloat(param string) float64 {
246
247         i, err := strconv.ParseFloat(param, 64)
248         panicIf(err)
249
250         return i
251 }
252
253 func panicIf(err error) {
254         if err != nil {
255                 panic(err.Error())
256         }
257 }