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