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