...

Source file src/google.golang.org/protobuf/reflect/protoreflect/proto.go

Documentation: google.golang.org/protobuf/reflect/protoreflect

     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].
   133  package protoreflect
   134  
   135  import (
   136  	"fmt"
   137  	"strings"
   138  
   139  	"google.golang.org/protobuf/encoding/protowire"
   140  	"google.golang.org/protobuf/internal/pragma"
   141  )
   142  
   143  type 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.
   148  type ProtoMessage interface{ ProtoReflect() Message }
   149  
   150  // Syntax is the language version of the proto file.
   151  type Syntax syntax
   152  
   153  type syntax int8 // keep exact type opaque as the int type may change
   154  
   155  const (
   156  	Proto2   Syntax = 2
   157  	Proto3   Syntax = 3
   158  	Editions Syntax = 4
   159  )
   160  
   161  // IsValid reports whether the syntax is valid.
   162  func (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").
   172  func (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").
   186  func (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.
   198  type Cardinality cardinality
   199  
   200  type cardinality int8 // keep exact type opaque as the int type may change
   201  
   202  // Constants as defined by the google.protobuf.Cardinality enumeration.
   203  const (
   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.
   210  func (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").
   220  func (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").
   234  func (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.
   248  type Kind kind
   249  
   250  type kind int8 // keep exact type opaque as the int type may change
   251  
   252  // Constants as defined by the google.protobuf.Field.Kind enumeration.
   253  const (
   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.
   275  func (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").
   290  func (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").
   334  func (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.
   378  type FieldNumber = protowire.Number
   379  
   380  // FieldNumbers represent a list of field numbers.
   381  type 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.
   393  type 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.
   405  type EnumNumber int32
   406  
   407  // EnumRanges represent a list of enum number ranges.
   408  type 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.
   421  type Name string // e.g., "Kind"
   422  
   423  // IsValid reports whether s is a syntactically valid name.
   424  // An empty name is invalid.
   425  func (s Name) IsValid() bool {
   426  	return consumeIdent(string(s)) == len(s)
   427  }
   428  
   429  // Names represent a list of names.
   430  type 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.
   447  type 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.
   451  func (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  
   470  func 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  }
   480  func isLetter(c byte) bool {
   481  	return c == '_' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')
   482  }
   483  func 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.
   489  func (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.
   498  func (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
   508  func (n FullName) Append(s Name) FullName {
   509  	if n == "" {
   510  		return FullName(s)
   511  	}
   512  	return n + "." + FullName(s)
   513  }
   514  

View as plain text