proto.go

  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
  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//
 11// # Protocol Buffer Descriptors
 12//
 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//
 28// # Go Type Descriptors
 29//
 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//
 42// # Value Interfaces
 43//
 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 [google.golang.org/protobuf/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//
 55// # Relationships
 56//
 57// The following diagrams demonstrate the relationships between
 58// various types declared in this package.
 59//
 60//	                       ┌───────────────────────────────────┐
 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//
 81//	  ┌──────────────── 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// Just as how Go's [reflect.Type] is a reflective description of a Go type,
 96// a [MessageType] is a reflective description of a Go type for a protobuf message.
 97//
 98// • A [MessageDescriptor] describes an abstract protobuf message type.
 99// It has no understanding of Go types. In order to construct a [MessageType]
100// from just a [MessageDescriptor], you can consider looking up the message type
101// in the global registry using the FindMessageByName method on
102// [google.golang.org/protobuf/reflect/protoregistry.GlobalTypes]
103// or constructing a dynamic [MessageType] using
104// [google.golang.org/protobuf/types/dynamicpb.NewMessageType].
105//
106// • A [Message] is a reflective view over a concrete message instance.
107// Generated messages implement [ProtoMessage], which can convert to a [Message].
108// Just as how Go's [reflect.Value] is a reflective view over a Go value,
109// a [Message] is a reflective view over a concrete protobuf message instance.
110// Using Go reflection as an analogy, the [ProtoMessage.ProtoReflect] method is similar to
111// calling [reflect.ValueOf], and the [Message.Interface] method is similar to
112// calling [reflect.Value.Interface].
113//
114//	      ┌── TypeDescriptor() ──┐    ┌───── Descriptor() ─────┐
115//	      │                      V    │                        V
116//	╔═══════════════╗  ╔═════════════════════════╗  ╔═════════════════════╗
117//	║ ExtensionType ║  ║ ExtensionTypeDescriptor ║  ║ ExtensionDescriptor ║
118//	╚═══════════════╝  ╚═════════════════════════╝  ╚═════════════════════╝
119//	      Λ                      │   │ Λ                      │ Λ
120//	      └─────── Type() ───────┘   │ └─── may implement ────┘ │
121//	                                 │                          │
122//	                                 └────── implements ────────┘
123//
124// • An [ExtensionType] describes a concrete Go implementation of an extension.
125// It has an [ExtensionTypeDescriptor] and can convert to/from
126// an abstract [Value] and a Go value.
127//
128// • An [ExtensionTypeDescriptor] is an [ExtensionDescriptor]
129// which also has an [ExtensionType].
130//
131// • An [ExtensionDescriptor] describes an abstract protobuf extension field and
132// may not always be an [ExtensionTypeDescriptor].
133package protoreflect
134
135import (
136	"fmt"
137	"strings"
138
139	"google.golang.org/protobuf/encoding/protowire"
140	"google.golang.org/protobuf/internal/pragma"
141)
142
143type doNotImplement pragma.DoNotImplement
144
145// ProtoMessage is the top-level interface that all proto messages implement.
146// This is declared in the protoreflect package to avoid a cyclic dependency;
147// use the [google.golang.org/protobuf/proto.Message] type instead, which aliases this type.
148type ProtoMessage interface{ ProtoReflect() Message }
149
150// Syntax is the language version of the proto file.
151type Syntax syntax
152
153type syntax int8 // keep exact type opaque as the int type may change
154
155const (
156	Proto2   Syntax = 2
157	Proto3   Syntax = 3
158	Editions Syntax = 4
159)
160
161// IsValid reports whether the syntax is valid.
162func (s Syntax) IsValid() bool {
163	switch s {
164	case Proto2, Proto3, Editions:
165		return true
166	default:
167		return false
168	}
169}
170
171// String returns s as a proto source identifier (e.g., "proto2").
172func (s Syntax) String() string {
173	switch s {
174	case Proto2:
175		return "proto2"
176	case Proto3:
177		return "proto3"
178	case Editions:
179		return "editions"
180	default:
181		return fmt.Sprintf("<unknown:%d>", s)
182	}
183}
184
185// GoString returns s as a Go source identifier (e.g., "Proto2").
186func (s Syntax) GoString() string {
187	switch s {
188	case Proto2:
189		return "Proto2"
190	case Proto3:
191		return "Proto3"
192	default:
193		return fmt.Sprintf("Syntax(%d)", s)
194	}
195}
196
197// Cardinality determines whether a field is optional, required, or repeated.
198type Cardinality cardinality
199
200type cardinality int8 // keep exact type opaque as the int type may change
201
202// Constants as defined by the google.protobuf.Cardinality enumeration.
203const (
204	Optional Cardinality = 1 // appears zero or one times
205	Required Cardinality = 2 // appears exactly one time; invalid with Proto3
206	Repeated Cardinality = 3 // appears zero or more times
207)
208
209// IsValid reports whether the cardinality is valid.
210func (c Cardinality) IsValid() bool {
211	switch c {
212	case Optional, Required, Repeated:
213		return true
214	default:
215		return false
216	}
217}
218
219// String returns c as a proto source identifier (e.g., "optional").
220func (c Cardinality) String() string {
221	switch c {
222	case Optional:
223		return "optional"
224	case Required:
225		return "required"
226	case Repeated:
227		return "repeated"
228	default:
229		return fmt.Sprintf("<unknown:%d>", c)
230	}
231}
232
233// GoString returns c as a Go source identifier (e.g., "Optional").
234func (c Cardinality) GoString() string {
235	switch c {
236	case Optional:
237		return "Optional"
238	case Required:
239		return "Required"
240	case Repeated:
241		return "Repeated"
242	default:
243		return fmt.Sprintf("Cardinality(%d)", c)
244	}
245}
246
247// Kind indicates the basic proto kind of a field.
248type Kind kind
249
250type kind int8 // keep exact type opaque as the int type may change
251
252// Constants as defined by the google.protobuf.Field.Kind enumeration.
253const (
254	BoolKind     Kind = 8
255	EnumKind     Kind = 14
256	Int32Kind    Kind = 5
257	Sint32Kind   Kind = 17
258	Uint32Kind   Kind = 13
259	Int64Kind    Kind = 3
260	Sint64Kind   Kind = 18
261	Uint64Kind   Kind = 4
262	Sfixed32Kind Kind = 15
263	Fixed32Kind  Kind = 7
264	FloatKind    Kind = 2
265	Sfixed64Kind Kind = 16
266	Fixed64Kind  Kind = 6
267	DoubleKind   Kind = 1
268	StringKind   Kind = 9
269	BytesKind    Kind = 12
270	MessageKind  Kind = 11
271	GroupKind    Kind = 10
272)
273
274// IsValid reports whether the kind is valid.
275func (k Kind) IsValid() bool {
276	switch k {
277	case BoolKind, EnumKind,
278		Int32Kind, Sint32Kind, Uint32Kind,
279		Int64Kind, Sint64Kind, Uint64Kind,
280		Sfixed32Kind, Fixed32Kind, FloatKind,
281		Sfixed64Kind, Fixed64Kind, DoubleKind,
282		StringKind, BytesKind, MessageKind, GroupKind:
283		return true
284	default:
285		return false
286	}
287}
288
289// String returns k as a proto source identifier (e.g., "bool").
290func (k Kind) String() string {
291	switch k {
292	case BoolKind:
293		return "bool"
294	case EnumKind:
295		return "enum"
296	case Int32Kind:
297		return "int32"
298	case Sint32Kind:
299		return "sint32"
300	case Uint32Kind:
301		return "uint32"
302	case Int64Kind:
303		return "int64"
304	case Sint64Kind:
305		return "sint64"
306	case Uint64Kind:
307		return "uint64"
308	case Sfixed32Kind:
309		return "sfixed32"
310	case Fixed32Kind:
311		return "fixed32"
312	case FloatKind:
313		return "float"
314	case Sfixed64Kind:
315		return "sfixed64"
316	case Fixed64Kind:
317		return "fixed64"
318	case DoubleKind:
319		return "double"
320	case StringKind:
321		return "string"
322	case BytesKind:
323		return "bytes"
324	case MessageKind:
325		return "message"
326	case GroupKind:
327		return "group"
328	default:
329		return fmt.Sprintf("<unknown:%d>", k)
330	}
331}
332
333// GoString returns k as a Go source identifier (e.g., "BoolKind").
334func (k Kind) GoString() string {
335	switch k {
336	case BoolKind:
337		return "BoolKind"
338	case EnumKind:
339		return "EnumKind"
340	case Int32Kind:
341		return "Int32Kind"
342	case Sint32Kind:
343		return "Sint32Kind"
344	case Uint32Kind:
345		return "Uint32Kind"
346	case Int64Kind:
347		return "Int64Kind"
348	case Sint64Kind:
349		return "Sint64Kind"
350	case Uint64Kind:
351		return "Uint64Kind"
352	case Sfixed32Kind:
353		return "Sfixed32Kind"
354	case Fixed32Kind:
355		return "Fixed32Kind"
356	case FloatKind:
357		return "FloatKind"
358	case Sfixed64Kind:
359		return "Sfixed64Kind"
360	case Fixed64Kind:
361		return "Fixed64Kind"
362	case DoubleKind:
363		return "DoubleKind"
364	case StringKind:
365		return "StringKind"
366	case BytesKind:
367		return "BytesKind"
368	case MessageKind:
369		return "MessageKind"
370	case GroupKind:
371		return "GroupKind"
372	default:
373		return fmt.Sprintf("Kind(%d)", k)
374	}
375}
376
377// FieldNumber is the field number in a message.
378type FieldNumber = protowire.Number
379
380// FieldNumbers represent a list of field numbers.
381type FieldNumbers interface {
382	// Len reports the number of fields in the list.
383	Len() int
384	// Get returns the ith field number. It panics if out of bounds.
385	Get(i int) FieldNumber
386	// Has reports whether n is within the list of fields.
387	Has(n FieldNumber) bool
388
389	doNotImplement
390}
391
392// FieldRanges represent a list of field number ranges.
393type FieldRanges interface {
394	// Len reports the number of ranges in the list.
395	Len() int
396	// Get returns the ith range. It panics if out of bounds.
397	Get(i int) [2]FieldNumber // start inclusive; end exclusive
398	// Has reports whether n is within any of the ranges.
399	Has(n FieldNumber) bool
400
401	doNotImplement
402}
403
404// EnumNumber is the numeric value for an enum.
405type EnumNumber int32
406
407// EnumRanges represent a list of enum number ranges.
408type EnumRanges interface {
409	// Len reports the number of ranges in the list.
410	Len() int
411	// Get returns the ith range. It panics if out of bounds.
412	Get(i int) [2]EnumNumber // start inclusive; end inclusive
413	// Has reports whether n is within any of the ranges.
414	Has(n EnumNumber) bool
415
416	doNotImplement
417}
418
419// Name is the short name for a proto declaration. This is not the name
420// as used in Go source code, which might not be identical to the proto name.
421type Name string // e.g., "Kind"
422
423// IsValid reports whether s is a syntactically valid name.
424// An empty name is invalid.
425func (s Name) IsValid() bool {
426	return consumeIdent(string(s)) == len(s)
427}
428
429// Names represent a list of names.
430type Names interface {
431	// Len reports the number of names in the list.
432	Len() int
433	// Get returns the ith name. It panics if out of bounds.
434	Get(i int) Name
435	// Has reports whether s matches any names in the list.
436	Has(s Name) bool
437
438	doNotImplement
439}
440
441// FullName is a qualified name that uniquely identifies a proto declaration.
442// A qualified name is the concatenation of the proto package along with the
443// fully-declared name (i.e., name of parent preceding the name of the child),
444// with a '.' delimiter placed between each [Name].
445//
446// This should not have any leading or trailing dots.
447type FullName string // e.g., "google.protobuf.Field.Kind"
448
449// IsValid reports whether s is a syntactically valid full name.
450// An empty full name is invalid.
451func (s FullName) IsValid() bool {
452	i := consumeIdent(string(s))
453	if i < 0 {
454		return false
455	}
456	for len(s) > i {
457		if s[i] != '.' {
458			return false
459		}
460		i++
461		n := consumeIdent(string(s[i:]))
462		if n < 0 {
463			return false
464		}
465		i += n
466	}
467	return true
468}
469
470func consumeIdent(s string) (i int) {
471	if len(s) == 0 || !isLetter(s[i]) {
472		return -1
473	}
474	i++
475	for len(s) > i && isLetterDigit(s[i]) {
476		i++
477	}
478	return i
479}
480func isLetter(c byte) bool {
481	return c == '_' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')
482}
483func isLetterDigit(c byte) bool {
484	return isLetter(c) || ('0' <= c && c <= '9')
485}
486
487// Name returns the short name, which is the last identifier segment.
488// A single segment FullName is the [Name] itself.
489func (n FullName) Name() Name {
490	if i := strings.LastIndexByte(string(n), '.'); i >= 0 {
491		return Name(n[i+1:])
492	}
493	return Name(n)
494}
495
496// Parent returns the full name with the trailing identifier removed.
497// A single segment FullName has no parent.
498func (n FullName) Parent() FullName {
499	if i := strings.LastIndexByte(string(n), '.'); i >= 0 {
500		return n[:i]
501	}
502	return ""
503}
504
505// Append returns the qualified name appended with the provided short name.
506//
507// Invariant: n == n.Parent().Append(n.Name()) // assuming n is valid
508func (n FullName) Append(s Name) FullName {
509	if n == "" {
510		return FullName(s)
511	}
512	return n + "." + FullName(s)
513}