proto.go raw

   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