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