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