registry.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // Copyright 2018 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package proto
  5. import (
  6. "fmt"
  7. "log"
  8. "reflect"
  9. "strconv"
  10. )
  11. var enumValueMaps = make(map[string]map[string]int32)
  12. // RegisterEnum is called from the generated code to install the enum descriptor
  13. // maps into the global table to aid parsing text format protocol buffers.
  14. func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) {
  15. if registerEnumAlt != nil {
  16. registerEnumAlt(typeName, unusedNameMap, valueMap) // populated by hooks_enabled.go
  17. return
  18. }
  19. if _, ok := enumValueMaps[typeName]; ok {
  20. panic("proto: duplicate enum registered: " + typeName)
  21. }
  22. enumValueMaps[typeName] = valueMap
  23. }
  24. // EnumValueMap returns the mapping from names to integers of the
  25. // enum type enumType, or a nil if not found.
  26. func EnumValueMap(enumType string) map[string]int32 {
  27. if enumValueMapAlt != nil {
  28. return enumValueMapAlt(enumType) // populated by hooks_enabled.go
  29. }
  30. return enumValueMaps[enumType]
  31. }
  32. // A registry of all linked message types.
  33. // The string is a fully-qualified proto name ("pkg.Message").
  34. var (
  35. protoTypedNils = make(map[string]Message) // a map from proto names to typed nil pointers
  36. protoMapTypes = make(map[string]reflect.Type) // a map from proto names to map types
  37. revProtoTypes = make(map[reflect.Type]string)
  38. )
  39. // RegisterType is called from generated code and maps from the fully qualified
  40. // proto name to the type (pointer to struct) of the protocol buffer.
  41. func RegisterType(x Message, name string) {
  42. if registerTypeAlt != nil {
  43. registerTypeAlt(x, name) // populated by hooks_enabled.go
  44. return
  45. }
  46. if _, ok := protoTypedNils[name]; ok {
  47. // TODO: Some day, make this a panic.
  48. log.Printf("proto: duplicate proto type registered: %s", name)
  49. return
  50. }
  51. t := reflect.TypeOf(x)
  52. if v := reflect.ValueOf(x); v.Kind() == reflect.Ptr && v.Pointer() == 0 {
  53. // Generated code always calls RegisterType with nil x.
  54. // This check is just for extra safety.
  55. protoTypedNils[name] = x
  56. } else {
  57. protoTypedNils[name] = reflect.Zero(t).Interface().(Message)
  58. }
  59. revProtoTypes[t] = name
  60. }
  61. // RegisterMapType is called from generated code and maps from the fully qualified
  62. // proto name to the native map type of the proto map definition.
  63. func RegisterMapType(x interface{}, name string) {
  64. if registerMapTypeAlt != nil {
  65. registerMapTypeAlt(x, name) // populated by hooks_enabled.go
  66. return
  67. }
  68. if reflect.TypeOf(x).Kind() != reflect.Map {
  69. panic(fmt.Sprintf("RegisterMapType(%T, %q); want map", x, name))
  70. }
  71. if _, ok := protoMapTypes[name]; ok {
  72. log.Printf("proto: duplicate proto type registered: %s", name)
  73. return
  74. }
  75. t := reflect.TypeOf(x)
  76. protoMapTypes[name] = t
  77. // Avoid registering into revProtoTypes since map types are not unique.
  78. // revProtoTypes[t] = name
  79. }
  80. // MessageName returns the fully-qualified proto name for the given message type.
  81. func MessageName(x Message) string {
  82. if messageNameAlt != nil {
  83. return messageNameAlt(x) // populated by hooks_enabled.go
  84. }
  85. type xname interface {
  86. XXX_MessageName() string
  87. }
  88. if m, ok := x.(xname); ok {
  89. return m.XXX_MessageName()
  90. }
  91. return revProtoTypes[reflect.TypeOf(x)]
  92. }
  93. // MessageType returns the message type (pointer to struct) for a named message.
  94. // The type is not guaranteed to implement proto.Message if the name refers to a
  95. // map entry.
  96. func MessageType(name string) reflect.Type {
  97. if messageTypeAlt != nil {
  98. return messageTypeAlt(name) // populated by hooks_enabled.go
  99. }
  100. if t, ok := protoTypedNils[name]; ok {
  101. return reflect.TypeOf(t)
  102. }
  103. return protoMapTypes[name]
  104. }
  105. // A registry of all linked proto files.
  106. var protoFiles = make(map[string][]byte) // file name => fileDescriptor
  107. // RegisterFile is called from generated code and maps from the
  108. // full file name of a .proto file to its compressed FileDescriptorProto.
  109. func RegisterFile(filename string, fileDescriptor []byte) {
  110. if registerFileAlt != nil {
  111. registerFileAlt(filename, fileDescriptor) // populated by hooks_enabled.go
  112. return
  113. }
  114. protoFiles[filename] = fileDescriptor
  115. }
  116. // FileDescriptor returns the compressed FileDescriptorProto for a .proto file.
  117. func FileDescriptor(filename string) []byte {
  118. if fileDescriptorAlt != nil {
  119. return fileDescriptorAlt(filename) // populated by hooks_enabled.go
  120. }
  121. return protoFiles[filename]
  122. }
  123. var extensionMaps = make(map[reflect.Type]map[int32]*ExtensionDesc)
  124. // RegisterExtension is called from the generated code.
  125. func RegisterExtension(desc *ExtensionDesc) {
  126. if registerExtensionAlt != nil {
  127. registerExtensionAlt(desc) // populated by hooks_enabled.go
  128. return
  129. }
  130. st := reflect.TypeOf(desc.ExtendedType).Elem()
  131. m := extensionMaps[st]
  132. if m == nil {
  133. m = make(map[int32]*ExtensionDesc)
  134. extensionMaps[st] = m
  135. }
  136. if _, ok := m[desc.Field]; ok {
  137. panic("proto: duplicate extension registered: " + st.String() + " " + strconv.Itoa(int(desc.Field)))
  138. }
  139. m[desc.Field] = desc
  140. }
  141. // RegisteredExtensions returns a map of the registered extensions of a
  142. // protocol buffer struct, indexed by the extension number.
  143. // The argument pb should be a nil pointer to the struct type.
  144. func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc {
  145. if registeredExtensionsAlt != nil {
  146. return registeredExtensionsAlt(pb) // populated by hooks_enabled.go
  147. }
  148. return extensionMaps[reflect.TypeOf(pb).Elem()]
  149. }