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 package proto
38
39
42
43 import (
44 "fmt"
45 "log"
46 "reflect"
47 "sort"
48 "strconv"
49 "strings"
50 "sync"
51 )
52
53 const debug bool = false
54
55
56 const (
57 WireVarint = 0
58 WireFixed64 = 1
59 WireBytes = 2
60 WireStartGroup = 3
61 WireEndGroup = 4
62 WireFixed32 = 5
63 )
64
65
66
67
68 type tagMap struct {
69 fastTags []int
70 slowTags map[int]int
71 }
72
73
74
75 const tagMapFastLimit = 1024
76
77 func (p *tagMap) get(t int) (int, bool) {
78 if t > 0 && t < tagMapFastLimit {
79 if t >= len(p.fastTags) {
80 return 0, false
81 }
82 fi := p.fastTags[t]
83 return fi, fi >= 0
84 }
85 fi, ok := p.slowTags[t]
86 return fi, ok
87 }
88
89 func (p *tagMap) put(t int, fi int) {
90 if t > 0 && t < tagMapFastLimit {
91 for len(p.fastTags) < t+1 {
92 p.fastTags = append(p.fastTags, -1)
93 }
94 p.fastTags[t] = fi
95 return
96 }
97 if p.slowTags == nil {
98 p.slowTags = make(map[int]int)
99 }
100 p.slowTags[t] = fi
101 }
102
103
104
105 type StructProperties struct {
106 Prop []*Properties
107 reqCount int
108 decoderTags tagMap
109 decoderOrigNames map[string]int
110 order []int
111
112
113
114 OneofTypes map[string]*OneofProperties
115 }
116
117
118 type OneofProperties struct {
119 Type reflect.Type
120 Field int
121 Prop *Properties
122 }
123
124
125
126
127 func (sp *StructProperties) Len() int { return len(sp.order) }
128 func (sp *StructProperties) Less(i, j int) bool {
129 return sp.Prop[sp.order[i]].Tag < sp.Prop[sp.order[j]].Tag
130 }
131 func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order[j], sp.order[i] }
132
133
134 type Properties struct {
135 Name string
136 OrigName string
137 JSONName string
138 Wire string
139 WireType int
140 Tag int
141 Required bool
142 Optional bool
143 Repeated bool
144 Packed bool
145 Enum string
146 proto3 bool
147 oneof bool
148
149 Default string
150 HasDefault bool
151 CustomType string
152 CastType string
153 StdTime bool
154 StdDuration bool
155 WktPointer bool
156
157 stype reflect.Type
158 ctype reflect.Type
159 sprop *StructProperties
160
161 mtype reflect.Type
162 MapKeyProp *Properties
163 MapValProp *Properties
164 }
165
166
167 func (p *Properties) String() string {
168 s := p.Wire
169 s += ","
170 s += strconv.Itoa(p.Tag)
171 if p.Required {
172 s += ",req"
173 }
174 if p.Optional {
175 s += ",opt"
176 }
177 if p.Repeated {
178 s += ",rep"
179 }
180 if p.Packed {
181 s += ",packed"
182 }
183 s += ",name=" + p.OrigName
184 if p.JSONName != p.OrigName {
185 s += ",json=" + p.JSONName
186 }
187 if p.proto3 {
188 s += ",proto3"
189 }
190 if p.oneof {
191 s += ",oneof"
192 }
193 if len(p.Enum) > 0 {
194 s += ",enum=" + p.Enum
195 }
196 if p.HasDefault {
197 s += ",def=" + p.Default
198 }
199 return s
200 }
201
202
203 func (p *Properties) Parse(s string) {
204
205 fields := strings.Split(s, ",")
206 if len(fields) < 2 {
207 log.Printf("proto: tag has too few fields: %q", s)
208 return
209 }
210
211 p.Wire = fields[0]
212 switch p.Wire {
213 case "varint":
214 p.WireType = WireVarint
215 case "fixed32":
216 p.WireType = WireFixed32
217 case "fixed64":
218 p.WireType = WireFixed64
219 case "zigzag32":
220 p.WireType = WireVarint
221 case "zigzag64":
222 p.WireType = WireVarint
223 case "bytes", "group":
224 p.WireType = WireBytes
225
226 default:
227 log.Printf("proto: tag has unknown wire type: %q", s)
228 return
229 }
230
231 var err error
232 p.Tag, err = strconv.Atoi(fields[1])
233 if err != nil {
234 return
235 }
236
237 outer:
238 for i := 2; i < len(fields); i++ {
239 f := fields[i]
240 switch {
241 case f == "req":
242 p.Required = true
243 case f == "opt":
244 p.Optional = true
245 case f == "rep":
246 p.Repeated = true
247 case f == "packed":
248 p.Packed = true
249 case strings.HasPrefix(f, "name="):
250 p.OrigName = f[5:]
251 case strings.HasPrefix(f, "json="):
252 p.JSONName = f[5:]
253 case strings.HasPrefix(f, "enum="):
254 p.Enum = f[5:]
255 case f == "proto3":
256 p.proto3 = true
257 case f == "oneof":
258 p.oneof = true
259 case strings.HasPrefix(f, "def="):
260 p.HasDefault = true
261 p.Default = f[4:]
262 if i+1 < len(fields) {
263
264 p.Default += "," + strings.Join(fields[i+1:], ",")
265 break outer
266 }
267 case strings.HasPrefix(f, "embedded="):
268 p.OrigName = strings.Split(f, "=")[1]
269 case strings.HasPrefix(f, "customtype="):
270 p.CustomType = strings.Split(f, "=")[1]
271 case strings.HasPrefix(f, "casttype="):
272 p.CastType = strings.Split(f, "=")[1]
273 case f == "stdtime":
274 p.StdTime = true
275 case f == "stdduration":
276 p.StdDuration = true
277 case f == "wktptr":
278 p.WktPointer = true
279 }
280 }
281 }
282
283 var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()
284
285
286 func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
287 isMap := typ.Kind() == reflect.Map
288 if len(p.CustomType) > 0 && !isMap {
289 p.ctype = typ
290 p.setTag(lockGetProp)
291 return
292 }
293 if p.StdTime && !isMap {
294 p.setTag(lockGetProp)
295 return
296 }
297 if p.StdDuration && !isMap {
298 p.setTag(lockGetProp)
299 return
300 }
301 if p.WktPointer && !isMap {
302 p.setTag(lockGetProp)
303 return
304 }
305 switch t1 := typ; t1.Kind() {
306 case reflect.Struct:
307 p.stype = typ
308 case reflect.Ptr:
309 if t1.Elem().Kind() == reflect.Struct {
310 p.stype = t1.Elem()
311 }
312 case reflect.Slice:
313 switch t2 := t1.Elem(); t2.Kind() {
314 case reflect.Ptr:
315 switch t3 := t2.Elem(); t3.Kind() {
316 case reflect.Struct:
317 p.stype = t3
318 }
319 case reflect.Struct:
320 p.stype = t2
321 }
322
323 case reflect.Map:
324
325 p.mtype = t1
326 p.MapKeyProp = &Properties{}
327 p.MapKeyProp.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
328 p.MapValProp = &Properties{}
329 vtype := p.mtype.Elem()
330 if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice {
331
332
333 vtype = reflect.PtrTo(vtype)
334 }
335
336 p.MapValProp.CustomType = p.CustomType
337 p.MapValProp.StdDuration = p.StdDuration
338 p.MapValProp.StdTime = p.StdTime
339 p.MapValProp.WktPointer = p.WktPointer
340 p.MapValProp.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
341 }
342 p.setTag(lockGetProp)
343 }
344
345 func (p *Properties) setTag(lockGetProp bool) {
346 if p.stype != nil {
347 if lockGetProp {
348 p.sprop = GetProperties(p.stype)
349 } else {
350 p.sprop = getPropertiesLocked(p.stype)
351 }
352 }
353 }
354
355 var (
356 marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
357 )
358
359
360 func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
361 p.init(typ, name, tag, f, true)
362 }
363
364 func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, lockGetProp bool) {
365
366 p.Name = name
367 p.OrigName = name
368 if tag == "" {
369 return
370 }
371 p.Parse(tag)
372 p.setFieldProps(typ, f, lockGetProp)
373 }
374
375 var (
376 propertiesMu sync.RWMutex
377 propertiesMap = make(map[reflect.Type]*StructProperties)
378 )
379
380
381
382 func GetProperties(t reflect.Type) *StructProperties {
383 if t.Kind() != reflect.Struct {
384 panic("proto: type must have kind struct")
385 }
386
387
388
389 propertiesMu.RLock()
390 sprop, ok := propertiesMap[t]
391 propertiesMu.RUnlock()
392 if ok {
393 return sprop
394 }
395
396 propertiesMu.Lock()
397 sprop = getPropertiesLocked(t)
398 propertiesMu.Unlock()
399 return sprop
400 }
401
402 type (
403 oneofFuncsIface interface {
404 XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
405 }
406 oneofWrappersIface interface {
407 XXX_OneofWrappers() []interface{}
408 }
409 )
410
411
412 func getPropertiesLocked(t reflect.Type) *StructProperties {
413 if prop, ok := propertiesMap[t]; ok {
414 return prop
415 }
416
417 prop := new(StructProperties)
418
419 propertiesMap[t] = prop
420
421
422 prop.Prop = make([]*Properties, t.NumField())
423 prop.order = make([]int, t.NumField())
424
425 isOneofMessage := false
426 for i := 0; i < t.NumField(); i++ {
427 f := t.Field(i)
428 p := new(Properties)
429 name := f.Name
430 p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
431
432 oneof := f.Tag.Get("protobuf_oneof")
433 if oneof != "" {
434 isOneofMessage = true
435
436 p.OrigName = oneof
437 }
438 prop.Prop[i] = p
439 prop.order[i] = i
440 if debug {
441 print(i, " ", f.Name, " ", t.String(), " ")
442 if p.Tag > 0 {
443 print(p.String())
444 }
445 print("\n")
446 }
447 }
448
449
450 sort.Sort(prop)
451
452 if isOneofMessage {
453 var oots []interface{}
454 switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
455 case oneofFuncsIface:
456 _, _, _, oots = m.XXX_OneofFuncs()
457 case oneofWrappersIface:
458 oots = m.XXX_OneofWrappers()
459 }
460 if len(oots) > 0 {
461
462 prop.OneofTypes = make(map[string]*OneofProperties)
463 for _, oot := range oots {
464 oop := &OneofProperties{
465 Type: reflect.ValueOf(oot).Type(),
466 Prop: new(Properties),
467 }
468 sft := oop.Type.Elem().Field(0)
469 oop.Prop.Name = sft.Name
470 oop.Prop.Parse(sft.Tag.Get("protobuf"))
471
472
473 for i := 0; i < t.NumField(); i++ {
474 f := t.Field(i)
475 if f.Type.Kind() != reflect.Interface {
476 continue
477 }
478 if !oop.Type.AssignableTo(f.Type) {
479 continue
480 }
481 oop.Field = i
482 break
483 }
484 prop.OneofTypes[oop.Prop.OrigName] = oop
485 }
486 }
487 }
488
489
490
491 reqCount := 0
492 prop.decoderOrigNames = make(map[string]int)
493 for i, p := range prop.Prop {
494 if strings.HasPrefix(p.Name, "XXX_") {
495
496
497 continue
498 }
499 if p.Required {
500 reqCount++
501 }
502 prop.decoderTags.put(p.Tag, i)
503 prop.decoderOrigNames[p.OrigName] = i
504 }
505 prop.reqCount = reqCount
506
507 return prop
508 }
509
510
511
512
513 var enumValueMaps = make(map[string]map[string]int32)
514 var enumStringMaps = make(map[string]map[int32]string)
515
516
517
518 func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) {
519 if _, ok := enumValueMaps[typeName]; ok {
520 panic("proto: duplicate enum registered: " + typeName)
521 }
522 enumValueMaps[typeName] = valueMap
523 if _, ok := enumStringMaps[typeName]; ok {
524 panic("proto: duplicate enum registered: " + typeName)
525 }
526 enumStringMaps[typeName] = unusedNameMap
527 }
528
529
530
531 func EnumValueMap(enumType string) map[string]int32 {
532 return enumValueMaps[enumType]
533 }
534
535
536
537 var (
538 protoTypedNils = make(map[string]Message)
539 protoMapTypes = make(map[string]reflect.Type)
540 revProtoTypes = make(map[reflect.Type]string)
541 )
542
543
544
545 func RegisterType(x Message, name string) {
546 if _, ok := protoTypedNils[name]; ok {
547
548 log.Printf("proto: duplicate proto type registered: %s", name)
549 return
550 }
551 t := reflect.TypeOf(x)
552 if v := reflect.ValueOf(x); v.Kind() == reflect.Ptr && v.Pointer() == 0 {
553
554
555 protoTypedNils[name] = x
556 } else {
557 protoTypedNils[name] = reflect.Zero(t).Interface().(Message)
558 }
559 revProtoTypes[t] = name
560 }
561
562
563
564 func RegisterMapType(x interface{}, name string) {
565 if reflect.TypeOf(x).Kind() != reflect.Map {
566 panic(fmt.Sprintf("RegisterMapType(%T, %q); want map", x, name))
567 }
568 if _, ok := protoMapTypes[name]; ok {
569 log.Printf("proto: duplicate proto type registered: %s", name)
570 return
571 }
572 t := reflect.TypeOf(x)
573 protoMapTypes[name] = t
574 revProtoTypes[t] = name
575 }
576
577
578 func MessageName(x Message) string {
579 type xname interface {
580 XXX_MessageName() string
581 }
582 if m, ok := x.(xname); ok {
583 return m.XXX_MessageName()
584 }
585 return revProtoTypes[reflect.TypeOf(x)]
586 }
587
588
589
590
591 func MessageType(name string) reflect.Type {
592 if t, ok := protoTypedNils[name]; ok {
593 return reflect.TypeOf(t)
594 }
595 return protoMapTypes[name]
596 }
597
598
599 var (
600 protoFiles = make(map[string][]byte)
601 )
602
603
604
605 func RegisterFile(filename string, fileDescriptor []byte) {
606 protoFiles[filename] = fileDescriptor
607 }
608
609
610 func FileDescriptor(filename string) []byte { return protoFiles[filename] }
611
View as plain text