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