OSDN Git Service

Merge pull request #41 from Bytom/dev
[bytom/vapor.git] / vendor / github.com / golang / protobuf / proto / properties.go
1 // Go support for Protocol Buffers - Google's data interchange format
2 //
3 // Copyright 2010 The Go Authors.  All rights reserved.
4 // https://github.com/golang/protobuf
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are
8 // met:
9 //
10 //     * Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 //     * Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following disclaimer
14 // in the documentation and/or other materials provided with the
15 // distribution.
16 //     * Neither the name of Google Inc. nor the names of its
17 // contributors may be used to endorse or promote products derived from
18 // this software without specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32 package proto
33
34 /*
35  * Routines for encoding data into the wire format for protocol buffers.
36  */
37
38 import (
39         "fmt"
40         "log"
41         "os"
42         "reflect"
43         "sort"
44         "strconv"
45         "strings"
46         "sync"
47 )
48
49 const debug bool = false
50
51 // Constants that identify the encoding of a value on the wire.
52 const (
53         WireVarint     = 0
54         WireFixed64    = 1
55         WireBytes      = 2
56         WireStartGroup = 3
57         WireEndGroup   = 4
58         WireFixed32    = 5
59 )
60
61 const startSize = 10 // initial slice/string sizes
62
63 // Encoders are defined in encode.go
64 // An encoder outputs the full representation of a field, including its
65 // tag and encoder type.
66 type encoder func(p *Buffer, prop *Properties, base structPointer) error
67
68 // A valueEncoder encodes a single integer in a particular encoding.
69 type valueEncoder func(o *Buffer, x uint64) error
70
71 // Sizers are defined in encode.go
72 // A sizer returns the encoded size of a field, including its tag and encoder
73 // type.
74 type sizer func(prop *Properties, base structPointer) int
75
76 // A valueSizer returns the encoded size of a single integer in a particular
77 // encoding.
78 type valueSizer func(x uint64) int
79
80 // Decoders are defined in decode.go
81 // A decoder creates a value from its wire representation.
82 // Unrecognized subelements are saved in unrec.
83 type decoder func(p *Buffer, prop *Properties, base structPointer) error
84
85 // A valueDecoder decodes a single integer in a particular encoding.
86 type valueDecoder func(o *Buffer) (x uint64, err error)
87
88 // A oneofMarshaler does the marshaling for all oneof fields in a message.
89 type oneofMarshaler func(Message, *Buffer) error
90
91 // A oneofUnmarshaler does the unmarshaling for a oneof field in a message.
92 type oneofUnmarshaler func(Message, int, int, *Buffer) (bool, error)
93
94 // A oneofSizer does the sizing for all oneof fields in a message.
95 type oneofSizer func(Message) int
96
97 // tagMap is an optimization over map[int]int for typical protocol buffer
98 // use-cases. Encoded protocol buffers are often in tag order with small tag
99 // numbers.
100 type tagMap struct {
101         fastTags []int
102         slowTags map[int]int
103 }
104
105 // tagMapFastLimit is the upper bound on the tag number that will be stored in
106 // the tagMap slice rather than its map.
107 const tagMapFastLimit = 1024
108
109 func (p *tagMap) get(t int) (int, bool) {
110         if t > 0 && t < tagMapFastLimit {
111                 if t >= len(p.fastTags) {
112                         return 0, false
113                 }
114                 fi := p.fastTags[t]
115                 return fi, fi >= 0
116         }
117         fi, ok := p.slowTags[t]
118         return fi, ok
119 }
120
121 func (p *tagMap) put(t int, fi int) {
122         if t > 0 && t < tagMapFastLimit {
123                 for len(p.fastTags) < t+1 {
124                         p.fastTags = append(p.fastTags, -1)
125                 }
126                 p.fastTags[t] = fi
127                 return
128         }
129         if p.slowTags == nil {
130                 p.slowTags = make(map[int]int)
131         }
132         p.slowTags[t] = fi
133 }
134
135 // StructProperties represents properties for all the fields of a struct.
136 // decoderTags and decoderOrigNames should only be used by the decoder.
137 type StructProperties struct {
138         Prop             []*Properties  // properties for each field
139         reqCount         int            // required count
140         decoderTags      tagMap         // map from proto tag to struct field number
141         decoderOrigNames map[string]int // map from original name to struct field number
142         order            []int          // list of struct field numbers in tag order
143         unrecField       field          // field id of the XXX_unrecognized []byte field
144         extendable       bool           // is this an extendable proto
145
146         oneofMarshaler   oneofMarshaler
147         oneofUnmarshaler oneofUnmarshaler
148         oneofSizer       oneofSizer
149         stype            reflect.Type
150
151         // OneofTypes contains information about the oneof fields in this message.
152         // It is keyed by the original name of a field.
153         OneofTypes map[string]*OneofProperties
154 }
155
156 // OneofProperties represents information about a specific field in a oneof.
157 type OneofProperties struct {
158         Type  reflect.Type // pointer to generated struct type for this oneof field
159         Field int          // struct field number of the containing oneof in the message
160         Prop  *Properties
161 }
162
163 // Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec.
164 // See encode.go, (*Buffer).enc_struct.
165
166 func (sp *StructProperties) Len() int { return len(sp.order) }
167 func (sp *StructProperties) Less(i, j int) bool {
168         return sp.Prop[sp.order[i]].Tag < sp.Prop[sp.order[j]].Tag
169 }
170 func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order[j], sp.order[i] }
171
172 // Properties represents the protocol-specific behavior of a single struct field.
173 type Properties struct {
174         Name     string // name of the field, for error messages
175         OrigName string // original name before protocol compiler (always set)
176         JSONName string // name to use for JSON; determined by protoc
177         Wire     string
178         WireType int
179         Tag      int
180         Required bool
181         Optional bool
182         Repeated bool
183         Packed   bool   // relevant for repeated primitives only
184         Enum     string // set for enum types only
185         proto3   bool   // whether this is known to be a proto3 field; set for []byte only
186         oneof    bool   // whether this is a oneof field
187
188         Default    string // default value
189         HasDefault bool   // whether an explicit default was provided
190         def_uint64 uint64
191
192         enc           encoder
193         valEnc        valueEncoder // set for bool and numeric types only
194         field         field
195         tagcode       []byte // encoding of EncodeVarint((Tag<<3)|WireType)
196         tagbuf        [8]byte
197         stype         reflect.Type      // set for struct types only
198         sprop         *StructProperties // set for struct types only
199         isMarshaler   bool
200         isUnmarshaler bool
201
202         mtype    reflect.Type // set for map types only
203         mkeyprop *Properties  // set for map types only
204         mvalprop *Properties  // set for map types only
205
206         size    sizer
207         valSize valueSizer // set for bool and numeric types only
208
209         dec    decoder
210         valDec valueDecoder // set for bool and numeric types only
211
212         // If this is a packable field, this will be the decoder for the packed version of the field.
213         packedDec decoder
214 }
215
216 // String formats the properties in the protobuf struct field tag style.
217 func (p *Properties) String() string {
218         s := p.Wire
219         s = ","
220         s += strconv.Itoa(p.Tag)
221         if p.Required {
222                 s += ",req"
223         }
224         if p.Optional {
225                 s += ",opt"
226         }
227         if p.Repeated {
228                 s += ",rep"
229         }
230         if p.Packed {
231                 s += ",packed"
232         }
233         s += ",name=" + p.OrigName
234         if p.JSONName != p.OrigName {
235                 s += ",json=" + p.JSONName
236         }
237         if p.proto3 {
238                 s += ",proto3"
239         }
240         if p.oneof {
241                 s += ",oneof"
242         }
243         if len(p.Enum) > 0 {
244                 s += ",enum=" + p.Enum
245         }
246         if p.HasDefault {
247                 s += ",def=" + p.Default
248         }
249         return s
250 }
251
252 // Parse populates p by parsing a string in the protobuf struct field tag style.
253 func (p *Properties) Parse(s string) {
254         // "bytes,49,opt,name=foo,def=hello!"
255         fields := strings.Split(s, ",") // breaks def=, but handled below.
256         if len(fields) < 2 {
257                 fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s)
258                 return
259         }
260
261         p.Wire = fields[0]
262         switch p.Wire {
263         case "varint":
264                 p.WireType = WireVarint
265                 p.valEnc = (*Buffer).EncodeVarint
266                 p.valDec = (*Buffer).DecodeVarint
267                 p.valSize = sizeVarint
268         case "fixed32":
269                 p.WireType = WireFixed32
270                 p.valEnc = (*Buffer).EncodeFixed32
271                 p.valDec = (*Buffer).DecodeFixed32
272                 p.valSize = sizeFixed32
273         case "fixed64":
274                 p.WireType = WireFixed64
275                 p.valEnc = (*Buffer).EncodeFixed64
276                 p.valDec = (*Buffer).DecodeFixed64
277                 p.valSize = sizeFixed64
278         case "zigzag32":
279                 p.WireType = WireVarint
280                 p.valEnc = (*Buffer).EncodeZigzag32
281                 p.valDec = (*Buffer).DecodeZigzag32
282                 p.valSize = sizeZigzag32
283         case "zigzag64":
284                 p.WireType = WireVarint
285                 p.valEnc = (*Buffer).EncodeZigzag64
286                 p.valDec = (*Buffer).DecodeZigzag64
287                 p.valSize = sizeZigzag64
288         case "bytes", "group":
289                 p.WireType = WireBytes
290                 // no numeric converter for non-numeric types
291         default:
292                 fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s)
293                 return
294         }
295
296         var err error
297         p.Tag, err = strconv.Atoi(fields[1])
298         if err != nil {
299                 return
300         }
301
302         for i := 2; i < len(fields); i++ {
303                 f := fields[i]
304                 switch {
305                 case f == "req":
306                         p.Required = true
307                 case f == "opt":
308                         p.Optional = true
309                 case f == "rep":
310                         p.Repeated = true
311                 case f == "packed":
312                         p.Packed = true
313                 case strings.HasPrefix(f, "name="):
314                         p.OrigName = f[5:]
315                 case strings.HasPrefix(f, "json="):
316                         p.JSONName = f[5:]
317                 case strings.HasPrefix(f, "enum="):
318                         p.Enum = f[5:]
319                 case f == "proto3":
320                         p.proto3 = true
321                 case f == "oneof":
322                         p.oneof = true
323                 case strings.HasPrefix(f, "def="):
324                         p.HasDefault = true
325                         p.Default = f[4:] // rest of string
326                         if i+1 < len(fields) {
327                                 // Commas aren't escaped, and def is always last.
328                                 p.Default += "," + strings.Join(fields[i+1:], ",")
329                                 break
330                         }
331                 }
332         }
333 }
334
335 func logNoSliceEnc(t1, t2 reflect.Type) {
336         fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2)
337 }
338
339 var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()
340
341 // Initialize the fields for encoding and decoding.
342 func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
343         p.enc = nil
344         p.dec = nil
345         p.size = nil
346
347         switch t1 := typ; t1.Kind() {
348         default:
349                 fmt.Fprintf(os.Stderr, "proto: no coders for %v\n", t1)
350
351         // proto3 scalar types
352
353         case reflect.Bool:
354                 p.enc = (*Buffer).enc_proto3_bool
355                 p.dec = (*Buffer).dec_proto3_bool
356                 p.size = size_proto3_bool
357         case reflect.Int32:
358                 p.enc = (*Buffer).enc_proto3_int32
359                 p.dec = (*Buffer).dec_proto3_int32
360                 p.size = size_proto3_int32
361         case reflect.Uint32:
362                 p.enc = (*Buffer).enc_proto3_uint32
363                 p.dec = (*Buffer).dec_proto3_int32 // can reuse
364                 p.size = size_proto3_uint32
365         case reflect.Int64, reflect.Uint64:
366                 p.enc = (*Buffer).enc_proto3_int64
367                 p.dec = (*Buffer).dec_proto3_int64
368                 p.size = size_proto3_int64
369         case reflect.Float32:
370                 p.enc = (*Buffer).enc_proto3_uint32 // can just treat them as bits
371                 p.dec = (*Buffer).dec_proto3_int32
372                 p.size = size_proto3_uint32
373         case reflect.Float64:
374                 p.enc = (*Buffer).enc_proto3_int64 // can just treat them as bits
375                 p.dec = (*Buffer).dec_proto3_int64
376                 p.size = size_proto3_int64
377         case reflect.String:
378                 p.enc = (*Buffer).enc_proto3_string
379                 p.dec = (*Buffer).dec_proto3_string
380                 p.size = size_proto3_string
381
382         case reflect.Ptr:
383                 switch t2 := t1.Elem(); t2.Kind() {
384                 default:
385                         fmt.Fprintf(os.Stderr, "proto: no encoder function for %v -> %v\n", t1, t2)
386                         break
387                 case reflect.Bool:
388                         p.enc = (*Buffer).enc_bool
389                         p.dec = (*Buffer).dec_bool
390                         p.size = size_bool
391                 case reflect.Int32:
392                         p.enc = (*Buffer).enc_int32
393                         p.dec = (*Buffer).dec_int32
394                         p.size = size_int32
395                 case reflect.Uint32:
396                         p.enc = (*Buffer).enc_uint32
397                         p.dec = (*Buffer).dec_int32 // can reuse
398                         p.size = size_uint32
399                 case reflect.Int64, reflect.Uint64:
400                         p.enc = (*Buffer).enc_int64
401                         p.dec = (*Buffer).dec_int64
402                         p.size = size_int64
403                 case reflect.Float32:
404                         p.enc = (*Buffer).enc_uint32 // can just treat them as bits
405                         p.dec = (*Buffer).dec_int32
406                         p.size = size_uint32
407                 case reflect.Float64:
408                         p.enc = (*Buffer).enc_int64 // can just treat them as bits
409                         p.dec = (*Buffer).dec_int64
410                         p.size = size_int64
411                 case reflect.String:
412                         p.enc = (*Buffer).enc_string
413                         p.dec = (*Buffer).dec_string
414                         p.size = size_string
415                 case reflect.Struct:
416                         p.stype = t1.Elem()
417                         p.isMarshaler = isMarshaler(t1)
418                         p.isUnmarshaler = isUnmarshaler(t1)
419                         if p.Wire == "bytes" {
420                                 p.enc = (*Buffer).enc_struct_message
421                                 p.dec = (*Buffer).dec_struct_message
422                                 p.size = size_struct_message
423                         } else {
424                                 p.enc = (*Buffer).enc_struct_group
425                                 p.dec = (*Buffer).dec_struct_group
426                                 p.size = size_struct_group
427                         }
428                 }
429
430         case reflect.Slice:
431                 switch t2 := t1.Elem(); t2.Kind() {
432                 default:
433                         logNoSliceEnc(t1, t2)
434                         break
435                 case reflect.Bool:
436                         if p.Packed {
437                                 p.enc = (*Buffer).enc_slice_packed_bool
438                                 p.size = size_slice_packed_bool
439                         } else {
440                                 p.enc = (*Buffer).enc_slice_bool
441                                 p.size = size_slice_bool
442                         }
443                         p.dec = (*Buffer).dec_slice_bool
444                         p.packedDec = (*Buffer).dec_slice_packed_bool
445                 case reflect.Int32:
446                         if p.Packed {
447                                 p.enc = (*Buffer).enc_slice_packed_int32
448                                 p.size = size_slice_packed_int32
449                         } else {
450                                 p.enc = (*Buffer).enc_slice_int32
451                                 p.size = size_slice_int32
452                         }
453                         p.dec = (*Buffer).dec_slice_int32
454                         p.packedDec = (*Buffer).dec_slice_packed_int32
455                 case reflect.Uint32:
456                         if p.Packed {
457                                 p.enc = (*Buffer).enc_slice_packed_uint32
458                                 p.size = size_slice_packed_uint32
459                         } else {
460                                 p.enc = (*Buffer).enc_slice_uint32
461                                 p.size = size_slice_uint32
462                         }
463                         p.dec = (*Buffer).dec_slice_int32
464                         p.packedDec = (*Buffer).dec_slice_packed_int32
465                 case reflect.Int64, reflect.Uint64:
466                         if p.Packed {
467                                 p.enc = (*Buffer).enc_slice_packed_int64
468                                 p.size = size_slice_packed_int64
469                         } else {
470                                 p.enc = (*Buffer).enc_slice_int64
471                                 p.size = size_slice_int64
472                         }
473                         p.dec = (*Buffer).dec_slice_int64
474                         p.packedDec = (*Buffer).dec_slice_packed_int64
475                 case reflect.Uint8:
476                         p.dec = (*Buffer).dec_slice_byte
477                         if p.proto3 {
478                                 p.enc = (*Buffer).enc_proto3_slice_byte
479                                 p.size = size_proto3_slice_byte
480                         } else {
481                                 p.enc = (*Buffer).enc_slice_byte
482                                 p.size = size_slice_byte
483                         }
484                 case reflect.Float32, reflect.Float64:
485                         switch t2.Bits() {
486                         case 32:
487                                 // can just treat them as bits
488                                 if p.Packed {
489                                         p.enc = (*Buffer).enc_slice_packed_uint32
490                                         p.size = size_slice_packed_uint32
491                                 } else {
492                                         p.enc = (*Buffer).enc_slice_uint32
493                                         p.size = size_slice_uint32
494                                 }
495                                 p.dec = (*Buffer).dec_slice_int32
496                                 p.packedDec = (*Buffer).dec_slice_packed_int32
497                         case 64:
498                                 // can just treat them as bits
499                                 if p.Packed {
500                                         p.enc = (*Buffer).enc_slice_packed_int64
501                                         p.size = size_slice_packed_int64
502                                 } else {
503                                         p.enc = (*Buffer).enc_slice_int64
504                                         p.size = size_slice_int64
505                                 }
506                                 p.dec = (*Buffer).dec_slice_int64
507                                 p.packedDec = (*Buffer).dec_slice_packed_int64
508                         default:
509                                 logNoSliceEnc(t1, t2)
510                                 break
511                         }
512                 case reflect.String:
513                         p.enc = (*Buffer).enc_slice_string
514                         p.dec = (*Buffer).dec_slice_string
515                         p.size = size_slice_string
516                 case reflect.Ptr:
517                         switch t3 := t2.Elem(); t3.Kind() {
518                         default:
519                                 fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3)
520                                 break
521                         case reflect.Struct:
522                                 p.stype = t2.Elem()
523                                 p.isMarshaler = isMarshaler(t2)
524                                 p.isUnmarshaler = isUnmarshaler(t2)
525                                 if p.Wire == "bytes" {
526                                         p.enc = (*Buffer).enc_slice_struct_message
527                                         p.dec = (*Buffer).dec_slice_struct_message
528                                         p.size = size_slice_struct_message
529                                 } else {
530                                         p.enc = (*Buffer).enc_slice_struct_group
531                                         p.dec = (*Buffer).dec_slice_struct_group
532                                         p.size = size_slice_struct_group
533                                 }
534                         }
535                 case reflect.Slice:
536                         switch t2.Elem().Kind() {
537                         default:
538                                 fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem())
539                                 break
540                         case reflect.Uint8:
541                                 p.enc = (*Buffer).enc_slice_slice_byte
542                                 p.dec = (*Buffer).dec_slice_slice_byte
543                                 p.size = size_slice_slice_byte
544                         }
545                 }
546
547         case reflect.Map:
548                 p.enc = (*Buffer).enc_new_map
549                 p.dec = (*Buffer).dec_new_map
550                 p.size = size_new_map
551
552                 p.mtype = t1
553                 p.mkeyprop = &Properties{}
554                 p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
555                 p.mvalprop = &Properties{}
556                 vtype := p.mtype.Elem()
557                 if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice {
558                         // The value type is not a message (*T) or bytes ([]byte),
559                         // so we need encoders for the pointer to this type.
560                         vtype = reflect.PtrTo(vtype)
561                 }
562                 p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
563         }
564
565         // precalculate tag code
566         wire := p.WireType
567         if p.Packed {
568                 wire = WireBytes
569         }
570         x := uint32(p.Tag)<<3 | uint32(wire)
571         i := 0
572         for i = 0; x > 127; i++ {
573                 p.tagbuf[i] = 0x80 | uint8(x&0x7F)
574                 x >>= 7
575         }
576         p.tagbuf[i] = uint8(x)
577         p.tagcode = p.tagbuf[0 : i+1]
578
579         if p.stype != nil {
580                 if lockGetProp {
581                         p.sprop = GetProperties(p.stype)
582                 } else {
583                         p.sprop = getPropertiesLocked(p.stype)
584                 }
585         }
586 }
587
588 var (
589         marshalerType   = reflect.TypeOf((*Marshaler)(nil)).Elem()
590         unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
591 )
592
593 // isMarshaler reports whether type t implements Marshaler.
594 func isMarshaler(t reflect.Type) bool {
595         // We're checking for (likely) pointer-receiver methods
596         // so if t is not a pointer, something is very wrong.
597         // The calls above only invoke isMarshaler on pointer types.
598         if t.Kind() != reflect.Ptr {
599                 panic("proto: misuse of isMarshaler")
600         }
601         return t.Implements(marshalerType)
602 }
603
604 // isUnmarshaler reports whether type t implements Unmarshaler.
605 func isUnmarshaler(t reflect.Type) bool {
606         // We're checking for (likely) pointer-receiver methods
607         // so if t is not a pointer, something is very wrong.
608         // The calls above only invoke isUnmarshaler on pointer types.
609         if t.Kind() != reflect.Ptr {
610                 panic("proto: misuse of isUnmarshaler")
611         }
612         return t.Implements(unmarshalerType)
613 }
614
615 // Init populates the properties from a protocol buffer struct tag.
616 func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
617         p.init(typ, name, tag, f, true)
618 }
619
620 func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, lockGetProp bool) {
621         // "bytes,49,opt,def=hello!"
622         p.Name = name
623         p.OrigName = name
624         if f != nil {
625                 p.field = toField(f)
626         }
627         if tag == "" {
628                 return
629         }
630         p.Parse(tag)
631         p.setEncAndDec(typ, f, lockGetProp)
632 }
633
634 var (
635         propertiesMu  sync.RWMutex
636         propertiesMap = make(map[reflect.Type]*StructProperties)
637 )
638
639 // GetProperties returns the list of properties for the type represented by t.
640 // t must represent a generated struct type of a protocol message.
641 func GetProperties(t reflect.Type) *StructProperties {
642         if t.Kind() != reflect.Struct {
643                 panic("proto: type must have kind struct")
644         }
645
646         // Most calls to GetProperties in a long-running program will be
647         // retrieving details for types we have seen before.
648         propertiesMu.RLock()
649         sprop, ok := propertiesMap[t]
650         propertiesMu.RUnlock()
651         if ok {
652                 if collectStats {
653                         stats.Chit++
654                 }
655                 return sprop
656         }
657
658         propertiesMu.Lock()
659         sprop = getPropertiesLocked(t)
660         propertiesMu.Unlock()
661         return sprop
662 }
663
664 // getPropertiesLocked requires that propertiesMu is held.
665 func getPropertiesLocked(t reflect.Type) *StructProperties {
666         if prop, ok := propertiesMap[t]; ok {
667                 if collectStats {
668                         stats.Chit++
669                 }
670                 return prop
671         }
672         if collectStats {
673                 stats.Cmiss++
674         }
675
676         prop := new(StructProperties)
677         // in case of recursive protos, fill this in now.
678         propertiesMap[t] = prop
679
680         // build properties
681         prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) ||
682                 reflect.PtrTo(t).Implements(extendableProtoV1Type)
683         prop.unrecField = invalidField
684         prop.Prop = make([]*Properties, t.NumField())
685         prop.order = make([]int, t.NumField())
686
687         for i := 0; i < t.NumField(); i++ {
688                 f := t.Field(i)
689                 p := new(Properties)
690                 name := f.Name
691                 p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
692
693                 if f.Name == "XXX_InternalExtensions" { // special case
694                         p.enc = (*Buffer).enc_exts
695                         p.dec = nil // not needed
696                         p.size = size_exts
697                 } else if f.Name == "XXX_extensions" { // special case
698                         p.enc = (*Buffer).enc_map
699                         p.dec = nil // not needed
700                         p.size = size_map
701                 } else if f.Name == "XXX_unrecognized" { // special case
702                         prop.unrecField = toField(&f)
703                 }
704                 oneof := f.Tag.Get("protobuf_oneof") // special case
705                 if oneof != "" {
706                         // Oneof fields don't use the traditional protobuf tag.
707                         p.OrigName = oneof
708                 }
709                 prop.Prop[i] = p
710                 prop.order[i] = i
711                 if debug {
712                         print(i, " ", f.Name, " ", t.String(), " ")
713                         if p.Tag > 0 {
714                                 print(p.String())
715                         }
716                         print("\n")
717                 }
718                 if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && oneof == "" {
719                         fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]")
720                 }
721         }
722
723         // Re-order prop.order.
724         sort.Sort(prop)
725
726         type oneofMessage interface {
727                 XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
728         }
729         if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
730                 var oots []interface{}
731                 prop.oneofMarshaler, prop.oneofUnmarshaler, prop.oneofSizer, oots = om.XXX_OneofFuncs()
732                 prop.stype = t
733
734                 // Interpret oneof metadata.
735                 prop.OneofTypes = make(map[string]*OneofProperties)
736                 for _, oot := range oots {
737                         oop := &OneofProperties{
738                                 Type: reflect.ValueOf(oot).Type(), // *T
739                                 Prop: new(Properties),
740                         }
741                         sft := oop.Type.Elem().Field(0)
742                         oop.Prop.Name = sft.Name
743                         oop.Prop.Parse(sft.Tag.Get("protobuf"))
744                         // There will be exactly one interface field that
745                         // this new value is assignable to.
746                         for i := 0; i < t.NumField(); i++ {
747                                 f := t.Field(i)
748                                 if f.Type.Kind() != reflect.Interface {
749                                         continue
750                                 }
751                                 if !oop.Type.AssignableTo(f.Type) {
752                                         continue
753                                 }
754                                 oop.Field = i
755                                 break
756                         }
757                         prop.OneofTypes[oop.Prop.OrigName] = oop
758                 }
759         }
760
761         // build required counts
762         // build tags
763         reqCount := 0
764         prop.decoderOrigNames = make(map[string]int)
765         for i, p := range prop.Prop {
766                 if strings.HasPrefix(p.Name, "XXX_") {
767                         // Internal fields should not appear in tags/origNames maps.
768                         // They are handled specially when encoding and decoding.
769                         continue
770                 }
771                 if p.Required {
772                         reqCount++
773                 }
774                 prop.decoderTags.put(p.Tag, i)
775                 prop.decoderOrigNames[p.OrigName] = i
776         }
777         prop.reqCount = reqCount
778
779         return prop
780 }
781
782 // Return the Properties object for the x[0]'th field of the structure.
783 func propByIndex(t reflect.Type, x []int) *Properties {
784         if len(x) != 1 {
785                 fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t)
786                 return nil
787         }
788         prop := GetProperties(t)
789         return prop.Prop[x[0]]
790 }
791
792 // Get the address and type of a pointer to a struct from an interface.
793 func getbase(pb Message) (t reflect.Type, b structPointer, err error) {
794         if pb == nil {
795                 err = ErrNil
796                 return
797         }
798         // get the reflect type of the pointer to the struct.
799         t = reflect.TypeOf(pb)
800         // get the address of the struct.
801         value := reflect.ValueOf(pb)
802         b = toStructPointer(value)
803         return
804 }
805
806 // A global registry of enum types.
807 // The generated code will register the generated maps by calling RegisterEnum.
808
809 var enumValueMaps = make(map[string]map[string]int32)
810
811 // RegisterEnum is called from the generated code to install the enum descriptor
812 // maps into the global table to aid parsing text format protocol buffers.
813 func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) {
814         if _, ok := enumValueMaps[typeName]; ok {
815                 panic("proto: duplicate enum registered: " + typeName)
816         }
817         enumValueMaps[typeName] = valueMap
818 }
819
820 // EnumValueMap returns the mapping from names to integers of the
821 // enum type enumType, or a nil if not found.
822 func EnumValueMap(enumType string) map[string]int32 {
823         return enumValueMaps[enumType]
824 }
825
826 // A registry of all linked message types.
827 // The string is a fully-qualified proto name ("pkg.Message").
828 var (
829         protoTypes    = make(map[string]reflect.Type)
830         revProtoTypes = make(map[reflect.Type]string)
831 )
832
833 // RegisterType is called from generated code and maps from the fully qualified
834 // proto name to the type (pointer to struct) of the protocol buffer.
835 func RegisterType(x Message, name string) {
836         if _, ok := protoTypes[name]; ok {
837                 // TODO: Some day, make this a panic.
838                 log.Printf("proto: duplicate proto type registered: %s", name)
839                 return
840         }
841         t := reflect.TypeOf(x)
842         protoTypes[name] = t
843         revProtoTypes[t] = name
844 }
845
846 // MessageName returns the fully-qualified proto name for the given message type.
847 func MessageName(x Message) string {
848         type xname interface {
849                 XXX_MessageName() string
850         }
851         if m, ok := x.(xname); ok {
852                 return m.XXX_MessageName()
853         }
854         return revProtoTypes[reflect.TypeOf(x)]
855 }
856
857 // MessageType returns the message type (pointer to struct) for a named message.
858 func MessageType(name string) reflect.Type { return protoTypes[name] }
859
860 // A registry of all linked proto files.
861 var (
862         protoFiles = make(map[string][]byte) // file name => fileDescriptor
863 )
864
865 // RegisterFile is called from generated code and maps from the
866 // full file name of a .proto file to its compressed FileDescriptorProto.
867 func RegisterFile(filename string, fileDescriptor []byte) {
868         protoFiles[filename] = fileDescriptor
869 }
870
871 // FileDescriptor returns the compressed FileDescriptorProto for a .proto file.
872 func FileDescriptor(filename string) []byte { return protoFiles[filename] }