1 package serde
2
3 import (
4 "reflect"
5 "sort"
6 )
7
8 const tagKey = "document"
9
10
11 type Field struct {
12 Tag
13
14 Name string
15 NameFromTag bool
16
17 Index []int
18 Type reflect.Type
19 }
20
21 func buildField(pIdx []int, i int, sf reflect.StructField, fieldTag Tag) Field {
22 f := Field{
23 Name: sf.Name,
24 Type: sf.Type,
25 Tag: fieldTag,
26 }
27
28 if len(fieldTag.Name) != 0 {
29 f.NameFromTag = true
30 f.Name = fieldTag.Name
31 }
32
33 f.Index = make([]int, len(pIdx)+1)
34 copy(f.Index, pIdx)
35 f.Index[len(pIdx)] = i
36
37 return f
38 }
39
40
41
42 func GetStructFields(t reflect.Type) *CachedFields {
43 if cached, ok := fieldCache.Load(t); ok {
44 return cached
45 }
46
47 f := enumFields(t)
48 sort.Sort(fieldsByName(f))
49 f = visibleFields(f)
50
51 fs := &CachedFields{
52 fields: f,
53 fieldsByName: make(map[string]int, len(f)),
54 }
55 for i, f := range fs.fields {
56 fs.fieldsByName[f.Name] = i
57 }
58
59 cached, _ := fieldCache.LoadOrStore(t, fs)
60 return cached
61 }
62
63
64
65
66
67
68 func enumFields(t reflect.Type) []Field {
69
70 current := []Field{}
71 next := []Field{{Type: t}}
72
73
74 count := map[reflect.Type]int{}
75 nextCount := map[reflect.Type]int{}
76
77 visited := map[reflect.Type]struct{}{}
78 fields := []Field{}
79
80 for len(next) > 0 {
81 current, next = next, current[:0]
82 count, nextCount = nextCount, map[reflect.Type]int{}
83
84 for _, f := range current {
85 if _, ok := visited[f.Type]; ok {
86 continue
87 }
88 visited[f.Type] = struct{}{}
89
90 for i := 0; i < f.Type.NumField(); i++ {
91 sf := f.Type.Field(i)
92 if sf.PkgPath != "" && !sf.Anonymous {
93
94
95
96 continue
97 }
98
99 fieldTag := ParseTag(sf.Tag.Get(tagKey))
100
101 if fieldTag.Ignore {
102 continue
103 }
104
105 ft := sf.Type
106 if ft.Name() == "" && ft.Kind() == reflect.Ptr {
107 ft = ft.Elem()
108 }
109
110 structField := buildField(f.Index, i, sf, fieldTag)
111 structField.Type = ft
112
113 if !sf.Anonymous || ft.Kind() != reflect.Struct {
114 fields = append(fields, structField)
115 if count[f.Type] > 1 {
116
117
118
119
120 fields = append(fields, structField)
121 }
122 continue
123 }
124
125
126 nextCount[ft]++
127 if nextCount[ft] == 1 {
128 next = append(next, structField)
129 }
130 }
131 }
132 }
133
134 return fields
135 }
136
137
138
139
140
141
142
143 func visibleFields(fields []Field) []Field {
144
145
146
147
148
149
150 out := fields[:0]
151 for advance, i := 0, 0; i < len(fields); i += advance {
152
153
154 fi := fields[i]
155 name := fi.Name
156 for advance = 1; i+advance < len(fields); advance++ {
157 fj := fields[i+advance]
158 if fj.Name != name {
159 break
160 }
161 }
162 if advance == 1 {
163 out = append(out, fi)
164 continue
165 }
166 dominant, ok := dominantField(fields[i : i+advance])
167 if ok {
168 out = append(out, dominant)
169 }
170 }
171
172 fields = out
173 sort.Sort(fieldsByIndex(fields))
174
175 return fields
176 }
177
178
179
180
181
182
183
184
185
186
187 func dominantField(fields []Field) (Field, bool) {
188
189
190
191 length := len(fields[0].Index)
192 tagged := -1
193 for i, f := range fields {
194 if len(f.Index) > length {
195 fields = fields[:i]
196 break
197 }
198 if f.NameFromTag {
199 if tagged >= 0 {
200
201
202 return Field{}, false
203 }
204 tagged = i
205 }
206 }
207 if tagged >= 0 {
208 return fields[tagged], true
209 }
210
211
212
213 if len(fields) > 1 {
214 return Field{}, false
215 }
216 return fields[0], true
217 }
218
219
220
221
222
223
224
225 type fieldsByName []Field
226
227 func (x fieldsByName) Len() int { return len(x) }
228
229 func (x fieldsByName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
230
231 func (x fieldsByName) Less(i, j int) bool {
232 if x[i].Name != x[j].Name {
233 return x[i].Name < x[j].Name
234 }
235 if len(x[i].Index) != len(x[j].Index) {
236 return len(x[i].Index) < len(x[j].Index)
237 }
238 if x[i].NameFromTag != x[j].NameFromTag {
239 return x[i].NameFromTag
240 }
241 return fieldsByIndex(x).Less(i, j)
242 }
243
244
245
246
247
248 type fieldsByIndex []Field
249
250 func (x fieldsByIndex) Len() int { return len(x) }
251
252 func (x fieldsByIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
253
254 func (x fieldsByIndex) Less(i, j int) bool {
255 for k, xik := range x[i].Index {
256 if k >= len(x[j].Index) {
257 return false
258 }
259 if xik != x[j].Index[k] {
260 return xik < x[j].Index[k]
261 }
262 }
263 return len(x[i].Index) < len(x[j].Index)
264 }
265
266
267
268 func DecoderFieldByIndex(v reflect.Value, index []int) reflect.Value {
269 for i, x := range index {
270 if i > 0 && v.Kind() == reflect.Ptr && v.Type().Elem().Kind() == reflect.Struct {
271 if v.IsNil() {
272 v.Set(reflect.New(v.Type().Elem()))
273 }
274 v = v.Elem()
275 }
276 v = v.Field(x)
277 }
278 return v
279 }
280
281
282 func EncoderFieldByIndex(v reflect.Value, index []int) (reflect.Value, bool) {
283 for i, x := range index {
284 if i > 0 && v.Kind() == reflect.Ptr && v.Type().Elem().Kind() == reflect.Struct {
285 if v.IsNil() {
286 return reflect.Value{}, false
287 }
288 v = v.Elem()
289 }
290 v = v.Field(x)
291 }
292 return v, true
293 }
294
View as plain text