-
Notifications
You must be signed in to change notification settings - Fork 90
/
serializer.go
118 lines (96 loc) · 2.83 KB
/
serializer.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
package sendtables2
import (
"fmt"
"strings"
)
type fieldIndex struct {
index int
field *field
}
type serializer struct {
name string
version int32
fields []*field
fieldIndexes map[string]*fieldIndex
fieldNameChecks map[string]bool
}
func newSerializer(name string, version int32) *serializer {
return &serializer{
name: name,
version: version,
fields: []*field{},
fieldIndexes: make(map[string]*fieldIndex),
fieldNameChecks: make(map[string]bool),
}
}
func (s *serializer) id() string {
return serializerId(s.name, s.version)
}
func (s *serializer) getNameForFieldPath(fp *fieldPath, pos int) []string {
return s.fields[fp.path[pos]].getNameForFieldPath(fp, pos+1)
}
func (s *serializer) getTypeForFieldPath(fp *fieldPath, pos int) *fieldType {
return s.fields[fp.path[pos]].getTypeForFieldPath(fp, pos+1)
}
func (s *serializer) getDecoderForFieldPath(fp *fieldPath, pos int) fieldDecoder {
index := fp.path[pos]
if len(s.fields) <= index {
_panicf("serializer %s: field path %s has no field (%d)", s.name, fp, index)
}
dec, _ := s.fields[index].getDecoderForFieldPath(fp, pos+1)
return dec
}
func (s *serializer) getDecoderForFieldPath2(fp *fieldPath, pos int) (fieldDecoder, bool) {
index := fp.path[pos]
if len(s.fields) <= index {
_panicf("serializer %s: field path %s has no field (%d)", s.name, fp, index)
}
return s.fields[index].getDecoderForFieldPath(fp, pos+1)
}
func (s *serializer) getFieldForFieldPath(fp *fieldPath, pos int) *field {
return s.fields[fp.path[pos]].getFieldForFieldPath(fp, pos+1)
}
func (s *serializer) getFieldPathForName(fp *fieldPath, name string) bool {
if s.fieldIndexes[name] != nil {
fp.path[fp.last] = s.fieldIndexes[name].index
return true
}
dotIndex := strings.Index(name, ".")
if dotIndex != -1 {
nameBeforeDot := name[:dotIndex]
if s.fieldIndexes[nameBeforeDot] != nil {
fp.path[fp.last] = s.fieldIndexes[nameBeforeDot].index
fp.last++
f := s.fieldIndexes[nameBeforeDot].field
return f.getFieldPathForName(fp, name[len(f.varName)+1:])
}
}
return false
}
func (s *serializer) getFieldPaths(fp *fieldPath, state *fieldState) []*fieldPath {
results := make([]*fieldPath, 0, 4)
for i, f := range s.fields {
fp.path[fp.last] = i
results = append(results, f.getFieldPaths(fp, state)...)
}
return results
}
func serializerId(name string, version int32) string {
return fmt.Sprintf("%s(%d)", name, version)
}
func (s *serializer) addField(f *field) {
newFieldIndex := len(s.fields)
s.fields = append(s.fields, f)
s.fieldIndexes[f.varName] = &fieldIndex{
index: newFieldIndex,
field: f,
}
}
func (s *serializer) checkFieldName(name string) bool {
ok, exists := s.fieldNameChecks[name]
if !exists {
ok = s.getFieldPathForName(newFieldPath(), name)
s.fieldNameChecks[name] = ok
}
return ok
}