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: 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 default: 179 return fmt.Sprintf("<unknown:%d>", s) 180 } 181 } 182 183 // GoString returns s as a Go source identifier (e.g., "Proto2"). 184 func (s Syntax) GoString() string { 185 switch s { 186 case Proto2: 187 return "Proto2" 188 case Proto3: 189 return "Proto3" 190 default: 191 return fmt.Sprintf("Syntax(%d)", s) 192 } 193 } 194 195 // Cardinality determines whether a field is optional, required, or repeated. 196 type Cardinality cardinality 197 198 type cardinality int8 // keep exact type opaque as the int type may change 199 200 // Constants as defined by the google.protobuf.Cardinality enumeration. 201 const ( 202 Optional Cardinality = 1 // appears zero or one times 203 Required Cardinality = 2 // appears exactly one time; invalid with Proto3 204 Repeated Cardinality = 3 // appears zero or more times 205 ) 206 207 // IsValid reports whether the cardinality is valid. 208 func (c Cardinality) IsValid() bool { 209 switch c { 210 case Optional, Required, Repeated: 211 return true 212 default: 213 return false 214 } 215 } 216 217 // String returns c as a proto source identifier (e.g., "optional"). 218 func (c Cardinality) String() string { 219 switch c { 220 case Optional: 221 return "optional" 222 case Required: 223 return "required" 224 case Repeated: 225 return "repeated" 226 default: 227 return fmt.Sprintf("<unknown:%d>", c) 228 } 229 } 230 231 // GoString returns c as a Go source identifier (e.g., "Optional"). 232 func (c Cardinality) GoString() string { 233 switch c { 234 case Optional: 235 return "Optional" 236 case Required: 237 return "Required" 238 case Repeated: 239 return "Repeated" 240 default: 241 return fmt.Sprintf("Cardinality(%d)", c) 242 } 243 } 244 245 // Kind indicates the basic proto kind of a field. 246 type Kind kind 247 248 type kind int8 // keep exact type opaque as the int type may change 249 250 // Constants as defined by the google.protobuf.Field.Kind enumeration. 251 const ( 252 BoolKind Kind = 8 253 EnumKind Kind = 14 254 Int32Kind Kind = 5 255 Sint32Kind Kind = 17 256 Uint32Kind Kind = 13 257 Int64Kind Kind = 3 258 Sint64Kind Kind = 18 259 Uint64Kind Kind = 4 260 Sfixed32Kind Kind = 15 261 Fixed32Kind Kind = 7 262 FloatKind Kind = 2 263 Sfixed64Kind Kind = 16 264 Fixed64Kind Kind = 6 265 DoubleKind Kind = 1 266 StringKind Kind = 9 267 BytesKind Kind = 12 268 MessageKind Kind = 11 269 GroupKind Kind = 10 270 ) 271 272 // IsValid reports whether the kind is valid. 273 func (k Kind) IsValid() bool { 274 switch k { 275 case BoolKind, EnumKind, 276 Int32Kind, Sint32Kind, Uint32Kind, 277 Int64Kind, Sint64Kind, Uint64Kind, 278 Sfixed32Kind, Fixed32Kind, FloatKind, 279 Sfixed64Kind, Fixed64Kind, DoubleKind, 280 StringKind, BytesKind, MessageKind, GroupKind: 281 return true 282 default: 283 return false 284 } 285 } 286 287 // String returns k as a proto source identifier (e.g., "bool"). 288 func (k Kind) String() string { 289 switch k { 290 case BoolKind: 291 return "bool" 292 case EnumKind: 293 return "enum" 294 case Int32Kind: 295 return "int32" 296 case Sint32Kind: 297 return "sint32" 298 case Uint32Kind: 299 return "uint32" 300 case Int64Kind: 301 return "int64" 302 case Sint64Kind: 303 return "sint64" 304 case Uint64Kind: 305 return "uint64" 306 case Sfixed32Kind: 307 return "sfixed32" 308 case Fixed32Kind: 309 return "fixed32" 310 case FloatKind: 311 return "float" 312 case Sfixed64Kind: 313 return "sfixed64" 314 case Fixed64Kind: 315 return "fixed64" 316 case DoubleKind: 317 return "double" 318 case StringKind: 319 return "string" 320 case BytesKind: 321 return "bytes" 322 case MessageKind: 323 return "message" 324 case GroupKind: 325 return "group" 326 default: 327 return fmt.Sprintf("<unknown:%d>", k) 328 } 329 } 330 331 // GoString returns k as a Go source identifier (e.g., "BoolKind"). 332 func (k Kind) GoString() string { 333 switch k { 334 case BoolKind: 335 return "BoolKind" 336 case EnumKind: 337 return "EnumKind" 338 case Int32Kind: 339 return "Int32Kind" 340 case Sint32Kind: 341 return "Sint32Kind" 342 case Uint32Kind: 343 return "Uint32Kind" 344 case Int64Kind: 345 return "Int64Kind" 346 case Sint64Kind: 347 return "Sint64Kind" 348 case Uint64Kind: 349 return "Uint64Kind" 350 case Sfixed32Kind: 351 return "Sfixed32Kind" 352 case Fixed32Kind: 353 return "Fixed32Kind" 354 case FloatKind: 355 return "FloatKind" 356 case Sfixed64Kind: 357 return "Sfixed64Kind" 358 case Fixed64Kind: 359 return "Fixed64Kind" 360 case DoubleKind: 361 return "DoubleKind" 362 case StringKind: 363 return "StringKind" 364 case BytesKind: 365 return "BytesKind" 366 case MessageKind: 367 return "MessageKind" 368 case GroupKind: 369 return "GroupKind" 370 default: 371 return fmt.Sprintf("Kind(%d)", k) 372 } 373 } 374 375 // FieldNumber is the field number in a message. 376 type FieldNumber = protowire.Number 377 378 // FieldNumbers represent a list of field numbers. 379 type FieldNumbers interface { 380 // Len reports the number of fields in the list. 381 Len() int 382 // Get returns the ith field number. It panics if out of bounds. 383 Get(i int) FieldNumber 384 // Has reports whether n is within the list of fields. 385 Has(n FieldNumber) bool 386 387 doNotImplement 388 } 389 390 // FieldRanges represent a list of field number ranges. 391 type FieldRanges interface { 392 // Len reports the number of ranges in the list. 393 Len() int 394 // Get returns the ith range. It panics if out of bounds. 395 Get(i int) [2]FieldNumber // start inclusive; end exclusive 396 // Has reports whether n is within any of the ranges. 397 Has(n FieldNumber) bool 398 399 doNotImplement 400 } 401 402 // EnumNumber is the numeric value for an enum. 403 type EnumNumber int32 404 405 // EnumRanges represent a list of enum number ranges. 406 type EnumRanges interface { 407 // Len reports the number of ranges in the list. 408 Len() int 409 // Get returns the ith range. It panics if out of bounds. 410 Get(i int) [2]EnumNumber // start inclusive; end inclusive 411 // Has reports whether n is within any of the ranges. 412 Has(n EnumNumber) bool 413 414 doNotImplement 415 } 416 417 // Name is the short name for a proto declaration. This is not the name 418 // as used in Go source code, which might not be identical to the proto name. 419 type Name string // e.g., "Kind" 420 421 // IsValid reports whether s is a syntactically valid name. 422 // An empty name is invalid. 423 func (s Name) IsValid() bool { 424 return consumeIdent(string(s)) == len(s) 425 } 426 427 // Names represent a list of names. 428 type Names interface { 429 // Len reports the number of names in the list. 430 Len() int 431 // Get returns the ith name. It panics if out of bounds. 432 Get(i int) Name 433 // Has reports whether s matches any names in the list. 434 Has(s Name) bool 435 436 doNotImplement 437 } 438 439 // FullName is a qualified name that uniquely identifies a proto declaration. 440 // A qualified name is the concatenation of the proto package along with the 441 // fully-declared name (i.e., name of parent preceding the name of the child), 442 // with a '.' delimiter placed between each [Name]. 443 // 444 // This should not have any leading or trailing dots. 445 type FullName string // e.g., "google.protobuf.Field.Kind" 446 447 // IsValid reports whether s is a syntactically valid full name. 448 // An empty full name is invalid. 449 func (s FullName) IsValid() bool { 450 i := consumeIdent(string(s)) 451 if i < 0 { 452 return false 453 } 454 for len(s) > i { 455 if s[i] != '.' { 456 return false 457 } 458 i++ 459 n := consumeIdent(string(s[i:])) 460 if n < 0 { 461 return false 462 } 463 i += n 464 } 465 return true 466 } 467 468 func consumeIdent(s string) (i int) { 469 if len(s) == 0 || !isLetter(s[i]) { 470 return -1 471 } 472 i++ 473 for len(s) > i && isLetterDigit(s[i]) { 474 i++ 475 } 476 return i 477 } 478 func isLetter(c byte) bool { 479 return c == '_' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') 480 } 481 func isLetterDigit(c byte) bool { 482 return isLetter(c) || ('0' <= c && c <= '9') 483 } 484 485 // Name returns the short name, which is the last identifier segment. 486 // A single segment FullName is the [Name] itself. 487 func (n FullName) Name() Name { 488 if i := strings.LastIndexByte(string(n), '.'); i >= 0 { 489 return Name(n[i+1:]) 490 } 491 return Name(n) 492 } 493 494 // Parent returns the full name with the trailing identifier removed. 495 // A single segment FullName has no parent. 496 func (n FullName) Parent() FullName { 497 if i := strings.LastIndexByte(string(n), '.'); i >= 0 { 498 return n[:i] 499 } 500 return "" 501 } 502 503 // Append returns the qualified name appended with the provided short name. 504 // 505 // Invariant: n == n.Parent().Append(n.Name()) // assuming n is valid 506 func (n FullName) Append(s Name) FullName { 507 if n == "" { 508 return FullName(s) 509 } 510 return n + "." + FullName(s) 511 } 512