value_union.go 11 KB

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