protofile.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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. // TODO: Delete this package and re-write functionality to depend on
  5. // reflect/protodesc and internal/fileinit.
  6. // Package prototype provides builders to construct protobuf types that
  7. // implement the interfaces defined in the protoreflect package.
  8. //
  9. // Protobuf types can either be constructed as standalone types
  10. // (e.g., StandaloneMessage), or together as a batch of types in a single
  11. // proto file (e.g., File). When creating standalone types, additional
  12. // information must be provided such as the full type name and the proto syntax.
  13. // When creating an entire file, the syntax and full name is derived from
  14. // the parent type.
  15. //
  16. // Most types contain options, defined as messages in descriptor.proto.
  17. // To avoid cyclic dependencies, the prototype package treats these options
  18. // as opaque protoreflect.ProtoMessage values. In some cases where the option
  19. // contains semantically important information (e.g.,
  20. // google.protobuf.MessageOptions.map_entry), this information must be provided
  21. // as a field of the corresponding type (e.g., prototype.Message.MapEntry).
  22. package prototype
  23. import "github.com/golang/protobuf/v2/reflect/protoreflect"
  24. // Every struct has a "meta" struct embedded within it as a pointer.
  25. // The meta type provides additional data structures for efficient lookup on
  26. // certain methods (e.g., ByName) or derived information that can be
  27. // derived from the parent (e.g., FullName). The meta type is lazily allocated
  28. // and initialized. This architectural approach keeps the literal representation
  29. // smaller, which then keeps the generated code size smaller.
  30. // TODO: Instead of a top-down construction approach where internal references
  31. // to message types use placeholder types, we could add a Reference method
  32. // on Message and Enum that creates a MessageDescriptor or EnumDescriptor
  33. // reference that only becomes valid after NewFile.
  34. // However, that API approach is more error prone, as it causes more memory
  35. // aliasing and provides more opportunity for misuse.
  36. // Also, it requires that NewFile at least eagerly initialize all
  37. // messages and enums list types. We can always add that API in the future.
  38. // File is a constructor for protoreflect.FileDescriptor.
  39. type File struct {
  40. Syntax protoreflect.Syntax
  41. Path string
  42. Package protoreflect.FullName
  43. Imports []protoreflect.FileImport
  44. Options protoreflect.ProtoMessage
  45. Enums []Enum
  46. Messages []Message
  47. Extensions []Extension
  48. Services []Service
  49. *fileMeta
  50. }
  51. // NewFile creates a new protoreflect.FileDescriptor from the provided value.
  52. // The file must represent a valid proto file according to protobuf semantics.
  53. //
  54. // Fields that reference an enum or message that is being declared within the
  55. // same File can be represented using a placeholder descriptor. NewFile will
  56. // automatically resolve the placeholder to point to a concrete descriptor.
  57. // Alternatively, a reference descriptor obtained via Enum.Reference or
  58. // Message.Reference can be used instead. The placeholder approach makes it
  59. // possible to declare the file descriptor as a single File literal and
  60. // is generally easier to use. The reference approach is more performant,
  61. // but also more error prone.
  62. //
  63. // The caller must relinquish full ownership of the input t and must not
  64. // access or mutate any fields. The input must not contain slices that are
  65. // sub-slices of each other.
  66. func NewFile(t *File) (protoreflect.FileDescriptor, error) {
  67. // TODO: Provide an unverified make that avoids validating the file.
  68. // This is useful for generated code since we know that protoc-gen-go
  69. // already validated the protobuf types.
  70. ft := newFile(t)
  71. if err := validateFile(ft); err != nil {
  72. return nil, err
  73. }
  74. // TODO: When using reference descriptors, it is vital that all enums and
  75. // messages are touched so that they are initialized before returning.
  76. // Otherwise, reference descriptors may still be invalid.
  77. //
  78. // We can remove this once validateFile is implemented, since it will
  79. // inherently touch all the necessary messages and enums.
  80. visitMessages(ft)
  81. return ft, nil
  82. }
  83. func visitMessages(d interface {
  84. Enums() protoreflect.EnumDescriptors
  85. Messages() protoreflect.MessageDescriptors
  86. }) {
  87. d.Enums()
  88. ms := d.Messages()
  89. for i := 0; i < ms.Len(); i++ {
  90. visitMessages(ms.Get(i))
  91. }
  92. }
  93. // Message is a constructor for protoreflect.MessageDescriptor.
  94. type Message struct {
  95. Name protoreflect.Name
  96. Fields []Field
  97. Oneofs []Oneof
  98. ReservedNames []protoreflect.Name
  99. ReservedRanges [][2]protoreflect.FieldNumber
  100. ExtensionRanges [][2]protoreflect.FieldNumber
  101. ExtensionRangeOptions []protoreflect.ProtoMessage
  102. Options protoreflect.ProtoMessage
  103. IsMapEntry bool
  104. Enums []Enum
  105. Messages []Message
  106. Extensions []Extension
  107. *messageMeta
  108. }
  109. // Reference returns m as a reference protoreflect.MessageDescriptor,
  110. // which can be used to satisfy internal dependencies within a proto file.
  111. // Methods on the returned descriptor are not valid until the file that this
  112. // message belongs to has been constructed via NewFile.
  113. func (m *Message) Reference() protoreflect.MessageDescriptor {
  114. return messageDesc{m}
  115. }
  116. // Field is a constructor for protoreflect.FieldDescriptor.
  117. type Field struct {
  118. Name protoreflect.Name
  119. Number protoreflect.FieldNumber
  120. Cardinality protoreflect.Cardinality
  121. Kind protoreflect.Kind
  122. JSONName string
  123. Default protoreflect.Value
  124. OneofName protoreflect.Name
  125. MessageType protoreflect.MessageDescriptor
  126. EnumType protoreflect.EnumDescriptor
  127. Options protoreflect.ProtoMessage
  128. IsPacked OptionalBool
  129. IsWeak bool
  130. *fieldMeta
  131. }
  132. // Oneof is a constructor for protoreflect.OneofDescriptor.
  133. type Oneof struct {
  134. Name protoreflect.Name
  135. Options protoreflect.ProtoMessage
  136. *oneofMeta
  137. }
  138. // Extension is a constructor for protoreflect.ExtensionDescriptor.
  139. type Extension struct {
  140. Name protoreflect.Name
  141. Number protoreflect.FieldNumber
  142. Cardinality protoreflect.Cardinality
  143. Kind protoreflect.Kind
  144. Default protoreflect.Value
  145. MessageType protoreflect.MessageDescriptor
  146. EnumType protoreflect.EnumDescriptor
  147. ExtendedType protoreflect.MessageDescriptor
  148. Options protoreflect.ProtoMessage
  149. IsPacked OptionalBool
  150. *extensionMeta
  151. }
  152. // Enum is a constructor for protoreflect.EnumDescriptor.
  153. type Enum struct {
  154. Name protoreflect.Name
  155. Values []EnumValue
  156. ReservedNames []protoreflect.Name
  157. ReservedRanges [][2]protoreflect.EnumNumber
  158. Options protoreflect.ProtoMessage
  159. *enumMeta
  160. }
  161. // Reference returns e as a reference protoreflect.EnumDescriptor,
  162. // which can be used to satisfy internal dependencies within a proto file.
  163. // Methods on the returned descriptor are not valid until the file that this
  164. // enum belongs to has been constructed via NewFile.
  165. func (e *Enum) Reference() protoreflect.EnumDescriptor {
  166. return enumDesc{e}
  167. }
  168. // EnumValue is a constructor for protoreflect.EnumValueDescriptor.
  169. type EnumValue struct {
  170. Name protoreflect.Name
  171. Number protoreflect.EnumNumber
  172. Options protoreflect.ProtoMessage
  173. *enumValueMeta
  174. }
  175. // Service is a constructor for protoreflect.ServiceDescriptor.
  176. type Service struct {
  177. Name protoreflect.Name
  178. Methods []Method
  179. Options protoreflect.ProtoMessage
  180. *serviceMeta
  181. }
  182. // Method is a constructor for protoreflect.MethodDescriptor.
  183. type Method struct {
  184. Name protoreflect.Name
  185. InputType protoreflect.MessageDescriptor
  186. OutputType protoreflect.MessageDescriptor
  187. IsStreamingClient bool
  188. IsStreamingServer bool
  189. Options protoreflect.ProtoMessage
  190. *methodMeta
  191. }
  192. // OptionalBool is a tristate boolean.
  193. type OptionalBool uint8
  194. // Tristate boolean values.
  195. const (
  196. DefaultBool OptionalBool = iota
  197. True
  198. False
  199. )