mirror of
https://github.com/mainflux/mainflux.git
synced 2025-04-29 13:49:28 +08:00

* Use normalizer as stream source Renamed 'writer' service to 'normalizer' and dropped Cassandra facilities from it. Extracted the common dependencies to 'mainflux' package for easier sharing. Fixed the API docs and unified environment variables. Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Use docker build arguments to specify build Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Remove cassandra libraries Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Update go-kit version to 0.6.0 Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Fix manager configuration Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Refactor docker-compose Merged individual compose files and dropped external links. Remove CoAP container since it is not referenced from NginX config at the moment. Update port mapping in compose and nginx.conf. Dropped bin scripts. Updated service documentation. Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Drop content-type check Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Implement users data access layer in PostgreSQL Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Bump version to 0.1.0 Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Use go-kit logger everywhere (except CoAP) Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Improve factory methods naming Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Implement clients data access layer on PostgreSQL Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Make tests stateless All tests are refactored to use map-based table-driven tests. No cross-tests dependencies is present anymore. Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Remove gitignore Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Fix nginx proxying Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Mark client-user FK explicit Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Update API documentation Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Update channel model Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Add channel PostgreSQL repository tests Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Implement PostgreSQL channels DAO Replaced update queries with raw SQL. Explicitly defined M2M table due to difficulties of ensuring the referential integrity through GORM. Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Expose connection endpoints Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Fix swagger docs and remove DB logging Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Fix nested query remarks Signed-off-by: Dejan Mijic <dejan@mainflux.com> * Add unique indices Signed-off-by: Dejan Mijic <dejan@mainflux.com>
633 lines
20 KiB
Go
633 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
|
|
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
|
|
}
|
|
|
|
// --------------------------
|
|
|
|
type atomicTypeInfoSlice struct { // expected to be 2 words
|
|
v unsafe.Pointer // data array - Pointer (not uintptr) to maintain GC reference
|
|
l int64 // length of the data array
|
|
}
|
|
|
|
func (x *atomicTypeInfoSlice) load() []rtid2ti {
|
|
l := int(atomic.LoadInt64(&x.l))
|
|
if l == 0 {
|
|
return nil
|
|
}
|
|
return *(*[]rtid2ti)(unsafe.Pointer(&unsafeSlice{Data: atomic.LoadPointer(&x.v), Len: l, Cap: l}))
|
|
// return (*[]rtid2ti)(atomic.LoadPointer(&x.v))
|
|
}
|
|
|
|
func (x *atomicTypeInfoSlice) store(p []rtid2ti) {
|
|
s := (*unsafeSlice)(unsafe.Pointer(&p))
|
|
atomic.StorePointer(&x.v, s.Data)
|
|
atomic.StoreInt64(&x.l, int64(s.Len))
|
|
// atomic.StorePointer(&x.v, unsafe.Pointer(p))
|
|
}
|
|
|
|
// --------------------------
|
|
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
|
|
// }
|