-
Notifications
You must be signed in to change notification settings - Fork 1
/
metadata.go
180 lines (164 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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
package metadata
import (
"sort"
"time"
)
type TypeKind int
const (
InvalidType TypeKind = iota
Int32Kind
Uint32Kind
Int64Kind
Uint64Kind
BoolKind
FloatKind
DoubleKind
Fixed32Kind
Fixed64Kind
EnumKind
Sfixed32Kind
Sfixed64Kind
Sint32Kind
Sint64Kind
StringKind
BytesKind
MessageKind
MapKind
MaxTypeKind
)
const (
FromDefault = iota
FromContext
FromQuery
FromHeader
FromParams
)
type FieldOptions struct {
OmitEmpty bool
RawData bool
Validate bool
Bind int
}
type Field struct {
Tag int
Name string
Kind TypeKind
Message *Message
Repeated bool
Options FieldOptions
}
type MessageOptions struct {
Flat bool
ExtraInfo interface{}
}
type Message struct {
Name string
Fields []*Field
tagIndex []int
nameField []*Field
Options MessageOptions
}
func (m *Message) BakeTagIndex() {
fields := m.Fields
if len(fields) == 0 {
m.tagIndex = nil
return
}
maxTag := 0
for _, f := range fields {
if f.Tag > maxTag {
maxTag = f.Tag
}
}
if maxTag-len(m.Fields) < 3 {
// dense
tagIndex := make([]int, maxTag+1)
for i := range tagIndex {
tagIndex[i] = -1
}
for i, f := range fields {
tagIndex[f.Tag] = i
}
m.tagIndex = tagIndex
return
}
// sparse
tagIndex := make([]int, len(fields))
for i := range fields {
tagIndex[i] = i
}
sort.Slice(tagIndex, func(i, j int) bool {
return fields[tagIndex[i]].Tag < fields[tagIndex[j]].Tag
})
m.tagIndex = tagIndex
}
func (m *Message) TagIndex(tag int) int {
if len(m.tagIndex) > len(m.Fields) {
if tag < len(m.tagIndex) {
return m.tagIndex[tag]
} else {
return -1
}
}
l, r := 0, len(m.tagIndex)-1
for l <= r {
mid := (l + r) / 2
i := m.tagIndex[mid]
x := m.Fields[i].Tag
if x == tag {
return i
} else if x > tag {
r = mid - 1
} else {
l = mid + 1
}
}
return -1
}
func (m *Message) BakeNameField() {
if len(m.Fields) == 0 {
return
}
fields := m.Fields
nameField := make([]*Field, len(fields))
copy(nameField, fields)
sort.Slice(nameField, func(i, j int) bool {
return nameField[i].Name < nameField[j].Name
})
m.nameField = nameField
}
func (m *Message) GetField(fieldName string) *Field {
l, r := 0, len(m.nameField)-1
for l <= r {
mid := (l + r) / 2
field := m.nameField[mid]
if field.Name == fieldName {
return field
} else if field.Name > fieldName {
r = mid - 1
} else {
l = mid + 1
}
}
return nil
}
type Call struct {
Server string
Handler string
Name string
In *Message
Out *Message
Timeout time.Duration
}
type RouteOptions struct {
Middlewares []string
}
type Route struct {
Method string
Path string
Options RouteOptions
Call *Call
}
type Metadata struct {
Routes []*Route
}