-
Notifications
You must be signed in to change notification settings - Fork 0
/
metadata.go
163 lines (148 loc) · 2.69 KB
/
metadata.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
package jsonpb
import "sort"
type Kind uint8
const (
DoubleKind Kind = iota
FloatKind
Int32Kind
Int64Kind
Uint32Kind
Uint64Kind
Sint32Kind
Sint64Kind
Fixed32Kind
Fixed64Kind
Sfixed32Kind
Sfixed64Kind
BoolKind
StringKind
BytesKind
MapKind
MessageKind
)
func IsNumericKind(k Kind) bool {
return DoubleKind <= k && k <= Sfixed64Kind
}
type Message struct {
Name string
Fields []Field
tagIdx []int
nameIdx map[string]int
}
func NewMessage(name string, fields []Field, indexTag bool, indexName bool) *Message {
msg := &Message{
Name: name,
Fields: fields,
}
if indexTag {
msg.BakeTagIndex()
}
if indexName {
msg.BakeNameIndex()
}
return msg
}
func (m *Message) BakeTagIndex() {
fields := m.Fields
maxTag := uint32(0)
for i := range fields {
if fields[i].Tag > maxTag {
maxTag = fields[i].Tag
}
}
var tagIdx []int
if int(maxTag) < len(fields)+len(fields)/4+3 {
tagIdx = make([]int, maxTag+1)
for i := range tagIdx {
tagIdx[i] = -1
}
for i := range fields {
tagIdx[fields[i].Tag] = i
}
} else {
// sparse-index
tagIdx = make([]int, len(fields))
for i := range tagIdx {
tagIdx[i] = i
}
sort.Slice(tagIdx, func(i, j int) bool {
return fields[tagIdx[i]].Tag < fields[tagIdx[j]].Tag
})
}
m.tagIdx = tagIdx
}
func (m *Message) FieldIndexByTag(tag uint32) int {
if len(m.tagIdx) == len(m.Fields) {
l, r := 0, len(m.tagIdx)-1
for l <= r {
mid := (l + r) / 2
i := m.tagIdx[mid]
x := m.Fields[i].Tag
if x == tag {
return i
} else if x > tag {
r = mid - 1
} else {
l = mid + 1
}
}
} else if int(tag) < len(m.tagIdx) {
idx := m.tagIdx[tag]
if idx >= 0 {
return idx
}
} else {
for i := 0; i < len(m.Fields); i++ {
if m.Fields[i].Tag == tag {
return i
}
}
}
return -1
}
func (m *Message) FieldByTag(tag uint32) *Field {
idx := m.FieldIndexByTag(tag)
if idx >= 0 {
return &m.Fields[idx]
}
return nil
}
func (m *Message) BakeNameIndex() {
names := make(map[string]int, len(m.Fields))
for i := range m.Fields {
names[m.Fields[i].Name] = i
}
m.nameIdx = names
}
func (m *Message) FieldByName(name string) *Field {
if m.nameIdx != nil {
idx, ok := m.nameIdx[name]
if ok {
return &m.Fields[idx]
}
} else {
for i := 0; i < len(m.Fields); i++ {
if m.Fields[i].Name == name {
return &m.Fields[i]
}
}
}
return nil
}
type OmitRule uint8
const (
// OmitProtoEmpty 只在 pb 输出"空值"时跳过字段
OmitProtoEmpty OmitRule = iota
// OmitEmpty 在 pb 和 json 输出"空值"跳过字段
OmitEmpty
// OmitAlways 总是跳过字段
OmitAlways
)
type Field struct {
Name string
Kind Kind
Ref *Message
Tag uint32
Repeated bool
Omit OmitRule
}