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