blob: b669a4e7619dfb2384830ef9e0062c3e9b17a50f [file] [log] [blame]
Andrea Campanella3614a922021-02-25 12:40:42 +01001// 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 "regexp"
132 "strings"
133
134 "google.golang.org/protobuf/encoding/protowire"
135 "google.golang.org/protobuf/internal/pragma"
136)
137
138type doNotImplement pragma.DoNotImplement
139
140// ProtoMessage is the top-level interface that all proto messages implement.
141// This is declared in the protoreflect package to avoid a cyclic dependency;
142// use the proto.Message type instead, which aliases this type.
143type ProtoMessage interface{ ProtoReflect() Message }
144
145// Syntax is the language version of the proto file.
146type Syntax syntax
147
148type syntax int8 // keep exact type opaque as the int type may change
149
150const (
151 Proto2 Syntax = 2
152 Proto3 Syntax = 3
153)
154
155// IsValid reports whether the syntax is valid.
156func (s Syntax) IsValid() bool {
157 switch s {
158 case Proto2, Proto3:
159 return true
160 default:
161 return false
162 }
163}
164
165// String returns s as a proto source identifier (e.g., "proto2").
166func (s Syntax) String() string {
167 switch s {
168 case Proto2:
169 return "proto2"
170 case Proto3:
171 return "proto3"
172 default:
173 return fmt.Sprintf("<unknown:%d>", s)
174 }
175}
176
177// GoString returns s as a Go source identifier (e.g., "Proto2").
178func (s Syntax) GoString() string {
179 switch s {
180 case Proto2:
181 return "Proto2"
182 case Proto3:
183 return "Proto3"
184 default:
185 return fmt.Sprintf("Syntax(%d)", s)
186 }
187}
188
189// Cardinality determines whether a field is optional, required, or repeated.
190type Cardinality cardinality
191
192type cardinality int8 // keep exact type opaque as the int type may change
193
194// Constants as defined by the google.protobuf.Cardinality enumeration.
195const (
196 Optional Cardinality = 1 // appears zero or one times
197 Required Cardinality = 2 // appears exactly one time; invalid with Proto3
198 Repeated Cardinality = 3 // appears zero or more times
199)
200
201// IsValid reports whether the cardinality is valid.
202func (c Cardinality) IsValid() bool {
203 switch c {
204 case Optional, Required, Repeated:
205 return true
206 default:
207 return false
208 }
209}
210
211// String returns c as a proto source identifier (e.g., "optional").
212func (c Cardinality) String() 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("<unknown:%d>", c)
222 }
223}
224
225// GoString returns c as a Go source identifier (e.g., "Optional").
226func (c Cardinality) GoString() string {
227 switch c {
228 case Optional:
229 return "Optional"
230 case Required:
231 return "Required"
232 case Repeated:
233 return "Repeated"
234 default:
235 return fmt.Sprintf("Cardinality(%d)", c)
236 }
237}
238
239// Kind indicates the basic proto kind of a field.
240type Kind kind
241
242type kind int8 // keep exact type opaque as the int type may change
243
244// Constants as defined by the google.protobuf.Field.Kind enumeration.
245const (
246 BoolKind Kind = 8
247 EnumKind Kind = 14
248 Int32Kind Kind = 5
249 Sint32Kind Kind = 17
250 Uint32Kind Kind = 13
251 Int64Kind Kind = 3
252 Sint64Kind Kind = 18
253 Uint64Kind Kind = 4
254 Sfixed32Kind Kind = 15
255 Fixed32Kind Kind = 7
256 FloatKind Kind = 2
257 Sfixed64Kind Kind = 16
258 Fixed64Kind Kind = 6
259 DoubleKind Kind = 1
260 StringKind Kind = 9
261 BytesKind Kind = 12
262 MessageKind Kind = 11
263 GroupKind Kind = 10
264)
265
266// IsValid reports whether the kind is valid.
267func (k Kind) IsValid() bool {
268 switch k {
269 case BoolKind, EnumKind,
270 Int32Kind, Sint32Kind, Uint32Kind,
271 Int64Kind, Sint64Kind, Uint64Kind,
272 Sfixed32Kind, Fixed32Kind, FloatKind,
273 Sfixed64Kind, Fixed64Kind, DoubleKind,
274 StringKind, BytesKind, MessageKind, GroupKind:
275 return true
276 default:
277 return false
278 }
279}
280
281// String returns k as a proto source identifier (e.g., "bool").
282func (k Kind) String() string {
283 switch k {
284 case BoolKind:
285 return "bool"
286 case EnumKind:
287 return "enum"
288 case Int32Kind:
289 return "int32"
290 case Sint32Kind:
291 return "sint32"
292 case Uint32Kind:
293 return "uint32"
294 case Int64Kind:
295 return "int64"
296 case Sint64Kind:
297 return "sint64"
298 case Uint64Kind:
299 return "uint64"
300 case Sfixed32Kind:
301 return "sfixed32"
302 case Fixed32Kind:
303 return "fixed32"
304 case FloatKind:
305 return "float"
306 case Sfixed64Kind:
307 return "sfixed64"
308 case Fixed64Kind:
309 return "fixed64"
310 case DoubleKind:
311 return "double"
312 case StringKind:
313 return "string"
314 case BytesKind:
315 return "bytes"
316 case MessageKind:
317 return "message"
318 case GroupKind:
319 return "group"
320 default:
321 return fmt.Sprintf("<unknown:%d>", k)
322 }
323}
324
325// GoString returns k as a Go source identifier (e.g., "BoolKind").
326func (k Kind) GoString() string {
327 switch k {
328 case BoolKind:
329 return "BoolKind"
330 case EnumKind:
331 return "EnumKind"
332 case Int32Kind:
333 return "Int32Kind"
334 case Sint32Kind:
335 return "Sint32Kind"
336 case Uint32Kind:
337 return "Uint32Kind"
338 case Int64Kind:
339 return "Int64Kind"
340 case Sint64Kind:
341 return "Sint64Kind"
342 case Uint64Kind:
343 return "Uint64Kind"
344 case Sfixed32Kind:
345 return "Sfixed32Kind"
346 case Fixed32Kind:
347 return "Fixed32Kind"
348 case FloatKind:
349 return "FloatKind"
350 case Sfixed64Kind:
351 return "Sfixed64Kind"
352 case Fixed64Kind:
353 return "Fixed64Kind"
354 case DoubleKind:
355 return "DoubleKind"
356 case StringKind:
357 return "StringKind"
358 case BytesKind:
359 return "BytesKind"
360 case MessageKind:
361 return "MessageKind"
362 case GroupKind:
363 return "GroupKind"
364 default:
365 return fmt.Sprintf("Kind(%d)", k)
366 }
367}
368
369// FieldNumber is the field number in a message.
370type FieldNumber = protowire.Number
371
372// FieldNumbers represent a list of field numbers.
373type FieldNumbers interface {
374 // Len reports the number of fields in the list.
375 Len() int
376 // Get returns the ith field number. It panics if out of bounds.
377 Get(i int) FieldNumber
378 // Has reports whether n is within the list of fields.
379 Has(n FieldNumber) bool
380
381 doNotImplement
382}
383
384// FieldRanges represent a list of field number ranges.
385type FieldRanges interface {
386 // Len reports the number of ranges in the list.
387 Len() int
388 // Get returns the ith range. It panics if out of bounds.
389 Get(i int) [2]FieldNumber // start inclusive; end exclusive
390 // Has reports whether n is within any of the ranges.
391 Has(n FieldNumber) bool
392
393 doNotImplement
394}
395
396// EnumNumber is the numeric value for an enum.
397type EnumNumber int32
398
399// EnumRanges represent a list of enum number ranges.
400type EnumRanges interface {
401 // Len reports the number of ranges in the list.
402 Len() int
403 // Get returns the ith range. It panics if out of bounds.
404 Get(i int) [2]EnumNumber // start inclusive; end inclusive
405 // Has reports whether n is within any of the ranges.
406 Has(n EnumNumber) bool
407
408 doNotImplement
409}
410
411var (
412 regexName = regexp.MustCompile(`^[_a-zA-Z][_a-zA-Z0-9]*$`)
413 regexFullName = regexp.MustCompile(`^[_a-zA-Z][_a-zA-Z0-9]*(\.[_a-zA-Z][_a-zA-Z0-9]*)*$`)
414)
415
416// Name is the short name for a proto declaration. This is not the name
417// as used in Go source code, which might not be identical to the proto name.
418type Name string // e.g., "Kind"
419
420// IsValid reports whether n is a syntactically valid name.
421// An empty name is invalid.
422func (n Name) IsValid() bool {
423 return regexName.MatchString(string(n))
424}
425
426// Names represent a list of names.
427type Names interface {
428 // Len reports the number of names in the list.
429 Len() int
430 // Get returns the ith name. It panics if out of bounds.
431 Get(i int) Name
432 // Has reports whether s matches any names in the list.
433 Has(s Name) bool
434
435 doNotImplement
436}
437
438// FullName is a qualified name that uniquely identifies a proto declaration.
439// A qualified name is the concatenation of the proto package along with the
440// fully-declared name (i.e., name of parent preceding the name of the child),
441// with a '.' delimiter placed between each Name.
442//
443// This should not have any leading or trailing dots.
444type FullName string // e.g., "google.protobuf.Field.Kind"
445
446// IsValid reports whether n is a syntactically valid full name.
447// An empty full name is invalid.
448func (n FullName) IsValid() bool {
449 return regexFullName.MatchString(string(n))
450}
451
452// Name returns the short name, which is the last identifier segment.
453// A single segment FullName is the Name itself.
454func (n FullName) Name() Name {
455 if i := strings.LastIndexByte(string(n), '.'); i >= 0 {
456 return Name(n[i+1:])
457 }
458 return Name(n)
459}
460
461// Parent returns the full name with the trailing identifier removed.
462// A single segment FullName has no parent.
463func (n FullName) Parent() FullName {
464 if i := strings.LastIndexByte(string(n), '.'); i >= 0 {
465 return n[:i]
466 }
467 return ""
468}
469
470// Append returns the qualified name appended with the provided short name.
471//
472// Invariant: n == n.Parent().Append(n.Name()) // assuming n is valid
473func (n FullName) Append(s Name) FullName {
474 if n == "" {
475 return FullName(s)
476 }
477 return n + "." + FullName(s)
478}