github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/not-internal/reflectlite/value.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package reflectlite 6 7 import ( 8 "runtime" 9 "unsafe" 10 ) 11 12 const ptrSize = 4 << (^uintptr(0) >> 63) // unsafe.Sizeof(uintptr(0)) but an ideal const 13 14 // Value is the reflection interface to a Go value. 15 // 16 // Not all methods apply to all kinds of values. Restrictions, 17 // if any, are noted in the documentation for each method. 18 // Use the Kind method to find out the kind of value before 19 // calling kind-specific methods. Calling a method 20 // inappropriate to the kind of type causes a run time panic. 21 // 22 // The zero Value represents no value. 23 // Its IsValid method returns false, its Kind method returns Invalid, 24 // its String method returns "<invalid Value>", and all other methods panic. 25 // Most functions and methods never return an invalid value. 26 // If one does, its documentation states the conditions explicitly. 27 // 28 // A Value can be used concurrently by multiple goroutines provided that 29 // the underlying Go value can be used concurrently for the equivalent 30 // direct operations. 31 // 32 // To compare two Values, compare the results of the Interface method. 33 // Using == on two Values does not compare the underlying values 34 // they represent. 35 type Value struct { 36 // typ holds the type of the value represented by a Value. 37 typ *rtype 38 39 // Pointer-valued data or, if flagIndir is set, pointer to data. 40 // Valid when either flagIndir is set or typ.pointers() is true. 41 ptr unsafe.Pointer 42 43 // flag holds metadata about the value. 44 // The lowest bits are flag bits: 45 // - flagStickyRO: obtained via unexported not embedded field, so read-only 46 // - flagEmbedRO: obtained via unexported embedded field, so read-only 47 // - flagIndir: val holds a pointer to the data 48 // - flagAddr: v.CanAddr is true (implies flagIndir) 49 // Value cannot represent method values. 50 // The next five bits give the Kind of the value. 51 // This repeats typ.Kind() except for method values. 52 // The remaining 23+ bits give a method number for method values. 53 // If flag.kind() != Func, code can assume that flagMethod is unset. 54 // If ifaceIndir(typ), code can assume that flagIndir is set. 55 flag 56 57 // A method value represents a curried method invocation 58 // like r.Read for some receiver r. The typ+val+flag bits describe 59 // the receiver r, but the flag's Kind bits say Func (methods are 60 // functions), and the top bits of the flag give the method number 61 // in r's type's method table. 62 } 63 64 type flag uintptr 65 66 const ( 67 flagKindWidth = 5 // there are 27 kinds 68 flagKindMask flag = 1<<flagKindWidth - 1 69 flagStickyRO flag = 1 << 5 70 flagEmbedRO flag = 1 << 6 71 flagIndir flag = 1 << 7 72 flagAddr flag = 1 << 8 73 flagMethod flag = 1 << 9 74 flagMethodShift = 10 75 flagRO flag = flagStickyRO | flagEmbedRO 76 ) 77 78 func (f flag) kind() Kind { 79 return Kind(f & flagKindMask) 80 } 81 82 func (f flag) ro() flag { 83 if f&flagRO != 0 { 84 return flagStickyRO 85 } 86 return 0 87 } 88 89 // pointer returns the underlying pointer represented by v. 90 // v.Kind() must be Ptr, Map, Chan, Func, or UnsafePointer 91 func (v Value) pointer() unsafe.Pointer { 92 if v.typ.size != ptrSize || !v.typ.pointers() { 93 panic("can't call pointer on a non-pointer Value") 94 } 95 if v.flag&flagIndir != 0 { 96 return *(*unsafe.Pointer)(v.ptr) 97 } 98 return v.ptr 99 } 100 101 // packEface converts v to the empty interface. 102 func packEface(v Value) interface{} { 103 t := v.typ 104 var i interface{} 105 e := (*emptyInterface)(unsafe.Pointer(&i)) 106 // First, fill in the data portion of the interface. 107 switch { 108 case ifaceIndir(t): 109 if v.flag&flagIndir == 0 { 110 panic("bad indir") 111 } 112 // Value is indirect, and so is the interface we're making. 113 ptr := v.ptr 114 if v.flag&flagAddr != 0 { 115 // TODO: pass safe boolean from valueInterface so 116 // we don't need to copy if safe==true? 117 c := unsafe_New(t) 118 typedmemmove(t, c, ptr) 119 ptr = c 120 } 121 e.word = ptr 122 case v.flag&flagIndir != 0: 123 // Value is indirect, but interface is direct. We need 124 // to load the data at v.ptr into the interface data word. 125 e.word = *(*unsafe.Pointer)(v.ptr) 126 default: 127 // Value is direct, and so is the interface. 128 e.word = v.ptr 129 } 130 // Now, fill in the type portion. We're very careful here not 131 // to have any operation between the e.word and e.typ assignments 132 // that would let the garbage collector observe the partially-built 133 // interface value. 134 e.typ = t 135 return i 136 } 137 138 // unpackEface converts the empty interface i to a Value. 139 func unpackEface(i interface{}) Value { 140 e := (*emptyInterface)(unsafe.Pointer(&i)) 141 // NOTE: don't read e.word until we know whether it is really a pointer or not. 142 t := e.typ 143 if t == nil { 144 return Value{} 145 } 146 f := flag(t.Kind()) 147 if ifaceIndir(t) { 148 f |= flagIndir 149 } 150 return Value{t, e.word, f} 151 } 152 153 // A ValueError occurs when a Value method is invoked on 154 // a Value that does not support it. Such cases are documented 155 // in the description of each method. 156 type ValueError struct { 157 Method string 158 Kind Kind 159 } 160 161 func (e *ValueError) Error() string { 162 return "reflect: call of " + e.Method + " on zero Value" 163 } 164 165 // methodName returns the name of the calling method, 166 // assumed to be two stack frames above. 167 func methodName() string { 168 pc, _, _, _ := runtime.Caller(2) 169 f := runtime.FuncForPC(pc) 170 if f == nil { 171 return "unknown method" 172 } 173 return f.Name() 174 } 175 176 // emptyInterface is the header for an interface{} value. 177 type emptyInterface struct { 178 typ *rtype 179 word unsafe.Pointer 180 } 181 182 // mustBeExported panics if f records that the value was obtained using 183 // an unexported field. 184 func (f flag) mustBeExported() { 185 if f == 0 { 186 panic(&ValueError{methodName(), 0}) 187 } 188 if f&flagRO != 0 { 189 panic("reflect: " + methodName() + " using value obtained using unexported field") 190 } 191 } 192 193 // mustBeAssignable panics if f records that the value is not assignable, 194 // which is to say that either it was obtained using an unexported field 195 // or it is not addressable. 196 func (f flag) mustBeAssignable() { 197 if f == 0 { 198 panic(&ValueError{methodName(), Invalid}) 199 } 200 // Assignable if addressable and not read-only. 201 if f&flagRO != 0 { 202 panic("reflect: " + methodName() + " using value obtained using unexported field") 203 } 204 if f&flagAddr == 0 { 205 panic("reflect: " + methodName() + " using unaddressable value") 206 } 207 } 208 209 // CanSet reports whether the value of v can be changed. 210 // A Value can be changed only if it is addressable and was not 211 // obtained by the use of unexported struct fields. 212 // If CanSet returns false, calling Set or any type-specific 213 // setter (e.g., SetBool, SetInt) will panic. 214 func (v Value) CanSet() bool { 215 return v.flag&(flagAddr|flagRO) == flagAddr 216 } 217 218 // Elem returns the value that the interface v contains 219 // or that the pointer v points to. 220 // It panics if v's Kind is not Interface or Ptr. 221 // It returns the zero Value if v is nil. 222 func (v Value) Elem() Value { 223 k := v.kind() 224 switch k { 225 case Interface: 226 var eface interface{} 227 if v.typ.NumMethod() == 0 { 228 eface = *(*interface{})(v.ptr) 229 } else { 230 eface = (interface{})(*(*interface { 231 M() 232 })(v.ptr)) 233 } 234 x := unpackEface(eface) 235 if x.flag != 0 { 236 x.flag |= v.flag.ro() 237 } 238 return x 239 case Ptr: 240 ptr := v.ptr 241 if v.flag&flagIndir != 0 { 242 ptr = *(*unsafe.Pointer)(ptr) 243 } 244 // The returned value's address is v's value. 245 if ptr == nil { 246 return Value{} 247 } 248 tt := (*ptrType)(unsafe.Pointer(v.typ)) 249 typ := tt.elem 250 fl := v.flag&flagRO | flagIndir | flagAddr 251 fl |= flag(typ.Kind()) 252 return Value{typ, ptr, fl} 253 } 254 panic(&ValueError{"reflectlite.Value.Elem", v.kind()}) 255 } 256 257 func valueInterface(v Value) interface{} { 258 if v.flag == 0 { 259 panic(&ValueError{"reflectlite.Value.Interface", 0}) 260 } 261 262 if v.kind() == Interface { 263 // Special case: return the element inside the interface. 264 // Empty interface has one layout, all interfaces with 265 // methods have a second layout. 266 if v.numMethod() == 0 { 267 return *(*interface{})(v.ptr) 268 } 269 return *(*interface { 270 M() 271 })(v.ptr) 272 } 273 274 // TODO: pass safe to packEface so we don't need to copy if safe==true? 275 return packEface(v) 276 } 277 278 // IsNil reports whether its argument v is nil. The argument must be 279 // a chan, func, interface, map, pointer, or slice value; if it is 280 // not, IsNil panics. Note that IsNil is not always equivalent to a 281 // regular comparison with nil in Go. For example, if v was created 282 // by calling ValueOf with an uninitialized interface variable i, 283 // i==nil will be true but v.IsNil will panic as v will be the zero 284 // Value. 285 func (v Value) IsNil() bool { 286 k := v.kind() 287 switch k { 288 case Chan, Func, Map, Ptr, UnsafePointer: 289 // if v.flag&flagMethod != 0 { 290 // return false 291 // } 292 ptr := v.ptr 293 if v.flag&flagIndir != 0 { 294 ptr = *(*unsafe.Pointer)(ptr) 295 } 296 return ptr == nil 297 case Interface, Slice: 298 // Both interface and slice are nil if first word is 0. 299 // Both are always bigger than a word; assume flagIndir. 300 return *(*unsafe.Pointer)(v.ptr) == nil 301 } 302 panic(&ValueError{"reflectlite.Value.IsNil", v.kind()}) 303 } 304 305 // IsValid reports whether v represents a value. 306 // It returns false if v is the zero Value. 307 // If IsValid returns false, all other methods except String panic. 308 // Most functions and methods never return an invalid Value. 309 // If one does, its documentation states the conditions explicitly. 310 func (v Value) IsValid() bool { 311 return v.flag != 0 312 } 313 314 // Kind returns v's Kind. 315 // If v is the zero Value (IsValid returns false), Kind returns Invalid. 316 func (v Value) Kind() Kind { 317 return v.kind() 318 } 319 320 // implemented in runtime: 321 func chanlen(unsafe.Pointer) int 322 func maplen(unsafe.Pointer) int 323 324 // Len returns v's length. 325 // It panics if v's Kind is not Array, Chan, Map, Slice, or String. 326 func (v Value) Len() int { 327 k := v.kind() 328 switch k { 329 case Array: 330 tt := (*arrayType)(unsafe.Pointer(v.typ)) 331 return int(tt.len) 332 case Chan: 333 return chanlen(v.pointer()) 334 case Map: 335 return maplen(v.pointer()) 336 case Slice: 337 // Slice is bigger than a word; assume flagIndir. 338 return (*sliceHeader)(v.ptr).Len 339 case String: 340 // String is bigger than a word; assume flagIndir. 341 return (*stringHeader)(v.ptr).Len 342 } 343 panic(&ValueError{"reflect.Value.Len", v.kind()}) 344 } 345 346 // NumMethod returns the number of exported methods in the value's method set. 347 func (v Value) numMethod() int { 348 if v.typ == nil { 349 panic(&ValueError{"reflectlite.Value.NumMethod", Invalid}) 350 } 351 return v.typ.NumMethod() 352 } 353 354 // Set assigns x to the value v. 355 // It panics if CanSet returns false. 356 // As in Go, x's value must be assignable to v's type. 357 func (v Value) Set(x Value) { 358 v.mustBeAssignable() 359 x.mustBeExported() // do not let unexported x leak 360 var target unsafe.Pointer 361 if v.kind() == Interface { 362 target = v.ptr 363 } 364 x = x.assignTo("reflectlite.Set", v.typ, target) 365 if x.flag&flagIndir != 0 { 366 typedmemmove(v.typ, v.ptr, x.ptr) 367 } else { 368 *(*unsafe.Pointer)(v.ptr) = x.ptr 369 } 370 } 371 372 // Type returns v's type. 373 func (v Value) Type() Type { 374 f := v.flag 375 if f == 0 { 376 panic(&ValueError{"reflectlite.Value.Type", Invalid}) 377 } 378 // Method values not supported. 379 return v.typ 380 } 381 382 // stringHeader is a safe version of StringHeader used within this package. 383 type stringHeader struct { 384 Data unsafe.Pointer 385 Len int 386 } 387 388 // sliceHeader is a safe version of SliceHeader used within this package. 389 type sliceHeader struct { 390 Data unsafe.Pointer 391 Len int 392 Cap int 393 } 394 395 /* 396 * constructors 397 */ 398 399 // implemented in package runtime 400 func unsafe_New(*rtype) unsafe.Pointer 401 402 // ValueOf returns a new Value initialized to the concrete value 403 // stored in the interface i. ValueOf(nil) returns the zero Value. 404 func ValueOf(i interface{}) Value { 405 if i == nil { 406 return Value{} 407 } 408 409 // TODO: Maybe allow contents of a Value to live on the stack. 410 // For now we make the contents always escape to the heap. It 411 // makes life easier in a few places (see chanrecv/mapassign 412 // comment below). 413 escapes(i) 414 415 return unpackEface(i) 416 } 417 418 // assignTo returns a value v that can be assigned directly to typ. 419 // It panics if v is not assignable to typ. 420 // For a conversion to an interface type, target is a suggested scratch space to use. 421 func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value { 422 // if v.flag&flagMethod != 0 { 423 // v = makeMethodValue(context, v) 424 // } 425 426 switch { 427 case directlyAssignable(dst, v.typ): 428 // Overwrite type so that they match. 429 // Same memory layout, so no harm done. 430 fl := v.flag&(flagAddr|flagIndir) | v.flag.ro() 431 fl |= flag(dst.Kind()) 432 return Value{dst, v.ptr, fl} 433 434 case implements(dst, v.typ): 435 if target == nil { 436 target = unsafe_New(dst) 437 } 438 if v.Kind() == Interface && v.IsNil() { 439 // A nil ReadWriter passed to nil Reader is OK, 440 // but using ifaceE2I below will panic. 441 // Avoid the panic by returning a nil dst (e.g., Reader) explicitly. 442 return Value{dst, nil, flag(Interface)} 443 } 444 x := valueInterface(v) 445 if dst.NumMethod() == 0 { 446 *(*interface{})(target) = x 447 } else { 448 ifaceE2I(dst, x, target) 449 } 450 return Value{dst, target, flagIndir | flag(Interface)} 451 } 452 453 // Failed. 454 panic(context + ": value of type " + v.typ.String() + " is not assignable to type " + dst.String()) 455 } 456 457 // arrayAt returns the i-th element of p, 458 // an array whose elements are eltSize bytes wide. 459 // The array pointed at by p must have at least i+1 elements: 460 // it is invalid (but impossible to check here) to pass i >= len, 461 // because then the result will point outside the array. 462 // whySafe must explain why i < len. (Passing "i < len" is fine; 463 // the benefit is to surface this assumption at the call site.) 464 func arrayAt(p unsafe.Pointer, i int, eltSize uintptr, whySafe string) unsafe.Pointer { 465 return add(p, uintptr(i)*eltSize, "i < len") 466 } 467 468 func ifaceE2I(t *rtype, src interface{}, dst unsafe.Pointer) 469 470 // typedmemmove copies a value of type t to dst from src. 471 //go:noescape 472 func typedmemmove(t *rtype, dst, src unsafe.Pointer) 473 474 // Dummy annotation marking that the value x escapes, 475 // for use in cases where the reflect code is so clever that 476 // the compiler cannot follow. 477 func escapes(x interface{}) { 478 if dummy.b { 479 dummy.x = x 480 } 481 } 482 483 var dummy struct { 484 b bool 485 x interface{} 486 }