blob: b4aaac5789737df94b56f51572850d8b519b7cc0 [file] [log] [blame]
Rob Pikeaaa3a622010-03-20 22:32:34 -07001// Go support for Protocol Buffers - Google's data interchange format
2//
David Symondsee6e9c52012-11-29 08:51:07 +11003// Copyright 2010 The Go Authors. All rights reserved.
David Symonds558f13f2014-11-24 10:28:53 +11004// https://github.com/golang/protobuf
Rob Pikeaaa3a622010-03-20 22:32:34 -07005//
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"
David Symondsa7f1e752015-11-02 15:31:00 +110040 "log"
Rob Pikeaaa3a622010-03-20 22:32:34 -070041 "os"
42 "reflect"
David Symondsd15e81b2011-10-03 14:31:12 -070043 "sort"
Rob Pikeaaa3a622010-03-20 22:32:34 -070044 "strconv"
45 "strings"
46 "sync"
Rob Pikeaaa3a622010-03-20 22:32:34 -070047)
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
David Symonds0bf1ad52013-10-11 09:07:50 +110063// Encoders are defined in encode.go
Rob Pikeaaa3a622010-03-20 22:32:34 -070064// An encoder outputs the full representation of a field, including its
65// tag and encoder type.
Russ Coxd4ce3f12012-09-12 10:36:26 +100066type encoder func(p *Buffer, prop *Properties, base structPointer) error
Rob Pikeaaa3a622010-03-20 22:32:34 -070067
68// A valueEncoder encodes a single integer in a particular encoding.
Rob Pikea17fdd92011-11-02 12:43:05 -070069type valueEncoder func(o *Buffer, x uint64) error
Rob Pikeaaa3a622010-03-20 22:32:34 -070070
David Symonds0bf1ad52013-10-11 09:07:50 +110071// 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
Rob Pikeaaa3a622010-03-20 22:32:34 -070080// Decoders are defined in decode.go
81// A decoder creates a value from its wire representation.
82// Unrecognized subelements are saved in unrec.
Russ Coxd4ce3f12012-09-12 10:36:26 +100083type decoder func(p *Buffer, prop *Properties, base structPointer) error
Rob Pikeaaa3a622010-03-20 22:32:34 -070084
85// A valueDecoder decodes a single integer in a particular encoding.
Rob Pikea17fdd92011-11-02 12:43:05 -070086type valueDecoder func(o *Buffer) (x uint64, err error)
Rob Pikeaaa3a622010-03-20 22:32:34 -070087
David Symonds59b73b32015-08-24 13:22:02 +100088// 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
David Symonds6a6f82c2012-08-22 09:18:54 +100094// tagMap is an optimization over map[int]int for typical protocol buffer
95// use-cases. Encoded protocol buffers are often in tag order with small tag
96// numbers.
97type tagMap struct {
98 fastTags []int
99 slowTags map[int]int
100}
101
102// tagMapFastLimit is the upper bound on the tag number that will be stored in
103// the tagMap slice rather than its map.
104const tagMapFastLimit = 1024
105
106func (p *tagMap) get(t int) (int, bool) {
107 if t > 0 && t < tagMapFastLimit {
108 if t >= len(p.fastTags) {
109 return 0, false
110 }
111 fi := p.fastTags[t]
112 return fi, fi >= 0
113 }
114 fi, ok := p.slowTags[t]
115 return fi, ok
116}
117
118func (p *tagMap) put(t int, fi int) {
119 if t > 0 && t < tagMapFastLimit {
120 for len(p.fastTags) < t+1 {
121 p.fastTags = append(p.fastTags, -1)
122 }
123 p.fastTags[t] = fi
124 return
125 }
126 if p.slowTags == nil {
127 p.slowTags = make(map[int]int)
128 }
129 p.slowTags[t] = fi
130}
131
Rob Pikeaaa3a622010-03-20 22:32:34 -0700132// StructProperties represents properties for all the fields of a struct.
David Symonds2bba1b22012-09-26 14:53:08 +1000133// decoderTags and decoderOrigNames should only be used by the decoder.
Rob Pikeaaa3a622010-03-20 22:32:34 -0700134type StructProperties struct {
David Symonds2bba1b22012-09-26 14:53:08 +1000135 Prop []*Properties // properties for each field
136 reqCount int // required count
137 decoderTags tagMap // map from proto tag to struct field number
138 decoderOrigNames map[string]int // map from original name to struct field number
139 order []int // list of struct field numbers in tag order
140 unrecField field // field id of the XXX_unrecognized []byte field
141 extendable bool // is this an extendable proto
David Symonds59b73b32015-08-24 13:22:02 +1000142
143 oneofMarshaler oneofMarshaler
144 oneofUnmarshaler oneofUnmarshaler
145 stype reflect.Type
David Symonds1baed092015-08-25 15:42:00 +1000146
147 // OneofTypes contains information about the oneof fields in this message.
148 // It is keyed by the original name of a field.
149 OneofTypes map[string]*OneofProperties
150}
151
152// OneofProperties represents information about a specific field in a oneof.
153type OneofProperties struct {
154 Type reflect.Type // pointer to generated struct type for this oneof field
155 Field int // struct field number of the containing oneof in the message
156 Prop *Properties
Rob Pikeaaa3a622010-03-20 22:32:34 -0700157}
158
David Symondsd15e81b2011-10-03 14:31:12 -0700159// Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec.
David Symonds0bf1ad52013-10-11 09:07:50 +1100160// See encode.go, (*Buffer).enc_struct.
David Symondsd15e81b2011-10-03 14:31:12 -0700161
162func (sp *StructProperties) Len() int { return len(sp.order) }
163func (sp *StructProperties) Less(i, j int) bool {
164 return sp.Prop[sp.order[i]].Tag < sp.Prop[sp.order[j]].Tag
165}
166func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order[j], sp.order[i] }
167
Rob Pikeaaa3a622010-03-20 22:32:34 -0700168// Properties represents the protocol-specific behavior of a single struct field.
169type Properties struct {
David Symonds7e810982014-08-12 13:11:17 +1000170 Name string // name of the field, for error messages
171 OrigName string // original name before protocol compiler (always set)
172 Wire string
173 WireType int
174 Tag int
175 Required bool
176 Optional bool
177 Repeated bool
178 Packed bool // relevant for repeated primitives only
179 Enum string // set for enum types only
David Symondsabd3b412014-11-28 11:43:44 +1100180 proto3 bool // whether this is known to be a proto3 field; set for []byte only
David Symonds535a1042015-09-11 08:27:00 +1000181 oneof bool // whether this is a oneof field
David Symonds7e810982014-08-12 13:11:17 +1000182
Rob Pikeaaa3a622010-03-20 22:32:34 -0700183 Default string // default value
David Symonds7e810982014-08-12 13:11:17 +1000184 HasDefault bool // whether an explicit default was provided
Rob Pikeaaa3a622010-03-20 22:32:34 -0700185 def_uint64 uint64
186
David Symondsa80b2822012-03-14 14:31:25 +1100187 enc encoder
188 valEnc valueEncoder // set for bool and numeric types only
Russ Coxd4ce3f12012-09-12 10:36:26 +1000189 field field
David Symondsa80b2822012-03-14 14:31:25 +1100190 tagcode []byte // encoding of EncodeVarint((Tag<<3)|WireType)
191 tagbuf [8]byte
David Symondsc0287172012-08-15 11:10:30 +1000192 stype reflect.Type // set for struct types only
193 sprop *StructProperties // set for struct types only
David Symondsa80b2822012-03-14 14:31:25 +1100194 isMarshaler bool
195 isUnmarshaler bool
Rob Pikeaaa3a622010-03-20 22:32:34 -0700196
David Symonds3ea3e052014-12-22 16:15:28 +1100197 mtype reflect.Type // set for map types only
198 mkeyprop *Properties // set for map types only
199 mvalprop *Properties // set for map types only
200
David Symonds0bf1ad52013-10-11 09:07:50 +1100201 size sizer
202 valSize valueSizer // set for bool and numeric types only
203
David Symonds049646b2011-10-21 11:13:45 +1100204 dec decoder
205 valDec valueDecoder // set for bool and numeric types only
David Symonds5b7775e2010-12-01 10:09:04 +1100206
207 // If this is a packable field, this will be the decoder for the packed version of the field.
208 packedDec decoder
Rob Pikeaaa3a622010-03-20 22:32:34 -0700209}
210
David Symonds8935abf2011-07-04 15:53:16 +1000211// String formats the properties in the protobuf struct field tag style.
Rob Pikeaaa3a622010-03-20 22:32:34 -0700212func (p *Properties) String() string {
213 s := p.Wire
214 s = ","
215 s += strconv.Itoa(p.Tag)
216 if p.Required {
217 s += ",req"
218 }
219 if p.Optional {
220 s += ",opt"
221 }
222 if p.Repeated {
223 s += ",rep"
224 }
David Symonds5b7775e2010-12-01 10:09:04 +1100225 if p.Packed {
226 s += ",packed"
227 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700228 if p.OrigName != p.Name {
229 s += ",name=" + p.OrigName
230 }
David Symondsabd3b412014-11-28 11:43:44 +1100231 if p.proto3 {
232 s += ",proto3"
233 }
David Symonds535a1042015-09-11 08:27:00 +1000234 if p.oneof {
235 s += ",oneof"
236 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700237 if len(p.Enum) > 0 {
238 s += ",enum=" + p.Enum
239 }
David Symonds7e810982014-08-12 13:11:17 +1000240 if p.HasDefault {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700241 s += ",def=" + p.Default
242 }
243 return s
244}
245
David Symonds8935abf2011-07-04 15:53:16 +1000246// Parse populates p by parsing a string in the protobuf struct field tag style.
Rob Pikeaaa3a622010-03-20 22:32:34 -0700247func (p *Properties) Parse(s string) {
David Symondsa7e9ef92012-01-18 18:27:58 +1100248 // "bytes,49,opt,name=foo,def=hello!"
David Symonds8935abf2011-07-04 15:53:16 +1000249 fields := strings.Split(s, ",") // breaks def=, but handled below.
Rob Pikeaaa3a622010-03-20 22:32:34 -0700250 if len(fields) < 2 {
251 fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s)
252 return
253 }
254
255 p.Wire = fields[0]
256 switch p.Wire {
257 case "varint":
258 p.WireType = WireVarint
259 p.valEnc = (*Buffer).EncodeVarint
260 p.valDec = (*Buffer).DecodeVarint
David Symonds0bf1ad52013-10-11 09:07:50 +1100261 p.valSize = sizeVarint
Rob Pikeaaa3a622010-03-20 22:32:34 -0700262 case "fixed32":
263 p.WireType = WireFixed32
264 p.valEnc = (*Buffer).EncodeFixed32
265 p.valDec = (*Buffer).DecodeFixed32
David Symonds0bf1ad52013-10-11 09:07:50 +1100266 p.valSize = sizeFixed32
Rob Pikeaaa3a622010-03-20 22:32:34 -0700267 case "fixed64":
268 p.WireType = WireFixed64
269 p.valEnc = (*Buffer).EncodeFixed64
270 p.valDec = (*Buffer).DecodeFixed64
David Symonds0bf1ad52013-10-11 09:07:50 +1100271 p.valSize = sizeFixed64
Rob Pikeaaa3a622010-03-20 22:32:34 -0700272 case "zigzag32":
273 p.WireType = WireVarint
274 p.valEnc = (*Buffer).EncodeZigzag32
275 p.valDec = (*Buffer).DecodeZigzag32
David Symonds0bf1ad52013-10-11 09:07:50 +1100276 p.valSize = sizeZigzag32
Rob Pikeaaa3a622010-03-20 22:32:34 -0700277 case "zigzag64":
278 p.WireType = WireVarint
279 p.valEnc = (*Buffer).EncodeZigzag64
280 p.valDec = (*Buffer).DecodeZigzag64
David Symonds0bf1ad52013-10-11 09:07:50 +1100281 p.valSize = sizeZigzag64
Rob Pikeaaa3a622010-03-20 22:32:34 -0700282 case "bytes", "group":
283 p.WireType = WireBytes
284 // no numeric converter for non-numeric types
285 default:
286 fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s)
287 return
288 }
289
Rob Pikea17fdd92011-11-02 12:43:05 -0700290 var err error
Rob Pikeaaa3a622010-03-20 22:32:34 -0700291 p.Tag, err = strconv.Atoi(fields[1])
292 if err != nil {
293 return
294 }
295
296 for i := 2; i < len(fields); i++ {
297 f := fields[i]
298 switch {
299 case f == "req":
300 p.Required = true
301 case f == "opt":
302 p.Optional = true
303 case f == "rep":
304 p.Repeated = true
David Symonds5b7775e2010-12-01 10:09:04 +1100305 case f == "packed":
306 p.Packed = true
David Symondsa7e9ef92012-01-18 18:27:58 +1100307 case strings.HasPrefix(f, "name="):
Albert Strasheim4676f6a2013-04-07 08:59:06 +1000308 p.OrigName = f[5:]
David Symondsa7e9ef92012-01-18 18:27:58 +1100309 case strings.HasPrefix(f, "enum="):
Albert Strasheim4676f6a2013-04-07 08:59:06 +1000310 p.Enum = f[5:]
David Symondsabd3b412014-11-28 11:43:44 +1100311 case f == "proto3":
312 p.proto3 = true
David Symonds535a1042015-09-11 08:27:00 +1000313 case f == "oneof":
314 p.oneof = true
David Symondsa7e9ef92012-01-18 18:27:58 +1100315 case strings.HasPrefix(f, "def="):
David Symonds7e810982014-08-12 13:11:17 +1000316 p.HasDefault = true
Albert Strasheim4676f6a2013-04-07 08:59:06 +1000317 p.Default = f[4:] // rest of string
Rob Pikeaaa3a622010-03-20 22:32:34 -0700318 if i+1 < len(fields) {
319 // Commas aren't escaped, and def is always last.
Albert Strasheim4676f6a2013-04-07 08:59:06 +1000320 p.Default += "," + strings.Join(fields[i+1:], ",")
Rob Pikeaaa3a622010-03-20 22:32:34 -0700321 break
322 }
323 }
324 }
325}
326
David Symonds5922d072011-06-22 15:48:09 +1000327func logNoSliceEnc(t1, t2 reflect.Type) {
328 fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2)
329}
330
David Symonds525838c2012-07-20 15:42:49 +1000331var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()
332
Rob Pikeaaa3a622010-03-20 22:32:34 -0700333// Initialize the fields for encoding and decoding.
David Symonds3ea3e052014-12-22 16:15:28 +1100334func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700335 p.enc = nil
336 p.dec = nil
David Symonds0bf1ad52013-10-11 09:07:50 +1100337 p.size = nil
Rob Pikeaaa3a622010-03-20 22:32:34 -0700338
Rob Pike97e934d2011-04-11 12:52:49 -0700339 switch t1 := typ; t1.Kind() {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700340 default:
David Symonds50386d22014-10-28 11:00:50 +1100341 fmt.Fprintf(os.Stderr, "proto: no coders for %v\n", t1)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700342
David Symondsabd3b412014-11-28 11:43:44 +1100343 // proto3 scalar types
344
345 case reflect.Bool:
346 p.enc = (*Buffer).enc_proto3_bool
347 p.dec = (*Buffer).dec_proto3_bool
348 p.size = size_proto3_bool
349 case reflect.Int32:
350 p.enc = (*Buffer).enc_proto3_int32
351 p.dec = (*Buffer).dec_proto3_int32
352 p.size = size_proto3_int32
353 case reflect.Uint32:
354 p.enc = (*Buffer).enc_proto3_uint32
355 p.dec = (*Buffer).dec_proto3_int32 // can reuse
356 p.size = size_proto3_uint32
357 case reflect.Int64, reflect.Uint64:
358 p.enc = (*Buffer).enc_proto3_int64
359 p.dec = (*Buffer).dec_proto3_int64
360 p.size = size_proto3_int64
361 case reflect.Float32:
362 p.enc = (*Buffer).enc_proto3_uint32 // can just treat them as bits
363 p.dec = (*Buffer).dec_proto3_int32
364 p.size = size_proto3_uint32
365 case reflect.Float64:
366 p.enc = (*Buffer).enc_proto3_int64 // can just treat them as bits
367 p.dec = (*Buffer).dec_proto3_int64
368 p.size = size_proto3_int64
369 case reflect.String:
370 p.enc = (*Buffer).enc_proto3_string
371 p.dec = (*Buffer).dec_proto3_string
372 p.size = size_proto3_string
373
Rob Pike97e934d2011-04-11 12:52:49 -0700374 case reflect.Ptr:
375 switch t2 := t1.Elem(); t2.Kind() {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700376 default:
David Symonds3ea3e052014-12-22 16:15:28 +1100377 fmt.Fprintf(os.Stderr, "proto: no encoder function for %v -> %v\n", t1, t2)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700378 break
Rob Pike97e934d2011-04-11 12:52:49 -0700379 case reflect.Bool:
Rob Pikeaaa3a622010-03-20 22:32:34 -0700380 p.enc = (*Buffer).enc_bool
381 p.dec = (*Buffer).dec_bool
David Symonds0bf1ad52013-10-11 09:07:50 +1100382 p.size = size_bool
David Symondsf054e842014-07-22 14:06:27 +1000383 case reflect.Int32:
Rob Pikeac8b1ce2011-04-11 16:14:54 -0700384 p.enc = (*Buffer).enc_int32
385 p.dec = (*Buffer).dec_int32
David Symonds0bf1ad52013-10-11 09:07:50 +1100386 p.size = size_int32
David Symondsf054e842014-07-22 14:06:27 +1000387 case reflect.Uint32:
388 p.enc = (*Buffer).enc_uint32
389 p.dec = (*Buffer).dec_int32 // can reuse
390 p.size = size_uint32
Rob Pikeac8b1ce2011-04-11 16:14:54 -0700391 case reflect.Int64, reflect.Uint64:
392 p.enc = (*Buffer).enc_int64
393 p.dec = (*Buffer).dec_int64
David Symonds0bf1ad52013-10-11 09:07:50 +1100394 p.size = size_int64
Rob Pikeac8b1ce2011-04-11 16:14:54 -0700395 case reflect.Float32:
David Symondsf054e842014-07-22 14:06:27 +1000396 p.enc = (*Buffer).enc_uint32 // can just treat them as bits
Rob Pikeac8b1ce2011-04-11 16:14:54 -0700397 p.dec = (*Buffer).dec_int32
David Symondsf054e842014-07-22 14:06:27 +1000398 p.size = size_uint32
Rob Pikeac8b1ce2011-04-11 16:14:54 -0700399 case reflect.Float64:
400 p.enc = (*Buffer).enc_int64 // can just treat them as bits
401 p.dec = (*Buffer).dec_int64
David Symonds0bf1ad52013-10-11 09:07:50 +1100402 p.size = size_int64
Rob Pike97e934d2011-04-11 12:52:49 -0700403 case reflect.String:
Rob Pikeaaa3a622010-03-20 22:32:34 -0700404 p.enc = (*Buffer).enc_string
405 p.dec = (*Buffer).dec_string
David Symonds0bf1ad52013-10-11 09:07:50 +1100406 p.size = size_string
Rob Pike97e934d2011-04-11 12:52:49 -0700407 case reflect.Struct:
David Symonds6a6f82c2012-08-22 09:18:54 +1000408 p.stype = t1.Elem()
David Symondsa80b2822012-03-14 14:31:25 +1100409 p.isMarshaler = isMarshaler(t1)
410 p.isUnmarshaler = isUnmarshaler(t1)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700411 if p.Wire == "bytes" {
412 p.enc = (*Buffer).enc_struct_message
413 p.dec = (*Buffer).dec_struct_message
David Symonds0bf1ad52013-10-11 09:07:50 +1100414 p.size = size_struct_message
Rob Pikeaaa3a622010-03-20 22:32:34 -0700415 } else {
416 p.enc = (*Buffer).enc_struct_group
417 p.dec = (*Buffer).dec_struct_group
David Symonds0bf1ad52013-10-11 09:07:50 +1100418 p.size = size_struct_group
Rob Pikeaaa3a622010-03-20 22:32:34 -0700419 }
420 }
421
Rob Pike97e934d2011-04-11 12:52:49 -0700422 case reflect.Slice:
423 switch t2 := t1.Elem(); t2.Kind() {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700424 default:
David Symonds5922d072011-06-22 15:48:09 +1000425 logNoSliceEnc(t1, t2)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700426 break
Rob Pike97e934d2011-04-11 12:52:49 -0700427 case reflect.Bool:
David Symonds5b7775e2010-12-01 10:09:04 +1100428 if p.Packed {
429 p.enc = (*Buffer).enc_slice_packed_bool
David Symonds0bf1ad52013-10-11 09:07:50 +1100430 p.size = size_slice_packed_bool
David Symonds5b7775e2010-12-01 10:09:04 +1100431 } else {
432 p.enc = (*Buffer).enc_slice_bool
David Symonds0bf1ad52013-10-11 09:07:50 +1100433 p.size = size_slice_bool
David Symonds5b7775e2010-12-01 10:09:04 +1100434 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700435 p.dec = (*Buffer).dec_slice_bool
David Symonds5b7775e2010-12-01 10:09:04 +1100436 p.packedDec = (*Buffer).dec_slice_packed_bool
David Symonds0ec36a22014-08-12 13:21:46 +1000437 case reflect.Int32:
438 if p.Packed {
439 p.enc = (*Buffer).enc_slice_packed_int32
440 p.size = size_slice_packed_int32
441 } else {
442 p.enc = (*Buffer).enc_slice_int32
443 p.size = size_slice_int32
Rob Pikeab5b8022010-06-21 17:47:58 -0700444 }
David Symonds0ec36a22014-08-12 13:21:46 +1000445 p.dec = (*Buffer).dec_slice_int32
446 p.packedDec = (*Buffer).dec_slice_packed_int32
447 case reflect.Uint32:
448 if p.Packed {
449 p.enc = (*Buffer).enc_slice_packed_uint32
450 p.size = size_slice_packed_uint32
451 } else {
452 p.enc = (*Buffer).enc_slice_uint32
453 p.size = size_slice_uint32
454 }
455 p.dec = (*Buffer).dec_slice_int32
456 p.packedDec = (*Buffer).dec_slice_packed_int32
457 case reflect.Int64, reflect.Uint64:
458 if p.Packed {
459 p.enc = (*Buffer).enc_slice_packed_int64
460 p.size = size_slice_packed_int64
461 } else {
462 p.enc = (*Buffer).enc_slice_int64
463 p.size = size_slice_int64
464 }
465 p.dec = (*Buffer).dec_slice_int64
466 p.packedDec = (*Buffer).dec_slice_packed_int64
467 case reflect.Uint8:
468 p.enc = (*Buffer).enc_slice_byte
469 p.dec = (*Buffer).dec_slice_byte
470 p.size = size_slice_byte
David Symonds889ae492015-03-23 09:48:33 +1100471 // This is a []byte, which is either a bytes field,
472 // or the value of a map field. In the latter case,
473 // we always encode an empty []byte, so we should not
474 // use the proto3 enc/size funcs.
475 // f == nil iff this is the key/value of a map field.
476 if p.proto3 && f != nil {
David Symondsabd3b412014-11-28 11:43:44 +1100477 p.enc = (*Buffer).enc_proto3_slice_byte
478 p.size = size_proto3_slice_byte
479 }
Rob Pike97e934d2011-04-11 12:52:49 -0700480 case reflect.Float32, reflect.Float64:
Rob Pikeab5b8022010-06-21 17:47:58 -0700481 switch t2.Bits() {
482 case 32:
David Symonds5b7775e2010-12-01 10:09:04 +1100483 // can just treat them as bits
484 if p.Packed {
David Symonds0ec36a22014-08-12 13:21:46 +1000485 p.enc = (*Buffer).enc_slice_packed_uint32
486 p.size = size_slice_packed_uint32
David Symonds5b7775e2010-12-01 10:09:04 +1100487 } else {
David Symonds0ec36a22014-08-12 13:21:46 +1000488 p.enc = (*Buffer).enc_slice_uint32
489 p.size = size_slice_uint32
David Symonds5b7775e2010-12-01 10:09:04 +1100490 }
Rob Pikeab5b8022010-06-21 17:47:58 -0700491 p.dec = (*Buffer).dec_slice_int32
David Symonds5b7775e2010-12-01 10:09:04 +1100492 p.packedDec = (*Buffer).dec_slice_packed_int32
Rob Pikeab5b8022010-06-21 17:47:58 -0700493 case 64:
David Symonds5b7775e2010-12-01 10:09:04 +1100494 // can just treat them as bits
495 if p.Packed {
496 p.enc = (*Buffer).enc_slice_packed_int64
David Symonds0bf1ad52013-10-11 09:07:50 +1100497 p.size = size_slice_packed_int64
David Symonds5b7775e2010-12-01 10:09:04 +1100498 } else {
499 p.enc = (*Buffer).enc_slice_int64
David Symonds0bf1ad52013-10-11 09:07:50 +1100500 p.size = size_slice_int64
David Symonds5b7775e2010-12-01 10:09:04 +1100501 }
Rob Pikeab5b8022010-06-21 17:47:58 -0700502 p.dec = (*Buffer).dec_slice_int64
David Symonds5b7775e2010-12-01 10:09:04 +1100503 p.packedDec = (*Buffer).dec_slice_packed_int64
Rob Pikeab5b8022010-06-21 17:47:58 -0700504 default:
David Symonds5922d072011-06-22 15:48:09 +1000505 logNoSliceEnc(t1, t2)
506 break
Rob Pikeab5b8022010-06-21 17:47:58 -0700507 }
Rob Pike97e934d2011-04-11 12:52:49 -0700508 case reflect.String:
Rob Pikeaaa3a622010-03-20 22:32:34 -0700509 p.enc = (*Buffer).enc_slice_string
510 p.dec = (*Buffer).dec_slice_string
David Symonds0bf1ad52013-10-11 09:07:50 +1100511 p.size = size_slice_string
Rob Pike97e934d2011-04-11 12:52:49 -0700512 case reflect.Ptr:
513 switch t3 := t2.Elem(); t3.Kind() {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700514 default:
Rob Pikeab5b8022010-06-21 17:47:58 -0700515 fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700516 break
Rob Pike97e934d2011-04-11 12:52:49 -0700517 case reflect.Struct:
David Symonds6a6f82c2012-08-22 09:18:54 +1000518 p.stype = t2.Elem()
David Symondsa80b2822012-03-14 14:31:25 +1100519 p.isMarshaler = isMarshaler(t2)
520 p.isUnmarshaler = isUnmarshaler(t2)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700521 if p.Wire == "bytes" {
522 p.enc = (*Buffer).enc_slice_struct_message
523 p.dec = (*Buffer).dec_slice_struct_message
David Symonds0bf1ad52013-10-11 09:07:50 +1100524 p.size = size_slice_struct_message
525 } else {
526 p.enc = (*Buffer).enc_slice_struct_group
527 p.dec = (*Buffer).dec_slice_struct_group
528 p.size = size_slice_struct_group
Rob Pikeaaa3a622010-03-20 22:32:34 -0700529 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700530 }
Rob Pike97e934d2011-04-11 12:52:49 -0700531 case reflect.Slice:
Rob Pikeab5b8022010-06-21 17:47:58 -0700532 switch t2.Elem().Kind() {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700533 default:
Rob Pikeab5b8022010-06-21 17:47:58 -0700534 fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem())
Rob Pikeaaa3a622010-03-20 22:32:34 -0700535 break
Rob Pikeab5b8022010-06-21 17:47:58 -0700536 case reflect.Uint8:
Rob Pikeaaa3a622010-03-20 22:32:34 -0700537 p.enc = (*Buffer).enc_slice_slice_byte
538 p.dec = (*Buffer).dec_slice_slice_byte
David Symonds0bf1ad52013-10-11 09:07:50 +1100539 p.size = size_slice_slice_byte
Rob Pikeaaa3a622010-03-20 22:32:34 -0700540 }
541 }
David Symonds3ea3e052014-12-22 16:15:28 +1100542
543 case reflect.Map:
544 p.enc = (*Buffer).enc_new_map
545 p.dec = (*Buffer).dec_new_map
546 p.size = size_new_map
547
548 p.mtype = t1
549 p.mkeyprop = &Properties{}
550 p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
551 p.mvalprop = &Properties{}
552 vtype := p.mtype.Elem()
553 if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice {
554 // The value type is not a message (*T) or bytes ([]byte),
555 // so we need encoders for the pointer to this type.
556 vtype = reflect.PtrTo(vtype)
557 }
558 p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700559 }
560
561 // precalculate tag code
David Symonds5b7775e2010-12-01 10:09:04 +1100562 wire := p.WireType
563 if p.Packed {
564 wire = WireBytes
565 }
David Symondsd73d7b12011-09-28 10:56:43 -0700566 x := uint32(p.Tag)<<3 | uint32(wire)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700567 i := 0
568 for i = 0; x > 127; i++ {
569 p.tagbuf[i] = 0x80 | uint8(x&0x7F)
570 x >>= 7
571 }
572 p.tagbuf[i] = uint8(x)
573 p.tagcode = p.tagbuf[0 : i+1]
David Symondsc0287172012-08-15 11:10:30 +1000574
575 if p.stype != nil {
576 if lockGetProp {
David Symonds6a6f82c2012-08-22 09:18:54 +1000577 p.sprop = GetProperties(p.stype)
David Symondsc0287172012-08-15 11:10:30 +1000578 } else {
David Symonds6a6f82c2012-08-22 09:18:54 +1000579 p.sprop = getPropertiesLocked(p.stype)
David Symondsc0287172012-08-15 11:10:30 +1000580 }
581 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700582}
583
David Symondsa80b2822012-03-14 14:31:25 +1100584var (
585 marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
586 unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
587)
588
589// isMarshaler reports whether type t implements Marshaler.
590func isMarshaler(t reflect.Type) bool {
591 // We're checking for (likely) pointer-receiver methods
592 // so if t is not a pointer, something is very wrong.
593 // The calls above only invoke isMarshaler on pointer types.
594 if t.Kind() != reflect.Ptr {
595 panic("proto: misuse of isMarshaler")
596 }
597 return t.Implements(marshalerType)
598}
599
600// isUnmarshaler reports whether type t implements Unmarshaler.
601func isUnmarshaler(t reflect.Type) bool {
602 // We're checking for (likely) pointer-receiver methods
603 // so if t is not a pointer, something is very wrong.
604 // The calls above only invoke isUnmarshaler on pointer types.
605 if t.Kind() != reflect.Ptr {
606 panic("proto: misuse of isUnmarshaler")
607 }
608 return t.Implements(unmarshalerType)
609}
610
David Symonds8935abf2011-07-04 15:53:16 +1000611// Init populates the properties from a protocol buffer struct tag.
Russ Coxd4ce3f12012-09-12 10:36:26 +1000612func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
613 p.init(typ, name, tag, f, true)
David Symondsc0287172012-08-15 11:10:30 +1000614}
615
Russ Coxd4ce3f12012-09-12 10:36:26 +1000616func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, lockGetProp bool) {
David Symonds8935abf2011-07-04 15:53:16 +1000617 // "bytes,49,opt,def=hello!"
Rob Pikeaaa3a622010-03-20 22:32:34 -0700618 p.Name = name
619 p.OrigName = name
Russ Coxd4ce3f12012-09-12 10:36:26 +1000620 if f != nil {
621 p.field = toField(f)
622 }
David Symonds8935abf2011-07-04 15:53:16 +1000623 if tag == "" {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700624 return
625 }
David Symonds8935abf2011-07-04 15:53:16 +1000626 p.Parse(tag)
David Symonds3ea3e052014-12-22 16:15:28 +1100627 p.setEncAndDec(typ, f, lockGetProp)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700628}
629
630var (
David Symondsf7137ae2015-03-17 08:40:00 +1100631 propertiesMu sync.RWMutex
Rob Pike97e934d2011-04-11 12:52:49 -0700632 propertiesMap = make(map[reflect.Type]*StructProperties)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700633)
634
635// GetProperties returns the list of properties for the type represented by t.
David Symonds905b3fd2014-10-12 16:27:29 +1100636// t must represent a generated struct type of a protocol message.
Rob Pike97e934d2011-04-11 12:52:49 -0700637func GetProperties(t reflect.Type) *StructProperties {
David Symonds905b3fd2014-10-12 16:27:29 +1100638 if t.Kind() != reflect.Struct {
639 panic("proto: type must have kind struct")
640 }
David Symondsf7137ae2015-03-17 08:40:00 +1100641
642 // Most calls to GetProperties in a long-running program will be
643 // retrieving details for types we have seen before.
644 propertiesMu.RLock()
645 sprop, ok := propertiesMap[t]
646 propertiesMu.RUnlock()
647 if ok {
648 if collectStats {
649 stats.Chit++
650 }
651 return sprop
652 }
653
654 propertiesMu.Lock()
655 sprop = getPropertiesLocked(t)
656 propertiesMu.Unlock()
David Symondsc0287172012-08-15 11:10:30 +1000657 return sprop
658}
659
David Symondsf7137ae2015-03-17 08:40:00 +1100660// getPropertiesLocked requires that propertiesMu is held.
David Symondsc0287172012-08-15 11:10:30 +1000661func getPropertiesLocked(t reflect.Type) *StructProperties {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700662 if prop, ok := propertiesMap[t]; ok {
David Symonds9f60f432012-06-14 09:45:25 +1000663 if collectStats {
664 stats.Chit++
665 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700666 return prop
667 }
David Symonds9f60f432012-06-14 09:45:25 +1000668 if collectStats {
669 stats.Cmiss++
670 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700671
672 prop := new(StructProperties)
David Symondsc0287172012-08-15 11:10:30 +1000673 // in case of recursive protos, fill this in now.
674 propertiesMap[t] = prop
Rob Pikeaaa3a622010-03-20 22:32:34 -0700675
676 // build properties
Russ Coxd4ce3f12012-09-12 10:36:26 +1000677 prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType)
678 prop.unrecField = invalidField
Rob Pikeaaa3a622010-03-20 22:32:34 -0700679 prop.Prop = make([]*Properties, t.NumField())
David Symondsd15e81b2011-10-03 14:31:12 -0700680 prop.order = make([]int, t.NumField())
David Symonds20370902013-03-23 17:20:01 +1100681
Rob Pikeaaa3a622010-03-20 22:32:34 -0700682 for i := 0; i < t.NumField(); i++ {
683 f := t.Field(i)
684 p := new(Properties)
David Symonds20370902013-03-23 17:20:01 +1100685 name := f.Name
686 p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
687
Rob Pikeaaa3a622010-03-20 22:32:34 -0700688 if f.Name == "XXX_extensions" { // special case
Rob Pikeaaa3a622010-03-20 22:32:34 -0700689 p.enc = (*Buffer).enc_map
690 p.dec = nil // not needed
David Symonds0bf1ad52013-10-11 09:07:50 +1100691 p.size = size_map
Rob Pikeaaa3a622010-03-20 22:32:34 -0700692 }
David Symonds10c93ba2012-08-04 16:38:08 +1000693 if f.Name == "XXX_unrecognized" { // special case
Russ Coxd4ce3f12012-09-12 10:36:26 +1000694 prop.unrecField = toField(&f)
David Symonds10c93ba2012-08-04 16:38:08 +1000695 }
David Symonds59b73b32015-08-24 13:22:02 +1000696 oneof := f.Tag.Get("protobuf_oneof") != "" // special case
Rob Pikeaaa3a622010-03-20 22:32:34 -0700697 prop.Prop[i] = p
David Symondsd15e81b2011-10-03 14:31:12 -0700698 prop.order[i] = i
Rob Pikeaaa3a622010-03-20 22:32:34 -0700699 if debug {
700 print(i, " ", f.Name, " ", t.String(), " ")
701 if p.Tag > 0 {
702 print(p.String())
703 }
704 print("\n")
705 }
David Symonds59b73b32015-08-24 13:22:02 +1000706 if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && !oneof {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700707 fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]")
708 }
709 }
710
David Symondsd15e81b2011-10-03 14:31:12 -0700711 // Re-order prop.order.
712 sort.Sort(prop)
713
David Symonds59b73b32015-08-24 13:22:02 +1000714 type oneofMessage interface {
715 XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), []interface{})
716 }
717 if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
David Symonds1baed092015-08-25 15:42:00 +1000718 var oots []interface{}
719 prop.oneofMarshaler, prop.oneofUnmarshaler, oots = om.XXX_OneofFuncs()
David Symonds59b73b32015-08-24 13:22:02 +1000720 prop.stype = t
David Symonds1baed092015-08-25 15:42:00 +1000721
722 // Interpret oneof metadata.
723 prop.OneofTypes = make(map[string]*OneofProperties)
724 for _, oot := range oots {
725 oop := &OneofProperties{
726 Type: reflect.ValueOf(oot).Type(), // *T
727 Prop: new(Properties),
728 }
729 sft := oop.Type.Elem().Field(0)
730 oop.Prop.Name = sft.Name
731 oop.Prop.Parse(sft.Tag.Get("protobuf"))
732 // There will be exactly one interface field that
733 // this new value is assignable to.
734 for i := 0; i < t.NumField(); i++ {
735 f := t.Field(i)
736 if f.Type.Kind() != reflect.Interface {
737 continue
738 }
739 if !oop.Type.AssignableTo(f.Type) {
740 continue
741 }
742 oop.Field = i
743 break
744 }
745 prop.OneofTypes[oop.Prop.OrigName] = oop
746 }
David Symonds59b73b32015-08-24 13:22:02 +1000747 }
748
Rob Pikeaaa3a622010-03-20 22:32:34 -0700749 // build required counts
Rob Pikeaaa3a622010-03-20 22:32:34 -0700750 // build tags
751 reqCount := 0
David Symonds2bba1b22012-09-26 14:53:08 +1000752 prop.decoderOrigNames = make(map[string]int)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700753 for i, p := range prop.Prop {
David Symonds6e50db52012-02-11 15:56:22 +1100754 if strings.HasPrefix(p.Name, "XXX_") {
755 // Internal fields should not appear in tags/origNames maps.
756 // They are handled specially when encoding and decoding.
757 continue
758 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700759 if p.Required {
760 reqCount++
761 }
David Symonds2bba1b22012-09-26 14:53:08 +1000762 prop.decoderTags.put(p.Tag, i)
763 prop.decoderOrigNames[p.OrigName] = i
Rob Pikeaaa3a622010-03-20 22:32:34 -0700764 }
765 prop.reqCount = reqCount
Rob Pikeaaa3a622010-03-20 22:32:34 -0700766
Rob Pikeaaa3a622010-03-20 22:32:34 -0700767 return prop
768}
769
Rob Pikeaaa3a622010-03-20 22:32:34 -0700770// Return the Properties object for the x[0]'th field of the structure.
Rob Pike97e934d2011-04-11 12:52:49 -0700771func propByIndex(t reflect.Type, x []int) *Properties {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700772 if len(x) != 1 {
773 fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t)
774 return nil
775 }
776 prop := GetProperties(t)
777 return prop.Prop[x[0]]
778}
779
David Symonds7656e742011-07-22 14:54:17 +1000780// Get the address and type of a pointer to a struct from an interface.
Russ Coxd4ce3f12012-09-12 10:36:26 +1000781func getbase(pb Message) (t reflect.Type, b structPointer, err error) {
Rob Pikef1b341e2011-10-20 14:51:10 -0700782 if pb == nil {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700783 err = ErrNil
784 return
785 }
Rob Pikef1b341e2011-10-20 14:51:10 -0700786 // get the reflect type of the pointer to the struct.
Nigel Tao4ede8452011-04-28 11:27:25 +1000787 t = reflect.TypeOf(pb)
Rob Pikef1b341e2011-10-20 14:51:10 -0700788 // get the address of the struct.
789 value := reflect.ValueOf(pb)
Russ Coxd4ce3f12012-09-12 10:36:26 +1000790 b = toStructPointer(value)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700791 return
792}
793
Rob Pikeaaa3a622010-03-20 22:32:34 -0700794// A global registry of enum types.
795// The generated code will register the generated maps by calling RegisterEnum.
796
Rob Pikeaaa3a622010-03-20 22:32:34 -0700797var enumValueMaps = make(map[string]map[string]int32)
798
799// RegisterEnum is called from the generated code to install the enum descriptor
David Symondsf8a1fcc2013-05-03 08:51:23 +1000800// maps into the global table to aid parsing text format protocol buffers.
801func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) {
802 if _, ok := enumValueMaps[typeName]; ok {
Rob Pike79c63792010-03-24 17:48:35 -0700803 panic("proto: duplicate enum registered: " + typeName)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700804 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700805 enumValueMaps[typeName] = valueMap
806}
David Symonds5d7f79b2015-10-19 11:37:00 +1100807
808// EnumValueMap returns the mapping from names to integers of the
809// enum type enumType, or a nil if not found.
810func EnumValueMap(enumType string) map[string]int32 {
811 return enumValueMaps[enumType]
812}
David Symondsa7f1e752015-11-02 15:31:00 +1100813
814// A registry of all linked message types.
David Symondsd3d78382015-11-05 09:41:00 +1100815// The string is a fully-qualified proto name ("pkg.Message").
816var (
817 protoTypes = make(map[string]reflect.Type)
818 revProtoTypes = make(map[reflect.Type]string)
819)
David Symondsa7f1e752015-11-02 15:31:00 +1100820
821// RegisterType is called from generated code and maps from the fully qualified
822// proto name to the type (pointer to struct) of the protocol buffer.
David Symondsd3d78382015-11-05 09:41:00 +1100823func RegisterType(x Message, name string) {
David Symondsa7f1e752015-11-02 15:31:00 +1100824 if _, ok := protoTypes[name]; ok {
825 // TODO: Some day, make this a panic.
826 log.Printf("proto: duplicate proto type registered: %s", name)
827 return
828 }
David Symondsd3d78382015-11-05 09:41:00 +1100829 t := reflect.TypeOf(x)
830 protoTypes[name] = t
831 revProtoTypes[t] = name
David Symondsa7f1e752015-11-02 15:31:00 +1100832}
David Symondsd3d78382015-11-05 09:41:00 +1100833
834// MessageName returns the fully-qualified proto name for the given message type.
835func MessageName(x Message) string { return revProtoTypes[reflect.TypeOf(x)] }
836
837// MessageType returns the message type (pointer to struct) for a named message.
838func MessageType(name string) reflect.Type { return protoTypes[name] }