1*1c12ee1eSDan Willemsen// Copyright 2018 The Go Authors. All rights reserved. 2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style 3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file. 4*1c12ee1eSDan Willemsen 5*1c12ee1eSDan Willemsen// Package protoreflect provides interfaces to dynamically manipulate messages. 6*1c12ee1eSDan Willemsen// 7*1c12ee1eSDan Willemsen// This package includes type descriptors which describe the structure of types 8*1c12ee1eSDan Willemsen// defined in proto source files and value interfaces which provide the 9*1c12ee1eSDan Willemsen// ability to examine and manipulate the contents of messages. 10*1c12ee1eSDan Willemsen// 11*1c12ee1eSDan Willemsen// # Protocol Buffer Descriptors 12*1c12ee1eSDan Willemsen// 13*1c12ee1eSDan Willemsen// Protobuf descriptors (e.g., EnumDescriptor or MessageDescriptor) 14*1c12ee1eSDan Willemsen// are immutable objects that represent protobuf type information. 15*1c12ee1eSDan Willemsen// They are wrappers around the messages declared in descriptor.proto. 16*1c12ee1eSDan Willemsen// Protobuf descriptors alone lack any information regarding Go types. 17*1c12ee1eSDan Willemsen// 18*1c12ee1eSDan Willemsen// Enums and messages generated by this module implement Enum and ProtoMessage, 19*1c12ee1eSDan Willemsen// where the Descriptor and ProtoReflect.Descriptor accessors respectively 20*1c12ee1eSDan Willemsen// return the protobuf descriptor for the values. 21*1c12ee1eSDan Willemsen// 22*1c12ee1eSDan Willemsen// The protobuf descriptor interfaces are not meant to be implemented by 23*1c12ee1eSDan Willemsen// user code since they might need to be extended in the future to support 24*1c12ee1eSDan Willemsen// additions to the protobuf language. 25*1c12ee1eSDan Willemsen// The "google.golang.org/protobuf/reflect/protodesc" package converts between 26*1c12ee1eSDan Willemsen// google.protobuf.DescriptorProto messages and protobuf descriptors. 27*1c12ee1eSDan Willemsen// 28*1c12ee1eSDan Willemsen// # Go Type Descriptors 29*1c12ee1eSDan Willemsen// 30*1c12ee1eSDan Willemsen// A type descriptor (e.g., EnumType or MessageType) is a constructor for 31*1c12ee1eSDan Willemsen// a concrete Go type that represents the associated protobuf descriptor. 32*1c12ee1eSDan Willemsen// There is commonly a one-to-one relationship between protobuf descriptors and 33*1c12ee1eSDan Willemsen// Go type descriptors, but it can potentially be a one-to-many relationship. 34*1c12ee1eSDan Willemsen// 35*1c12ee1eSDan Willemsen// Enums and messages generated by this module implement Enum and ProtoMessage, 36*1c12ee1eSDan Willemsen// where the Type and ProtoReflect.Type accessors respectively 37*1c12ee1eSDan Willemsen// return the protobuf descriptor for the values. 38*1c12ee1eSDan Willemsen// 39*1c12ee1eSDan Willemsen// The "google.golang.org/protobuf/types/dynamicpb" package can be used to 40*1c12ee1eSDan Willemsen// create Go type descriptors from protobuf descriptors. 41*1c12ee1eSDan Willemsen// 42*1c12ee1eSDan Willemsen// # Value Interfaces 43*1c12ee1eSDan Willemsen// 44*1c12ee1eSDan Willemsen// The Enum and Message interfaces provide a reflective view over an 45*1c12ee1eSDan Willemsen// enum or message instance. For enums, it provides the ability to retrieve 46*1c12ee1eSDan Willemsen// the enum value number for any concrete enum type. For messages, it provides 47*1c12ee1eSDan Willemsen// the ability to access or manipulate fields of the message. 48*1c12ee1eSDan Willemsen// 49*1c12ee1eSDan Willemsen// To convert a proto.Message to a protoreflect.Message, use the 50*1c12ee1eSDan Willemsen// former's ProtoReflect method. Since the ProtoReflect method is new to the 51*1c12ee1eSDan Willemsen// v2 message interface, it may not be present on older message implementations. 52*1c12ee1eSDan Willemsen// The "github.com/golang/protobuf/proto".MessageReflect function can be used 53*1c12ee1eSDan Willemsen// to obtain a reflective view on older messages. 54*1c12ee1eSDan Willemsen// 55*1c12ee1eSDan Willemsen// # Relationships 56*1c12ee1eSDan Willemsen// 57*1c12ee1eSDan Willemsen// The following diagrams demonstrate the relationships between 58*1c12ee1eSDan Willemsen// various types declared in this package. 59*1c12ee1eSDan Willemsen// 60*1c12ee1eSDan Willemsen// ┌───────────────────────────────────┐ 61*1c12ee1eSDan Willemsen// V │ 62*1c12ee1eSDan Willemsen// ┌────────────── New(n) ─────────────┐ │ 63*1c12ee1eSDan Willemsen// │ │ │ 64*1c12ee1eSDan Willemsen// │ ┌──── Descriptor() ──┐ │ ┌── Number() ──┐ │ 65*1c12ee1eSDan Willemsen// │ │ V V │ V │ 66*1c12ee1eSDan Willemsen// ╔════════════╗ ╔════════════════╗ ╔════════╗ ╔════════════╗ 67*1c12ee1eSDan Willemsen// ║ EnumType ║ ║ EnumDescriptor ║ ║ Enum ║ ║ EnumNumber ║ 68*1c12ee1eSDan Willemsen// ╚════════════╝ ╚════════════════╝ ╚════════╝ ╚════════════╝ 69*1c12ee1eSDan Willemsen// Λ Λ │ │ 70*1c12ee1eSDan Willemsen// │ └─── Descriptor() ──┘ │ 71*1c12ee1eSDan Willemsen// │ │ 72*1c12ee1eSDan Willemsen// └────────────────── Type() ───────┘ 73*1c12ee1eSDan Willemsen// 74*1c12ee1eSDan Willemsen// • An EnumType describes a concrete Go enum type. 75*1c12ee1eSDan Willemsen// It has an EnumDescriptor and can construct an Enum instance. 76*1c12ee1eSDan Willemsen// 77*1c12ee1eSDan Willemsen// • An EnumDescriptor describes an abstract protobuf enum type. 78*1c12ee1eSDan Willemsen// 79*1c12ee1eSDan Willemsen// • An Enum is a concrete enum instance. Generated enums implement Enum. 80*1c12ee1eSDan Willemsen// 81*1c12ee1eSDan Willemsen// ┌──────────────── New() ─────────────────┐ 82*1c12ee1eSDan Willemsen// │ │ 83*1c12ee1eSDan Willemsen// │ ┌─── Descriptor() ─────┐ │ ┌── Interface() ───┐ 84*1c12ee1eSDan Willemsen// │ │ V V │ V 85*1c12ee1eSDan Willemsen// ╔═════════════╗ ╔═══════════════════╗ ╔═════════╗ ╔══════════════╗ 86*1c12ee1eSDan Willemsen// ║ MessageType ║ ║ MessageDescriptor ║ ║ Message ║ ║ ProtoMessage ║ 87*1c12ee1eSDan Willemsen// ╚═════════════╝ ╚═══════════════════╝ ╚═════════╝ ╚══════════════╝ 88*1c12ee1eSDan Willemsen// Λ Λ │ │ Λ │ 89*1c12ee1eSDan Willemsen// │ └──── Descriptor() ────┘ │ └─ ProtoReflect() ─┘ 90*1c12ee1eSDan Willemsen// │ │ 91*1c12ee1eSDan Willemsen// └─────────────────── Type() ─────────┘ 92*1c12ee1eSDan Willemsen// 93*1c12ee1eSDan Willemsen// • A MessageType describes a concrete Go message type. 94*1c12ee1eSDan Willemsen// It has a MessageDescriptor and can construct a Message instance. 95*1c12ee1eSDan Willemsen// Just as how Go's reflect.Type is a reflective description of a Go type, 96*1c12ee1eSDan Willemsen// a MessageType is a reflective description of a Go type for a protobuf message. 97*1c12ee1eSDan Willemsen// 98*1c12ee1eSDan Willemsen// • A MessageDescriptor describes an abstract protobuf message type. 99*1c12ee1eSDan Willemsen// It has no understanding of Go types. In order to construct a MessageType 100*1c12ee1eSDan Willemsen// from just a MessageDescriptor, you can consider looking up the message type 101*1c12ee1eSDan Willemsen// in the global registry using protoregistry.GlobalTypes.FindMessageByName 102*1c12ee1eSDan Willemsen// or constructing a dynamic MessageType using dynamicpb.NewMessageType. 103*1c12ee1eSDan Willemsen// 104*1c12ee1eSDan Willemsen// • A Message is a reflective view over a concrete message instance. 105*1c12ee1eSDan Willemsen// Generated messages implement ProtoMessage, which can convert to a Message. 106*1c12ee1eSDan Willemsen// Just as how Go's reflect.Value is a reflective view over a Go value, 107*1c12ee1eSDan Willemsen// a Message is a reflective view over a concrete protobuf message instance. 108*1c12ee1eSDan Willemsen// Using Go reflection as an analogy, the ProtoReflect method is similar to 109*1c12ee1eSDan Willemsen// calling reflect.ValueOf, and the Message.Interface method is similar to 110*1c12ee1eSDan Willemsen// calling reflect.Value.Interface. 111*1c12ee1eSDan Willemsen// 112*1c12ee1eSDan Willemsen// ┌── TypeDescriptor() ──┐ ┌───── Descriptor() ─────┐ 113*1c12ee1eSDan Willemsen// │ V │ V 114*1c12ee1eSDan Willemsen// ╔═══════════════╗ ╔═════════════════════════╗ ╔═════════════════════╗ 115*1c12ee1eSDan Willemsen// ║ ExtensionType ║ ║ ExtensionTypeDescriptor ║ ║ ExtensionDescriptor ║ 116*1c12ee1eSDan Willemsen// ╚═══════════════╝ ╚═════════════════════════╝ ╚═════════════════════╝ 117*1c12ee1eSDan Willemsen// Λ │ │ Λ │ Λ 118*1c12ee1eSDan Willemsen// └─────── Type() ───────┘ │ └─── may implement ────┘ │ 119*1c12ee1eSDan Willemsen// │ │ 120*1c12ee1eSDan Willemsen// └────── implements ────────┘ 121*1c12ee1eSDan Willemsen// 122*1c12ee1eSDan Willemsen// • An ExtensionType describes a concrete Go implementation of an extension. 123*1c12ee1eSDan Willemsen// It has an ExtensionTypeDescriptor and can convert to/from 124*1c12ee1eSDan Willemsen// abstract Values and Go values. 125*1c12ee1eSDan Willemsen// 126*1c12ee1eSDan Willemsen// • An ExtensionTypeDescriptor is an ExtensionDescriptor 127*1c12ee1eSDan Willemsen// which also has an ExtensionType. 128*1c12ee1eSDan Willemsen// 129*1c12ee1eSDan Willemsen// • An ExtensionDescriptor describes an abstract protobuf extension field and 130*1c12ee1eSDan Willemsen// may not always be an ExtensionTypeDescriptor. 131*1c12ee1eSDan Willemsenpackage protoreflect 132*1c12ee1eSDan Willemsen 133*1c12ee1eSDan Willemsenimport ( 134*1c12ee1eSDan Willemsen "fmt" 135*1c12ee1eSDan Willemsen "strings" 136*1c12ee1eSDan Willemsen 137*1c12ee1eSDan Willemsen "google.golang.org/protobuf/encoding/protowire" 138*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/pragma" 139*1c12ee1eSDan Willemsen) 140*1c12ee1eSDan Willemsen 141*1c12ee1eSDan Willemsentype doNotImplement pragma.DoNotImplement 142*1c12ee1eSDan Willemsen 143*1c12ee1eSDan Willemsen// ProtoMessage is the top-level interface that all proto messages implement. 144*1c12ee1eSDan Willemsen// This is declared in the protoreflect package to avoid a cyclic dependency; 145*1c12ee1eSDan Willemsen// use the proto.Message type instead, which aliases this type. 146*1c12ee1eSDan Willemsentype ProtoMessage interface{ ProtoReflect() Message } 147*1c12ee1eSDan Willemsen 148*1c12ee1eSDan Willemsen// Syntax is the language version of the proto file. 149*1c12ee1eSDan Willemsentype Syntax syntax 150*1c12ee1eSDan Willemsen 151*1c12ee1eSDan Willemsentype syntax int8 // keep exact type opaque as the int type may change 152*1c12ee1eSDan Willemsen 153*1c12ee1eSDan Willemsenconst ( 154*1c12ee1eSDan Willemsen Proto2 Syntax = 2 155*1c12ee1eSDan Willemsen Proto3 Syntax = 3 156*1c12ee1eSDan Willemsen) 157*1c12ee1eSDan Willemsen 158*1c12ee1eSDan Willemsen// IsValid reports whether the syntax is valid. 159*1c12ee1eSDan Willemsenfunc (s Syntax) IsValid() bool { 160*1c12ee1eSDan Willemsen switch s { 161*1c12ee1eSDan Willemsen case Proto2, Proto3: 162*1c12ee1eSDan Willemsen return true 163*1c12ee1eSDan Willemsen default: 164*1c12ee1eSDan Willemsen return false 165*1c12ee1eSDan Willemsen } 166*1c12ee1eSDan Willemsen} 167*1c12ee1eSDan Willemsen 168*1c12ee1eSDan Willemsen// String returns s as a proto source identifier (e.g., "proto2"). 169*1c12ee1eSDan Willemsenfunc (s Syntax) String() string { 170*1c12ee1eSDan Willemsen switch s { 171*1c12ee1eSDan Willemsen case Proto2: 172*1c12ee1eSDan Willemsen return "proto2" 173*1c12ee1eSDan Willemsen case Proto3: 174*1c12ee1eSDan Willemsen return "proto3" 175*1c12ee1eSDan Willemsen default: 176*1c12ee1eSDan Willemsen return fmt.Sprintf("<unknown:%d>", s) 177*1c12ee1eSDan Willemsen } 178*1c12ee1eSDan Willemsen} 179*1c12ee1eSDan Willemsen 180*1c12ee1eSDan Willemsen// GoString returns s as a Go source identifier (e.g., "Proto2"). 181*1c12ee1eSDan Willemsenfunc (s Syntax) GoString() string { 182*1c12ee1eSDan Willemsen switch s { 183*1c12ee1eSDan Willemsen case Proto2: 184*1c12ee1eSDan Willemsen return "Proto2" 185*1c12ee1eSDan Willemsen case Proto3: 186*1c12ee1eSDan Willemsen return "Proto3" 187*1c12ee1eSDan Willemsen default: 188*1c12ee1eSDan Willemsen return fmt.Sprintf("Syntax(%d)", s) 189*1c12ee1eSDan Willemsen } 190*1c12ee1eSDan Willemsen} 191*1c12ee1eSDan Willemsen 192*1c12ee1eSDan Willemsen// Cardinality determines whether a field is optional, required, or repeated. 193*1c12ee1eSDan Willemsentype Cardinality cardinality 194*1c12ee1eSDan Willemsen 195*1c12ee1eSDan Willemsentype cardinality int8 // keep exact type opaque as the int type may change 196*1c12ee1eSDan Willemsen 197*1c12ee1eSDan Willemsen// Constants as defined by the google.protobuf.Cardinality enumeration. 198*1c12ee1eSDan Willemsenconst ( 199*1c12ee1eSDan Willemsen Optional Cardinality = 1 // appears zero or one times 200*1c12ee1eSDan Willemsen Required Cardinality = 2 // appears exactly one time; invalid with Proto3 201*1c12ee1eSDan Willemsen Repeated Cardinality = 3 // appears zero or more times 202*1c12ee1eSDan Willemsen) 203*1c12ee1eSDan Willemsen 204*1c12ee1eSDan Willemsen// IsValid reports whether the cardinality is valid. 205*1c12ee1eSDan Willemsenfunc (c Cardinality) IsValid() bool { 206*1c12ee1eSDan Willemsen switch c { 207*1c12ee1eSDan Willemsen case Optional, Required, Repeated: 208*1c12ee1eSDan Willemsen return true 209*1c12ee1eSDan Willemsen default: 210*1c12ee1eSDan Willemsen return false 211*1c12ee1eSDan Willemsen } 212*1c12ee1eSDan Willemsen} 213*1c12ee1eSDan Willemsen 214*1c12ee1eSDan Willemsen// String returns c as a proto source identifier (e.g., "optional"). 215*1c12ee1eSDan Willemsenfunc (c Cardinality) String() string { 216*1c12ee1eSDan Willemsen switch c { 217*1c12ee1eSDan Willemsen case Optional: 218*1c12ee1eSDan Willemsen return "optional" 219*1c12ee1eSDan Willemsen case Required: 220*1c12ee1eSDan Willemsen return "required" 221*1c12ee1eSDan Willemsen case Repeated: 222*1c12ee1eSDan Willemsen return "repeated" 223*1c12ee1eSDan Willemsen default: 224*1c12ee1eSDan Willemsen return fmt.Sprintf("<unknown:%d>", c) 225*1c12ee1eSDan Willemsen } 226*1c12ee1eSDan Willemsen} 227*1c12ee1eSDan Willemsen 228*1c12ee1eSDan Willemsen// GoString returns c as a Go source identifier (e.g., "Optional"). 229*1c12ee1eSDan Willemsenfunc (c Cardinality) GoString() string { 230*1c12ee1eSDan Willemsen switch c { 231*1c12ee1eSDan Willemsen case Optional: 232*1c12ee1eSDan Willemsen return "Optional" 233*1c12ee1eSDan Willemsen case Required: 234*1c12ee1eSDan Willemsen return "Required" 235*1c12ee1eSDan Willemsen case Repeated: 236*1c12ee1eSDan Willemsen return "Repeated" 237*1c12ee1eSDan Willemsen default: 238*1c12ee1eSDan Willemsen return fmt.Sprintf("Cardinality(%d)", c) 239*1c12ee1eSDan Willemsen } 240*1c12ee1eSDan Willemsen} 241*1c12ee1eSDan Willemsen 242*1c12ee1eSDan Willemsen// Kind indicates the basic proto kind of a field. 243*1c12ee1eSDan Willemsentype Kind kind 244*1c12ee1eSDan Willemsen 245*1c12ee1eSDan Willemsentype kind int8 // keep exact type opaque as the int type may change 246*1c12ee1eSDan Willemsen 247*1c12ee1eSDan Willemsen// Constants as defined by the google.protobuf.Field.Kind enumeration. 248*1c12ee1eSDan Willemsenconst ( 249*1c12ee1eSDan Willemsen BoolKind Kind = 8 250*1c12ee1eSDan Willemsen EnumKind Kind = 14 251*1c12ee1eSDan Willemsen Int32Kind Kind = 5 252*1c12ee1eSDan Willemsen Sint32Kind Kind = 17 253*1c12ee1eSDan Willemsen Uint32Kind Kind = 13 254*1c12ee1eSDan Willemsen Int64Kind Kind = 3 255*1c12ee1eSDan Willemsen Sint64Kind Kind = 18 256*1c12ee1eSDan Willemsen Uint64Kind Kind = 4 257*1c12ee1eSDan Willemsen Sfixed32Kind Kind = 15 258*1c12ee1eSDan Willemsen Fixed32Kind Kind = 7 259*1c12ee1eSDan Willemsen FloatKind Kind = 2 260*1c12ee1eSDan Willemsen Sfixed64Kind Kind = 16 261*1c12ee1eSDan Willemsen Fixed64Kind Kind = 6 262*1c12ee1eSDan Willemsen DoubleKind Kind = 1 263*1c12ee1eSDan Willemsen StringKind Kind = 9 264*1c12ee1eSDan Willemsen BytesKind Kind = 12 265*1c12ee1eSDan Willemsen MessageKind Kind = 11 266*1c12ee1eSDan Willemsen GroupKind Kind = 10 267*1c12ee1eSDan Willemsen) 268*1c12ee1eSDan Willemsen 269*1c12ee1eSDan Willemsen// IsValid reports whether the kind is valid. 270*1c12ee1eSDan Willemsenfunc (k Kind) IsValid() bool { 271*1c12ee1eSDan Willemsen switch k { 272*1c12ee1eSDan Willemsen case BoolKind, EnumKind, 273*1c12ee1eSDan Willemsen Int32Kind, Sint32Kind, Uint32Kind, 274*1c12ee1eSDan Willemsen Int64Kind, Sint64Kind, Uint64Kind, 275*1c12ee1eSDan Willemsen Sfixed32Kind, Fixed32Kind, FloatKind, 276*1c12ee1eSDan Willemsen Sfixed64Kind, Fixed64Kind, DoubleKind, 277*1c12ee1eSDan Willemsen StringKind, BytesKind, MessageKind, GroupKind: 278*1c12ee1eSDan Willemsen return true 279*1c12ee1eSDan Willemsen default: 280*1c12ee1eSDan Willemsen return false 281*1c12ee1eSDan Willemsen } 282*1c12ee1eSDan Willemsen} 283*1c12ee1eSDan Willemsen 284*1c12ee1eSDan Willemsen// String returns k as a proto source identifier (e.g., "bool"). 285*1c12ee1eSDan Willemsenfunc (k Kind) String() string { 286*1c12ee1eSDan Willemsen switch k { 287*1c12ee1eSDan Willemsen case BoolKind: 288*1c12ee1eSDan Willemsen return "bool" 289*1c12ee1eSDan Willemsen case EnumKind: 290*1c12ee1eSDan Willemsen return "enum" 291*1c12ee1eSDan Willemsen case Int32Kind: 292*1c12ee1eSDan Willemsen return "int32" 293*1c12ee1eSDan Willemsen case Sint32Kind: 294*1c12ee1eSDan Willemsen return "sint32" 295*1c12ee1eSDan Willemsen case Uint32Kind: 296*1c12ee1eSDan Willemsen return "uint32" 297*1c12ee1eSDan Willemsen case Int64Kind: 298*1c12ee1eSDan Willemsen return "int64" 299*1c12ee1eSDan Willemsen case Sint64Kind: 300*1c12ee1eSDan Willemsen return "sint64" 301*1c12ee1eSDan Willemsen case Uint64Kind: 302*1c12ee1eSDan Willemsen return "uint64" 303*1c12ee1eSDan Willemsen case Sfixed32Kind: 304*1c12ee1eSDan Willemsen return "sfixed32" 305*1c12ee1eSDan Willemsen case Fixed32Kind: 306*1c12ee1eSDan Willemsen return "fixed32" 307*1c12ee1eSDan Willemsen case FloatKind: 308*1c12ee1eSDan Willemsen return "float" 309*1c12ee1eSDan Willemsen case Sfixed64Kind: 310*1c12ee1eSDan Willemsen return "sfixed64" 311*1c12ee1eSDan Willemsen case Fixed64Kind: 312*1c12ee1eSDan Willemsen return "fixed64" 313*1c12ee1eSDan Willemsen case DoubleKind: 314*1c12ee1eSDan Willemsen return "double" 315*1c12ee1eSDan Willemsen case StringKind: 316*1c12ee1eSDan Willemsen return "string" 317*1c12ee1eSDan Willemsen case BytesKind: 318*1c12ee1eSDan Willemsen return "bytes" 319*1c12ee1eSDan Willemsen case MessageKind: 320*1c12ee1eSDan Willemsen return "message" 321*1c12ee1eSDan Willemsen case GroupKind: 322*1c12ee1eSDan Willemsen return "group" 323*1c12ee1eSDan Willemsen default: 324*1c12ee1eSDan Willemsen return fmt.Sprintf("<unknown:%d>", k) 325*1c12ee1eSDan Willemsen } 326*1c12ee1eSDan Willemsen} 327*1c12ee1eSDan Willemsen 328*1c12ee1eSDan Willemsen// GoString returns k as a Go source identifier (e.g., "BoolKind"). 329*1c12ee1eSDan Willemsenfunc (k Kind) GoString() string { 330*1c12ee1eSDan Willemsen switch k { 331*1c12ee1eSDan Willemsen case BoolKind: 332*1c12ee1eSDan Willemsen return "BoolKind" 333*1c12ee1eSDan Willemsen case EnumKind: 334*1c12ee1eSDan Willemsen return "EnumKind" 335*1c12ee1eSDan Willemsen case Int32Kind: 336*1c12ee1eSDan Willemsen return "Int32Kind" 337*1c12ee1eSDan Willemsen case Sint32Kind: 338*1c12ee1eSDan Willemsen return "Sint32Kind" 339*1c12ee1eSDan Willemsen case Uint32Kind: 340*1c12ee1eSDan Willemsen return "Uint32Kind" 341*1c12ee1eSDan Willemsen case Int64Kind: 342*1c12ee1eSDan Willemsen return "Int64Kind" 343*1c12ee1eSDan Willemsen case Sint64Kind: 344*1c12ee1eSDan Willemsen return "Sint64Kind" 345*1c12ee1eSDan Willemsen case Uint64Kind: 346*1c12ee1eSDan Willemsen return "Uint64Kind" 347*1c12ee1eSDan Willemsen case Sfixed32Kind: 348*1c12ee1eSDan Willemsen return "Sfixed32Kind" 349*1c12ee1eSDan Willemsen case Fixed32Kind: 350*1c12ee1eSDan Willemsen return "Fixed32Kind" 351*1c12ee1eSDan Willemsen case FloatKind: 352*1c12ee1eSDan Willemsen return "FloatKind" 353*1c12ee1eSDan Willemsen case Sfixed64Kind: 354*1c12ee1eSDan Willemsen return "Sfixed64Kind" 355*1c12ee1eSDan Willemsen case Fixed64Kind: 356*1c12ee1eSDan Willemsen return "Fixed64Kind" 357*1c12ee1eSDan Willemsen case DoubleKind: 358*1c12ee1eSDan Willemsen return "DoubleKind" 359*1c12ee1eSDan Willemsen case StringKind: 360*1c12ee1eSDan Willemsen return "StringKind" 361*1c12ee1eSDan Willemsen case BytesKind: 362*1c12ee1eSDan Willemsen return "BytesKind" 363*1c12ee1eSDan Willemsen case MessageKind: 364*1c12ee1eSDan Willemsen return "MessageKind" 365*1c12ee1eSDan Willemsen case GroupKind: 366*1c12ee1eSDan Willemsen return "GroupKind" 367*1c12ee1eSDan Willemsen default: 368*1c12ee1eSDan Willemsen return fmt.Sprintf("Kind(%d)", k) 369*1c12ee1eSDan Willemsen } 370*1c12ee1eSDan Willemsen} 371*1c12ee1eSDan Willemsen 372*1c12ee1eSDan Willemsen// FieldNumber is the field number in a message. 373*1c12ee1eSDan Willemsentype FieldNumber = protowire.Number 374*1c12ee1eSDan Willemsen 375*1c12ee1eSDan Willemsen// FieldNumbers represent a list of field numbers. 376*1c12ee1eSDan Willemsentype FieldNumbers interface { 377*1c12ee1eSDan Willemsen // Len reports the number of fields in the list. 378*1c12ee1eSDan Willemsen Len() int 379*1c12ee1eSDan Willemsen // Get returns the ith field number. It panics if out of bounds. 380*1c12ee1eSDan Willemsen Get(i int) FieldNumber 381*1c12ee1eSDan Willemsen // Has reports whether n is within the list of fields. 382*1c12ee1eSDan Willemsen Has(n FieldNumber) bool 383*1c12ee1eSDan Willemsen 384*1c12ee1eSDan Willemsen doNotImplement 385*1c12ee1eSDan Willemsen} 386*1c12ee1eSDan Willemsen 387*1c12ee1eSDan Willemsen// FieldRanges represent a list of field number ranges. 388*1c12ee1eSDan Willemsentype FieldRanges interface { 389*1c12ee1eSDan Willemsen // Len reports the number of ranges in the list. 390*1c12ee1eSDan Willemsen Len() int 391*1c12ee1eSDan Willemsen // Get returns the ith range. It panics if out of bounds. 392*1c12ee1eSDan Willemsen Get(i int) [2]FieldNumber // start inclusive; end exclusive 393*1c12ee1eSDan Willemsen // Has reports whether n is within any of the ranges. 394*1c12ee1eSDan Willemsen Has(n FieldNumber) bool 395*1c12ee1eSDan Willemsen 396*1c12ee1eSDan Willemsen doNotImplement 397*1c12ee1eSDan Willemsen} 398*1c12ee1eSDan Willemsen 399*1c12ee1eSDan Willemsen// EnumNumber is the numeric value for an enum. 400*1c12ee1eSDan Willemsentype EnumNumber int32 401*1c12ee1eSDan Willemsen 402*1c12ee1eSDan Willemsen// EnumRanges represent a list of enum number ranges. 403*1c12ee1eSDan Willemsentype EnumRanges interface { 404*1c12ee1eSDan Willemsen // Len reports the number of ranges in the list. 405*1c12ee1eSDan Willemsen Len() int 406*1c12ee1eSDan Willemsen // Get returns the ith range. It panics if out of bounds. 407*1c12ee1eSDan Willemsen Get(i int) [2]EnumNumber // start inclusive; end inclusive 408*1c12ee1eSDan Willemsen // Has reports whether n is within any of the ranges. 409*1c12ee1eSDan Willemsen Has(n EnumNumber) bool 410*1c12ee1eSDan Willemsen 411*1c12ee1eSDan Willemsen doNotImplement 412*1c12ee1eSDan Willemsen} 413*1c12ee1eSDan Willemsen 414*1c12ee1eSDan Willemsen// Name is the short name for a proto declaration. This is not the name 415*1c12ee1eSDan Willemsen// as used in Go source code, which might not be identical to the proto name. 416*1c12ee1eSDan Willemsentype Name string // e.g., "Kind" 417*1c12ee1eSDan Willemsen 418*1c12ee1eSDan Willemsen// IsValid reports whether s is a syntactically valid name. 419*1c12ee1eSDan Willemsen// An empty name is invalid. 420*1c12ee1eSDan Willemsenfunc (s Name) IsValid() bool { 421*1c12ee1eSDan Willemsen return consumeIdent(string(s)) == len(s) 422*1c12ee1eSDan Willemsen} 423*1c12ee1eSDan Willemsen 424*1c12ee1eSDan Willemsen// Names represent a list of names. 425*1c12ee1eSDan Willemsentype Names interface { 426*1c12ee1eSDan Willemsen // Len reports the number of names in the list. 427*1c12ee1eSDan Willemsen Len() int 428*1c12ee1eSDan Willemsen // Get returns the ith name. It panics if out of bounds. 429*1c12ee1eSDan Willemsen Get(i int) Name 430*1c12ee1eSDan Willemsen // Has reports whether s matches any names in the list. 431*1c12ee1eSDan Willemsen Has(s Name) bool 432*1c12ee1eSDan Willemsen 433*1c12ee1eSDan Willemsen doNotImplement 434*1c12ee1eSDan Willemsen} 435*1c12ee1eSDan Willemsen 436*1c12ee1eSDan Willemsen// FullName is a qualified name that uniquely identifies a proto declaration. 437*1c12ee1eSDan Willemsen// A qualified name is the concatenation of the proto package along with the 438*1c12ee1eSDan Willemsen// fully-declared name (i.e., name of parent preceding the name of the child), 439*1c12ee1eSDan Willemsen// with a '.' delimiter placed between each Name. 440*1c12ee1eSDan Willemsen// 441*1c12ee1eSDan Willemsen// This should not have any leading or trailing dots. 442*1c12ee1eSDan Willemsentype FullName string // e.g., "google.protobuf.Field.Kind" 443*1c12ee1eSDan Willemsen 444*1c12ee1eSDan Willemsen// IsValid reports whether s is a syntactically valid full name. 445*1c12ee1eSDan Willemsen// An empty full name is invalid. 446*1c12ee1eSDan Willemsenfunc (s FullName) IsValid() bool { 447*1c12ee1eSDan Willemsen i := consumeIdent(string(s)) 448*1c12ee1eSDan Willemsen if i < 0 { 449*1c12ee1eSDan Willemsen return false 450*1c12ee1eSDan Willemsen } 451*1c12ee1eSDan Willemsen for len(s) > i { 452*1c12ee1eSDan Willemsen if s[i] != '.' { 453*1c12ee1eSDan Willemsen return false 454*1c12ee1eSDan Willemsen } 455*1c12ee1eSDan Willemsen i++ 456*1c12ee1eSDan Willemsen n := consumeIdent(string(s[i:])) 457*1c12ee1eSDan Willemsen if n < 0 { 458*1c12ee1eSDan Willemsen return false 459*1c12ee1eSDan Willemsen } 460*1c12ee1eSDan Willemsen i += n 461*1c12ee1eSDan Willemsen } 462*1c12ee1eSDan Willemsen return true 463*1c12ee1eSDan Willemsen} 464*1c12ee1eSDan Willemsen 465*1c12ee1eSDan Willemsenfunc consumeIdent(s string) (i int) { 466*1c12ee1eSDan Willemsen if len(s) == 0 || !isLetter(s[i]) { 467*1c12ee1eSDan Willemsen return -1 468*1c12ee1eSDan Willemsen } 469*1c12ee1eSDan Willemsen i++ 470*1c12ee1eSDan Willemsen for len(s) > i && isLetterDigit(s[i]) { 471*1c12ee1eSDan Willemsen i++ 472*1c12ee1eSDan Willemsen } 473*1c12ee1eSDan Willemsen return i 474*1c12ee1eSDan Willemsen} 475*1c12ee1eSDan Willemsenfunc isLetter(c byte) bool { 476*1c12ee1eSDan Willemsen return c == '_' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') 477*1c12ee1eSDan Willemsen} 478*1c12ee1eSDan Willemsenfunc isLetterDigit(c byte) bool { 479*1c12ee1eSDan Willemsen return isLetter(c) || ('0' <= c && c <= '9') 480*1c12ee1eSDan Willemsen} 481*1c12ee1eSDan Willemsen 482*1c12ee1eSDan Willemsen// Name returns the short name, which is the last identifier segment. 483*1c12ee1eSDan Willemsen// A single segment FullName is the Name itself. 484*1c12ee1eSDan Willemsenfunc (n FullName) Name() Name { 485*1c12ee1eSDan Willemsen if i := strings.LastIndexByte(string(n), '.'); i >= 0 { 486*1c12ee1eSDan Willemsen return Name(n[i+1:]) 487*1c12ee1eSDan Willemsen } 488*1c12ee1eSDan Willemsen return Name(n) 489*1c12ee1eSDan Willemsen} 490*1c12ee1eSDan Willemsen 491*1c12ee1eSDan Willemsen// Parent returns the full name with the trailing identifier removed. 492*1c12ee1eSDan Willemsen// A single segment FullName has no parent. 493*1c12ee1eSDan Willemsenfunc (n FullName) Parent() FullName { 494*1c12ee1eSDan Willemsen if i := strings.LastIndexByte(string(n), '.'); i >= 0 { 495*1c12ee1eSDan Willemsen return n[:i] 496*1c12ee1eSDan Willemsen } 497*1c12ee1eSDan Willemsen return "" 498*1c12ee1eSDan Willemsen} 499*1c12ee1eSDan Willemsen 500*1c12ee1eSDan Willemsen// Append returns the qualified name appended with the provided short name. 501*1c12ee1eSDan Willemsen// 502*1c12ee1eSDan Willemsen// Invariant: n == n.Parent().Append(n.Name()) // assuming n is valid 503*1c12ee1eSDan Willemsenfunc (n FullName) Append(s Name) FullName { 504*1c12ee1eSDan Willemsen if n == "" { 505*1c12ee1eSDan Willemsen return FullName(s) 506*1c12ee1eSDan Willemsen } 507*1c12ee1eSDan Willemsen return n + "." + FullName(s) 508*1c12ee1eSDan Willemsen} 509