build.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // Copyright 2019 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 filedesc provides functionality for constructing descriptors.
  5. //
  6. // The types in this package implement interfaces in the protoreflect package
  7. // related to protobuf descripriptors.
  8. package filedesc
  9. import (
  10. "google.golang.org/protobuf/encoding/protowire"
  11. "google.golang.org/protobuf/internal/genid"
  12. "google.golang.org/protobuf/reflect/protoreflect"
  13. pref "google.golang.org/protobuf/reflect/protoreflect"
  14. preg "google.golang.org/protobuf/reflect/protoregistry"
  15. )
  16. // Builder construct a protoreflect.FileDescriptor from the raw descriptor.
  17. type Builder struct {
  18. // GoPackagePath is the Go package path that is invoking this builder.
  19. GoPackagePath string
  20. // RawDescriptor is the wire-encoded bytes of FileDescriptorProto
  21. // and must be populated.
  22. RawDescriptor []byte
  23. // NumEnums is the total number of enums declared in the file.
  24. NumEnums int32
  25. // NumMessages is the total number of messages declared in the file.
  26. // It includes the implicit message declarations for map entries.
  27. NumMessages int32
  28. // NumExtensions is the total number of extensions declared in the file.
  29. NumExtensions int32
  30. // NumServices is the total number of services declared in the file.
  31. NumServices int32
  32. // TypeResolver resolves extension field types for descriptor options.
  33. // If nil, it uses protoregistry.GlobalTypes.
  34. TypeResolver interface {
  35. preg.ExtensionTypeResolver
  36. }
  37. // FileRegistry is use to lookup file, enum, and message dependencies.
  38. // Once constructed, the file descriptor is registered here.
  39. // If nil, it uses protoregistry.GlobalFiles.
  40. FileRegistry interface {
  41. FindFileByPath(string) (protoreflect.FileDescriptor, error)
  42. FindDescriptorByName(pref.FullName) (pref.Descriptor, error)
  43. RegisterFile(pref.FileDescriptor) error
  44. }
  45. }
  46. // resolverByIndex is an interface Builder.FileRegistry may implement.
  47. // If so, it permits looking up an enum or message dependency based on the
  48. // sub-list and element index into filetype.Builder.DependencyIndexes.
  49. type resolverByIndex interface {
  50. FindEnumByIndex(int32, int32, []Enum, []Message) pref.EnumDescriptor
  51. FindMessageByIndex(int32, int32, []Enum, []Message) pref.MessageDescriptor
  52. }
  53. // Indexes of each sub-list in filetype.Builder.DependencyIndexes.
  54. const (
  55. listFieldDeps int32 = iota
  56. listExtTargets
  57. listExtDeps
  58. listMethInDeps
  59. listMethOutDeps
  60. )
  61. // Out is the output of the Builder.
  62. type Out struct {
  63. File pref.FileDescriptor
  64. // Enums is all enum descriptors in "flattened ordering".
  65. Enums []Enum
  66. // Messages is all message descriptors in "flattened ordering".
  67. // It includes the implicit message declarations for map entries.
  68. Messages []Message
  69. // Extensions is all extension descriptors in "flattened ordering".
  70. Extensions []Extension
  71. // Service is all service descriptors in "flattened ordering".
  72. Services []Service
  73. }
  74. // Build constructs a FileDescriptor given the parameters set in Builder.
  75. // It assumes that the inputs are well-formed and panics if any inconsistencies
  76. // are encountered.
  77. //
  78. // If NumEnums+NumMessages+NumExtensions+NumServices is zero,
  79. // then Build automatically derives them from the raw descriptor.
  80. func (db Builder) Build() (out Out) {
  81. // Populate the counts if uninitialized.
  82. if db.NumEnums+db.NumMessages+db.NumExtensions+db.NumServices == 0 {
  83. db.unmarshalCounts(db.RawDescriptor, true)
  84. }
  85. // Initialize resolvers and registries if unpopulated.
  86. if db.TypeResolver == nil {
  87. db.TypeResolver = preg.GlobalTypes
  88. }
  89. if db.FileRegistry == nil {
  90. db.FileRegistry = preg.GlobalFiles
  91. }
  92. fd := newRawFile(db)
  93. out.File = fd
  94. out.Enums = fd.allEnums
  95. out.Messages = fd.allMessages
  96. out.Extensions = fd.allExtensions
  97. out.Services = fd.allServices
  98. if err := db.FileRegistry.RegisterFile(fd); err != nil {
  99. panic(err)
  100. }
  101. return out
  102. }
  103. // unmarshalCounts counts the number of enum, message, extension, and service
  104. // declarations in the raw message, which is either a FileDescriptorProto
  105. // or a MessageDescriptorProto depending on whether isFile is set.
  106. func (db *Builder) unmarshalCounts(b []byte, isFile bool) {
  107. for len(b) > 0 {
  108. num, typ, n := protowire.ConsumeTag(b)
  109. b = b[n:]
  110. switch typ {
  111. case protowire.BytesType:
  112. v, m := protowire.ConsumeBytes(b)
  113. b = b[m:]
  114. if isFile {
  115. switch num {
  116. case genid.FileDescriptorProto_EnumType_field_number:
  117. db.NumEnums++
  118. case genid.FileDescriptorProto_MessageType_field_number:
  119. db.unmarshalCounts(v, false)
  120. db.NumMessages++
  121. case genid.FileDescriptorProto_Extension_field_number:
  122. db.NumExtensions++
  123. case genid.FileDescriptorProto_Service_field_number:
  124. db.NumServices++
  125. }
  126. } else {
  127. switch num {
  128. case genid.DescriptorProto_EnumType_field_number:
  129. db.NumEnums++
  130. case genid.DescriptorProto_NestedType_field_number:
  131. db.unmarshalCounts(v, false)
  132. db.NumMessages++
  133. case genid.DescriptorProto_Extension_field_number:
  134. db.NumExtensions++
  135. }
  136. }
  137. default:
  138. m := protowire.ConsumeFieldValue(num, typ, b)
  139. b = b[m:]
  140. }
  141. }
  142. }