mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
* add DateTime sans mgo * change all uses of strfmt.DateTime to common.DateTime, remove test strfmt usage * remove api tests, system-test dep on api test multiple reasons to remove the api tests: * awkward dependency with fn_go meant generating bindings on a branched fn to vendor those to test new stuff. this is at a minimum not at all intuitive, worth it, nor a fun way to spend the finite amount of time we have to live. * api tests only tested a subset of functionality that the server/ api tests already test, and we risk having tests where one tests some thing and the other doesn't. let's not. we have too many test suites as it is, and these pretty much only test that we updated the fn_go bindings, which is actually a hassle as noted above and the cli will pretty quickly figure out anyway. * fn_go relies on openapi, which relies on mgo, which is deprecated and we'd like to remove as a dependency. openapi is a _huge_ dep built in a NIH fashion, that cannot simply remove the mgo dep as users may be using it. we've now stolen their date time and otherwise killed usage of it in fn core, for fn_go it still exists but that's less of a problem. * update deps removals: * easyjson * mgo * go-openapi * mapstructure * fn_go * purell * go-validator also, had to lock docker. we shouldn't use docker on master anyway, they strongly advise against that. had no luck with latest version rev, so i locked it to what we were using before. until next time. the rest is just playing dep roulette, those end up removing a ton tho * fix exec test to work * account for john le cache
640 lines
20 KiB
Go
640 lines
20 KiB
Go
// +build !safe
|
|
// +build !appengine
|
|
// +build go1.7
|
|
|
|
// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
|
|
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
|
|
|
package codec
|
|
|
|
import (
|
|
"reflect"
|
|
"sync/atomic"
|
|
"time"
|
|
"unsafe"
|
|
)
|
|
|
|
// This file has unsafe variants of some helper methods.
|
|
// NOTE: See helper_not_unsafe.go for the usage information.
|
|
|
|
// var zeroRTv [4]uintptr
|
|
|
|
const safeMode = false
|
|
const unsafeFlagIndir = 1 << 7 // keep in sync with GO_ROOT/src/reflect/value.go
|
|
|
|
type unsafeString struct {
|
|
Data unsafe.Pointer
|
|
Len int
|
|
}
|
|
|
|
type unsafeSlice struct {
|
|
Data unsafe.Pointer
|
|
Len int
|
|
Cap int
|
|
}
|
|
|
|
type unsafeIntf struct {
|
|
typ unsafe.Pointer
|
|
word unsafe.Pointer
|
|
}
|
|
|
|
type unsafeReflectValue struct {
|
|
typ unsafe.Pointer
|
|
ptr unsafe.Pointer
|
|
flag uintptr
|
|
}
|
|
|
|
func stringView(v []byte) string {
|
|
if len(v) == 0 {
|
|
return ""
|
|
}
|
|
bx := (*unsafeSlice)(unsafe.Pointer(&v))
|
|
return *(*string)(unsafe.Pointer(&unsafeString{bx.Data, bx.Len}))
|
|
}
|
|
|
|
func bytesView(v string) []byte {
|
|
if len(v) == 0 {
|
|
return zeroByteSlice
|
|
}
|
|
sx := (*unsafeString)(unsafe.Pointer(&v))
|
|
return *(*[]byte)(unsafe.Pointer(&unsafeSlice{sx.Data, sx.Len, sx.Len}))
|
|
}
|
|
|
|
func definitelyNil(v interface{}) bool {
|
|
// There is no global way of checking if an interface is nil.
|
|
// For true references (map, ptr, func, chan), you can just look
|
|
// at the word of the interface. However, for slices, you have to dereference
|
|
// the word, and get a pointer to the 3-word interface value.
|
|
//
|
|
// However, the following are cheap calls
|
|
// - TypeOf(interface): cheap 2-line call.
|
|
// - ValueOf(interface{}): expensive
|
|
// - type.Kind: cheap call through an interface
|
|
// - Value.Type(): cheap call
|
|
// except it's a method value (e.g. r.Read, which implies that it is a Func)
|
|
|
|
return ((*unsafeIntf)(unsafe.Pointer(&v))).word == nil
|
|
}
|
|
|
|
func rv2i(rv reflect.Value) interface{} {
|
|
// TODO: consider a more generally-known optimization for reflect.Value ==> Interface
|
|
//
|
|
// Currently, we use this fragile method that taps into implememtation details from
|
|
// the source go stdlib reflect/value.go, and trims the implementation.
|
|
|
|
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
// true references (map, func, chan, ptr - NOT slice) may be double-referenced as flagIndir
|
|
var ptr unsafe.Pointer
|
|
if refBitset.isset(byte(urv.flag&(1<<5-1))) && urv.flag&unsafeFlagIndir != 0 {
|
|
ptr = *(*unsafe.Pointer)(urv.ptr)
|
|
} else {
|
|
ptr = urv.ptr
|
|
}
|
|
return *(*interface{})(unsafe.Pointer(&unsafeIntf{typ: urv.typ, word: ptr}))
|
|
}
|
|
|
|
func rt2id(rt reflect.Type) uintptr {
|
|
return uintptr(((*unsafeIntf)(unsafe.Pointer(&rt))).word)
|
|
}
|
|
|
|
func rv2rtid(rv reflect.Value) uintptr {
|
|
return uintptr((*unsafeReflectValue)(unsafe.Pointer(&rv)).typ)
|
|
}
|
|
|
|
func i2rtid(i interface{}) uintptr {
|
|
return uintptr(((*unsafeIntf)(unsafe.Pointer(&i))).typ)
|
|
}
|
|
|
|
// --------------------------
|
|
|
|
func isEmptyValue(v reflect.Value, tinfos *TypeInfos, deref, checkStruct bool) bool {
|
|
urv := (*unsafeReflectValue)(unsafe.Pointer(&v))
|
|
if urv.flag == 0 {
|
|
return true
|
|
}
|
|
switch v.Kind() {
|
|
case reflect.Invalid:
|
|
return true
|
|
case reflect.String:
|
|
return (*unsafeString)(urv.ptr).Len == 0
|
|
case reflect.Slice:
|
|
return (*unsafeSlice)(urv.ptr).Len == 0
|
|
case reflect.Bool:
|
|
return !*(*bool)(urv.ptr)
|
|
case reflect.Int:
|
|
return *(*int)(urv.ptr) == 0
|
|
case reflect.Int8:
|
|
return *(*int8)(urv.ptr) == 0
|
|
case reflect.Int16:
|
|
return *(*int16)(urv.ptr) == 0
|
|
case reflect.Int32:
|
|
return *(*int32)(urv.ptr) == 0
|
|
case reflect.Int64:
|
|
return *(*int64)(urv.ptr) == 0
|
|
case reflect.Uint:
|
|
return *(*uint)(urv.ptr) == 0
|
|
case reflect.Uint8:
|
|
return *(*uint8)(urv.ptr) == 0
|
|
case reflect.Uint16:
|
|
return *(*uint16)(urv.ptr) == 0
|
|
case reflect.Uint32:
|
|
return *(*uint32)(urv.ptr) == 0
|
|
case reflect.Uint64:
|
|
return *(*uint64)(urv.ptr) == 0
|
|
case reflect.Uintptr:
|
|
return *(*uintptr)(urv.ptr) == 0
|
|
case reflect.Float32:
|
|
return *(*float32)(urv.ptr) == 0
|
|
case reflect.Float64:
|
|
return *(*float64)(urv.ptr) == 0
|
|
case reflect.Interface:
|
|
isnil := urv.ptr == nil || *(*unsafe.Pointer)(urv.ptr) == nil
|
|
if deref {
|
|
if isnil {
|
|
return true
|
|
}
|
|
return isEmptyValue(v.Elem(), tinfos, deref, checkStruct)
|
|
}
|
|
return isnil
|
|
case reflect.Ptr:
|
|
// isnil := urv.ptr == nil (not sufficient, as a pointer value encodes the type)
|
|
isnil := urv.ptr == nil || *(*unsafe.Pointer)(urv.ptr) == nil
|
|
if deref {
|
|
if isnil {
|
|
return true
|
|
}
|
|
return isEmptyValue(v.Elem(), tinfos, deref, checkStruct)
|
|
}
|
|
return isnil
|
|
case reflect.Struct:
|
|
return isEmptyStruct(v, tinfos, deref, checkStruct)
|
|
case reflect.Map, reflect.Array, reflect.Chan:
|
|
return v.Len() == 0
|
|
}
|
|
return false
|
|
}
|
|
|
|
// --------------------------
|
|
|
|
// atomicTypeInfoSlice contains length and pointer to the array for a slice.
|
|
// It is expected to be 2 words.
|
|
//
|
|
// Previously, we atomically loaded and stored the length and array pointer separately,
|
|
// which could lead to some races.
|
|
// We now just atomically store and load the pointer to the value directly.
|
|
|
|
type atomicTypeInfoSlice struct { // expected to be 2 words
|
|
l int // length of the data array (must be first in struct, for 64-bit alignment necessary for 386)
|
|
v unsafe.Pointer // data array - Pointer (not uintptr) to maintain GC reference
|
|
}
|
|
|
|
func (x *atomicTypeInfoSlice) load() []rtid2ti {
|
|
xp := unsafe.Pointer(x)
|
|
x2 := *(*atomicTypeInfoSlice)(atomic.LoadPointer(&xp))
|
|
if x2.l == 0 {
|
|
return nil
|
|
}
|
|
return *(*[]rtid2ti)(unsafe.Pointer(&unsafeSlice{Data: x2.v, Len: x2.l, Cap: x2.l}))
|
|
}
|
|
|
|
func (x *atomicTypeInfoSlice) store(p []rtid2ti) {
|
|
s := (*unsafeSlice)(unsafe.Pointer(&p))
|
|
xp := unsafe.Pointer(x)
|
|
atomic.StorePointer(&xp, unsafe.Pointer(&atomicTypeInfoSlice{l: s.Len, v: s.Data}))
|
|
}
|
|
|
|
// --------------------------
|
|
func (d *Decoder) raw(f *codecFnInfo, rv reflect.Value) {
|
|
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
*(*[]byte)(urv.ptr) = d.rawBytes()
|
|
}
|
|
|
|
func (d *Decoder) kString(f *codecFnInfo, rv reflect.Value) {
|
|
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
*(*string)(urv.ptr) = d.d.DecodeString()
|
|
}
|
|
|
|
func (d *Decoder) kBool(f *codecFnInfo, rv reflect.Value) {
|
|
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
*(*bool)(urv.ptr) = d.d.DecodeBool()
|
|
}
|
|
|
|
func (d *Decoder) kTime(f *codecFnInfo, rv reflect.Value) {
|
|
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
*(*time.Time)(urv.ptr) = d.d.DecodeTime()
|
|
}
|
|
|
|
func (d *Decoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
|
|
fv := d.d.DecodeFloat64()
|
|
if chkOvf.Float32(fv) {
|
|
d.errorf("float32 overflow: %v", fv)
|
|
}
|
|
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
*(*float32)(urv.ptr) = float32(fv)
|
|
}
|
|
|
|
func (d *Decoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
|
|
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
*(*float64)(urv.ptr) = d.d.DecodeFloat64()
|
|
}
|
|
|
|
func (d *Decoder) kInt(f *codecFnInfo, rv reflect.Value) {
|
|
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
*(*int)(urv.ptr) = int(chkOvf.IntV(d.d.DecodeInt64(), intBitsize))
|
|
}
|
|
|
|
func (d *Decoder) kInt8(f *codecFnInfo, rv reflect.Value) {
|
|
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
*(*int8)(urv.ptr) = int8(chkOvf.IntV(d.d.DecodeInt64(), 8))
|
|
}
|
|
|
|
func (d *Decoder) kInt16(f *codecFnInfo, rv reflect.Value) {
|
|
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
*(*int16)(urv.ptr) = int16(chkOvf.IntV(d.d.DecodeInt64(), 16))
|
|
}
|
|
|
|
func (d *Decoder) kInt32(f *codecFnInfo, rv reflect.Value) {
|
|
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
*(*int32)(urv.ptr) = int32(chkOvf.IntV(d.d.DecodeInt64(), 32))
|
|
}
|
|
|
|
func (d *Decoder) kInt64(f *codecFnInfo, rv reflect.Value) {
|
|
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
*(*int64)(urv.ptr) = d.d.DecodeInt64()
|
|
}
|
|
|
|
func (d *Decoder) kUint(f *codecFnInfo, rv reflect.Value) {
|
|
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
*(*uint)(urv.ptr) = uint(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))
|
|
}
|
|
|
|
func (d *Decoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
|
|
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
*(*uintptr)(urv.ptr) = uintptr(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))
|
|
}
|
|
|
|
func (d *Decoder) kUint8(f *codecFnInfo, rv reflect.Value) {
|
|
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
*(*uint8)(urv.ptr) = uint8(chkOvf.UintV(d.d.DecodeUint64(), 8))
|
|
}
|
|
|
|
func (d *Decoder) kUint16(f *codecFnInfo, rv reflect.Value) {
|
|
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
*(*uint16)(urv.ptr) = uint16(chkOvf.UintV(d.d.DecodeUint64(), 16))
|
|
}
|
|
|
|
func (d *Decoder) kUint32(f *codecFnInfo, rv reflect.Value) {
|
|
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
*(*uint32)(urv.ptr) = uint32(chkOvf.UintV(d.d.DecodeUint64(), 32))
|
|
}
|
|
|
|
func (d *Decoder) kUint64(f *codecFnInfo, rv reflect.Value) {
|
|
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
*(*uint64)(urv.ptr) = d.d.DecodeUint64()
|
|
}
|
|
|
|
// ------------
|
|
|
|
func (e *Encoder) kBool(f *codecFnInfo, rv reflect.Value) {
|
|
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
e.e.EncodeBool(*(*bool)(v.ptr))
|
|
}
|
|
|
|
func (e *Encoder) kTime(f *codecFnInfo, rv reflect.Value) {
|
|
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
e.e.EncodeTime(*(*time.Time)(v.ptr))
|
|
}
|
|
|
|
func (e *Encoder) kString(f *codecFnInfo, rv reflect.Value) {
|
|
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
e.e.EncodeString(cUTF8, *(*string)(v.ptr))
|
|
}
|
|
|
|
func (e *Encoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
|
|
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
e.e.EncodeFloat64(*(*float64)(v.ptr))
|
|
}
|
|
|
|
func (e *Encoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
|
|
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
e.e.EncodeFloat32(*(*float32)(v.ptr))
|
|
}
|
|
|
|
func (e *Encoder) kInt(f *codecFnInfo, rv reflect.Value) {
|
|
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
e.e.EncodeInt(int64(*(*int)(v.ptr)))
|
|
}
|
|
|
|
func (e *Encoder) kInt8(f *codecFnInfo, rv reflect.Value) {
|
|
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
e.e.EncodeInt(int64(*(*int8)(v.ptr)))
|
|
}
|
|
|
|
func (e *Encoder) kInt16(f *codecFnInfo, rv reflect.Value) {
|
|
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
e.e.EncodeInt(int64(*(*int16)(v.ptr)))
|
|
}
|
|
|
|
func (e *Encoder) kInt32(f *codecFnInfo, rv reflect.Value) {
|
|
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
e.e.EncodeInt(int64(*(*int32)(v.ptr)))
|
|
}
|
|
|
|
func (e *Encoder) kInt64(f *codecFnInfo, rv reflect.Value) {
|
|
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
e.e.EncodeInt(int64(*(*int64)(v.ptr)))
|
|
}
|
|
|
|
func (e *Encoder) kUint(f *codecFnInfo, rv reflect.Value) {
|
|
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
e.e.EncodeUint(uint64(*(*uint)(v.ptr)))
|
|
}
|
|
|
|
func (e *Encoder) kUint8(f *codecFnInfo, rv reflect.Value) {
|
|
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
e.e.EncodeUint(uint64(*(*uint8)(v.ptr)))
|
|
}
|
|
|
|
func (e *Encoder) kUint16(f *codecFnInfo, rv reflect.Value) {
|
|
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
e.e.EncodeUint(uint64(*(*uint16)(v.ptr)))
|
|
}
|
|
|
|
func (e *Encoder) kUint32(f *codecFnInfo, rv reflect.Value) {
|
|
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
e.e.EncodeUint(uint64(*(*uint32)(v.ptr)))
|
|
}
|
|
|
|
func (e *Encoder) kUint64(f *codecFnInfo, rv reflect.Value) {
|
|
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
e.e.EncodeUint(uint64(*(*uint64)(v.ptr)))
|
|
}
|
|
|
|
func (e *Encoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
|
|
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
e.e.EncodeUint(uint64(*(*uintptr)(v.ptr)))
|
|
}
|
|
|
|
// ------------
|
|
|
|
// func (d *Decoder) raw(f *codecFnInfo, rv reflect.Value) {
|
|
// urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
// // if urv.flag&unsafeFlagIndir != 0 {
|
|
// // urv.ptr = *(*unsafe.Pointer)(urv.ptr)
|
|
// // }
|
|
// *(*[]byte)(urv.ptr) = d.rawBytes()
|
|
// }
|
|
|
|
// func rv0t(rt reflect.Type) reflect.Value {
|
|
// ut := (*unsafeIntf)(unsafe.Pointer(&rt))
|
|
// // we need to determine whether ifaceIndir, and then whether to just pass 0 as the ptr
|
|
// uv := unsafeReflectValue{ut.word, &zeroRTv, flag(rt.Kind())}
|
|
// return *(*reflect.Value)(unsafe.Pointer(&uv})
|
|
// }
|
|
|
|
// func rv2i(rv reflect.Value) interface{} {
|
|
// urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
// // true references (map, func, chan, ptr - NOT slice) may be double-referenced as flagIndir
|
|
// var ptr unsafe.Pointer
|
|
// // kk := reflect.Kind(urv.flag & (1<<5 - 1))
|
|
// // if (kk == reflect.Map || kk == reflect.Ptr || kk == reflect.Chan || kk == reflect.Func) && urv.flag&unsafeFlagIndir != 0 {
|
|
// if refBitset.isset(byte(urv.flag&(1<<5-1))) && urv.flag&unsafeFlagIndir != 0 {
|
|
// ptr = *(*unsafe.Pointer)(urv.ptr)
|
|
// } else {
|
|
// ptr = urv.ptr
|
|
// }
|
|
// return *(*interface{})(unsafe.Pointer(&unsafeIntf{typ: urv.typ, word: ptr}))
|
|
// // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
|
|
// // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
|
|
// }
|
|
|
|
// func definitelyNil(v interface{}) bool {
|
|
// var ui *unsafeIntf = (*unsafeIntf)(unsafe.Pointer(&v))
|
|
// if ui.word == nil {
|
|
// return true
|
|
// }
|
|
// var tk = reflect.TypeOf(v).Kind()
|
|
// return (tk == reflect.Interface || tk == reflect.Slice) && *(*unsafe.Pointer)(ui.word) == nil
|
|
// fmt.Printf(">>>> definitely nil: isnil: %v, TYPE: \t%T, word: %v, *word: %v, type: %v, nil: %v\n",
|
|
// v == nil, v, word, *((*unsafe.Pointer)(word)), ui.typ, nil)
|
|
// }
|
|
|
|
// func keepAlive4BytesView(v string) {
|
|
// runtime.KeepAlive(v)
|
|
// }
|
|
|
|
// func keepAlive4StringView(v []byte) {
|
|
// runtime.KeepAlive(v)
|
|
// }
|
|
|
|
// func rt2id(rt reflect.Type) uintptr {
|
|
// return uintptr(((*unsafeIntf)(unsafe.Pointer(&rt))).word)
|
|
// // var i interface{} = rt
|
|
// // // ui := (*unsafeIntf)(unsafe.Pointer(&i))
|
|
// // return ((*unsafeIntf)(unsafe.Pointer(&i))).word
|
|
// }
|
|
|
|
// func rv2i(rv reflect.Value) interface{} {
|
|
// urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
// // non-reference type: already indir
|
|
// // reference type: depend on flagIndir property ('cos maybe was double-referenced)
|
|
// // const (unsafeRvFlagKindMask = 1<<5 - 1 , unsafeRvFlagIndir = 1 << 7 )
|
|
// // rvk := reflect.Kind(urv.flag & (1<<5 - 1))
|
|
// // if (rvk == reflect.Chan ||
|
|
// // rvk == reflect.Func ||
|
|
// // rvk == reflect.Interface ||
|
|
// // rvk == reflect.Map ||
|
|
// // rvk == reflect.Ptr ||
|
|
// // rvk == reflect.UnsafePointer) && urv.flag&(1<<8) != 0 {
|
|
// // fmt.Printf(">>>>> ---- double indirect reference: %v, %v\n", rvk, rv.Type())
|
|
// // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
|
|
// // }
|
|
// if urv.flag&(1<<5-1) == uintptr(reflect.Map) && urv.flag&(1<<7) != 0 {
|
|
// // fmt.Printf(">>>>> ---- double indirect reference: %v, %v\n", rvk, rv.Type())
|
|
// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
|
|
// }
|
|
// // fmt.Printf(">>>>> ++++ direct reference: %v, %v\n", rvk, rv.Type())
|
|
// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
|
|
// }
|
|
|
|
// const (
|
|
// unsafeRvFlagKindMask = 1<<5 - 1
|
|
// unsafeRvKindDirectIface = 1 << 5
|
|
// unsafeRvFlagIndir = 1 << 7
|
|
// unsafeRvFlagAddr = 1 << 8
|
|
// unsafeRvFlagMethod = 1 << 9
|
|
|
|
// _USE_RV_INTERFACE bool = false
|
|
// _UNSAFE_RV_DEBUG = true
|
|
// )
|
|
|
|
// type unsafeRtype struct {
|
|
// _ [2]uintptr
|
|
// _ uint32
|
|
// _ uint8
|
|
// _ uint8
|
|
// _ uint8
|
|
// kind uint8
|
|
// _ [2]uintptr
|
|
// _ int32
|
|
// }
|
|
|
|
// func _rv2i(rv reflect.Value) interface{} {
|
|
// // Note: From use,
|
|
// // - it's never an interface
|
|
// // - the only calls here are for ifaceIndir types.
|
|
// // (though that conditional is wrong)
|
|
// // To know for sure, we need the value of t.kind (which is not exposed).
|
|
// //
|
|
// // Need to validate the path: type is indirect ==> only value is indirect ==> default (value is direct)
|
|
// // - Type indirect, Value indirect: ==> numbers, boolean, slice, struct, array, string
|
|
// // - Type Direct, Value indirect: ==> map???
|
|
// // - Type Direct, Value direct: ==> pointers, unsafe.Pointer, func, chan, map
|
|
// //
|
|
// // TRANSLATES TO:
|
|
// // if typeIndirect { } else if valueIndirect { } else { }
|
|
// //
|
|
// // Since we don't deal with funcs, then "flagNethod" is unset, and can be ignored.
|
|
|
|
// if _USE_RV_INTERFACE {
|
|
// return rv.Interface()
|
|
// }
|
|
// urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
|
|
// // if urv.flag&unsafeRvFlagMethod != 0 || urv.flag&unsafeRvFlagKindMask == uintptr(reflect.Interface) {
|
|
// // println("***** IS flag method or interface: delegating to rv.Interface()")
|
|
// // return rv.Interface()
|
|
// // }
|
|
|
|
// // if urv.flag&unsafeRvFlagKindMask == uintptr(reflect.Interface) {
|
|
// // println("***** IS Interface: delegate to rv.Interface")
|
|
// // return rv.Interface()
|
|
// // }
|
|
// // if urv.flag&unsafeRvFlagKindMask&unsafeRvKindDirectIface == 0 {
|
|
// // if urv.flag&unsafeRvFlagAddr == 0 {
|
|
// // println("***** IS ifaceIndir typ")
|
|
// // // ui := unsafeIntf{word: urv.ptr, typ: urv.typ}
|
|
// // // return *(*interface{})(unsafe.Pointer(&ui))
|
|
// // // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
|
|
// // }
|
|
// // } else if urv.flag&unsafeRvFlagIndir != 0 {
|
|
// // println("***** IS flagindir")
|
|
// // // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
|
|
// // } else {
|
|
// // println("***** NOT flagindir")
|
|
// // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
|
|
// // }
|
|
// // println("***** default: delegate to rv.Interface")
|
|
|
|
// urt := (*unsafeRtype)(unsafe.Pointer(urv.typ))
|
|
// if _UNSAFE_RV_DEBUG {
|
|
// fmt.Printf(">>>> start: %v: ", rv.Type())
|
|
// fmt.Printf("%v - %v\n", *urv, *urt)
|
|
// }
|
|
// if urt.kind&unsafeRvKindDirectIface == 0 {
|
|
// if _UNSAFE_RV_DEBUG {
|
|
// fmt.Printf("**** +ifaceIndir type: %v\n", rv.Type())
|
|
// }
|
|
// // println("***** IS ifaceIndir typ")
|
|
// // if true || urv.flag&unsafeRvFlagAddr == 0 {
|
|
// // // println(" ***** IS NOT addr")
|
|
// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
|
|
// // }
|
|
// } else if urv.flag&unsafeRvFlagIndir != 0 {
|
|
// if _UNSAFE_RV_DEBUG {
|
|
// fmt.Printf("**** +flagIndir type: %v\n", rv.Type())
|
|
// }
|
|
// // println("***** IS flagindir")
|
|
// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
|
|
// } else {
|
|
// if _UNSAFE_RV_DEBUG {
|
|
// fmt.Printf("**** -flagIndir type: %v\n", rv.Type())
|
|
// }
|
|
// // println("***** NOT flagindir")
|
|
// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
|
|
// }
|
|
// // println("***** default: delegating to rv.Interface()")
|
|
// // return rv.Interface()
|
|
// }
|
|
|
|
// var staticM0 = make(map[string]uint64)
|
|
// var staticI0 = (int32)(-5)
|
|
|
|
// func staticRv2iTest() {
|
|
// i0 := (int32)(-5)
|
|
// m0 := make(map[string]uint16)
|
|
// m0["1"] = 1
|
|
// for _, i := range []interface{}{
|
|
// (int)(7),
|
|
// (uint)(8),
|
|
// (int16)(-9),
|
|
// (uint16)(19),
|
|
// (uintptr)(77),
|
|
// (bool)(true),
|
|
// float32(-32.7),
|
|
// float64(64.9),
|
|
// complex(float32(19), 5),
|
|
// complex(float64(-32), 7),
|
|
// [4]uint64{1, 2, 3, 4},
|
|
// (chan<- int)(nil), // chan,
|
|
// rv2i, // func
|
|
// io.Writer(ioutil.Discard),
|
|
// make(map[string]uint),
|
|
// (map[string]uint)(nil),
|
|
// staticM0,
|
|
// m0,
|
|
// &m0,
|
|
// i0,
|
|
// &i0,
|
|
// &staticI0,
|
|
// &staticM0,
|
|
// []uint32{6, 7, 8},
|
|
// "abc",
|
|
// Raw{},
|
|
// RawExt{},
|
|
// &Raw{},
|
|
// &RawExt{},
|
|
// unsafe.Pointer(&i0),
|
|
// } {
|
|
// i2 := rv2i(reflect.ValueOf(i))
|
|
// eq := reflect.DeepEqual(i, i2)
|
|
// fmt.Printf(">>>> %v == %v? %v\n", i, i2, eq)
|
|
// }
|
|
// // os.Exit(0)
|
|
// }
|
|
|
|
// func init() {
|
|
// staticRv2iTest()
|
|
// }
|
|
|
|
// func rv2i(rv reflect.Value) interface{} {
|
|
// if _USE_RV_INTERFACE || rv.Kind() == reflect.Interface || rv.CanAddr() {
|
|
// return rv.Interface()
|
|
// }
|
|
// // var i interface{}
|
|
// // ui := (*unsafeIntf)(unsafe.Pointer(&i))
|
|
// var ui unsafeIntf
|
|
// urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
// // fmt.Printf("urv: flag: %b, typ: %b, ptr: %b\n", urv.flag, uintptr(urv.typ), uintptr(urv.ptr))
|
|
// if (urv.flag&unsafeRvFlagKindMask)&unsafeRvKindDirectIface == 0 {
|
|
// if urv.flag&unsafeRvFlagAddr != 0 {
|
|
// println("***** indirect and addressable! Needs typed move - delegate to rv.Interface()")
|
|
// return rv.Interface()
|
|
// }
|
|
// println("****** indirect type/kind")
|
|
// ui.word = urv.ptr
|
|
// } else if urv.flag&unsafeRvFlagIndir != 0 {
|
|
// println("****** unsafe rv flag indir")
|
|
// ui.word = *(*unsafe.Pointer)(urv.ptr)
|
|
// } else {
|
|
// println("****** default: assign prt to word directly")
|
|
// ui.word = urv.ptr
|
|
// }
|
|
// // ui.word = urv.ptr
|
|
// ui.typ = urv.typ
|
|
// // fmt.Printf("(pointers) ui.typ: %p, word: %p\n", ui.typ, ui.word)
|
|
// // fmt.Printf("(binary) ui.typ: %b, word: %b\n", uintptr(ui.typ), uintptr(ui.word))
|
|
// return *(*interface{})(unsafe.Pointer(&ui))
|
|
// // return i
|
|
// }
|