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