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