xref: /aosp_15_r20/external/golang-protobuf/reflect/protoreflect/value_union.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
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