value_unsafe.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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. //go:build !purego && !appengine
  5. // +build !purego,!appengine
  6. package protoreflect
  7. import (
  8. "unsafe"
  9. "google.golang.org/protobuf/internal/pragma"
  10. )
  11. type (
  12. stringHeader struct {
  13. Data unsafe.Pointer
  14. Len int
  15. }
  16. sliceHeader struct {
  17. Data unsafe.Pointer
  18. Len int
  19. Cap int
  20. }
  21. ifaceHeader struct {
  22. Type unsafe.Pointer
  23. Data unsafe.Pointer
  24. }
  25. )
  26. var (
  27. nilType = typeOf(nil)
  28. boolType = typeOf(*new(bool))
  29. int32Type = typeOf(*new(int32))
  30. int64Type = typeOf(*new(int64))
  31. uint32Type = typeOf(*new(uint32))
  32. uint64Type = typeOf(*new(uint64))
  33. float32Type = typeOf(*new(float32))
  34. float64Type = typeOf(*new(float64))
  35. stringType = typeOf(*new(string))
  36. bytesType = typeOf(*new([]byte))
  37. enumType = typeOf(*new(EnumNumber))
  38. )
  39. // typeOf returns a pointer to the Go type information.
  40. // The pointer is comparable and equal if and only if the types are identical.
  41. func typeOf(t interface{}) unsafe.Pointer {
  42. return (*ifaceHeader)(unsafe.Pointer(&t)).Type
  43. }
  44. // value is a union where only one type can be represented at a time.
  45. // The struct is 24B large on 64-bit systems and requires the minimum storage
  46. // necessary to represent each possible type.
  47. //
  48. // The Go GC needs to be able to scan variables containing pointers.
  49. // As such, pointers and non-pointers cannot be intermixed.
  50. type value struct {
  51. pragma.DoNotCompare // 0B
  52. // typ stores the type of the value as a pointer to the Go type.
  53. typ unsafe.Pointer // 8B
  54. // ptr stores the data pointer for a String, Bytes, or interface value.
  55. ptr unsafe.Pointer // 8B
  56. // num stores a Bool, Int32, Int64, Uint32, Uint64, Float32, Float64, or
  57. // Enum value as a raw uint64.
  58. //
  59. // It is also used to store the length of a String or Bytes value;
  60. // the capacity is ignored.
  61. num uint64 // 8B
  62. }
  63. func valueOfString(v string) Value {
  64. p := (*stringHeader)(unsafe.Pointer(&v))
  65. return Value{typ: stringType, ptr: p.Data, num: uint64(len(v))}
  66. }
  67. func valueOfBytes(v []byte) Value {
  68. p := (*sliceHeader)(unsafe.Pointer(&v))
  69. return Value{typ: bytesType, ptr: p.Data, num: uint64(len(v))}
  70. }
  71. func valueOfIface(v interface{}) Value {
  72. p := (*ifaceHeader)(unsafe.Pointer(&v))
  73. return Value{typ: p.Type, ptr: p.Data}
  74. }
  75. func (v Value) getString() (x string) {
  76. *(*stringHeader)(unsafe.Pointer(&x)) = stringHeader{Data: v.ptr, Len: int(v.num)}
  77. return x
  78. }
  79. func (v Value) getBytes() (x []byte) {
  80. *(*sliceHeader)(unsafe.Pointer(&x)) = sliceHeader{Data: v.ptr, Len: int(v.num), Cap: int(v.num)}
  81. return x
  82. }
  83. func (v Value) getIface() (x interface{}) {
  84. *(*ifaceHeader)(unsafe.Pointer(&x)) = ifaceHeader{Type: v.typ, Data: v.ptr}
  85. return x
  86. }