-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstruct_util.go
100 lines (89 loc) · 2 KB
/
struct_util.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
package henge
import (
"reflect"
)
const (
structTagKey = "henge"
)
type structTag struct {
ignore bool
}
// newStructTag is create a `structTag` from `reflect.StructField`
func newStructTag(f reflect.StructField) structTag {
value := f.Tag.Get(structTagKey)
switch value {
case "-":
return structTag{ignore: true}
default:
return structTag{ignore: false}
}
}
// getStructFieldIndexes returns all field indexes including embedded fields of the type.
func getStructFieldIndexes(t reflect.Type) [][]int {
fieldIndexes := make([][]int, 0)
for t.Kind() == reflect.Ptr {
t = t.Elem()
}
if t.Kind() == reflect.Struct {
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
fieldIndexes = append(fieldIndexes, f.Index)
if f.Anonymous {
for _, index := range getStructFieldIndexes(f.Type) {
fieldIndexes = append(fieldIndexes, append(f.Index, index...))
}
}
}
}
return fieldIndexes
}
type structField struct {
name string
index []int
tags []structTag
}
// getStructFields returns all fields including embedded fields of the type.
func getStructFields(t reflect.Type) []structField {
fieldIndexes := getStructFieldIndexes(t)
fields := make([]structField, len(fieldIndexes))
for t.Kind() == reflect.Ptr {
t = t.Elem()
}
if t.Kind() == reflect.Struct {
for i, fieldIndex := range fieldIndexes {
f := t.FieldByIndex(fieldIndex)
tags := make([]structTag, len(fieldIndex))
for i := 0; i < len(fieldIndex); i++ {
tags[i] = newStructTag(t.FieldByIndex(fieldIndex[0 : i+1]))
}
fields[i] = structField{
name: f.Name,
index: fieldIndex,
tags: tags,
}
}
}
return fields
}
func (f *structField) isIgnore() bool {
for _, t := range f.tags {
if t.ignore {
return true
}
}
return false
}
func (f *structField) isMatch(rf reflect.StructField) bool {
if len(f.index) != len(rf.Index) {
return false
}
if f.name != rf.Name {
return false
}
for i := 0; i < len(f.index); i++ {
if f.index[i] != rf.Index[i] {
return false
}
}
return true
}