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 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 protoregistry.GlobalTypes.FindMessageByName 102// or constructing a dynamic MessageType using dynamicpb.NewMessageType. 103// 104// • A Message is a reflective view over a concrete message instance. 105// Generated messages implement ProtoMessage, which can convert to a Message. 106// Just as how Go's reflect.Value is a reflective view over a Go value, 107// a Message is a reflective view over a concrete protobuf message instance. 108// Using Go reflection as an analogy, the ProtoReflect method is similar to 109// calling reflect.ValueOf, and the Message.Interface method is similar to 110// calling reflect.Value.Interface. 111// 112// ┌── TypeDescriptor() ──┐ ┌───── Descriptor() ─────┐ 113// │ V │ V 114// ╔═══════════════╗ ╔═════════════════════════╗ ╔═════════════════════╗ 115// ║ ExtensionType ║ ║ ExtensionTypeDescriptor ║ ║ ExtensionDescriptor ║ 116// ╚═══════════════╝ ╚═════════════════════════╝ ╚═════════════════════╝ 117// Λ │ │ Λ │ Λ 118// └─────── Type() ───────┘ │ └─── may implement ────┘ │ 119// │ │ 120// └────── implements ────────┘ 121// 122// • An ExtensionType describes a concrete Go implementation of an extension. 123// It has an ExtensionTypeDescriptor and can convert to/from 124// abstract Values and Go values. 125// 126// • An ExtensionTypeDescriptor is an ExtensionDescriptor 127// which also has an ExtensionType. 128// 129// • An ExtensionDescriptor describes an abstract protobuf extension field and 130// may not always be an ExtensionTypeDescriptor. 131package protoreflect 132 133import ( 134 "fmt" 135 "strings" 136 137 "google.golang.org/protobuf/encoding/protowire" 138 "google.golang.org/protobuf/internal/pragma" 139) 140 141type doNotImplement pragma.DoNotImplement 142 143// ProtoMessage is the top-level interface that all proto messages implement. 144// This is declared in the protoreflect package to avoid a cyclic dependency; 145// use the proto.Message type instead, which aliases this type. 146type ProtoMessage interface{ ProtoReflect() Message } 147 148// Syntax is the language version of the proto file. 149type Syntax syntax 150 151type syntax int8 // keep exact type opaque as the int type may change 152 153const ( 154 Proto2 Syntax = 2 155 Proto3 Syntax = 3 156) 157 158// IsValid reports whether the syntax is valid. 159func (s Syntax) IsValid() bool { 160 switch s { 161 case Proto2, Proto3: 162 return true 163 default: 164 return false 165 } 166} 167 168// String returns s as a proto source identifier (e.g., "proto2"). 169func (s Syntax) String() string { 170 switch s { 171 case Proto2: 172 return "proto2" 173 case Proto3: 174 return "proto3" 175 default: 176 return fmt.Sprintf("<unknown:%d>", s) 177 } 178} 179 180// GoString returns s as a Go source identifier (e.g., "Proto2"). 181func (s Syntax) GoString() string { 182 switch s { 183 case Proto2: 184 return "Proto2" 185 case Proto3: 186 return "Proto3" 187 default: 188 return fmt.Sprintf("Syntax(%d)", s) 189 } 190} 191 192// Cardinality determines whether a field is optional, required, or repeated. 193type Cardinality cardinality 194 195type cardinality int8 // keep exact type opaque as the int type may change 196 197// Constants as defined by the google.protobuf.Cardinality enumeration. 198const ( 199 Optional Cardinality = 1 // appears zero or one times 200 Required Cardinality = 2 // appears exactly one time; invalid with Proto3 201 Repeated Cardinality = 3 // appears zero or more times 202) 203 204// IsValid reports whether the cardinality is valid. 205func (c Cardinality) IsValid() bool { 206 switch c { 207 case Optional, Required, Repeated: 208 return true 209 default: 210 return false 211 } 212} 213 214// String returns c as a proto source identifier (e.g., "optional"). 215func (c Cardinality) String() string { 216 switch c { 217 case Optional: 218 return "optional" 219 case Required: 220 return "required" 221 case Repeated: 222 return "repeated" 223 default: 224 return fmt.Sprintf("<unknown:%d>", c) 225 } 226} 227 228// GoString returns c as a Go source identifier (e.g., "Optional"). 229func (c Cardinality) GoString() string { 230 switch c { 231 case Optional: 232 return "Optional" 233 case Required: 234 return "Required" 235 case Repeated: 236 return "Repeated" 237 default: 238 return fmt.Sprintf("Cardinality(%d)", c) 239 } 240} 241 242// Kind indicates the basic proto kind of a field. 243type Kind kind 244 245type kind int8 // keep exact type opaque as the int type may change 246 247// Constants as defined by the google.protobuf.Field.Kind enumeration. 248const ( 249 BoolKind Kind = 8 250 EnumKind Kind = 14 251 Int32Kind Kind = 5 252 Sint32Kind Kind = 17 253 Uint32Kind Kind = 13 254 Int64Kind Kind = 3 255 Sint64Kind Kind = 18 256 Uint64Kind Kind = 4 257 Sfixed32Kind Kind = 15 258 Fixed32Kind Kind = 7 259 FloatKind Kind = 2 260 Sfixed64Kind Kind = 16 261 Fixed64Kind Kind = 6 262 DoubleKind Kind = 1 263 StringKind Kind = 9 264 BytesKind Kind = 12 265 MessageKind Kind = 11 266 GroupKind Kind = 10 267) 268 269// IsValid reports whether the kind is valid. 270func (k Kind) IsValid() bool { 271 switch k { 272 case BoolKind, EnumKind, 273 Int32Kind, Sint32Kind, Uint32Kind, 274 Int64Kind, Sint64Kind, Uint64Kind, 275 Sfixed32Kind, Fixed32Kind, FloatKind, 276 Sfixed64Kind, Fixed64Kind, DoubleKind, 277 StringKind, BytesKind, MessageKind, GroupKind: 278 return true 279 default: 280 return false 281 } 282} 283 284// String returns k as a proto source identifier (e.g., "bool"). 285func (k Kind) String() string { 286 switch k { 287 case BoolKind: 288 return "bool" 289 case EnumKind: 290 return "enum" 291 case Int32Kind: 292 return "int32" 293 case Sint32Kind: 294 return "sint32" 295 case Uint32Kind: 296 return "uint32" 297 case Int64Kind: 298 return "int64" 299 case Sint64Kind: 300 return "sint64" 301 case Uint64Kind: 302 return "uint64" 303 case Sfixed32Kind: 304 return "sfixed32" 305 case Fixed32Kind: 306 return "fixed32" 307 case FloatKind: 308 return "float" 309 case Sfixed64Kind: 310 return "sfixed64" 311 case Fixed64Kind: 312 return "fixed64" 313 case DoubleKind: 314 return "double" 315 case StringKind: 316 return "string" 317 case BytesKind: 318 return "bytes" 319 case MessageKind: 320 return "message" 321 case GroupKind: 322 return "group" 323 default: 324 return fmt.Sprintf("<unknown:%d>", k) 325 } 326} 327 328// GoString returns k as a Go source identifier (e.g., "BoolKind"). 329func (k Kind) GoString() string { 330 switch k { 331 case BoolKind: 332 return "BoolKind" 333 case EnumKind: 334 return "EnumKind" 335 case Int32Kind: 336 return "Int32Kind" 337 case Sint32Kind: 338 return "Sint32Kind" 339 case Uint32Kind: 340 return "Uint32Kind" 341 case Int64Kind: 342 return "Int64Kind" 343 case Sint64Kind: 344 return "Sint64Kind" 345 case Uint64Kind: 346 return "Uint64Kind" 347 case Sfixed32Kind: 348 return "Sfixed32Kind" 349 case Fixed32Kind: 350 return "Fixed32Kind" 351 case FloatKind: 352 return "FloatKind" 353 case Sfixed64Kind: 354 return "Sfixed64Kind" 355 case Fixed64Kind: 356 return "Fixed64Kind" 357 case DoubleKind: 358 return "DoubleKind" 359 case StringKind: 360 return "StringKind" 361 case BytesKind: 362 return "BytesKind" 363 case MessageKind: 364 return "MessageKind" 365 case GroupKind: 366 return "GroupKind" 367 default: 368 return fmt.Sprintf("Kind(%d)", k) 369 } 370} 371 372// FieldNumber is the field number in a message. 373type FieldNumber = protowire.Number 374 375// FieldNumbers represent a list of field numbers. 376type FieldNumbers interface { 377 // Len reports the number of fields in the list. 378 Len() int 379 // Get returns the ith field number. It panics if out of bounds. 380 Get(i int) FieldNumber 381 // Has reports whether n is within the list of fields. 382 Has(n FieldNumber) bool 383 384 doNotImplement 385} 386 387// FieldRanges represent a list of field number ranges. 388type FieldRanges interface { 389 // Len reports the number of ranges in the list. 390 Len() int 391 // Get returns the ith range. It panics if out of bounds. 392 Get(i int) [2]FieldNumber // start inclusive; end exclusive 393 // Has reports whether n is within any of the ranges. 394 Has(n FieldNumber) bool 395 396 doNotImplement 397} 398 399// EnumNumber is the numeric value for an enum. 400type EnumNumber int32 401 402// EnumRanges represent a list of enum number ranges. 403type EnumRanges interface { 404 // Len reports the number of ranges in the list. 405 Len() int 406 // Get returns the ith range. It panics if out of bounds. 407 Get(i int) [2]EnumNumber // start inclusive; end inclusive 408 // Has reports whether n is within any of the ranges. 409 Has(n EnumNumber) bool 410 411 doNotImplement 412} 413 414// Name is the short name for a proto declaration. This is not the name 415// as used in Go source code, which might not be identical to the proto name. 416type Name string // e.g., "Kind" 417 418// IsValid reports whether s is a syntactically valid name. 419// An empty name is invalid. 420func (s Name) IsValid() bool { 421 return consumeIdent(string(s)) == len(s) 422} 423 424// Names represent a list of names. 425type Names interface { 426 // Len reports the number of names in the list. 427 Len() int 428 // Get returns the ith name. It panics if out of bounds. 429 Get(i int) Name 430 // Has reports whether s matches any names in the list. 431 Has(s Name) bool 432 433 doNotImplement 434} 435 436// FullName is a qualified name that uniquely identifies a proto declaration. 437// A qualified name is the concatenation of the proto package along with the 438// fully-declared name (i.e., name of parent preceding the name of the child), 439// with a '.' delimiter placed between each Name. 440// 441// This should not have any leading or trailing dots. 442type FullName string // e.g., "google.protobuf.Field.Kind" 443 444// IsValid reports whether s is a syntactically valid full name. 445// An empty full name is invalid. 446func (s FullName) IsValid() bool { 447 i := consumeIdent(string(s)) 448 if i < 0 { 449 return false 450 } 451 for len(s) > i { 452 if s[i] != '.' { 453 return false 454 } 455 i++ 456 n := consumeIdent(string(s[i:])) 457 if n < 0 { 458 return false 459 } 460 i += n 461 } 462 return true 463} 464 465func consumeIdent(s string) (i int) { 466 if len(s) == 0 || !isLetter(s[i]) { 467 return -1 468 } 469 i++ 470 for len(s) > i && isLetterDigit(s[i]) { 471 i++ 472 } 473 return i 474} 475func isLetter(c byte) bool { 476 return c == '_' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') 477} 478func isLetterDigit(c byte) bool { 479 return isLetter(c) || ('0' <= c && c <= '9') 480} 481 482// Name returns the short name, which is the last identifier segment. 483// A single segment FullName is the Name itself. 484func (n FullName) Name() Name { 485 if i := strings.LastIndexByte(string(n), '.'); i >= 0 { 486 return Name(n[i+1:]) 487 } 488 return Name(n) 489} 490 491// Parent returns the full name with the trailing identifier removed. 492// A single segment FullName has no parent. 493func (n FullName) Parent() FullName { 494 if i := strings.LastIndexByte(string(n), '.'); i >= 0 { 495 return n[:i] 496 } 497 return "" 498} 499 500// Append returns the qualified name appended with the provided short name. 501// 502// Invariant: n == n.Parent().Append(n.Name()) // assuming n is valid 503func (n FullName) Append(s Name) FullName { 504 if n == "" { 505 return FullName(s) 506 } 507 return n + "." + FullName(s) 508} 509