github.com/goplus/yap@v0.8.1/reflectutil/value.go (about) 1 /* 2 * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package reflectutil 18 19 import ( 20 "reflect" 21 "unsafe" 22 ) 23 24 type flag uintptr 25 26 const ( 27 flagKindWidth = 5 // there are 27 kinds 28 flagKindMask flag = 1<<flagKindWidth - 1 29 flagStickyRO flag = 1 << 5 30 flagEmbedRO flag = 1 << 6 31 flagIndir flag = 1 << 7 32 flagAddr flag = 1 << 8 33 flagMethod flag = 1 << 9 34 flagMethodShift = 10 35 flagRO flag = flagStickyRO | flagEmbedRO 36 ) 37 38 type value struct { 39 // typ_ holds the type of the value represented by a Value. 40 // Access using the typ method to avoid escape of v. 41 typ_ unsafe.Pointer 42 43 // Pointer-valued data or, if flagIndir is set, pointer to data. 44 // Valid when either flagIndir is set or typ.pointers() is true. 45 ptr unsafe.Pointer 46 47 // flag holds metadata about the value. 48 // 49 // The lowest five bits give the Kind of the value, mirroring typ.Kind(). 50 // 51 // The next set of bits are flag bits: 52 // - flagStickyRO: obtained via unexported not embedded field, so read-only 53 // - flagEmbedRO: obtained via unexported embedded field, so read-only 54 // - flagIndir: val holds a pointer to the data 55 // - flagAddr: v.CanAddr is true (implies flagIndir and ptr is non-nil) 56 // - flagMethod: v is a method value. 57 // If ifaceIndir(typ), code can assume that flagIndir is set. 58 // 59 // The remaining 22+ bits give a method number for method values. 60 // If flag.kind() != Func, code can assume that flagMethod is unset. 61 flag 62 63 // A method value represents a curried method invocation 64 // like r.Read for some receiver r. The typ+val+flag bits describe 65 // the receiver r, but the flag's Kind bits say Func (methods are 66 // functions), and the top bits of the flag give the method number 67 // in r's type's method table. 68 } 69 70 func UnsafeAddr(v reflect.Value) uintptr { 71 (*value)(unsafe.Pointer(&v)).flag |= flagAddr 72 return v.UnsafeAddr() 73 }