• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
32package proto
33
34/*
35 * Routines for encoding data into the wire format for protocol buffers.
36 */
37
38import (
39	"fmt"
40	"log"
41	"os"
42	"reflect"
43	"sort"
44	"strconv"
45	"strings"
46	"sync"
47)
48
49const debug bool = false
50
51// Constants that identify the encoding of a value on the wire.
52const (
53	WireVarint     = 0
54	WireFixed64    = 1
55	WireBytes      = 2
56	WireStartGroup = 3
57	WireEndGroup   = 4
58	WireFixed32    = 5
59)
60
61const 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.
66type encoder func(p *Buffer, prop *Properties, base structPointer) error
67
68// A valueEncoder encodes a single integer in a particular encoding.
69type 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.
74type sizer func(prop *Properties, base structPointer) int
75
76// A valueSizer returns the encoded size of a single integer in a particular
77// encoding.
78type 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.
83type decoder func(p *Buffer, prop *Properties, base structPointer) error
84
85// A valueDecoder decodes a single integer in a particular encoding.
86type valueDecoder func(o *Buffer) (x uint64, err error)
87
88// A oneofMarshaler does the marshaling for all oneof fields in a message.
89type oneofMarshaler func(Message, *Buffer) error
90
91// A oneofUnmarshaler does the unmarshaling for a oneof field in a message.
92type oneofUnmarshaler func(Message, int, int, *Buffer) (bool, error)
93
94// A oneofSizer does the sizing for all oneof fields in a message.
95type 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.
100type 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.
107const tagMapFastLimit = 1024
108
109func (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
121func (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.
137type 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.
157type 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
166func (sp *StructProperties) Len() int { return len(sp.order) }
167func (sp *StructProperties) Less(i, j int) bool {
168	return sp.Prop[sp.order[i]].Tag < sp.Prop[sp.order[j]].Tag
169}
170func (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.
173type 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.
217func (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.
253func (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
335func logNoSliceEnc(t1, t2 reflect.Type) {
336	fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2)
337}
338
339var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()
340
341// Initialize the fields for encoding and decoding.
342func (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
588var (
589	marshalerType   = reflect.TypeOf((*Marshaler)(nil)).Elem()
590	unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
591)
592
593// isMarshaler reports whether type t implements Marshaler.
594func 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.
605func 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.
616func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
617	p.init(typ, name, tag, f, true)
618}
619
620func (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
634var (
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.
641func 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.
665func 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.
783func 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.
793func 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
809var 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.
813func 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.
822func 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").
828var (
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.
835func 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.
847func 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.
858func MessageType(name string) reflect.Type { return protoTypes[name] }
859
860// A registry of all linked proto files.
861var (
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.
867func RegisterFile(filename string, fileDescriptor []byte) {
868	protoFiles[filename] = fileDescriptor
869}
870
871// FileDescriptor returns the compressed FileDescriptorProto for a .proto file.
872func FileDescriptor(filename string) []byte { return protoFiles[filename] }
873