xref: /aosp_15_r20/external/golang-protobuf/reflect/protoreflect/value_unsafe.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
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
5//go:build !purego && !appengine
6// +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}
100