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