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 Willemsenpackage protoreflect 6*1c12ee1eSDan Willemsen 7*1c12ee1eSDan Willemsenimport ( 8*1c12ee1eSDan Willemsen "fmt" 9*1c12ee1eSDan Willemsen "math" 10*1c12ee1eSDan Willemsen) 11*1c12ee1eSDan Willemsen 12*1c12ee1eSDan Willemsen// Value is a union where only one Go type may be set at a time. 13*1c12ee1eSDan Willemsen// The Value is used to represent all possible values a field may take. 14*1c12ee1eSDan Willemsen// The following shows which Go type is used to represent each proto Kind: 15*1c12ee1eSDan Willemsen// 16*1c12ee1eSDan Willemsen// ╔════════════╤═════════════════════════════════════╗ 17*1c12ee1eSDan Willemsen// ║ Go type │ Protobuf kind ║ 18*1c12ee1eSDan Willemsen// ╠════════════╪═════════════════════════════════════╣ 19*1c12ee1eSDan Willemsen// ║ bool │ BoolKind ║ 20*1c12ee1eSDan Willemsen// ║ int32 │ Int32Kind, Sint32Kind, Sfixed32Kind ║ 21*1c12ee1eSDan Willemsen// ║ int64 │ Int64Kind, Sint64Kind, Sfixed64Kind ║ 22*1c12ee1eSDan Willemsen// ║ uint32 │ Uint32Kind, Fixed32Kind ║ 23*1c12ee1eSDan Willemsen// ║ uint64 │ Uint64Kind, Fixed64Kind ║ 24*1c12ee1eSDan Willemsen// ║ float32 │ FloatKind ║ 25*1c12ee1eSDan Willemsen// ║ float64 │ DoubleKind ║ 26*1c12ee1eSDan Willemsen// ║ string │ StringKind ║ 27*1c12ee1eSDan Willemsen// ║ []byte │ BytesKind ║ 28*1c12ee1eSDan Willemsen// ║ EnumNumber │ EnumKind ║ 29*1c12ee1eSDan Willemsen// ║ Message │ MessageKind, GroupKind ║ 30*1c12ee1eSDan Willemsen// ╚════════════╧═════════════════════════════════════╝ 31*1c12ee1eSDan Willemsen// 32*1c12ee1eSDan Willemsen// Multiple protobuf Kinds may be represented by a single Go type if the type 33*1c12ee1eSDan Willemsen// can losslessly represent the information for the proto kind. For example, 34*1c12ee1eSDan Willemsen// Int64Kind, Sint64Kind, and Sfixed64Kind are all represented by int64, 35*1c12ee1eSDan Willemsen// but use different integer encoding methods. 36*1c12ee1eSDan Willemsen// 37*1c12ee1eSDan Willemsen// The List or Map types are used if the field cardinality is repeated. 38*1c12ee1eSDan Willemsen// A field is a List if FieldDescriptor.IsList reports true. 39*1c12ee1eSDan Willemsen// A field is a Map if FieldDescriptor.IsMap reports true. 40*1c12ee1eSDan Willemsen// 41*1c12ee1eSDan Willemsen// Converting to/from a Value and a concrete Go value panics on type mismatch. 42*1c12ee1eSDan Willemsen// For example, ValueOf("hello").Int() panics because this attempts to 43*1c12ee1eSDan Willemsen// retrieve an int64 from a string. 44*1c12ee1eSDan Willemsen// 45*1c12ee1eSDan Willemsen// List, Map, and Message Values are called "composite" values. 46*1c12ee1eSDan Willemsen// 47*1c12ee1eSDan Willemsen// A composite Value may alias (reference) memory at some location, 48*1c12ee1eSDan Willemsen// such that changes to the Value updates the that location. 49*1c12ee1eSDan Willemsen// A composite value acquired with a Mutable method, such as Message.Mutable, 50*1c12ee1eSDan Willemsen// always references the source object. 51*1c12ee1eSDan Willemsen// 52*1c12ee1eSDan Willemsen// For example: 53*1c12ee1eSDan Willemsen// 54*1c12ee1eSDan Willemsen// // Append a 0 to a "repeated int32" field. 55*1c12ee1eSDan Willemsen// // Since the Value returned by Mutable is guaranteed to alias 56*1c12ee1eSDan Willemsen// // the source message, modifying the Value modifies the message. 57*1c12ee1eSDan Willemsen// message.Mutable(fieldDesc).List().Append(protoreflect.ValueOfInt32(0)) 58*1c12ee1eSDan Willemsen// 59*1c12ee1eSDan Willemsen// // Assign [0] to a "repeated int32" field by creating a new Value, 60*1c12ee1eSDan Willemsen// // modifying it, and assigning it. 61*1c12ee1eSDan Willemsen// list := message.NewField(fieldDesc).List() 62*1c12ee1eSDan Willemsen// list.Append(protoreflect.ValueOfInt32(0)) 63*1c12ee1eSDan Willemsen// message.Set(fieldDesc, list) 64*1c12ee1eSDan Willemsen// // ERROR: Since it is not defined whether Set aliases the source, 65*1c12ee1eSDan Willemsen// // appending to the List here may or may not modify the message. 66*1c12ee1eSDan Willemsen// list.Append(protoreflect.ValueOfInt32(0)) 67*1c12ee1eSDan Willemsen// 68*1c12ee1eSDan Willemsen// Some operations, such as Message.Get, may return an "empty, read-only" 69*1c12ee1eSDan Willemsen// composite Value. Modifying an empty, read-only value panics. 70*1c12ee1eSDan Willemsentype Value value 71*1c12ee1eSDan Willemsen 72*1c12ee1eSDan Willemsen// The protoreflect API uses a custom Value union type instead of interface{} 73*1c12ee1eSDan Willemsen// to keep the future open for performance optimizations. Using an interface{} 74*1c12ee1eSDan Willemsen// always incurs an allocation for primitives (e.g., int64) since it needs to 75*1c12ee1eSDan Willemsen// be boxed on the heap (as interfaces can only contain pointers natively). 76*1c12ee1eSDan Willemsen// Instead, we represent the Value union as a flat struct that internally keeps 77*1c12ee1eSDan Willemsen// track of which type is set. Using unsafe, the Value union can be reduced 78*1c12ee1eSDan Willemsen// down to 24B, which is identical in size to a slice. 79*1c12ee1eSDan Willemsen// 80*1c12ee1eSDan Willemsen// The latest compiler (Go1.11) currently suffers from some limitations: 81*1c12ee1eSDan Willemsen// • With inlining, the compiler should be able to statically prove that 82*1c12ee1eSDan Willemsen// only one of these switch cases are taken and inline one specific case. 83*1c12ee1eSDan Willemsen// See https://golang.org/issue/22310. 84*1c12ee1eSDan Willemsen 85*1c12ee1eSDan Willemsen// ValueOf returns a Value initialized with the concrete value stored in v. 86*1c12ee1eSDan Willemsen// This panics if the type does not match one of the allowed types in the 87*1c12ee1eSDan Willemsen// Value union. 88*1c12ee1eSDan Willemsenfunc ValueOf(v interface{}) Value { 89*1c12ee1eSDan Willemsen switch v := v.(type) { 90*1c12ee1eSDan Willemsen case nil: 91*1c12ee1eSDan Willemsen return Value{} 92*1c12ee1eSDan Willemsen case bool: 93*1c12ee1eSDan Willemsen return ValueOfBool(v) 94*1c12ee1eSDan Willemsen case int32: 95*1c12ee1eSDan Willemsen return ValueOfInt32(v) 96*1c12ee1eSDan Willemsen case int64: 97*1c12ee1eSDan Willemsen return ValueOfInt64(v) 98*1c12ee1eSDan Willemsen case uint32: 99*1c12ee1eSDan Willemsen return ValueOfUint32(v) 100*1c12ee1eSDan Willemsen case uint64: 101*1c12ee1eSDan Willemsen return ValueOfUint64(v) 102*1c12ee1eSDan Willemsen case float32: 103*1c12ee1eSDan Willemsen return ValueOfFloat32(v) 104*1c12ee1eSDan Willemsen case float64: 105*1c12ee1eSDan Willemsen return ValueOfFloat64(v) 106*1c12ee1eSDan Willemsen case string: 107*1c12ee1eSDan Willemsen return ValueOfString(v) 108*1c12ee1eSDan Willemsen case []byte: 109*1c12ee1eSDan Willemsen return ValueOfBytes(v) 110*1c12ee1eSDan Willemsen case EnumNumber: 111*1c12ee1eSDan Willemsen return ValueOfEnum(v) 112*1c12ee1eSDan Willemsen case Message, List, Map: 113*1c12ee1eSDan Willemsen return valueOfIface(v) 114*1c12ee1eSDan Willemsen case ProtoMessage: 115*1c12ee1eSDan Willemsen panic(fmt.Sprintf("invalid proto.Message(%T) type, expected a protoreflect.Message type", v)) 116*1c12ee1eSDan Willemsen default: 117*1c12ee1eSDan Willemsen panic(fmt.Sprintf("invalid type: %T", v)) 118*1c12ee1eSDan Willemsen } 119*1c12ee1eSDan Willemsen} 120*1c12ee1eSDan Willemsen 121*1c12ee1eSDan Willemsen// ValueOfBool returns a new boolean value. 122*1c12ee1eSDan Willemsenfunc ValueOfBool(v bool) Value { 123*1c12ee1eSDan Willemsen if v { 124*1c12ee1eSDan Willemsen return Value{typ: boolType, num: 1} 125*1c12ee1eSDan Willemsen } else { 126*1c12ee1eSDan Willemsen return Value{typ: boolType, num: 0} 127*1c12ee1eSDan Willemsen } 128*1c12ee1eSDan Willemsen} 129*1c12ee1eSDan Willemsen 130*1c12ee1eSDan Willemsen// ValueOfInt32 returns a new int32 value. 131*1c12ee1eSDan Willemsenfunc ValueOfInt32(v int32) Value { 132*1c12ee1eSDan Willemsen return Value{typ: int32Type, num: uint64(v)} 133*1c12ee1eSDan Willemsen} 134*1c12ee1eSDan Willemsen 135*1c12ee1eSDan Willemsen// ValueOfInt64 returns a new int64 value. 136*1c12ee1eSDan Willemsenfunc ValueOfInt64(v int64) Value { 137*1c12ee1eSDan Willemsen return Value{typ: int64Type, num: uint64(v)} 138*1c12ee1eSDan Willemsen} 139*1c12ee1eSDan Willemsen 140*1c12ee1eSDan Willemsen// ValueOfUint32 returns a new uint32 value. 141*1c12ee1eSDan Willemsenfunc ValueOfUint32(v uint32) Value { 142*1c12ee1eSDan Willemsen return Value{typ: uint32Type, num: uint64(v)} 143*1c12ee1eSDan Willemsen} 144*1c12ee1eSDan Willemsen 145*1c12ee1eSDan Willemsen// ValueOfUint64 returns a new uint64 value. 146*1c12ee1eSDan Willemsenfunc ValueOfUint64(v uint64) Value { 147*1c12ee1eSDan Willemsen return Value{typ: uint64Type, num: v} 148*1c12ee1eSDan Willemsen} 149*1c12ee1eSDan Willemsen 150*1c12ee1eSDan Willemsen// ValueOfFloat32 returns a new float32 value. 151*1c12ee1eSDan Willemsenfunc ValueOfFloat32(v float32) Value { 152*1c12ee1eSDan Willemsen return Value{typ: float32Type, num: uint64(math.Float64bits(float64(v)))} 153*1c12ee1eSDan Willemsen} 154*1c12ee1eSDan Willemsen 155*1c12ee1eSDan Willemsen// ValueOfFloat64 returns a new float64 value. 156*1c12ee1eSDan Willemsenfunc ValueOfFloat64(v float64) Value { 157*1c12ee1eSDan Willemsen return Value{typ: float64Type, num: uint64(math.Float64bits(float64(v)))} 158*1c12ee1eSDan Willemsen} 159*1c12ee1eSDan Willemsen 160*1c12ee1eSDan Willemsen// ValueOfString returns a new string value. 161*1c12ee1eSDan Willemsenfunc ValueOfString(v string) Value { 162*1c12ee1eSDan Willemsen return valueOfString(v) 163*1c12ee1eSDan Willemsen} 164*1c12ee1eSDan Willemsen 165*1c12ee1eSDan Willemsen// ValueOfBytes returns a new bytes value. 166*1c12ee1eSDan Willemsenfunc ValueOfBytes(v []byte) Value { 167*1c12ee1eSDan Willemsen return valueOfBytes(v[:len(v):len(v)]) 168*1c12ee1eSDan Willemsen} 169*1c12ee1eSDan Willemsen 170*1c12ee1eSDan Willemsen// ValueOfEnum returns a new enum value. 171*1c12ee1eSDan Willemsenfunc ValueOfEnum(v EnumNumber) Value { 172*1c12ee1eSDan Willemsen return Value{typ: enumType, num: uint64(v)} 173*1c12ee1eSDan Willemsen} 174*1c12ee1eSDan Willemsen 175*1c12ee1eSDan Willemsen// ValueOfMessage returns a new Message value. 176*1c12ee1eSDan Willemsenfunc ValueOfMessage(v Message) Value { 177*1c12ee1eSDan Willemsen return valueOfIface(v) 178*1c12ee1eSDan Willemsen} 179*1c12ee1eSDan Willemsen 180*1c12ee1eSDan Willemsen// ValueOfList returns a new List value. 181*1c12ee1eSDan Willemsenfunc ValueOfList(v List) Value { 182*1c12ee1eSDan Willemsen return valueOfIface(v) 183*1c12ee1eSDan Willemsen} 184*1c12ee1eSDan Willemsen 185*1c12ee1eSDan Willemsen// ValueOfMap returns a new Map value. 186*1c12ee1eSDan Willemsenfunc ValueOfMap(v Map) Value { 187*1c12ee1eSDan Willemsen return valueOfIface(v) 188*1c12ee1eSDan Willemsen} 189*1c12ee1eSDan Willemsen 190*1c12ee1eSDan Willemsen// IsValid reports whether v is populated with a value. 191*1c12ee1eSDan Willemsenfunc (v Value) IsValid() bool { 192*1c12ee1eSDan Willemsen return v.typ != nilType 193*1c12ee1eSDan Willemsen} 194*1c12ee1eSDan Willemsen 195*1c12ee1eSDan Willemsen// Interface returns v as an interface{}. 196*1c12ee1eSDan Willemsen// 197*1c12ee1eSDan Willemsen// Invariant: v == ValueOf(v).Interface() 198*1c12ee1eSDan Willemsenfunc (v Value) Interface() interface{} { 199*1c12ee1eSDan Willemsen switch v.typ { 200*1c12ee1eSDan Willemsen case nilType: 201*1c12ee1eSDan Willemsen return nil 202*1c12ee1eSDan Willemsen case boolType: 203*1c12ee1eSDan Willemsen return v.Bool() 204*1c12ee1eSDan Willemsen case int32Type: 205*1c12ee1eSDan Willemsen return int32(v.Int()) 206*1c12ee1eSDan Willemsen case int64Type: 207*1c12ee1eSDan Willemsen return int64(v.Int()) 208*1c12ee1eSDan Willemsen case uint32Type: 209*1c12ee1eSDan Willemsen return uint32(v.Uint()) 210*1c12ee1eSDan Willemsen case uint64Type: 211*1c12ee1eSDan Willemsen return uint64(v.Uint()) 212*1c12ee1eSDan Willemsen case float32Type: 213*1c12ee1eSDan Willemsen return float32(v.Float()) 214*1c12ee1eSDan Willemsen case float64Type: 215*1c12ee1eSDan Willemsen return float64(v.Float()) 216*1c12ee1eSDan Willemsen case stringType: 217*1c12ee1eSDan Willemsen return v.String() 218*1c12ee1eSDan Willemsen case bytesType: 219*1c12ee1eSDan Willemsen return v.Bytes() 220*1c12ee1eSDan Willemsen case enumType: 221*1c12ee1eSDan Willemsen return v.Enum() 222*1c12ee1eSDan Willemsen default: 223*1c12ee1eSDan Willemsen return v.getIface() 224*1c12ee1eSDan Willemsen } 225*1c12ee1eSDan Willemsen} 226*1c12ee1eSDan Willemsen 227*1c12ee1eSDan Willemsenfunc (v Value) typeName() string { 228*1c12ee1eSDan Willemsen switch v.typ { 229*1c12ee1eSDan Willemsen case nilType: 230*1c12ee1eSDan Willemsen return "nil" 231*1c12ee1eSDan Willemsen case boolType: 232*1c12ee1eSDan Willemsen return "bool" 233*1c12ee1eSDan Willemsen case int32Type: 234*1c12ee1eSDan Willemsen return "int32" 235*1c12ee1eSDan Willemsen case int64Type: 236*1c12ee1eSDan Willemsen return "int64" 237*1c12ee1eSDan Willemsen case uint32Type: 238*1c12ee1eSDan Willemsen return "uint32" 239*1c12ee1eSDan Willemsen case uint64Type: 240*1c12ee1eSDan Willemsen return "uint64" 241*1c12ee1eSDan Willemsen case float32Type: 242*1c12ee1eSDan Willemsen return "float32" 243*1c12ee1eSDan Willemsen case float64Type: 244*1c12ee1eSDan Willemsen return "float64" 245*1c12ee1eSDan Willemsen case stringType: 246*1c12ee1eSDan Willemsen return "string" 247*1c12ee1eSDan Willemsen case bytesType: 248*1c12ee1eSDan Willemsen return "bytes" 249*1c12ee1eSDan Willemsen case enumType: 250*1c12ee1eSDan Willemsen return "enum" 251*1c12ee1eSDan Willemsen default: 252*1c12ee1eSDan Willemsen switch v := v.getIface().(type) { 253*1c12ee1eSDan Willemsen case Message: 254*1c12ee1eSDan Willemsen return "message" 255*1c12ee1eSDan Willemsen case List: 256*1c12ee1eSDan Willemsen return "list" 257*1c12ee1eSDan Willemsen case Map: 258*1c12ee1eSDan Willemsen return "map" 259*1c12ee1eSDan Willemsen default: 260*1c12ee1eSDan Willemsen return fmt.Sprintf("<unknown: %T>", v) 261*1c12ee1eSDan Willemsen } 262*1c12ee1eSDan Willemsen } 263*1c12ee1eSDan Willemsen} 264*1c12ee1eSDan Willemsen 265*1c12ee1eSDan Willemsenfunc (v Value) panicMessage(what string) string { 266*1c12ee1eSDan Willemsen return fmt.Sprintf("type mismatch: cannot convert %v to %s", v.typeName(), what) 267*1c12ee1eSDan Willemsen} 268*1c12ee1eSDan Willemsen 269*1c12ee1eSDan Willemsen// Bool returns v as a bool and panics if the type is not a bool. 270*1c12ee1eSDan Willemsenfunc (v Value) Bool() bool { 271*1c12ee1eSDan Willemsen switch v.typ { 272*1c12ee1eSDan Willemsen case boolType: 273*1c12ee1eSDan Willemsen return v.num > 0 274*1c12ee1eSDan Willemsen default: 275*1c12ee1eSDan Willemsen panic(v.panicMessage("bool")) 276*1c12ee1eSDan Willemsen } 277*1c12ee1eSDan Willemsen} 278*1c12ee1eSDan Willemsen 279*1c12ee1eSDan Willemsen// Int returns v as a int64 and panics if the type is not a int32 or int64. 280*1c12ee1eSDan Willemsenfunc (v Value) Int() int64 { 281*1c12ee1eSDan Willemsen switch v.typ { 282*1c12ee1eSDan Willemsen case int32Type, int64Type: 283*1c12ee1eSDan Willemsen return int64(v.num) 284*1c12ee1eSDan Willemsen default: 285*1c12ee1eSDan Willemsen panic(v.panicMessage("int")) 286*1c12ee1eSDan Willemsen } 287*1c12ee1eSDan Willemsen} 288*1c12ee1eSDan Willemsen 289*1c12ee1eSDan Willemsen// Uint returns v as a uint64 and panics if the type is not a uint32 or uint64. 290*1c12ee1eSDan Willemsenfunc (v Value) Uint() uint64 { 291*1c12ee1eSDan Willemsen switch v.typ { 292*1c12ee1eSDan Willemsen case uint32Type, uint64Type: 293*1c12ee1eSDan Willemsen return uint64(v.num) 294*1c12ee1eSDan Willemsen default: 295*1c12ee1eSDan Willemsen panic(v.panicMessage("uint")) 296*1c12ee1eSDan Willemsen } 297*1c12ee1eSDan Willemsen} 298*1c12ee1eSDan Willemsen 299*1c12ee1eSDan Willemsen// Float returns v as a float64 and panics if the type is not a float32 or float64. 300*1c12ee1eSDan Willemsenfunc (v Value) Float() float64 { 301*1c12ee1eSDan Willemsen switch v.typ { 302*1c12ee1eSDan Willemsen case float32Type, float64Type: 303*1c12ee1eSDan Willemsen return math.Float64frombits(uint64(v.num)) 304*1c12ee1eSDan Willemsen default: 305*1c12ee1eSDan Willemsen panic(v.panicMessage("float")) 306*1c12ee1eSDan Willemsen } 307*1c12ee1eSDan Willemsen} 308*1c12ee1eSDan Willemsen 309*1c12ee1eSDan Willemsen// String returns v as a string. Since this method implements fmt.Stringer, 310*1c12ee1eSDan Willemsen// this returns the formatted string value for any non-string type. 311*1c12ee1eSDan Willemsenfunc (v Value) String() string { 312*1c12ee1eSDan Willemsen switch v.typ { 313*1c12ee1eSDan Willemsen case stringType: 314*1c12ee1eSDan Willemsen return v.getString() 315*1c12ee1eSDan Willemsen default: 316*1c12ee1eSDan Willemsen return fmt.Sprint(v.Interface()) 317*1c12ee1eSDan Willemsen } 318*1c12ee1eSDan Willemsen} 319*1c12ee1eSDan Willemsen 320*1c12ee1eSDan Willemsen// Bytes returns v as a []byte and panics if the type is not a []byte. 321*1c12ee1eSDan Willemsenfunc (v Value) Bytes() []byte { 322*1c12ee1eSDan Willemsen switch v.typ { 323*1c12ee1eSDan Willemsen case bytesType: 324*1c12ee1eSDan Willemsen return v.getBytes() 325*1c12ee1eSDan Willemsen default: 326*1c12ee1eSDan Willemsen panic(v.panicMessage("bytes")) 327*1c12ee1eSDan Willemsen } 328*1c12ee1eSDan Willemsen} 329*1c12ee1eSDan Willemsen 330*1c12ee1eSDan Willemsen// Enum returns v as a EnumNumber and panics if the type is not a EnumNumber. 331*1c12ee1eSDan Willemsenfunc (v Value) Enum() EnumNumber { 332*1c12ee1eSDan Willemsen switch v.typ { 333*1c12ee1eSDan Willemsen case enumType: 334*1c12ee1eSDan Willemsen return EnumNumber(v.num) 335*1c12ee1eSDan Willemsen default: 336*1c12ee1eSDan Willemsen panic(v.panicMessage("enum")) 337*1c12ee1eSDan Willemsen } 338*1c12ee1eSDan Willemsen} 339*1c12ee1eSDan Willemsen 340*1c12ee1eSDan Willemsen// Message returns v as a Message and panics if the type is not a Message. 341*1c12ee1eSDan Willemsenfunc (v Value) Message() Message { 342*1c12ee1eSDan Willemsen switch vi := v.getIface().(type) { 343*1c12ee1eSDan Willemsen case Message: 344*1c12ee1eSDan Willemsen return vi 345*1c12ee1eSDan Willemsen default: 346*1c12ee1eSDan Willemsen panic(v.panicMessage("message")) 347*1c12ee1eSDan Willemsen } 348*1c12ee1eSDan Willemsen} 349*1c12ee1eSDan Willemsen 350*1c12ee1eSDan Willemsen// List returns v as a List and panics if the type is not a List. 351*1c12ee1eSDan Willemsenfunc (v Value) List() List { 352*1c12ee1eSDan Willemsen switch vi := v.getIface().(type) { 353*1c12ee1eSDan Willemsen case List: 354*1c12ee1eSDan Willemsen return vi 355*1c12ee1eSDan Willemsen default: 356*1c12ee1eSDan Willemsen panic(v.panicMessage("list")) 357*1c12ee1eSDan Willemsen } 358*1c12ee1eSDan Willemsen} 359*1c12ee1eSDan Willemsen 360*1c12ee1eSDan Willemsen// Map returns v as a Map and panics if the type is not a Map. 361*1c12ee1eSDan Willemsenfunc (v Value) Map() Map { 362*1c12ee1eSDan Willemsen switch vi := v.getIface().(type) { 363*1c12ee1eSDan Willemsen case Map: 364*1c12ee1eSDan Willemsen return vi 365*1c12ee1eSDan Willemsen default: 366*1c12ee1eSDan Willemsen panic(v.panicMessage("map")) 367*1c12ee1eSDan Willemsen } 368*1c12ee1eSDan Willemsen} 369*1c12ee1eSDan Willemsen 370*1c12ee1eSDan Willemsen// MapKey returns v as a MapKey and panics for invalid MapKey types. 371*1c12ee1eSDan Willemsenfunc (v Value) MapKey() MapKey { 372*1c12ee1eSDan Willemsen switch v.typ { 373*1c12ee1eSDan Willemsen case boolType, int32Type, int64Type, uint32Type, uint64Type, stringType: 374*1c12ee1eSDan Willemsen return MapKey(v) 375*1c12ee1eSDan Willemsen default: 376*1c12ee1eSDan Willemsen panic(v.panicMessage("map key")) 377*1c12ee1eSDan Willemsen } 378*1c12ee1eSDan Willemsen} 379*1c12ee1eSDan Willemsen 380*1c12ee1eSDan Willemsen// MapKey is used to index maps, where the Go type of the MapKey must match 381*1c12ee1eSDan Willemsen// the specified key Kind (see MessageDescriptor.IsMapEntry). 382*1c12ee1eSDan Willemsen// The following shows what Go type is used to represent each proto Kind: 383*1c12ee1eSDan Willemsen// 384*1c12ee1eSDan Willemsen// ╔═════════╤═════════════════════════════════════╗ 385*1c12ee1eSDan Willemsen// ║ Go type │ Protobuf kind ║ 386*1c12ee1eSDan Willemsen// ╠═════════╪═════════════════════════════════════╣ 387*1c12ee1eSDan Willemsen// ║ bool │ BoolKind ║ 388*1c12ee1eSDan Willemsen// ║ int32 │ Int32Kind, Sint32Kind, Sfixed32Kind ║ 389*1c12ee1eSDan Willemsen// ║ int64 │ Int64Kind, Sint64Kind, Sfixed64Kind ║ 390*1c12ee1eSDan Willemsen// ║ uint32 │ Uint32Kind, Fixed32Kind ║ 391*1c12ee1eSDan Willemsen// ║ uint64 │ Uint64Kind, Fixed64Kind ║ 392*1c12ee1eSDan Willemsen// ║ string │ StringKind ║ 393*1c12ee1eSDan Willemsen// ╚═════════╧═════════════════════════════════════╝ 394*1c12ee1eSDan Willemsen// 395*1c12ee1eSDan Willemsen// A MapKey is constructed and accessed through a Value: 396*1c12ee1eSDan Willemsen// 397*1c12ee1eSDan Willemsen// k := ValueOf("hash").MapKey() // convert string to MapKey 398*1c12ee1eSDan Willemsen// s := k.String() // convert MapKey to string 399*1c12ee1eSDan Willemsen// 400*1c12ee1eSDan Willemsen// The MapKey is a strict subset of valid types used in Value; 401*1c12ee1eSDan Willemsen// converting a Value to a MapKey with an invalid type panics. 402*1c12ee1eSDan Willemsentype MapKey value 403*1c12ee1eSDan Willemsen 404*1c12ee1eSDan Willemsen// IsValid reports whether k is populated with a value. 405*1c12ee1eSDan Willemsenfunc (k MapKey) IsValid() bool { 406*1c12ee1eSDan Willemsen return Value(k).IsValid() 407*1c12ee1eSDan Willemsen} 408*1c12ee1eSDan Willemsen 409*1c12ee1eSDan Willemsen// Interface returns k as an interface{}. 410*1c12ee1eSDan Willemsenfunc (k MapKey) Interface() interface{} { 411*1c12ee1eSDan Willemsen return Value(k).Interface() 412*1c12ee1eSDan Willemsen} 413*1c12ee1eSDan Willemsen 414*1c12ee1eSDan Willemsen// Bool returns k as a bool and panics if the type is not a bool. 415*1c12ee1eSDan Willemsenfunc (k MapKey) Bool() bool { 416*1c12ee1eSDan Willemsen return Value(k).Bool() 417*1c12ee1eSDan Willemsen} 418*1c12ee1eSDan Willemsen 419*1c12ee1eSDan Willemsen// Int returns k as a int64 and panics if the type is not a int32 or int64. 420*1c12ee1eSDan Willemsenfunc (k MapKey) Int() int64 { 421*1c12ee1eSDan Willemsen return Value(k).Int() 422*1c12ee1eSDan Willemsen} 423*1c12ee1eSDan Willemsen 424*1c12ee1eSDan Willemsen// Uint returns k as a uint64 and panics if the type is not a uint32 or uint64. 425*1c12ee1eSDan Willemsenfunc (k MapKey) Uint() uint64 { 426*1c12ee1eSDan Willemsen return Value(k).Uint() 427*1c12ee1eSDan Willemsen} 428*1c12ee1eSDan Willemsen 429*1c12ee1eSDan Willemsen// String returns k as a string. Since this method implements fmt.Stringer, 430*1c12ee1eSDan Willemsen// this returns the formatted string value for any non-string type. 431*1c12ee1eSDan Willemsenfunc (k MapKey) String() string { 432*1c12ee1eSDan Willemsen return Value(k).String() 433*1c12ee1eSDan Willemsen} 434*1c12ee1eSDan Willemsen 435*1c12ee1eSDan Willemsen// Value returns k as a Value. 436*1c12ee1eSDan Willemsenfunc (k MapKey) Value() Value { 437*1c12ee1eSDan Willemsen return Value(k) 438*1c12ee1eSDan Willemsen} 439