Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

509 rader
17 KiB

  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 protoreflect provides interfaces to dynamically manipulate messages.
  5. //
  6. // This package includes type descriptors which describe the structure of types
  7. // defined in proto source files and value interfaces which provide the
  8. // ability to examine and manipulate the contents of messages.
  9. //
  10. // # Protocol Buffer Descriptors
  11. //
  12. // Protobuf descriptors (e.g., EnumDescriptor or MessageDescriptor)
  13. // are immutable objects that represent protobuf type information.
  14. // They are wrappers around the messages declared in descriptor.proto.
  15. // Protobuf descriptors alone lack any information regarding Go types.
  16. //
  17. // Enums and messages generated by this module implement Enum and ProtoMessage,
  18. // where the Descriptor and ProtoReflect.Descriptor accessors respectively
  19. // return the protobuf descriptor for the values.
  20. //
  21. // The protobuf descriptor interfaces are not meant to be implemented by
  22. // user code since they might need to be extended in the future to support
  23. // additions to the protobuf language.
  24. // The "google.golang.org/protobuf/reflect/protodesc" package converts between
  25. // google.protobuf.DescriptorProto messages and protobuf descriptors.
  26. //
  27. // # Go Type Descriptors
  28. //
  29. // A type descriptor (e.g., EnumType or MessageType) is a constructor for
  30. // a concrete Go type that represents the associated protobuf descriptor.
  31. // There is commonly a one-to-one relationship between protobuf descriptors and
  32. // Go type descriptors, but it can potentially be a one-to-many relationship.
  33. //
  34. // Enums and messages generated by this module implement Enum and ProtoMessage,
  35. // where the Type and ProtoReflect.Type accessors respectively
  36. // return the protobuf descriptor for the values.
  37. //
  38. // The "google.golang.org/protobuf/types/dynamicpb" package can be used to
  39. // create Go type descriptors from protobuf descriptors.
  40. //
  41. // # Value Interfaces
  42. //
  43. // The Enum and Message interfaces provide a reflective view over an
  44. // enum or message instance. For enums, it provides the ability to retrieve
  45. // the enum value number for any concrete enum type. For messages, it provides
  46. // the ability to access or manipulate fields of the message.
  47. //
  48. // To convert a proto.Message to a protoreflect.Message, use the
  49. // former's ProtoReflect method. Since the ProtoReflect method is new to the
  50. // v2 message interface, it may not be present on older message implementations.
  51. // The "github.com/golang/protobuf/proto".MessageReflect function can be used
  52. // to obtain a reflective view on older messages.
  53. //
  54. // # Relationships
  55. //
  56. // The following diagrams demonstrate the relationships between
  57. // various types declared in this package.
  58. //
  59. // ┌───────────────────────────────────┐
  60. // V │
  61. // ┌────────────── New(n) ─────────────┐ │
  62. // │ │ │
  63. // │ ┌──── Descriptor() ──┐ │ ┌── Number() ──┐ │
  64. // │ │ V V │ V │
  65. // ╔════════════╗ ╔════════════════╗ ╔════════╗ ╔════════════╗
  66. // ║ EnumType ║ ║ EnumDescriptor ║ ║ Enum ║ ║ EnumNumber ║
  67. // ╚════════════╝ ╚════════════════╝ ╚════════╝ ╚════════════╝
  68. // Λ Λ │ │
  69. // │ └─── Descriptor() ──┘ │
  70. // │ │
  71. // └────────────────── Type() ───────┘
  72. //
  73. // • An EnumType describes a concrete Go enum type.
  74. // It has an EnumDescriptor and can construct an Enum instance.
  75. //
  76. // • An EnumDescriptor describes an abstract protobuf enum type.
  77. //
  78. // • An Enum is a concrete enum instance. Generated enums implement Enum.
  79. //
  80. // ┌──────────────── New() ─────────────────┐
  81. // │ │
  82. // │ ┌─── Descriptor() ─────┐ │ ┌── Interface() ───┐
  83. // │ │ V V │ V
  84. // ╔═════════════╗ ╔═══════════════════╗ ╔═════════╗ ╔══════════════╗
  85. // ║ MessageType ║ ║ MessageDescriptor ║ ║ Message ║ ║ ProtoMessage ║
  86. // ╚═════════════╝ ╚═══════════════════╝ ╚═════════╝ ╚══════════════╝
  87. // Λ Λ │ │ Λ │
  88. // │ └──── Descriptor() ────┘ │ └─ ProtoReflect() ─┘
  89. // │ │
  90. // └─────────────────── Type() ─────────┘
  91. //
  92. // • A MessageType describes a concrete Go message type.
  93. // It has a MessageDescriptor and can construct a Message instance.
  94. // Just as how Go's reflect.Type is a reflective description of a Go type,
  95. // a MessageType is a reflective description of a Go type for a protobuf message.
  96. //
  97. // • A MessageDescriptor describes an abstract protobuf message type.
  98. // It has no understanding of Go types. In order to construct a MessageType
  99. // from just a MessageDescriptor, you can consider looking up the message type
  100. // in the global registry using protoregistry.GlobalTypes.FindMessageByName
  101. // or constructing a dynamic MessageType using dynamicpb.NewMessageType.
  102. //
  103. // • A Message is a reflective view over a concrete message instance.
  104. // Generated messages implement ProtoMessage, which can convert to a Message.
  105. // Just as how Go's reflect.Value is a reflective view over a Go value,
  106. // a Message is a reflective view over a concrete protobuf message instance.
  107. // Using Go reflection as an analogy, the ProtoReflect method is similar to
  108. // calling reflect.ValueOf, and the Message.Interface method is similar to
  109. // calling reflect.Value.Interface.
  110. //
  111. // ┌── TypeDescriptor() ──┐ ┌───── Descriptor() ─────┐
  112. // │ V │ V
  113. // ╔═══════════════╗ ╔═════════════════════════╗ ╔═════════════════════╗
  114. // ║ ExtensionType ║ ║ ExtensionTypeDescriptor ║ ║ ExtensionDescriptor ║
  115. // ╚═══════════════╝ ╚═════════════════════════╝ ╚═════════════════════╝
  116. // Λ │ │ Λ │ Λ
  117. // └─────── Type() ───────┘ │ └─── may implement ────┘ │
  118. // │ │
  119. // └────── implements ────────┘
  120. //
  121. // • An ExtensionType describes a concrete Go implementation of an extension.
  122. // It has an ExtensionTypeDescriptor and can convert to/from
  123. // abstract Values and Go values.
  124. //
  125. // • An ExtensionTypeDescriptor is an ExtensionDescriptor
  126. // which also has an ExtensionType.
  127. //
  128. // • An ExtensionDescriptor describes an abstract protobuf extension field and
  129. // may not always be an ExtensionTypeDescriptor.
  130. package protoreflect
  131. import (
  132. "fmt"
  133. "strings"
  134. "google.golang.org/protobuf/encoding/protowire"
  135. "google.golang.org/protobuf/internal/pragma"
  136. )
  137. type doNotImplement pragma.DoNotImplement
  138. // ProtoMessage is the top-level interface that all proto messages implement.
  139. // This is declared in the protoreflect package to avoid a cyclic dependency;
  140. // use the proto.Message type instead, which aliases this type.
  141. type ProtoMessage interface{ ProtoReflect() Message }
  142. // Syntax is the language version of the proto file.
  143. type Syntax syntax
  144. type syntax int8 // keep exact type opaque as the int type may change
  145. const (
  146. Proto2 Syntax = 2
  147. Proto3 Syntax = 3
  148. )
  149. // IsValid reports whether the syntax is valid.
  150. func (s Syntax) IsValid() bool {
  151. switch s {
  152. case Proto2, Proto3:
  153. return true
  154. default:
  155. return false
  156. }
  157. }
  158. // String returns s as a proto source identifier (e.g., "proto2").
  159. func (s Syntax) String() string {
  160. switch s {
  161. case Proto2:
  162. return "proto2"
  163. case Proto3:
  164. return "proto3"
  165. default:
  166. return fmt.Sprintf("<unknown:%d>", s)
  167. }
  168. }
  169. // GoString returns s as a Go source identifier (e.g., "Proto2").
  170. func (s Syntax) GoString() string {
  171. switch s {
  172. case Proto2:
  173. return "Proto2"
  174. case Proto3:
  175. return "Proto3"
  176. default:
  177. return fmt.Sprintf("Syntax(%d)", s)
  178. }
  179. }
  180. // Cardinality determines whether a field is optional, required, or repeated.
  181. type Cardinality cardinality
  182. type cardinality int8 // keep exact type opaque as the int type may change
  183. // Constants as defined by the google.protobuf.Cardinality enumeration.
  184. const (
  185. Optional Cardinality = 1 // appears zero or one times
  186. Required Cardinality = 2 // appears exactly one time; invalid with Proto3
  187. Repeated Cardinality = 3 // appears zero or more times
  188. )
  189. // IsValid reports whether the cardinality is valid.
  190. func (c Cardinality) IsValid() bool {
  191. switch c {
  192. case Optional, Required, Repeated:
  193. return true
  194. default:
  195. return false
  196. }
  197. }
  198. // String returns c as a proto source identifier (e.g., "optional").
  199. func (c Cardinality) String() string {
  200. switch c {
  201. case Optional:
  202. return "optional"
  203. case Required:
  204. return "required"
  205. case Repeated:
  206. return "repeated"
  207. default:
  208. return fmt.Sprintf("<unknown:%d>", c)
  209. }
  210. }
  211. // GoString returns c as a Go source identifier (e.g., "Optional").
  212. func (c Cardinality) GoString() string {
  213. switch c {
  214. case Optional:
  215. return "Optional"
  216. case Required:
  217. return "Required"
  218. case Repeated:
  219. return "Repeated"
  220. default:
  221. return fmt.Sprintf("Cardinality(%d)", c)
  222. }
  223. }
  224. // Kind indicates the basic proto kind of a field.
  225. type Kind kind
  226. type kind int8 // keep exact type opaque as the int type may change
  227. // Constants as defined by the google.protobuf.Field.Kind enumeration.
  228. const (
  229. BoolKind Kind = 8
  230. EnumKind Kind = 14
  231. Int32Kind Kind = 5
  232. Sint32Kind Kind = 17
  233. Uint32Kind Kind = 13
  234. Int64Kind Kind = 3
  235. Sint64Kind Kind = 18
  236. Uint64Kind Kind = 4
  237. Sfixed32Kind Kind = 15
  238. Fixed32Kind Kind = 7
  239. FloatKind Kind = 2
  240. Sfixed64Kind Kind = 16
  241. Fixed64Kind Kind = 6
  242. DoubleKind Kind = 1
  243. StringKind Kind = 9
  244. BytesKind Kind = 12
  245. MessageKind Kind = 11
  246. GroupKind Kind = 10
  247. )
  248. // IsValid reports whether the kind is valid.
  249. func (k Kind) IsValid() bool {
  250. switch k {
  251. case BoolKind, EnumKind,
  252. Int32Kind, Sint32Kind, Uint32Kind,
  253. Int64Kind, Sint64Kind, Uint64Kind,
  254. Sfixed32Kind, Fixed32Kind, FloatKind,
  255. Sfixed64Kind, Fixed64Kind, DoubleKind,
  256. StringKind, BytesKind, MessageKind, GroupKind:
  257. return true
  258. default:
  259. return false
  260. }
  261. }
  262. // String returns k as a proto source identifier (e.g., "bool").
  263. func (k Kind) String() string {
  264. switch k {
  265. case BoolKind:
  266. return "bool"
  267. case EnumKind:
  268. return "enum"
  269. case Int32Kind:
  270. return "int32"
  271. case Sint32Kind:
  272. return "sint32"
  273. case Uint32Kind:
  274. return "uint32"
  275. case Int64Kind:
  276. return "int64"
  277. case Sint64Kind:
  278. return "sint64"
  279. case Uint64Kind:
  280. return "uint64"
  281. case Sfixed32Kind:
  282. return "sfixed32"
  283. case Fixed32Kind:
  284. return "fixed32"
  285. case FloatKind:
  286. return "float"
  287. case Sfixed64Kind:
  288. return "sfixed64"
  289. case Fixed64Kind:
  290. return "fixed64"
  291. case DoubleKind:
  292. return "double"
  293. case StringKind:
  294. return "string"
  295. case BytesKind:
  296. return "bytes"
  297. case MessageKind:
  298. return "message"
  299. case GroupKind:
  300. return "group"
  301. default:
  302. return fmt.Sprintf("<unknown:%d>", k)
  303. }
  304. }
  305. // GoString returns k as a Go source identifier (e.g., "BoolKind").
  306. func (k Kind) GoString() string {
  307. switch k {
  308. case BoolKind:
  309. return "BoolKind"
  310. case EnumKind:
  311. return "EnumKind"
  312. case Int32Kind:
  313. return "Int32Kind"
  314. case Sint32Kind:
  315. return "Sint32Kind"
  316. case Uint32Kind:
  317. return "Uint32Kind"
  318. case Int64Kind:
  319. return "Int64Kind"
  320. case Sint64Kind:
  321. return "Sint64Kind"
  322. case Uint64Kind:
  323. return "Uint64Kind"
  324. case Sfixed32Kind:
  325. return "Sfixed32Kind"
  326. case Fixed32Kind:
  327. return "Fixed32Kind"
  328. case FloatKind:
  329. return "FloatKind"
  330. case Sfixed64Kind:
  331. return "Sfixed64Kind"
  332. case Fixed64Kind:
  333. return "Fixed64Kind"
  334. case DoubleKind:
  335. return "DoubleKind"
  336. case StringKind:
  337. return "StringKind"
  338. case BytesKind:
  339. return "BytesKind"
  340. case MessageKind:
  341. return "MessageKind"
  342. case GroupKind:
  343. return "GroupKind"
  344. default:
  345. return fmt.Sprintf("Kind(%d)", k)
  346. }
  347. }
  348. // FieldNumber is the field number in a message.
  349. type FieldNumber = protowire.Number
  350. // FieldNumbers represent a list of field numbers.
  351. type FieldNumbers interface {
  352. // Len reports the number of fields in the list.
  353. Len() int
  354. // Get returns the ith field number. It panics if out of bounds.
  355. Get(i int) FieldNumber
  356. // Has reports whether n is within the list of fields.
  357. Has(n FieldNumber) bool
  358. doNotImplement
  359. }
  360. // FieldRanges represent a list of field number ranges.
  361. type FieldRanges interface {
  362. // Len reports the number of ranges in the list.
  363. Len() int
  364. // Get returns the ith range. It panics if out of bounds.
  365. Get(i int) [2]FieldNumber // start inclusive; end exclusive
  366. // Has reports whether n is within any of the ranges.
  367. Has(n FieldNumber) bool
  368. doNotImplement
  369. }
  370. // EnumNumber is the numeric value for an enum.
  371. type EnumNumber int32
  372. // EnumRanges represent a list of enum number ranges.
  373. type EnumRanges interface {
  374. // Len reports the number of ranges in the list.
  375. Len() int
  376. // Get returns the ith range. It panics if out of bounds.
  377. Get(i int) [2]EnumNumber // start inclusive; end inclusive
  378. // Has reports whether n is within any of the ranges.
  379. Has(n EnumNumber) bool
  380. doNotImplement
  381. }
  382. // Name is the short name for a proto declaration. This is not the name
  383. // as used in Go source code, which might not be identical to the proto name.
  384. type Name string // e.g., "Kind"
  385. // IsValid reports whether s is a syntactically valid name.
  386. // An empty name is invalid.
  387. func (s Name) IsValid() bool {
  388. return consumeIdent(string(s)) == len(s)
  389. }
  390. // Names represent a list of names.
  391. type Names interface {
  392. // Len reports the number of names in the list.
  393. Len() int
  394. // Get returns the ith name. It panics if out of bounds.
  395. Get(i int) Name
  396. // Has reports whether s matches any names in the list.
  397. Has(s Name) bool
  398. doNotImplement
  399. }
  400. // FullName is a qualified name that uniquely identifies a proto declaration.
  401. // A qualified name is the concatenation of the proto package along with the
  402. // fully-declared name (i.e., name of parent preceding the name of the child),
  403. // with a '.' delimiter placed between each Name.
  404. //
  405. // This should not have any leading or trailing dots.
  406. type FullName string // e.g., "google.protobuf.Field.Kind"
  407. // IsValid reports whether s is a syntactically valid full name.
  408. // An empty full name is invalid.
  409. func (s FullName) IsValid() bool {
  410. i := consumeIdent(string(s))
  411. if i < 0 {
  412. return false
  413. }
  414. for len(s) > i {
  415. if s[i] != '.' {
  416. return false
  417. }
  418. i++
  419. n := consumeIdent(string(s[i:]))
  420. if n < 0 {
  421. return false
  422. }
  423. i += n
  424. }
  425. return true
  426. }
  427. func consumeIdent(s string) (i int) {
  428. if len(s) == 0 || !isLetter(s[i]) {
  429. return -1
  430. }
  431. i++
  432. for len(s) > i && isLetterDigit(s[i]) {
  433. i++
  434. }
  435. return i
  436. }
  437. func isLetter(c byte) bool {
  438. return c == '_' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')
  439. }
  440. func isLetterDigit(c byte) bool {
  441. return isLetter(c) || ('0' <= c && c <= '9')
  442. }
  443. // Name returns the short name, which is the last identifier segment.
  444. // A single segment FullName is the Name itself.
  445. func (n FullName) Name() Name {
  446. if i := strings.LastIndexByte(string(n), '.'); i >= 0 {
  447. return Name(n[i+1:])
  448. }
  449. return Name(n)
  450. }
  451. // Parent returns the full name with the trailing identifier removed.
  452. // A single segment FullName has no parent.
  453. func (n FullName) Parent() FullName {
  454. if i := strings.LastIndexByte(string(n), '.'); i >= 0 {
  455. return n[:i]
  456. }
  457. return ""
  458. }
  459. // Append returns the qualified name appended with the provided short name.
  460. //
  461. // Invariant: n == n.Parent().Append(n.Name()) // assuming n is valid
  462. func (n FullName) Append(s Name) FullName {
  463. if n == "" {
  464. return FullName(s)
  465. }
  466. return n + "." + FullName(s)
  467. }