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