blob: e3df60abeab215f40f1fee27037bd7bfeffa48bb [file] [log] [blame]
khenaidooffe076b2019-01-15 16:08:08 -05001// +build !safe
2// +build !appengine
3// +build go1.7
4
5// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
6// Use of this source code is governed by a MIT license found in the LICENSE file.
7
8package codec
9
10import (
11 "reflect"
12 "sync/atomic"
13 "time"
14 "unsafe"
15)
16
17// This file has unsafe variants of some helper methods.
18// NOTE: See helper_not_unsafe.go for the usage information.
19
20// var zeroRTv [4]uintptr
21
22const safeMode = false
23const unsafeFlagIndir = 1 << 7 // keep in sync with GO_ROOT/src/reflect/value.go
24
25type unsafeString struct {
26 Data unsafe.Pointer
27 Len int
28}
29
30type unsafeSlice struct {
31 Data unsafe.Pointer
32 Len int
33 Cap int
34}
35
36type unsafeIntf struct {
37 typ unsafe.Pointer
38 word unsafe.Pointer
39}
40
41type unsafeReflectValue struct {
42 typ unsafe.Pointer
43 ptr unsafe.Pointer
44 flag uintptr
45}
46
47func stringView(v []byte) string {
48 if len(v) == 0 {
49 return ""
50 }
51 bx := (*unsafeSlice)(unsafe.Pointer(&v))
52 return *(*string)(unsafe.Pointer(&unsafeString{bx.Data, bx.Len}))
53}
54
55func bytesView(v string) []byte {
56 if len(v) == 0 {
57 return zeroByteSlice
58 }
59 sx := (*unsafeString)(unsafe.Pointer(&v))
60 return *(*[]byte)(unsafe.Pointer(&unsafeSlice{sx.Data, sx.Len, sx.Len}))
61}
62
63func definitelyNil(v interface{}) bool {
64 // There is no global way of checking if an interface is nil.
65 // For true references (map, ptr, func, chan), you can just look
66 // at the word of the interface. However, for slices, you have to dereference
67 // the word, and get a pointer to the 3-word interface value.
68 //
69 // However, the following are cheap calls
70 // - TypeOf(interface): cheap 2-line call.
71 // - ValueOf(interface{}): expensive
72 // - type.Kind: cheap call through an interface
73 // - Value.Type(): cheap call
74 // except it's a method value (e.g. r.Read, which implies that it is a Func)
75
76 return ((*unsafeIntf)(unsafe.Pointer(&v))).word == nil
77}
78
79func rv2i(rv reflect.Value) interface{} {
80 // TODO: consider a more generally-known optimization for reflect.Value ==> Interface
81 //
82 // Currently, we use this fragile method that taps into implememtation details from
83 // the source go stdlib reflect/value.go, and trims the implementation.
84
85 urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
86 // true references (map, func, chan, ptr - NOT slice) may be double-referenced as flagIndir
87 var ptr unsafe.Pointer
88 if refBitset.isset(byte(urv.flag&(1<<5-1))) && urv.flag&unsafeFlagIndir != 0 {
89 ptr = *(*unsafe.Pointer)(urv.ptr)
90 } else {
91 ptr = urv.ptr
92 }
93 return *(*interface{})(unsafe.Pointer(&unsafeIntf{typ: urv.typ, word: ptr}))
94}
95
96func rt2id(rt reflect.Type) uintptr {
97 return uintptr(((*unsafeIntf)(unsafe.Pointer(&rt))).word)
98}
99
100func rv2rtid(rv reflect.Value) uintptr {
101 return uintptr((*unsafeReflectValue)(unsafe.Pointer(&rv)).typ)
102}
103
104func i2rtid(i interface{}) uintptr {
105 return uintptr(((*unsafeIntf)(unsafe.Pointer(&i))).typ)
106}
107
108// --------------------------
109
110func isEmptyValue(v reflect.Value, tinfos *TypeInfos, deref, checkStruct bool) bool {
111 urv := (*unsafeReflectValue)(unsafe.Pointer(&v))
112 if urv.flag == 0 {
113 return true
114 }
115 switch v.Kind() {
116 case reflect.Invalid:
117 return true
118 case reflect.String:
119 return (*unsafeString)(urv.ptr).Len == 0
120 case reflect.Slice:
121 return (*unsafeSlice)(urv.ptr).Len == 0
122 case reflect.Bool:
123 return !*(*bool)(urv.ptr)
124 case reflect.Int:
125 return *(*int)(urv.ptr) == 0
126 case reflect.Int8:
127 return *(*int8)(urv.ptr) == 0
128 case reflect.Int16:
129 return *(*int16)(urv.ptr) == 0
130 case reflect.Int32:
131 return *(*int32)(urv.ptr) == 0
132 case reflect.Int64:
133 return *(*int64)(urv.ptr) == 0
134 case reflect.Uint:
135 return *(*uint)(urv.ptr) == 0
136 case reflect.Uint8:
137 return *(*uint8)(urv.ptr) == 0
138 case reflect.Uint16:
139 return *(*uint16)(urv.ptr) == 0
140 case reflect.Uint32:
141 return *(*uint32)(urv.ptr) == 0
142 case reflect.Uint64:
143 return *(*uint64)(urv.ptr) == 0
144 case reflect.Uintptr:
145 return *(*uintptr)(urv.ptr) == 0
146 case reflect.Float32:
147 return *(*float32)(urv.ptr) == 0
148 case reflect.Float64:
149 return *(*float64)(urv.ptr) == 0
150 case reflect.Interface:
151 isnil := urv.ptr == nil || *(*unsafe.Pointer)(urv.ptr) == nil
152 if deref {
153 if isnil {
154 return true
155 }
156 return isEmptyValue(v.Elem(), tinfos, deref, checkStruct)
157 }
158 return isnil
159 case reflect.Ptr:
160 // isnil := urv.ptr == nil (not sufficient, as a pointer value encodes the type)
161 isnil := urv.ptr == nil || *(*unsafe.Pointer)(urv.ptr) == nil
162 if deref {
163 if isnil {
164 return true
165 }
166 return isEmptyValue(v.Elem(), tinfos, deref, checkStruct)
167 }
168 return isnil
169 case reflect.Struct:
170 return isEmptyStruct(v, tinfos, deref, checkStruct)
171 case reflect.Map, reflect.Array, reflect.Chan:
172 return v.Len() == 0
173 }
174 return false
175}
176
177// --------------------------
178
179// atomicTypeInfoSlice contains length and pointer to the array for a slice.
180// It is expected to be 2 words.
181//
182// Previously, we atomically loaded and stored the length and array pointer separately,
183// which could lead to some races.
184// We now just atomically store and load the pointer to the value directly.
185
186type atomicTypeInfoSlice struct { // expected to be 2 words
187 l int // length of the data array (must be first in struct, for 64-bit alignment necessary for 386)
188 v unsafe.Pointer // data array - Pointer (not uintptr) to maintain GC reference
189}
190
191func (x *atomicTypeInfoSlice) load() []rtid2ti {
192 xp := unsafe.Pointer(x)
193 x2 := *(*atomicTypeInfoSlice)(atomic.LoadPointer(&xp))
194 if x2.l == 0 {
195 return nil
196 }
197 return *(*[]rtid2ti)(unsafe.Pointer(&unsafeSlice{Data: x2.v, Len: x2.l, Cap: x2.l}))
198}
199
200func (x *atomicTypeInfoSlice) store(p []rtid2ti) {
201 s := (*unsafeSlice)(unsafe.Pointer(&p))
202 xp := unsafe.Pointer(x)
203 atomic.StorePointer(&xp, unsafe.Pointer(&atomicTypeInfoSlice{l: s.Len, v: s.Data}))
204}
205
206// --------------------------
207func (d *Decoder) raw(f *codecFnInfo, rv reflect.Value) {
208 urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
209 *(*[]byte)(urv.ptr) = d.rawBytes()
210}
211
212func (d *Decoder) kString(f *codecFnInfo, rv reflect.Value) {
213 urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
214 *(*string)(urv.ptr) = d.d.DecodeString()
215}
216
217func (d *Decoder) kBool(f *codecFnInfo, rv reflect.Value) {
218 urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
219 *(*bool)(urv.ptr) = d.d.DecodeBool()
220}
221
222func (d *Decoder) kTime(f *codecFnInfo, rv reflect.Value) {
223 urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
224 *(*time.Time)(urv.ptr) = d.d.DecodeTime()
225}
226
227func (d *Decoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
228 fv := d.d.DecodeFloat64()
229 if chkOvf.Float32(fv) {
230 d.errorf("float32 overflow: %v", fv)
231 }
232 urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
233 *(*float32)(urv.ptr) = float32(fv)
234}
235
236func (d *Decoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
237 urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
238 *(*float64)(urv.ptr) = d.d.DecodeFloat64()
239}
240
241func (d *Decoder) kInt(f *codecFnInfo, rv reflect.Value) {
242 urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
243 *(*int)(urv.ptr) = int(chkOvf.IntV(d.d.DecodeInt64(), intBitsize))
244}
245
246func (d *Decoder) kInt8(f *codecFnInfo, rv reflect.Value) {
247 urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
248 *(*int8)(urv.ptr) = int8(chkOvf.IntV(d.d.DecodeInt64(), 8))
249}
250
251func (d *Decoder) kInt16(f *codecFnInfo, rv reflect.Value) {
252 urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
253 *(*int16)(urv.ptr) = int16(chkOvf.IntV(d.d.DecodeInt64(), 16))
254}
255
256func (d *Decoder) kInt32(f *codecFnInfo, rv reflect.Value) {
257 urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
258 *(*int32)(urv.ptr) = int32(chkOvf.IntV(d.d.DecodeInt64(), 32))
259}
260
261func (d *Decoder) kInt64(f *codecFnInfo, rv reflect.Value) {
262 urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
263 *(*int64)(urv.ptr) = d.d.DecodeInt64()
264}
265
266func (d *Decoder) kUint(f *codecFnInfo, rv reflect.Value) {
267 urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
268 *(*uint)(urv.ptr) = uint(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))
269}
270
271func (d *Decoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
272 urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
273 *(*uintptr)(urv.ptr) = uintptr(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))
274}
275
276func (d *Decoder) kUint8(f *codecFnInfo, rv reflect.Value) {
277 urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
278 *(*uint8)(urv.ptr) = uint8(chkOvf.UintV(d.d.DecodeUint64(), 8))
279}
280
281func (d *Decoder) kUint16(f *codecFnInfo, rv reflect.Value) {
282 urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
283 *(*uint16)(urv.ptr) = uint16(chkOvf.UintV(d.d.DecodeUint64(), 16))
284}
285
286func (d *Decoder) kUint32(f *codecFnInfo, rv reflect.Value) {
287 urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
288 *(*uint32)(urv.ptr) = uint32(chkOvf.UintV(d.d.DecodeUint64(), 32))
289}
290
291func (d *Decoder) kUint64(f *codecFnInfo, rv reflect.Value) {
292 urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
293 *(*uint64)(urv.ptr) = d.d.DecodeUint64()
294}
295
296// ------------
297
298func (e *Encoder) kBool(f *codecFnInfo, rv reflect.Value) {
299 v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
300 e.e.EncodeBool(*(*bool)(v.ptr))
301}
302
303func (e *Encoder) kTime(f *codecFnInfo, rv reflect.Value) {
304 v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
305 e.e.EncodeTime(*(*time.Time)(v.ptr))
306}
307
308func (e *Encoder) kString(f *codecFnInfo, rv reflect.Value) {
309 v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
310 e.e.EncodeString(cUTF8, *(*string)(v.ptr))
311}
312
313func (e *Encoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
314 v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
315 e.e.EncodeFloat64(*(*float64)(v.ptr))
316}
317
318func (e *Encoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
319 v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
320 e.e.EncodeFloat32(*(*float32)(v.ptr))
321}
322
323func (e *Encoder) kInt(f *codecFnInfo, rv reflect.Value) {
324 v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
325 e.e.EncodeInt(int64(*(*int)(v.ptr)))
326}
327
328func (e *Encoder) kInt8(f *codecFnInfo, rv reflect.Value) {
329 v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
330 e.e.EncodeInt(int64(*(*int8)(v.ptr)))
331}
332
333func (e *Encoder) kInt16(f *codecFnInfo, rv reflect.Value) {
334 v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
335 e.e.EncodeInt(int64(*(*int16)(v.ptr)))
336}
337
338func (e *Encoder) kInt32(f *codecFnInfo, rv reflect.Value) {
339 v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
340 e.e.EncodeInt(int64(*(*int32)(v.ptr)))
341}
342
343func (e *Encoder) kInt64(f *codecFnInfo, rv reflect.Value) {
344 v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
345 e.e.EncodeInt(int64(*(*int64)(v.ptr)))
346}
347
348func (e *Encoder) kUint(f *codecFnInfo, rv reflect.Value) {
349 v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
350 e.e.EncodeUint(uint64(*(*uint)(v.ptr)))
351}
352
353func (e *Encoder) kUint8(f *codecFnInfo, rv reflect.Value) {
354 v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
355 e.e.EncodeUint(uint64(*(*uint8)(v.ptr)))
356}
357
358func (e *Encoder) kUint16(f *codecFnInfo, rv reflect.Value) {
359 v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
360 e.e.EncodeUint(uint64(*(*uint16)(v.ptr)))
361}
362
363func (e *Encoder) kUint32(f *codecFnInfo, rv reflect.Value) {
364 v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
365 e.e.EncodeUint(uint64(*(*uint32)(v.ptr)))
366}
367
368func (e *Encoder) kUint64(f *codecFnInfo, rv reflect.Value) {
369 v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
370 e.e.EncodeUint(uint64(*(*uint64)(v.ptr)))
371}
372
373func (e *Encoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
374 v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
375 e.e.EncodeUint(uint64(*(*uintptr)(v.ptr)))
376}
377
378// ------------
379
380// func (d *Decoder) raw(f *codecFnInfo, rv reflect.Value) {
381// urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
382// // if urv.flag&unsafeFlagIndir != 0 {
383// // urv.ptr = *(*unsafe.Pointer)(urv.ptr)
384// // }
385// *(*[]byte)(urv.ptr) = d.rawBytes()
386// }
387
388// func rv0t(rt reflect.Type) reflect.Value {
389// ut := (*unsafeIntf)(unsafe.Pointer(&rt))
390// // we need to determine whether ifaceIndir, and then whether to just pass 0 as the ptr
391// uv := unsafeReflectValue{ut.word, &zeroRTv, flag(rt.Kind())}
392// return *(*reflect.Value)(unsafe.Pointer(&uv})
393// }
394
395// func rv2i(rv reflect.Value) interface{} {
396// urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
397// // true references (map, func, chan, ptr - NOT slice) may be double-referenced as flagIndir
398// var ptr unsafe.Pointer
399// // kk := reflect.Kind(urv.flag & (1<<5 - 1))
400// // if (kk == reflect.Map || kk == reflect.Ptr || kk == reflect.Chan || kk == reflect.Func) && urv.flag&unsafeFlagIndir != 0 {
401// if refBitset.isset(byte(urv.flag&(1<<5-1))) && urv.flag&unsafeFlagIndir != 0 {
402// ptr = *(*unsafe.Pointer)(urv.ptr)
403// } else {
404// ptr = urv.ptr
405// }
406// return *(*interface{})(unsafe.Pointer(&unsafeIntf{typ: urv.typ, word: ptr}))
407// // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
408// // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
409// }
410
411// func definitelyNil(v interface{}) bool {
412// var ui *unsafeIntf = (*unsafeIntf)(unsafe.Pointer(&v))
413// if ui.word == nil {
414// return true
415// }
416// var tk = reflect.TypeOf(v).Kind()
417// return (tk == reflect.Interface || tk == reflect.Slice) && *(*unsafe.Pointer)(ui.word) == nil
418// fmt.Printf(">>>> definitely nil: isnil: %v, TYPE: \t%T, word: %v, *word: %v, type: %v, nil: %v\n",
419// v == nil, v, word, *((*unsafe.Pointer)(word)), ui.typ, nil)
420// }
421
422// func keepAlive4BytesView(v string) {
423// runtime.KeepAlive(v)
424// }
425
426// func keepAlive4StringView(v []byte) {
427// runtime.KeepAlive(v)
428// }
429
430// func rt2id(rt reflect.Type) uintptr {
431// return uintptr(((*unsafeIntf)(unsafe.Pointer(&rt))).word)
432// // var i interface{} = rt
433// // // ui := (*unsafeIntf)(unsafe.Pointer(&i))
434// // return ((*unsafeIntf)(unsafe.Pointer(&i))).word
435// }
436
437// func rv2i(rv reflect.Value) interface{} {
438// urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
439// // non-reference type: already indir
440// // reference type: depend on flagIndir property ('cos maybe was double-referenced)
441// // const (unsafeRvFlagKindMask = 1<<5 - 1 , unsafeRvFlagIndir = 1 << 7 )
442// // rvk := reflect.Kind(urv.flag & (1<<5 - 1))
443// // if (rvk == reflect.Chan ||
444// // rvk == reflect.Func ||
445// // rvk == reflect.Interface ||
446// // rvk == reflect.Map ||
447// // rvk == reflect.Ptr ||
448// // rvk == reflect.UnsafePointer) && urv.flag&(1<<8) != 0 {
449// // fmt.Printf(">>>>> ---- double indirect reference: %v, %v\n", rvk, rv.Type())
450// // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
451// // }
452// if urv.flag&(1<<5-1) == uintptr(reflect.Map) && urv.flag&(1<<7) != 0 {
453// // fmt.Printf(">>>>> ---- double indirect reference: %v, %v\n", rvk, rv.Type())
454// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
455// }
456// // fmt.Printf(">>>>> ++++ direct reference: %v, %v\n", rvk, rv.Type())
457// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
458// }
459
460// const (
461// unsafeRvFlagKindMask = 1<<5 - 1
462// unsafeRvKindDirectIface = 1 << 5
463// unsafeRvFlagIndir = 1 << 7
464// unsafeRvFlagAddr = 1 << 8
465// unsafeRvFlagMethod = 1 << 9
466
467// _USE_RV_INTERFACE bool = false
468// _UNSAFE_RV_DEBUG = true
469// )
470
471// type unsafeRtype struct {
472// _ [2]uintptr
473// _ uint32
474// _ uint8
475// _ uint8
476// _ uint8
477// kind uint8
478// _ [2]uintptr
479// _ int32
480// }
481
482// func _rv2i(rv reflect.Value) interface{} {
483// // Note: From use,
484// // - it's never an interface
485// // - the only calls here are for ifaceIndir types.
486// // (though that conditional is wrong)
487// // To know for sure, we need the value of t.kind (which is not exposed).
488// //
489// // Need to validate the path: type is indirect ==> only value is indirect ==> default (value is direct)
490// // - Type indirect, Value indirect: ==> numbers, boolean, slice, struct, array, string
491// // - Type Direct, Value indirect: ==> map???
492// // - Type Direct, Value direct: ==> pointers, unsafe.Pointer, func, chan, map
493// //
494// // TRANSLATES TO:
495// // if typeIndirect { } else if valueIndirect { } else { }
496// //
497// // Since we don't deal with funcs, then "flagNethod" is unset, and can be ignored.
498
499// if _USE_RV_INTERFACE {
500// return rv.Interface()
501// }
502// urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
503
504// // if urv.flag&unsafeRvFlagMethod != 0 || urv.flag&unsafeRvFlagKindMask == uintptr(reflect.Interface) {
505// // println("***** IS flag method or interface: delegating to rv.Interface()")
506// // return rv.Interface()
507// // }
508
509// // if urv.flag&unsafeRvFlagKindMask == uintptr(reflect.Interface) {
510// // println("***** IS Interface: delegate to rv.Interface")
511// // return rv.Interface()
512// // }
513// // if urv.flag&unsafeRvFlagKindMask&unsafeRvKindDirectIface == 0 {
514// // if urv.flag&unsafeRvFlagAddr == 0 {
515// // println("***** IS ifaceIndir typ")
516// // // ui := unsafeIntf{word: urv.ptr, typ: urv.typ}
517// // // return *(*interface{})(unsafe.Pointer(&ui))
518// // // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
519// // }
520// // } else if urv.flag&unsafeRvFlagIndir != 0 {
521// // println("***** IS flagindir")
522// // // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
523// // } else {
524// // println("***** NOT flagindir")
525// // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
526// // }
527// // println("***** default: delegate to rv.Interface")
528
529// urt := (*unsafeRtype)(unsafe.Pointer(urv.typ))
530// if _UNSAFE_RV_DEBUG {
531// fmt.Printf(">>>> start: %v: ", rv.Type())
532// fmt.Printf("%v - %v\n", *urv, *urt)
533// }
534// if urt.kind&unsafeRvKindDirectIface == 0 {
535// if _UNSAFE_RV_DEBUG {
536// fmt.Printf("**** +ifaceIndir type: %v\n", rv.Type())
537// }
538// // println("***** IS ifaceIndir typ")
539// // if true || urv.flag&unsafeRvFlagAddr == 0 {
540// // // println(" ***** IS NOT addr")
541// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
542// // }
543// } else if urv.flag&unsafeRvFlagIndir != 0 {
544// if _UNSAFE_RV_DEBUG {
545// fmt.Printf("**** +flagIndir type: %v\n", rv.Type())
546// }
547// // println("***** IS flagindir")
548// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
549// } else {
550// if _UNSAFE_RV_DEBUG {
551// fmt.Printf("**** -flagIndir type: %v\n", rv.Type())
552// }
553// // println("***** NOT flagindir")
554// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
555// }
556// // println("***** default: delegating to rv.Interface()")
557// // return rv.Interface()
558// }
559
560// var staticM0 = make(map[string]uint64)
561// var staticI0 = (int32)(-5)
562
563// func staticRv2iTest() {
564// i0 := (int32)(-5)
565// m0 := make(map[string]uint16)
566// m0["1"] = 1
567// for _, i := range []interface{}{
568// (int)(7),
569// (uint)(8),
570// (int16)(-9),
571// (uint16)(19),
572// (uintptr)(77),
573// (bool)(true),
574// float32(-32.7),
575// float64(64.9),
576// complex(float32(19), 5),
577// complex(float64(-32), 7),
578// [4]uint64{1, 2, 3, 4},
579// (chan<- int)(nil), // chan,
580// rv2i, // func
581// io.Writer(ioutil.Discard),
582// make(map[string]uint),
583// (map[string]uint)(nil),
584// staticM0,
585// m0,
586// &m0,
587// i0,
588// &i0,
589// &staticI0,
590// &staticM0,
591// []uint32{6, 7, 8},
592// "abc",
593// Raw{},
594// RawExt{},
595// &Raw{},
596// &RawExt{},
597// unsafe.Pointer(&i0),
598// } {
599// i2 := rv2i(reflect.ValueOf(i))
600// eq := reflect.DeepEqual(i, i2)
601// fmt.Printf(">>>> %v == %v? %v\n", i, i2, eq)
602// }
603// // os.Exit(0)
604// }
605
606// func init() {
607// staticRv2iTest()
608// }
609
610// func rv2i(rv reflect.Value) interface{} {
611// if _USE_RV_INTERFACE || rv.Kind() == reflect.Interface || rv.CanAddr() {
612// return rv.Interface()
613// }
614// // var i interface{}
615// // ui := (*unsafeIntf)(unsafe.Pointer(&i))
616// var ui unsafeIntf
617// urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
618// // fmt.Printf("urv: flag: %b, typ: %b, ptr: %b\n", urv.flag, uintptr(urv.typ), uintptr(urv.ptr))
619// if (urv.flag&unsafeRvFlagKindMask)&unsafeRvKindDirectIface == 0 {
620// if urv.flag&unsafeRvFlagAddr != 0 {
621// println("***** indirect and addressable! Needs typed move - delegate to rv.Interface()")
622// return rv.Interface()
623// }
624// println("****** indirect type/kind")
625// ui.word = urv.ptr
626// } else if urv.flag&unsafeRvFlagIndir != 0 {
627// println("****** unsafe rv flag indir")
628// ui.word = *(*unsafe.Pointer)(urv.ptr)
629// } else {
630// println("****** default: assign prt to word directly")
631// ui.word = urv.ptr
632// }
633// // ui.word = urv.ptr
634// ui.typ = urv.typ
635// // fmt.Printf("(pointers) ui.typ: %p, word: %p\n", ui.typ, ui.word)
636// // fmt.Printf("(binary) ui.typ: %b, word: %b\n", uintptr(ui.typ), uintptr(ui.word))
637// return *(*interface{})(unsafe.Pointer(&ui))
638// // return i
639// }