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) {
15 switch current.Kind() {
21 return current, reflect.Ptr, nullable
24 current = current.Elem()
27 case reflect.Interface:
32 return current, reflect.Interface, nullable
35 current = current.Elem()
39 return current, reflect.Invalid, nullable
43 if v.v.hasCustomFuncs {
45 if fn, ok := v.v.customFuncs[current.Type()]; ok {
46 current = reflect.ValueOf(fn(current))
51 return current, current.Kind(), nullable
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.
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) {
63 current, kind, _ = v.ExtractType(val)
65 if kind == reflect.Invalid {
76 case reflect.Ptr, reflect.Interface:
87 idx := strings.Index(namespace, namespaceSeparator)
91 ns = namespace[idx+1:]
96 bracketIdx := strings.Index(fld, leftBracket)
98 fld = fld[:bracketIdx]
100 ns = namespace[bracketIdx:]
103 val = current.FieldByName(fld)
108 case reflect.Array, reflect.Slice:
109 idx := strings.Index(namespace, leftBracket)
110 idx2 := strings.Index(namespace, rightBracket)
112 arrIdx, _ := strconv.Atoi(namespace[idx+1 : idx2])
114 if arrIdx >= current.Len() {
115 return current, kind, false
120 if startIdx < len(namespace) {
121 if namespace[startIdx:startIdx+1] == namespaceSeparator {
126 val = current.Index(arrIdx)
127 namespace = namespace[startIdx:]
131 idx := strings.Index(namespace, leftBracket) + 1
132 idx2 := strings.Index(namespace, rightBracket)
136 if endIdx+1 < len(namespace) {
137 if namespace[endIdx+1:endIdx+2] == namespaceSeparator {
142 key := namespace[idx:idx2]
144 switch current.Type().Key().Kind() {
146 i, _ := strconv.Atoi(key)
147 val = current.MapIndex(reflect.ValueOf(i))
148 namespace = namespace[endIdx+1:]
151 i, _ := strconv.ParseInt(key, 10, 8)
152 val = current.MapIndex(reflect.ValueOf(int8(i)))
153 namespace = namespace[endIdx+1:]
156 i, _ := strconv.ParseInt(key, 10, 16)
157 val = current.MapIndex(reflect.ValueOf(int16(i)))
158 namespace = namespace[endIdx+1:]
161 i, _ := strconv.ParseInt(key, 10, 32)
162 val = current.MapIndex(reflect.ValueOf(int32(i)))
163 namespace = namespace[endIdx+1:]
166 i, _ := strconv.ParseInt(key, 10, 64)
167 val = current.MapIndex(reflect.ValueOf(i))
168 namespace = namespace[endIdx+1:]
171 i, _ := strconv.ParseUint(key, 10, 0)
172 val = current.MapIndex(reflect.ValueOf(uint(i)))
173 namespace = namespace[endIdx+1:]
176 i, _ := strconv.ParseUint(key, 10, 8)
177 val = current.MapIndex(reflect.ValueOf(uint8(i)))
178 namespace = namespace[endIdx+1:]
181 i, _ := strconv.ParseUint(key, 10, 16)
182 val = current.MapIndex(reflect.ValueOf(uint16(i)))
183 namespace = namespace[endIdx+1:]
186 i, _ := strconv.ParseUint(key, 10, 32)
187 val = current.MapIndex(reflect.ValueOf(uint32(i)))
188 namespace = namespace[endIdx+1:]
191 i, _ := strconv.ParseUint(key, 10, 64)
192 val = current.MapIndex(reflect.ValueOf(i))
193 namespace = namespace[endIdx+1:]
195 case reflect.Float32:
196 f, _ := strconv.ParseFloat(key, 32)
197 val = current.MapIndex(reflect.ValueOf(float32(f)))
198 namespace = namespace[endIdx+1:]
200 case reflect.Float64:
201 f, _ := strconv.ParseFloat(key, 64)
202 val = current.MapIndex(reflect.ValueOf(f))
203 namespace = namespace[endIdx+1:]
206 b, _ := strconv.ParseBool(key)
207 val = current.MapIndex(reflect.ValueOf(b))
208 namespace = namespace[endIdx+1:]
210 // reflect.Type = string
212 val = current.MapIndex(reflect.ValueOf(key))
213 namespace = namespace[endIdx+1:]
219 // if got here there was more namespace, cannot go any deeper
220 panic("Invalid field namespace")
223 // asInt returns the parameter as a int64
224 // or panics if it can't convert
225 func asInt(param string) int64 {
227 i, err := strconv.ParseInt(param, 0, 64)
233 // asUint returns the parameter as a uint64
234 // or panics if it can't convert
235 func asUint(param string) uint64 {
237 i, err := strconv.ParseUint(param, 0, 64)
243 // asFloat returns the parameter as a float64
244 // or panics if it can't convert
245 func asFloat(param string) float64 {
247 i, err := strconv.ParseFloat(param, 64)
253 func panicIf(err error) {