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

// --------------------------

// atomicXXX is expected to be 2 words (for symmetry with atomic.Value)
//
// Note that we do not atomically load/store length and data pointer separately,
// as this could lead to some races. Instead, we atomically load/store cappedSlice.
//
// Note: with atomic.(Load|Store)Pointer, we MUST work with an unsafe.Pointer directly.

// ----------------------
type atomicTypeInfoSlice struct {
	v unsafe.Pointer // *[]rtid2ti
	_ uintptr        // padding (atomicXXX expected to be 2 words)
}

func (x *atomicTypeInfoSlice) load() (s []rtid2ti) {
	x2 := atomic.LoadPointer(&x.v)
	if x2 != nil {
		s = *(*[]rtid2ti)(x2)
	}
	return
}

func (x *atomicTypeInfoSlice) store(p []rtid2ti) {
	atomic.StorePointer(&x.v, unsafe.Pointer(&p))
}

// --------------------------
type atomicRtidFnSlice struct {
	v unsafe.Pointer // *[]codecRtidFn
	_ uintptr        // padding (atomicXXX expected to be 2 words)
}

func (x *atomicRtidFnSlice) load() (s []codecRtidFn) {
	x2 := atomic.LoadPointer(&x.v)
	if x2 != nil {
		s = *(*[]codecRtidFn)(x2)
	}
	return
}

func (x *atomicRtidFnSlice) store(p []codecRtidFn) {
	atomic.StorePointer(&x.v, unsafe.Pointer(&p))
}

// --------------------------
type atomicClsErr struct {
	v unsafe.Pointer // *clsErr
	_ uintptr        // padding (atomicXXX expected to be 2 words)
}

func (x *atomicClsErr) load() (e clsErr) {
	x2 := (*clsErr)(atomic.LoadPointer(&x.v))
	if x2 != nil {
		e = *x2
	}
	return
}

func (x *atomicClsErr) store(p clsErr) {
	atomic.StorePointer(&x.v, unsafe.Pointer(&p))
}

// --------------------------

// to create a reflect.Value for each member field of decNaked,
// we first create a global decNaked, and create reflect.Value
// for them all.
// This way, we have the flags and type in the reflect.Value.
// Then, when a reflect.Value is called, we just copy it,
// update the ptr to the decNaked's, and return it.

type unsafeDecNakedWrapper struct {
	decNaked
	ru, ri, rf, rl, rs, rb, rt reflect.Value // mapping to the primitives above
}

func (n *unsafeDecNakedWrapper) init() {
	n.ru = reflect.ValueOf(&n.u).Elem()
	n.ri = reflect.ValueOf(&n.i).Elem()
	n.rf = reflect.ValueOf(&n.f).Elem()
	n.rl = reflect.ValueOf(&n.l).Elem()
	n.rs = reflect.ValueOf(&n.s).Elem()
	n.rt = reflect.ValueOf(&n.t).Elem()
	n.rb = reflect.ValueOf(&n.b).Elem()
	// n.rr[] = reflect.ValueOf(&n.)
}

var defUnsafeDecNakedWrapper unsafeDecNakedWrapper

func init() {
	defUnsafeDecNakedWrapper.init()
}

func (n *decNaked) ru() (v reflect.Value) {
	v = defUnsafeDecNakedWrapper.ru
	((*unsafeReflectValue)(unsafe.Pointer(&v))).ptr = unsafe.Pointer(&n.u)
	return
}
func (n *decNaked) ri() (v reflect.Value) {
	v = defUnsafeDecNakedWrapper.ri
	((*unsafeReflectValue)(unsafe.Pointer(&v))).ptr = unsafe.Pointer(&n.i)
	return
}
func (n *decNaked) rf() (v reflect.Value) {
	v = defUnsafeDecNakedWrapper.rf
	((*unsafeReflectValue)(unsafe.Pointer(&v))).ptr = unsafe.Pointer(&n.f)
	return
}
func (n *decNaked) rl() (v reflect.Value) {
	v = defUnsafeDecNakedWrapper.rl
	((*unsafeReflectValue)(unsafe.Pointer(&v))).ptr = unsafe.Pointer(&n.l)
	return
}
func (n *decNaked) rs() (v reflect.Value) {
	v = defUnsafeDecNakedWrapper.rs
	((*unsafeReflectValue)(unsafe.Pointer(&v))).ptr = unsafe.Pointer(&n.s)
	return
}
func (n *decNaked) rt() (v reflect.Value) {
	v = defUnsafeDecNakedWrapper.rt
	((*unsafeReflectValue)(unsafe.Pointer(&v))).ptr = unsafe.Pointer(&n.t)
	return
}
func (n *decNaked) rb() (v reflect.Value) {
	v = defUnsafeDecNakedWrapper.rb
	((*unsafeReflectValue)(unsafe.Pointer(&v))).ptr = unsafe.Pointer(&n.b)
	return
}

// --------------------------
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))
	s := *(*string)(v.ptr)
	if e.h.StringToRaw {
		e.e.EncodeStringBytesRaw(bytesView(s))
	} else {
		e.e.EncodeStringEnc(cUTF8, s)
	}
}

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