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// +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} 99