Skip to content

Commit 060d69e

Browse files
committed
feat: refactor reflections utilities as per v3
1 parent c1da0c5 commit 060d69e

File tree

2 files changed

+72
-16
lines changed

2 files changed

+72
-16
lines changed

api/query.go

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -289,22 +289,6 @@ func checkParamsType(p interface{}) error {
289289
return nil
290290
}
291291

292-
// getFieldType extracts type of value
293-
func getFieldType(v reflect.Value) reflect.Type {
294-
t := v.Type()
295-
if t.Kind() == reflect.Ptr {
296-
t = t.Elem()
297-
v = v.Elem()
298-
}
299-
if t.Kind() == reflect.Interface && !v.IsNil() {
300-
t = reflect.ValueOf(v.Interface()).Type()
301-
}
302-
return t
303-
}
304-
305-
// timeType is the exact type for the Time
306-
var timeType = reflect.TypeOf(time.Time{})
307-
308292
// validParamType validates that t is primitive type or string or interface
309293
func validParamType(t reflect.Type) bool {
310294
return (t.Kind() > reflect.Invalid && t.Kind() < reflect.Complex64) ||

api/reflection.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package api
2+
3+
import (
4+
"fmt"
5+
"reflect"
6+
"time"
7+
)
8+
9+
// checkContainerType validates the value is struct with simple type fields
10+
// or a map with key as string and value as a simple type
11+
func checkContainerType(p interface{}, alsoMap bool, usage string) error {
12+
if p == nil {
13+
return nil
14+
}
15+
t := reflect.TypeOf(p)
16+
v := reflect.ValueOf(p)
17+
if t.Kind() == reflect.Ptr {
18+
t = t.Elem()
19+
v = v.Elem()
20+
}
21+
if t.Kind() != reflect.Struct && (!alsoMap || t.Kind() != reflect.Map) {
22+
return fmt.Errorf("cannot use %v as %s", t, usage)
23+
}
24+
switch t.Kind() {
25+
case reflect.Struct:
26+
fields := reflect.VisibleFields(t)
27+
for _, f := range fields {
28+
fv := v.FieldByIndex(f.Index)
29+
t := getFieldType(fv)
30+
if !validFieldType(t) {
31+
return fmt.Errorf("cannot use field '%s' of type '%v' as a %s", f.Name, t, usage)
32+
}
33+
34+
}
35+
case reflect.Map:
36+
key := t.Key()
37+
if key.Kind() != reflect.String {
38+
return fmt.Errorf("cannot use map key of type '%v' for %s name", key, usage)
39+
}
40+
for _, k := range v.MapKeys() {
41+
f := v.MapIndex(k)
42+
t := getFieldType(f)
43+
if !validFieldType(t) {
44+
return fmt.Errorf("cannot use map value type '%v' as a %s", t, usage)
45+
}
46+
}
47+
}
48+
return nil
49+
}
50+
51+
// getFieldType extracts type of value
52+
func getFieldType(v reflect.Value) reflect.Type {
53+
t := v.Type()
54+
if t.Kind() == reflect.Ptr {
55+
t = t.Elem()
56+
v = v.Elem()
57+
}
58+
if t.Kind() == reflect.Interface && !v.IsNil() {
59+
t = reflect.ValueOf(v.Interface()).Type()
60+
}
61+
return t
62+
}
63+
64+
// timeType is the exact type for the Time
65+
var timeType = reflect.TypeOf(time.Time{})
66+
67+
// validFieldType validates that t is primitive type or string or interface
68+
func validFieldType(t reflect.Type) bool {
69+
return (t.Kind() > reflect.Invalid && t.Kind() < reflect.Complex64) ||
70+
t.Kind() == reflect.String ||
71+
t == timeType
72+
}

0 commit comments

Comments
 (0)