khenaidoo | ffe076b | 2019-01-15 16:08:08 -0500 | [diff] [blame^] | 1 | // +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 | |
| 8 | package codec |
| 9 | |
| 10 | import ( |
| 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 | |
| 22 | const safeMode = false |
| 23 | const unsafeFlagIndir = 1 << 7 // keep in sync with GO_ROOT/src/reflect/value.go |
| 24 | |
| 25 | type unsafeString struct { |
| 26 | Data unsafe.Pointer |
| 27 | Len int |
| 28 | } |
| 29 | |
| 30 | type unsafeSlice struct { |
| 31 | Data unsafe.Pointer |
| 32 | Len int |
| 33 | Cap int |
| 34 | } |
| 35 | |
| 36 | type unsafeIntf struct { |
| 37 | typ unsafe.Pointer |
| 38 | word unsafe.Pointer |
| 39 | } |
| 40 | |
| 41 | type unsafeReflectValue struct { |
| 42 | typ unsafe.Pointer |
| 43 | ptr unsafe.Pointer |
| 44 | flag uintptr |
| 45 | } |
| 46 | |
| 47 | func 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 | |
| 55 | func 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 | |
| 63 | func 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 | |
| 79 | func 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 | |
| 96 | func rt2id(rt reflect.Type) uintptr { |
| 97 | return uintptr(((*unsafeIntf)(unsafe.Pointer(&rt))).word) |
| 98 | } |
| 99 | |
| 100 | func rv2rtid(rv reflect.Value) uintptr { |
| 101 | return uintptr((*unsafeReflectValue)(unsafe.Pointer(&rv)).typ) |
| 102 | } |
| 103 | |
| 104 | func i2rtid(i interface{}) uintptr { |
| 105 | return uintptr(((*unsafeIntf)(unsafe.Pointer(&i))).typ) |
| 106 | } |
| 107 | |
| 108 | // -------------------------- |
| 109 | |
| 110 | func 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 | |
| 186 | type 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 | |
| 191 | func (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 | |
| 200 | func (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 | // -------------------------- |
| 207 | func (d *Decoder) raw(f *codecFnInfo, rv reflect.Value) { |
| 208 | urv := (*unsafeReflectValue)(unsafe.Pointer(&rv)) |
| 209 | *(*[]byte)(urv.ptr) = d.rawBytes() |
| 210 | } |
| 211 | |
| 212 | func (d *Decoder) kString(f *codecFnInfo, rv reflect.Value) { |
| 213 | urv := (*unsafeReflectValue)(unsafe.Pointer(&rv)) |
| 214 | *(*string)(urv.ptr) = d.d.DecodeString() |
| 215 | } |
| 216 | |
| 217 | func (d *Decoder) kBool(f *codecFnInfo, rv reflect.Value) { |
| 218 | urv := (*unsafeReflectValue)(unsafe.Pointer(&rv)) |
| 219 | *(*bool)(urv.ptr) = d.d.DecodeBool() |
| 220 | } |
| 221 | |
| 222 | func (d *Decoder) kTime(f *codecFnInfo, rv reflect.Value) { |
| 223 | urv := (*unsafeReflectValue)(unsafe.Pointer(&rv)) |
| 224 | *(*time.Time)(urv.ptr) = d.d.DecodeTime() |
| 225 | } |
| 226 | |
| 227 | func (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 | |
| 236 | func (d *Decoder) kFloat64(f *codecFnInfo, rv reflect.Value) { |
| 237 | urv := (*unsafeReflectValue)(unsafe.Pointer(&rv)) |
| 238 | *(*float64)(urv.ptr) = d.d.DecodeFloat64() |
| 239 | } |
| 240 | |
| 241 | func (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 | |
| 246 | func (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 | |
| 251 | func (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 | |
| 256 | func (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 | |
| 261 | func (d *Decoder) kInt64(f *codecFnInfo, rv reflect.Value) { |
| 262 | urv := (*unsafeReflectValue)(unsafe.Pointer(&rv)) |
| 263 | *(*int64)(urv.ptr) = d.d.DecodeInt64() |
| 264 | } |
| 265 | |
| 266 | func (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 | |
| 271 | func (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 | |
| 276 | func (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 | |
| 281 | func (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 | |
| 286 | func (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 | |
| 291 | func (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 | |
| 298 | func (e *Encoder) kBool(f *codecFnInfo, rv reflect.Value) { |
| 299 | v := (*unsafeReflectValue)(unsafe.Pointer(&rv)) |
| 300 | e.e.EncodeBool(*(*bool)(v.ptr)) |
| 301 | } |
| 302 | |
| 303 | func (e *Encoder) kTime(f *codecFnInfo, rv reflect.Value) { |
| 304 | v := (*unsafeReflectValue)(unsafe.Pointer(&rv)) |
| 305 | e.e.EncodeTime(*(*time.Time)(v.ptr)) |
| 306 | } |
| 307 | |
| 308 | func (e *Encoder) kString(f *codecFnInfo, rv reflect.Value) { |
| 309 | v := (*unsafeReflectValue)(unsafe.Pointer(&rv)) |
| 310 | e.e.EncodeString(cUTF8, *(*string)(v.ptr)) |
| 311 | } |
| 312 | |
| 313 | func (e *Encoder) kFloat64(f *codecFnInfo, rv reflect.Value) { |
| 314 | v := (*unsafeReflectValue)(unsafe.Pointer(&rv)) |
| 315 | e.e.EncodeFloat64(*(*float64)(v.ptr)) |
| 316 | } |
| 317 | |
| 318 | func (e *Encoder) kFloat32(f *codecFnInfo, rv reflect.Value) { |
| 319 | v := (*unsafeReflectValue)(unsafe.Pointer(&rv)) |
| 320 | e.e.EncodeFloat32(*(*float32)(v.ptr)) |
| 321 | } |
| 322 | |
| 323 | func (e *Encoder) kInt(f *codecFnInfo, rv reflect.Value) { |
| 324 | v := (*unsafeReflectValue)(unsafe.Pointer(&rv)) |
| 325 | e.e.EncodeInt(int64(*(*int)(v.ptr))) |
| 326 | } |
| 327 | |
| 328 | func (e *Encoder) kInt8(f *codecFnInfo, rv reflect.Value) { |
| 329 | v := (*unsafeReflectValue)(unsafe.Pointer(&rv)) |
| 330 | e.e.EncodeInt(int64(*(*int8)(v.ptr))) |
| 331 | } |
| 332 | |
| 333 | func (e *Encoder) kInt16(f *codecFnInfo, rv reflect.Value) { |
| 334 | v := (*unsafeReflectValue)(unsafe.Pointer(&rv)) |
| 335 | e.e.EncodeInt(int64(*(*int16)(v.ptr))) |
| 336 | } |
| 337 | |
| 338 | func (e *Encoder) kInt32(f *codecFnInfo, rv reflect.Value) { |
| 339 | v := (*unsafeReflectValue)(unsafe.Pointer(&rv)) |
| 340 | e.e.EncodeInt(int64(*(*int32)(v.ptr))) |
| 341 | } |
| 342 | |
| 343 | func (e *Encoder) kInt64(f *codecFnInfo, rv reflect.Value) { |
| 344 | v := (*unsafeReflectValue)(unsafe.Pointer(&rv)) |
| 345 | e.e.EncodeInt(int64(*(*int64)(v.ptr))) |
| 346 | } |
| 347 | |
| 348 | func (e *Encoder) kUint(f *codecFnInfo, rv reflect.Value) { |
| 349 | v := (*unsafeReflectValue)(unsafe.Pointer(&rv)) |
| 350 | e.e.EncodeUint(uint64(*(*uint)(v.ptr))) |
| 351 | } |
| 352 | |
| 353 | func (e *Encoder) kUint8(f *codecFnInfo, rv reflect.Value) { |
| 354 | v := (*unsafeReflectValue)(unsafe.Pointer(&rv)) |
| 355 | e.e.EncodeUint(uint64(*(*uint8)(v.ptr))) |
| 356 | } |
| 357 | |
| 358 | func (e *Encoder) kUint16(f *codecFnInfo, rv reflect.Value) { |
| 359 | v := (*unsafeReflectValue)(unsafe.Pointer(&rv)) |
| 360 | e.e.EncodeUint(uint64(*(*uint16)(v.ptr))) |
| 361 | } |
| 362 | |
| 363 | func (e *Encoder) kUint32(f *codecFnInfo, rv reflect.Value) { |
| 364 | v := (*unsafeReflectValue)(unsafe.Pointer(&rv)) |
| 365 | e.e.EncodeUint(uint64(*(*uint32)(v.ptr))) |
| 366 | } |
| 367 | |
| 368 | func (e *Encoder) kUint64(f *codecFnInfo, rv reflect.Value) { |
| 369 | v := (*unsafeReflectValue)(unsafe.Pointer(&rv)) |
| 370 | e.e.EncodeUint(uint64(*(*uint64)(v.ptr))) |
| 371 | } |
| 372 | |
| 373 | func (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 | // } |