-
-
Notifications
You must be signed in to change notification settings - Fork 491
/
Copy pathfield.go
129 lines (112 loc) · 2.87 KB
/
field.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
package structs
import (
"reflect"
"github.com/duke-git/lancet/v2/pointer"
)
// Field is abstract struct field for provide several high level functions
type Field struct {
Struct
field reflect.StructField
tag *Tag
}
func newField(v reflect.Value, f reflect.StructField, tagName string) *Field {
tag := f.Tag.Get(tagName)
field := &Field{
field: f,
tag: newTag(tag),
}
field.rvalue = v
field.rtype = v.Type()
field.TagName = tagName
return field
}
// Tag returns the value that the key in the tag string.
func (f *Field) Tag() *Tag {
return f.tag
}
// Value returns the underlying value of the field.
func (f *Field) Value() any {
return f.rvalue.Interface()
}
// IsEmbedded returns true if the given field is an embedded field.
func (f *Field) IsEmbedded() bool {
return len(f.field.Index) > 1
}
// IsExported returns true if the given field is exported.
func (f *Field) IsExported() bool {
return f.field.IsExported()
}
// IsZero returns true if the given field is zero value.
func (f *Field) IsZero() bool {
z := reflect.Zero(f.rvalue.Type()).Interface()
v := f.Value()
return reflect.DeepEqual(z, v)
}
// IsNil returns true if the given field is nil value.
func (f *Field) IsNil() bool {
v := f.Value()
if v == nil || (reflect.ValueOf(v)).Kind() == reflect.Ptr && reflect.ValueOf(v).IsNil() {
return true
}
return false
}
// Name returns the name of the given field
func (f *Field) Name() string {
return f.field.Name
}
// Kind returns the field's kind
func (f *Field) Kind() reflect.Kind {
return f.rvalue.Kind()
}
// IsSlice check if a struct field type is slice or not
func (f *Field) IsSlice() bool {
k := f.rvalue.Kind()
return k == reflect.Slice
}
// IsTargetType check if a struct field type is target type or not
func (f *Field) IsTargetType(targetType reflect.Kind) bool {
return f.rvalue.Kind() == targetType
}
// mapValue covert field value to map
func (f *Field) mapValue(value any) any {
val := pointer.ExtractPointer(value)
v := reflect.ValueOf(val)
var ret any
switch v.Kind() {
case reflect.Struct:
s := New(val)
s.TagName = f.TagName
m, _ := s.ToMap()
ret = m
case reflect.Map:
mapEl := v.Type().Elem()
switch mapEl.Kind() {
case reflect.Ptr, reflect.Array, reflect.Map, reflect.Slice, reflect.Chan:
// iterate the map
m := make(map[string]any, v.Len())
for _, key := range v.MapKeys() {
m[key.String()] = f.mapValue(v.MapIndex(key).Interface())
}
ret = m
default:
ret = v.Interface()
}
case reflect.Slice, reflect.Array:
sEl := v.Type().Elem()
switch sEl.Kind() {
case reflect.Ptr, reflect.Array, reflect.Map, reflect.Slice, reflect.Chan:
slices := make([]any, v.Len())
for i := 0; i < v.Len(); i++ {
slices[i] = f.mapValue(v.Index(i).Interface())
}
ret = slices
default:
ret = v.Interface()
}
default:
if v.Kind().String() != "invalid" {
ret = v.Interface()
}
}
return ret
}