1 // Go support for Protocol Buffers - Google's data interchange format
3 // Copyright 2010 The Go Authors. All rights reserved.
4 // https://github.com/golang/protobuf
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are
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
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.
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.
35 * Routines for encoding data into the wire format for protocol buffers.
49 const debug bool = false
51 // Constants that identify the encoding of a value on the wire.
61 const startSize = 10 // initial slice/string sizes
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
68 // A valueEncoder encodes a single integer in a particular encoding.
69 type valueEncoder func(o *Buffer, x uint64) error
71 // Sizers are defined in encode.go
72 // A sizer returns the encoded size of a field, including its tag and encoder
74 type sizer func(prop *Properties, base structPointer) int
76 // A valueSizer returns the encoded size of a single integer in a particular
78 type valueSizer func(x uint64) int
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
85 // A valueDecoder decodes a single integer in a particular encoding.
86 type valueDecoder func(o *Buffer) (x uint64, err error)
88 // A oneofMarshaler does the marshaling for all oneof fields in a message.
89 type oneofMarshaler func(Message, *Buffer) error
91 // A oneofUnmarshaler does the unmarshaling for a oneof field in a message.
92 type oneofUnmarshaler func(Message, int, int, *Buffer) (bool, error)
94 // A oneofSizer does the sizing for all oneof fields in a message.
95 type oneofSizer func(Message) int
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
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
109 func (p *tagMap) get(t int) (int, bool) {
110 if t > 0 && t < tagMapFastLimit {
111 if t >= len(p.fastTags) {
117 fi, ok := p.slowTags[t]
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)
129 if p.slowTags == nil {
130 p.slowTags = make(map[int]int)
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
146 oneofMarshaler oneofMarshaler
147 oneofUnmarshaler oneofUnmarshaler
148 oneofSizer oneofSizer
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
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
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.
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
170 func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order[j], sp.order[i] }
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
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
188 Default string // default value
189 HasDefault bool // whether an explicit default was provided
193 valEnc valueEncoder // set for bool and numeric types only
195 tagcode []byte // encoding of EncodeVarint((Tag<<3)|WireType)
197 stype reflect.Type // set for struct types only
198 sprop *StructProperties // set for struct types only
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
207 valSize valueSizer // set for bool and numeric types only
210 valDec valueDecoder // set for bool and numeric types only
212 // If this is a packable field, this will be the decoder for the packed version of the field.
216 // String formats the properties in the protobuf struct field tag style.
217 func (p *Properties) String() string {
220 s += strconv.Itoa(p.Tag)
233 s += ",name=" + p.OrigName
234 if p.JSONName != p.OrigName {
235 s += ",json=" + p.JSONName
244 s += ",enum=" + p.Enum
247 s += ",def=" + p.Default
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.
257 fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s)
264 p.WireType = WireVarint
265 p.valEnc = (*Buffer).EncodeVarint
266 p.valDec = (*Buffer).DecodeVarint
267 p.valSize = sizeVarint
269 p.WireType = WireFixed32
270 p.valEnc = (*Buffer).EncodeFixed32
271 p.valDec = (*Buffer).DecodeFixed32
272 p.valSize = sizeFixed32
274 p.WireType = WireFixed64
275 p.valEnc = (*Buffer).EncodeFixed64
276 p.valDec = (*Buffer).DecodeFixed64
277 p.valSize = sizeFixed64
279 p.WireType = WireVarint
280 p.valEnc = (*Buffer).EncodeZigzag32
281 p.valDec = (*Buffer).DecodeZigzag32
282 p.valSize = sizeZigzag32
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
292 fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s)
297 p.Tag, err = strconv.Atoi(fields[1])
302 for i := 2; i < len(fields); i++ {
313 case strings.HasPrefix(f, "name="):
315 case strings.HasPrefix(f, "json="):
317 case strings.HasPrefix(f, "enum="):
323 case strings.HasPrefix(f, "def="):
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:], ",")
335 func logNoSliceEnc(t1, t2 reflect.Type) {
336 fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2)
339 var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()
341 // Initialize the fields for encoding and decoding.
342 func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
347 switch t1 := typ; t1.Kind() {
349 fmt.Fprintf(os.Stderr, "proto: no coders for %v\n", t1)
351 // proto3 scalar types
354 p.enc = (*Buffer).enc_proto3_bool
355 p.dec = (*Buffer).dec_proto3_bool
356 p.size = size_proto3_bool
358 p.enc = (*Buffer).enc_proto3_int32
359 p.dec = (*Buffer).dec_proto3_int32
360 p.size = size_proto3_int32
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
378 p.enc = (*Buffer).enc_proto3_string
379 p.dec = (*Buffer).dec_proto3_string
380 p.size = size_proto3_string
383 switch t2 := t1.Elem(); t2.Kind() {
385 fmt.Fprintf(os.Stderr, "proto: no encoder function for %v -> %v\n", t1, t2)
388 p.enc = (*Buffer).enc_bool
389 p.dec = (*Buffer).dec_bool
392 p.enc = (*Buffer).enc_int32
393 p.dec = (*Buffer).dec_int32
396 p.enc = (*Buffer).enc_uint32
397 p.dec = (*Buffer).dec_int32 // can reuse
399 case reflect.Int64, reflect.Uint64:
400 p.enc = (*Buffer).enc_int64
401 p.dec = (*Buffer).dec_int64
403 case reflect.Float32:
404 p.enc = (*Buffer).enc_uint32 // can just treat them as bits
405 p.dec = (*Buffer).dec_int32
407 case reflect.Float64:
408 p.enc = (*Buffer).enc_int64 // can just treat them as bits
409 p.dec = (*Buffer).dec_int64
412 p.enc = (*Buffer).enc_string
413 p.dec = (*Buffer).dec_string
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
424 p.enc = (*Buffer).enc_struct_group
425 p.dec = (*Buffer).dec_struct_group
426 p.size = size_struct_group
431 switch t2 := t1.Elem(); t2.Kind() {
433 logNoSliceEnc(t1, t2)
437 p.enc = (*Buffer).enc_slice_packed_bool
438 p.size = size_slice_packed_bool
440 p.enc = (*Buffer).enc_slice_bool
441 p.size = size_slice_bool
443 p.dec = (*Buffer).dec_slice_bool
444 p.packedDec = (*Buffer).dec_slice_packed_bool
447 p.enc = (*Buffer).enc_slice_packed_int32
448 p.size = size_slice_packed_int32
450 p.enc = (*Buffer).enc_slice_int32
451 p.size = size_slice_int32
453 p.dec = (*Buffer).dec_slice_int32
454 p.packedDec = (*Buffer).dec_slice_packed_int32
457 p.enc = (*Buffer).enc_slice_packed_uint32
458 p.size = size_slice_packed_uint32
460 p.enc = (*Buffer).enc_slice_uint32
461 p.size = size_slice_uint32
463 p.dec = (*Buffer).dec_slice_int32
464 p.packedDec = (*Buffer).dec_slice_packed_int32
465 case reflect.Int64, reflect.Uint64:
467 p.enc = (*Buffer).enc_slice_packed_int64
468 p.size = size_slice_packed_int64
470 p.enc = (*Buffer).enc_slice_int64
471 p.size = size_slice_int64
473 p.dec = (*Buffer).dec_slice_int64
474 p.packedDec = (*Buffer).dec_slice_packed_int64
476 p.dec = (*Buffer).dec_slice_byte
478 p.enc = (*Buffer).enc_proto3_slice_byte
479 p.size = size_proto3_slice_byte
481 p.enc = (*Buffer).enc_slice_byte
482 p.size = size_slice_byte
484 case reflect.Float32, reflect.Float64:
487 // can just treat them as bits
489 p.enc = (*Buffer).enc_slice_packed_uint32
490 p.size = size_slice_packed_uint32
492 p.enc = (*Buffer).enc_slice_uint32
493 p.size = size_slice_uint32
495 p.dec = (*Buffer).dec_slice_int32
496 p.packedDec = (*Buffer).dec_slice_packed_int32
498 // can just treat them as bits
500 p.enc = (*Buffer).enc_slice_packed_int64
501 p.size = size_slice_packed_int64
503 p.enc = (*Buffer).enc_slice_int64
504 p.size = size_slice_int64
506 p.dec = (*Buffer).dec_slice_int64
507 p.packedDec = (*Buffer).dec_slice_packed_int64
509 logNoSliceEnc(t1, t2)
513 p.enc = (*Buffer).enc_slice_string
514 p.dec = (*Buffer).dec_slice_string
515 p.size = size_slice_string
517 switch t3 := t2.Elem(); t3.Kind() {
519 fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3)
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
530 p.enc = (*Buffer).enc_slice_struct_group
531 p.dec = (*Buffer).dec_slice_struct_group
532 p.size = size_slice_struct_group
536 switch t2.Elem().Kind() {
538 fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem())
541 p.enc = (*Buffer).enc_slice_slice_byte
542 p.dec = (*Buffer).dec_slice_slice_byte
543 p.size = size_slice_slice_byte
548 p.enc = (*Buffer).enc_new_map
549 p.dec = (*Buffer).dec_new_map
550 p.size = size_new_map
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)
562 p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
565 // precalculate tag code
570 x := uint32(p.Tag)<<3 | uint32(wire)
572 for i = 0; x > 127; i++ {
573 p.tagbuf[i] = 0x80 | uint8(x&0x7F)
576 p.tagbuf[i] = uint8(x)
577 p.tagcode = p.tagbuf[0 : i+1]
581 p.sprop = GetProperties(p.stype)
583 p.sprop = getPropertiesLocked(p.stype)
589 marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
590 unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
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")
601 return t.Implements(marshalerType)
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")
612 return t.Implements(unmarshalerType)
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)
620 func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, lockGetProp bool) {
621 // "bytes,49,opt,def=hello!"
631 p.setEncAndDec(typ, f, lockGetProp)
635 propertiesMu sync.RWMutex
636 propertiesMap = make(map[reflect.Type]*StructProperties)
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")
646 // Most calls to GetProperties in a long-running program will be
647 // retrieving details for types we have seen before.
649 sprop, ok := propertiesMap[t]
650 propertiesMu.RUnlock()
659 sprop = getPropertiesLocked(t)
660 propertiesMu.Unlock()
664 // getPropertiesLocked requires that propertiesMu is held.
665 func getPropertiesLocked(t reflect.Type) *StructProperties {
666 if prop, ok := propertiesMap[t]; ok {
676 prop := new(StructProperties)
677 // in case of recursive protos, fill this in now.
678 propertiesMap[t] = prop
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())
687 for i := 0; i < t.NumField(); i++ {
691 p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
693 if f.Name == "XXX_InternalExtensions" { // special case
694 p.enc = (*Buffer).enc_exts
695 p.dec = nil // not needed
697 } else if f.Name == "XXX_extensions" { // special case
698 p.enc = (*Buffer).enc_map
699 p.dec = nil // not needed
701 } else if f.Name == "XXX_unrecognized" { // special case
702 prop.unrecField = toField(&f)
704 oneof := f.Tag.Get("protobuf_oneof") // special case
706 // Oneof fields don't use the traditional protobuf tag.
712 print(i, " ", f.Name, " ", t.String(), " ")
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]")
723 // Re-order prop.order.
726 type oneofMessage interface {
727 XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
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()
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),
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++ {
748 if f.Type.Kind() != reflect.Interface {
751 if !oop.Type.AssignableTo(f.Type) {
757 prop.OneofTypes[oop.Prop.OrigName] = oop
761 // build required counts
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.
774 prop.decoderTags.put(p.Tag, i)
775 prop.decoderOrigNames[p.OrigName] = i
777 prop.reqCount = reqCount
782 // Return the Properties object for the x[0]'th field of the structure.
783 func propByIndex(t reflect.Type, x []int) *Properties {
785 fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t)
788 prop := GetProperties(t)
789 return prop.Prop[x[0]]
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) {
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)
806 // A global registry of enum types.
807 // The generated code will register the generated maps by calling RegisterEnum.
809 var enumValueMaps = make(map[string]map[string]int32)
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)
817 enumValueMaps[typeName] = valueMap
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]
826 // A registry of all linked message types.
827 // The string is a fully-qualified proto name ("pkg.Message").
829 protoTypes = make(map[string]reflect.Type)
830 revProtoTypes = make(map[reflect.Type]string)
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)
841 t := reflect.TypeOf(x)
843 revProtoTypes[t] = name
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
851 if m, ok := x.(xname); ok {
852 return m.XXX_MessageName()
854 return revProtoTypes[reflect.TypeOf(x)]
857 // MessageType returns the message type (pointer to struct) for a named message.
858 func MessageType(name string) reflect.Type { return protoTypes[name] }
860 // A registry of all linked proto files.
862 protoFiles = make(map[string][]byte) // file name => fileDescriptor
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
871 // FileDescriptor returns the compressed FileDescriptorProto for a .proto file.
872 func FileDescriptor(filename string) []byte { return protoFiles[filename] }