Source file
src/reflect/value.go
Documentation: reflect
package reflect
import (
"math"
"runtime"
"unsafe"
)
const ptrSize = 4 << (^uintptr(0) >> 63)
type Value struct {
typ *rtype
ptr unsafe.Pointer
flag
}
type flag uintptr
const (
flagKindWidth = 5
flagKindMask flag = 1<<flagKindWidth - 1
flagStickyRO flag = 1 << 5
flagEmbedRO flag = 1 << 6
flagIndir flag = 1 << 7
flagAddr flag = 1 << 8
flagMethod flag = 1 << 9
flagMethodShift = 10
flagRO flag = flagStickyRO | flagEmbedRO
)
func (f flag) kind() Kind {
return Kind(f & flagKindMask)
}
func (f flag) ro() flag {
if f&flagRO != 0 {
return flagStickyRO
}
return 0
}
func (v Value) pointer() unsafe.Pointer {
if v.typ.size != ptrSize || !v.typ.pointers() {
panic("can't call pointer on a non-pointer Value")
}
if v.flag&flagIndir != 0 {
return *(*unsafe.Pointer)(v.ptr)
}
return v.ptr
}
func packEface(v Value) interface{} {
t := v.typ
var i interface{}
e := (*emptyInterface)(unsafe.Pointer(&i))
switch {
case ifaceIndir(t):
if v.flag&flagIndir == 0 {
panic("bad indir")
}
ptr := v.ptr
if v.flag&flagAddr != 0 {
c := unsafe_New(t)
typedmemmove(t, c, ptr)
ptr = c
}
e.word = ptr
case v.flag&flagIndir != 0:
e.word = *(*unsafe.Pointer)(v.ptr)
default:
e.word = v.ptr
}
e.typ = t
return i
}
func unpackEface(i interface{}) Value {
e := (*emptyInterface)(unsafe.Pointer(&i))
t := e.typ
if t == nil {
return Value{}
}
f := flag(t.Kind())
if ifaceIndir(t) {
f |= flagIndir
}
return Value{t, e.word, f}
}
type ValueError struct {
Method string
Kind Kind
}
func (e *ValueError) Error() string {
if e.Kind == 0 {
return "reflect: call of " + e.Method + " on zero Value"
}
return "reflect: call of " + e.Method + " on " + e.Kind.String() + " Value"
}
func methodName() string {
pc, _, _, _ := runtime.Caller(2)
f := runtime.FuncForPC(pc)
if f == nil {
return "unknown method"
}
return f.Name()
}
type emptyInterface struct {
typ *rtype
word unsafe.Pointer
}
type nonEmptyInterface struct {
itab *struct {
ityp *rtype
typ *rtype
hash uint32
_ [4]byte
fun [100000]unsafe.Pointer
}
word unsafe.Pointer
}
func (f flag) mustBe(expected Kind) {
if f.kind() != expected {
panic(&ValueError{methodName(), f.kind()})
}
}
func (f flag) mustBeExported() {
if f == 0 {
panic(&ValueError{methodName(), 0})
}
if f&flagRO != 0 {
panic("reflect: " + methodName() + " using value obtained using unexported field")
}
}
func (f flag) mustBeAssignable() {
if f == 0 {
panic(&ValueError{methodName(), Invalid})
}
if f&flagRO != 0 {
panic("reflect: " + methodName() + " using value obtained using unexported field")
}
if f&flagAddr == 0 {
panic("reflect: " + methodName() + " using unaddressable value")
}
}
func (v Value) Addr() Value {
if v.flag&flagAddr == 0 {
panic("reflect.Value.Addr of unaddressable value")
}
return Value{v.typ.ptrTo(), v.ptr, v.flag.ro() | flag(Ptr)}
}
func (v Value) Bool() bool {
v.mustBe(Bool)
return *(*bool)(v.ptr)
}
func (v Value) Bytes() []byte {
v.mustBe(Slice)
if v.typ.Elem().Kind() != Uint8 {
panic("reflect.Value.Bytes of non-byte slice")
}
return *(*[]byte)(v.ptr)
}
func (v Value) runes() []rune {
v.mustBe(Slice)
if v.typ.Elem().Kind() != Int32 {
panic("reflect.Value.Bytes of non-rune slice")
}
return *(*[]rune)(v.ptr)
}
func (v Value) CanAddr() bool {
return v.flag&flagAddr != 0
}
func (v Value) CanSet() bool {
return v.flag&(flagAddr|flagRO) == flagAddr
}
func (v Value) Call(in []Value) []Value {
v.mustBe(Func)
v.mustBeExported()
return v.call("Call", in)
}
func (v Value) CallSlice(in []Value) []Value {
v.mustBe(Func)
v.mustBeExported()
return v.call("CallSlice", in)
}
var callGC bool
func (v Value) call(op string, in []Value) []Value {
t := v.typ
var (
fn unsafe.Pointer
rcvr Value
rcvrtype *rtype
)
if v.flag&flagMethod != 0 {
rcvr = v
rcvrtype, t, fn = methodReceiver(op, v, int(v.flag)>>flagMethodShift)
} else if v.flag&flagIndir != 0 {
fn = *(*unsafe.Pointer)(v.ptr)
} else {
fn = v.ptr
}
if fn == nil {
panic("reflect.Value.Call: call of nil function")
}
isSlice := op == "CallSlice"
n := t.NumIn()
if isSlice {
if !t.IsVariadic() {
panic("reflect: CallSlice of non-variadic function")
}
if len(in) < n {
panic("reflect: CallSlice with too few input arguments")
}
if len(in) > n {
panic("reflect: CallSlice with too many input arguments")
}
} else {
if t.IsVariadic() {
n--
}
if len(in) < n {
panic("reflect: Call with too few input arguments")
}
if !t.IsVariadic() && len(in) > n {
panic("reflect: Call with too many input arguments")
}
}
for _, x := range in {
if x.Kind() == Invalid {
panic("reflect: " + op + " using zero Value argument")
}
}
for i := 0; i < n; i++ {
if xt, targ := in[i].Type(), t.In(i); !xt.AssignableTo(targ) {
panic("reflect: " + op + " using " + xt.String() + " as type " + targ.String())
}
}
if !isSlice && t.IsVariadic() {
m := len(in) - n
slice := MakeSlice(t.In(n), m, m)
elem := t.In(n).Elem()
for i := 0; i < m; i++ {
x := in[n+i]
if xt := x.Type(); !xt.AssignableTo(elem) {
panic("reflect: cannot use " + xt.String() + " as type " + elem.String() + " in " + op)
}
slice.Index(i).Set(x)
}
origIn := in
in = make([]Value, n+1)
copy(in[:n], origIn)
in[n] = slice
}
nin := len(in)
if nin != t.NumIn() {
panic("reflect.Value.Call: wrong argument count")
}
nout := t.NumOut()
frametype, _, retOffset, _, framePool := funcLayout(t, rcvrtype)
var args unsafe.Pointer
if nout == 0 {
args = framePool.Get().(unsafe.Pointer)
} else {
args = unsafe_New(frametype)
}
off := uintptr(0)
if rcvrtype != nil {
storeRcvr(rcvr, args)
off = ptrSize
}
for i, v := range in {
v.mustBeExported()
targ := t.In(i).(*rtype)
a := uintptr(targ.align)
off = (off + a - 1) &^ (a - 1)
n := targ.size
if n == 0 {
v.assignTo("reflect.Value.Call", targ, nil)
continue
}
addr := add(args, off, "n > 0")
v = v.assignTo("reflect.Value.Call", targ, addr)
if v.flag&flagIndir != 0 {
typedmemmove(targ, addr, v.ptr)
} else {
*(*unsafe.Pointer)(addr) = v.ptr
}
off += n
}
call(frametype, fn, args, uint32(frametype.size), uint32(retOffset))
if callGC {
runtime.GC()
}
var ret []Value
if nout == 0 {
memclrNoHeapPointers(args, frametype.size)
framePool.Put(args)
} else {
memclrNoHeapPointers(args, retOffset)
ret = make([]Value, nout)
off = retOffset
for i := 0; i < nout; i++ {
tv := t.Out(i)
a := uintptr(tv.Align())
off = (off + a - 1) &^ (a - 1)
if tv.Size() != 0 {
fl := flagIndir | flag(tv.Kind())
ret[i] = Value{tv.common(), add(args, off, "tv.Size() != 0"), fl}
} else {
ret[i] = Zero(tv)
}
off += tv.Size()
}
}
return ret
}
func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer) {
ftyp := ctxt.typ
f := ctxt.fn
ptr := frame
off := uintptr(0)
in := make([]Value, 0, int(ftyp.inCount))
for _, typ := range ftyp.in() {
off += -off & uintptr(typ.align-1)
v := Value{typ, nil, flag(typ.Kind())}
if ifaceIndir(typ) {
v.ptr = unsafe_New(typ)
if typ.size > 0 {
typedmemmove(typ, v.ptr, add(ptr, off, "typ.size > 0"))
}
v.flag |= flagIndir
} else {
v.ptr = *(*unsafe.Pointer)(add(ptr, off, "1-ptr"))
}
in = append(in, v)
off += typ.size
}
out := f(in)
numOut := ftyp.NumOut()
if len(out) != numOut {
panic("reflect: wrong return count from function created by MakeFunc")
}
if numOut > 0 {
off += -off & (ptrSize - 1)
if runtime.GOARCH == "amd64p32" {
off = align(off, 8)
}
for i, typ := range ftyp.out() {
v := out[i]
if v.typ != typ {
panic("reflect: function created by MakeFunc using " + funcName(f) +
" returned wrong type: have " +
out[i].typ.String() + " for " + typ.String())
}
if v.flag&flagRO != 0 {
panic("reflect: function created by MakeFunc using " + funcName(f) +
" returned value obtained from unexported field")
}
off += -off & uintptr(typ.align-1)
if typ.size == 0 {
continue
}
addr := add(ptr, off, "typ.size > 0")
if v.flag&flagIndir != 0 {
typedmemmove(typ, addr, v.ptr)
} else {
*(*unsafe.Pointer)(addr) = v.ptr
}
off += typ.size
}
}
runtime.KeepAlive(ctxt)
}
func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn unsafe.Pointer) {
i := methodIndex
if v.typ.Kind() == Interface {
tt := (*interfaceType)(unsafe.Pointer(v.typ))
if uint(i) >= uint(len(tt.methods)) {
panic("reflect: internal error: invalid method index")
}
m := &tt.methods[i]
if !tt.nameOff(m.name).isExported() {
panic("reflect: " + op + " of unexported method")
}
iface := (*nonEmptyInterface)(v.ptr)
if iface.itab == nil {
panic("reflect: " + op + " of method on nil interface value")
}
rcvrtype = iface.itab.typ
fn = unsafe.Pointer(&iface.itab.fun[i])
t = tt.typeOff(m.typ)
} else {
rcvrtype = v.typ
ms := v.typ.exportedMethods()
if uint(i) >= uint(len(ms)) {
panic("reflect: internal error: invalid method index")
}
m := ms[i]
if !v.typ.nameOff(m.name).isExported() {
panic("reflect: " + op + " of unexported method")
}
ifn := v.typ.textOff(m.ifn)
fn = unsafe.Pointer(&ifn)
t = v.typ.typeOff(m.mtyp)
}
return
}
func storeRcvr(v Value, p unsafe.Pointer) {
t := v.typ
if t.Kind() == Interface {
iface := (*nonEmptyInterface)(v.ptr)
*(*unsafe.Pointer)(p) = iface.word
} else if v.flag&flagIndir != 0 && !ifaceIndir(t) {
*(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(v.ptr)
} else {
*(*unsafe.Pointer)(p) = v.ptr
}
}
func align(x, n uintptr) uintptr {
return (x + n - 1) &^ (n - 1)
}
func callMethod(ctxt *methodValue, frame unsafe.Pointer) {
rcvr := ctxt.rcvr
rcvrtype, t, fn := methodReceiver("call", rcvr, ctxt.method)
frametype, argSize, retOffset, _, framePool := funcLayout(t, rcvrtype)
args := framePool.Get().(unsafe.Pointer)
storeRcvr(rcvr, args)
if argSize-ptrSize > 0 {
typedmemmovepartial(frametype, add(args, ptrSize, "argSize > ptrSize"), frame, ptrSize, argSize-ptrSize)
}
call(frametype, fn, args, uint32(frametype.size), uint32(retOffset))
if frametype.size-retOffset > 0 {
callerRetOffset := retOffset - ptrSize
if runtime.GOARCH == "amd64p32" {
callerRetOffset = align(argSize-ptrSize, 8)
}
typedmemmovepartial(frametype,
add(frame, callerRetOffset, "frametype.size > retOffset"),
add(args, retOffset, "frametype.size > retOffset"),
retOffset,
frametype.size-retOffset)
}
memclrNoHeapPointers(args, frametype.size)
framePool.Put(args)
runtime.KeepAlive(ctxt)
}
func funcName(f func([]Value) []Value) string {
pc := *(*uintptr)(unsafe.Pointer(&f))
rf := runtime.FuncForPC(pc)
if rf != nil {
return rf.Name()
}
return "closure"
}
func (v Value) Cap() int {
k := v.kind()
switch k {
case Array:
return v.typ.Len()
case Chan:
return chancap(v.pointer())
case Slice:
return (*sliceHeader)(v.ptr).Cap
}
panic(&ValueError{"reflect.Value.Cap", v.kind()})
}
func (v Value) Close() {
v.mustBe(Chan)
v.mustBeExported()
chanclose(v.pointer())
}
func (v Value) Complex() complex128 {
k := v.kind()
switch k {
case Complex64:
return complex128(*(*complex64)(v.ptr))
case Complex128:
return *(*complex128)(v.ptr)
}
panic(&ValueError{"reflect.Value.Complex", v.kind()})
}
func (v Value) Elem() Value {
k := v.kind()
switch k {
case Interface:
var eface interface{}
if v.typ.NumMethod() == 0 {
eface = *(*interface{})(v.ptr)
} else {
eface = (interface{})(*(*interface {
M()
})(v.ptr))
}
x := unpackEface(eface)
if x.flag != 0 {
x.flag |= v.flag.ro()
}
return x
case Ptr:
ptr := v.ptr
if v.flag&flagIndir != 0 {
ptr = *(*unsafe.Pointer)(ptr)
}
if ptr == nil {
return Value{}
}
tt := (*ptrType)(unsafe.Pointer(v.typ))
typ := tt.elem
fl := v.flag&flagRO | flagIndir | flagAddr
fl |= flag(typ.Kind())
return Value{typ, ptr, fl}
}
panic(&ValueError{"reflect.Value.Elem", v.kind()})
}
func (v Value) Field(i int) Value {
if v.kind() != Struct {
panic(&ValueError{"reflect.Value.Field", v.kind()})
}
tt := (*structType)(unsafe.Pointer(v.typ))
if uint(i) >= uint(len(tt.fields)) {
panic("reflect: Field index out of range")
}
field := &tt.fields[i]
typ := field.typ
fl := v.flag&(flagStickyRO|flagIndir|flagAddr) | flag(typ.Kind())
if !field.name.isExported() {
if field.anon() {
fl |= flagEmbedRO
} else {
fl |= flagStickyRO
}
}
ptr := add(v.ptr, field.offset(), "same as non-reflect &v.field")
return Value{typ, ptr, fl}
}
func (v Value) FieldByIndex(index []int) Value {
if len(index) == 1 {
return v.Field(index[0])
}
v.mustBe(Struct)
for i, x := range index {
if i > 0 {
if v.Kind() == Ptr && v.typ.Elem().Kind() == Struct {
if v.IsNil() {
panic("reflect: indirection through nil pointer to embedded struct")
}
v = v.Elem()
}
}
v = v.Field(x)
}
return v
}
func (v Value) FieldByName(name string) Value {
v.mustBe(Struct)
if f, ok := v.typ.FieldByName(name); ok {
return v.FieldByIndex(f.Index)
}
return Value{}
}
func (v Value) FieldByNameFunc(match func(string) bool) Value {
if f, ok := v.typ.FieldByNameFunc(match); ok {
return v.FieldByIndex(f.Index)
}
return Value{}
}
func (v Value) Float() float64 {
k := v.kind()
switch k {
case Float32:
return float64(*(*float32)(v.ptr))
case Float64:
return *(*float64)(v.ptr)
}
panic(&ValueError{"reflect.Value.Float", v.kind()})
}
var uint8Type = TypeOf(uint8(0)).(*rtype)
func (v Value) Index(i int) Value {
switch v.kind() {
case Array:
tt := (*arrayType)(unsafe.Pointer(v.typ))
if uint(i) >= uint(tt.len) {
panic("reflect: array index out of range")
}
typ := tt.elem
offset := uintptr(i) * typ.size
val := add(v.ptr, offset, "same as &v[i], i < tt.len")
fl := v.flag&(flagIndir|flagAddr) | v.flag.ro() | flag(typ.Kind())
return Value{typ, val, fl}
case Slice:
s := (*sliceHeader)(v.ptr)
if uint(i) >= uint(s.Len) {
panic("reflect: slice index out of range")
}
tt := (*sliceType)(unsafe.Pointer(v.typ))
typ := tt.elem
val := arrayAt(s.Data, i, typ.size, "i < s.Len")
fl := flagAddr | flagIndir | v.flag.ro() | flag(typ.Kind())
return Value{typ, val, fl}
case String:
s := (*stringHeader)(v.ptr)
if uint(i) >= uint(s.Len) {
panic("reflect: string index out of range")
}
p := arrayAt(s.Data, i, 1, "i < s.Len")
fl := v.flag.ro() | flag(Uint8) | flagIndir
return Value{uint8Type, p, fl}
}
panic(&ValueError{"reflect.Value.Index", v.kind()})
}
func (v Value) Int() int64 {
k := v.kind()
p := v.ptr
switch k {
case Int:
return int64(*(*int)(p))
case Int8:
return int64(*(*int8)(p))
case Int16:
return int64(*(*int16)(p))
case Int32:
return int64(*(*int32)(p))
case Int64:
return *(*int64)(p)
}
panic(&ValueError{"reflect.Value.Int", v.kind()})
}
func (v Value) CanInterface() bool {
if v.flag == 0 {
panic(&ValueError{"reflect.Value.CanInterface", Invalid})
}
return v.flag&flagRO == 0
}
func (v Value) Interface() (i interface{}) {
return valueInterface(v, true)
}
func valueInterface(v Value, safe bool) interface{} {
if v.flag == 0 {
panic(&ValueError{"reflect.Value.Interface", 0})
}
if safe && v.flag&flagRO != 0 {
panic("reflect.Value.Interface: cannot return value obtained from unexported field or method")
}
if v.flag&flagMethod != 0 {
v = makeMethodValue("Interface", v)
}
if v.kind() == Interface {
if v.NumMethod() == 0 {
return *(*interface{})(v.ptr)
}
return *(*interface {
M()
})(v.ptr)
}
return packEface(v)
}
func (v Value) InterfaceData() [2]uintptr {
v.mustBe(Interface)
return *(*[2]uintptr)(v.ptr)
}
func (v Value) IsNil() bool {
k := v.kind()
switch k {
case Chan, Func, Map, Ptr:
if v.flag&flagMethod != 0 {
return false
}
ptr := v.ptr
if v.flag&flagIndir != 0 {
ptr = *(*unsafe.Pointer)(ptr)
}
return ptr == nil
case Interface, Slice:
return *(*unsafe.Pointer)(v.ptr) == nil
}
panic(&ValueError{"reflect.Value.IsNil", v.kind()})
}
func (v Value) IsValid() bool {
return v.flag != 0
}
func (v Value) Kind() Kind {
return v.kind()
}
func (v Value) Len() int {
k := v.kind()
switch k {
case Array:
tt := (*arrayType)(unsafe.Pointer(v.typ))
return int(tt.len)
case Chan:
return chanlen(v.pointer())
case Map:
return maplen(v.pointer())
case Slice:
return (*sliceHeader)(v.ptr).Len
case String:
return (*stringHeader)(v.ptr).Len
}
panic(&ValueError{"reflect.Value.Len", v.kind()})
}
func (v Value) MapIndex(key Value) Value {
v.mustBe(Map)
tt := (*mapType)(unsafe.Pointer(v.typ))
key = key.assignTo("reflect.Value.MapIndex", tt.key, nil)
var k unsafe.Pointer
if key.flag&flagIndir != 0 {
k = key.ptr
} else {
k = unsafe.Pointer(&key.ptr)
}
e := mapaccess(v.typ, v.pointer(), k)
if e == nil {
return Value{}
}
typ := tt.elem
fl := (v.flag | key.flag).ro()
fl |= flag(typ.Kind())
if !ifaceIndir(typ) {
return Value{typ, *(*unsafe.Pointer)(e), fl}
}
c := unsafe_New(typ)
typedmemmove(typ, c, e)
return Value{typ, c, fl | flagIndir}
}
func (v Value) MapKeys() []Value {
v.mustBe(Map)
tt := (*mapType)(unsafe.Pointer(v.typ))
keyType := tt.key
fl := v.flag.ro() | flag(keyType.Kind())
m := v.pointer()
mlen := int(0)
if m != nil {
mlen = maplen(m)
}
it := mapiterinit(v.typ, m)
a := make([]Value, mlen)
var i int
for i = 0; i < len(a); i++ {
key := mapiterkey(it)
if key == nil {
break
}
if ifaceIndir(keyType) {
c := unsafe_New(keyType)
typedmemmove(keyType, c, key)
a[i] = Value{keyType, c, fl | flagIndir}
} else {
a[i] = Value{keyType, *(*unsafe.Pointer)(key), fl}
}
mapiternext(it)
}
return a[:i]
}
func (v Value) Method(i int) Value {
if v.typ == nil {
panic(&ValueError{"reflect.Value.Method", Invalid})
}
if v.flag&flagMethod != 0 || uint(i) >= uint(v.typ.NumMethod()) {
panic("reflect: Method index out of range")
}
if v.typ.Kind() == Interface && v.IsNil() {
panic("reflect: Method on nil interface value")
}
fl := v.flag & (flagStickyRO | flagIndir)
fl |= flag(Func)
fl |= flag(i)<<flagMethodShift | flagMethod
return Value{v.typ, v.ptr, fl}
}
func (v Value) NumMethod() int {
if v.typ == nil {
panic(&ValueError{"reflect.Value.NumMethod", Invalid})
}
if v.flag&flagMethod != 0 {
return 0
}
return v.typ.NumMethod()
}
func (v Value) MethodByName(name string) Value {
if v.typ == nil {
panic(&ValueError{"reflect.Value.MethodByName", Invalid})
}
if v.flag&flagMethod != 0 {
return Value{}
}
m, ok := v.typ.MethodByName(name)
if !ok {
return Value{}
}
return v.Method(m.Index)
}
func (v Value) NumField() int {
v.mustBe(Struct)
tt := (*structType)(unsafe.Pointer(v.typ))
return len(tt.fields)
}
func (v Value) OverflowComplex(x complex128) bool {
k := v.kind()
switch k {
case Complex64:
return overflowFloat32(real(x)) || overflowFloat32(imag(x))
case Complex128:
return false
}
panic(&ValueError{"reflect.Value.OverflowComplex", v.kind()})
}
func (v Value) OverflowFloat(x float64) bool {
k := v.kind()
switch k {
case Float32:
return overflowFloat32(x)
case Float64:
return false
}
panic(&ValueError{"reflect.Value.OverflowFloat", v.kind()})
}
func overflowFloat32(x float64) bool {
if x < 0 {
x = -x
}
return math.MaxFloat32 < x && x <= math.MaxFloat64
}
func (v Value) OverflowInt(x int64) bool {
k := v.kind()
switch k {
case Int, Int8, Int16, Int32, Int64:
bitSize := v.typ.size * 8
trunc := (x << (64 - bitSize)) >> (64 - bitSize)
return x != trunc
}
panic(&ValueError{"reflect.Value.OverflowInt", v.kind()})
}
func (v Value) OverflowUint(x uint64) bool {
k := v.kind()
switch k {
case Uint, Uintptr, Uint8, Uint16, Uint32, Uint64:
bitSize := v.typ.size * 8
trunc := (x << (64 - bitSize)) >> (64 - bitSize)
return x != trunc
}
panic(&ValueError{"reflect.Value.OverflowUint", v.kind()})
}
func (v Value) Pointer() uintptr {
k := v.kind()
switch k {
case Chan, Map, Ptr, UnsafePointer:
return uintptr(v.pointer())
case Func:
if v.flag&flagMethod != 0 {
f := methodValueCall
return **(**uintptr)(unsafe.Pointer(&f))
}
p := v.pointer()
if p != nil {
p = *(*unsafe.Pointer)(p)
}
return uintptr(p)
case Slice:
return (*SliceHeader)(v.ptr).Data
}
panic(&ValueError{"reflect.Value.Pointer", v.kind()})
}
func (v Value) Recv() (x Value, ok bool) {
v.mustBe(Chan)
v.mustBeExported()
return v.recv(false)
}
func (v Value) recv(nb bool) (val Value, ok bool) {
tt := (*chanType)(unsafe.Pointer(v.typ))
if ChanDir(tt.dir)&RecvDir == 0 {
panic("reflect: recv on send-only channel")
}
t := tt.elem
val = Value{t, nil, flag(t.Kind())}
var p unsafe.Pointer
if ifaceIndir(t) {
p = unsafe_New(t)
val.ptr = p
val.flag |= flagIndir
} else {
p = unsafe.Pointer(&val.ptr)
}
selected, ok := chanrecv(v.pointer(), nb, p)
if !selected {
val = Value{}
}
return
}
func (v Value) Send(x Value) {
v.mustBe(Chan)
v.mustBeExported()
v.send(x, false)
}
func (v Value) send(x Value, nb bool) (selected bool) {
tt := (*chanType)(unsafe.Pointer(v.typ))
if ChanDir(tt.dir)&SendDir == 0 {
panic("reflect: send on recv-only channel")
}
x.mustBeExported()
x = x.assignTo("reflect.Value.Send", tt.elem, nil)
var p unsafe.Pointer
if x.flag&flagIndir != 0 {
p = x.ptr
} else {
p = unsafe.Pointer(&x.ptr)
}
return chansend(v.pointer(), p, nb)
}
func (v Value) Set(x Value) {
v.mustBeAssignable()
x.mustBeExported()
var target unsafe.Pointer
if v.kind() == Interface {
target = v.ptr
}
x = x.assignTo("reflect.Set", v.typ, target)
if x.flag&flagIndir != 0 {
typedmemmove(v.typ, v.ptr, x.ptr)
} else {
*(*unsafe.Pointer)(v.ptr) = x.ptr
}
}
func (v Value) SetBool(x bool) {
v.mustBeAssignable()
v.mustBe(Bool)
*(*bool)(v.ptr) = x
}
func (v Value) SetBytes(x []byte) {
v.mustBeAssignable()
v.mustBe(Slice)
if v.typ.Elem().Kind() != Uint8 {
panic("reflect.Value.SetBytes of non-byte slice")
}
*(*[]byte)(v.ptr) = x
}
func (v Value) setRunes(x []rune) {
v.mustBeAssignable()
v.mustBe(Slice)
if v.typ.Elem().Kind() != Int32 {
panic("reflect.Value.setRunes of non-rune slice")
}
*(*[]rune)(v.ptr) = x
}
func (v Value) SetComplex(x complex128) {
v.mustBeAssignable()
switch k := v.kind(); k {
default:
panic(&ValueError{"reflect.Value.SetComplex", v.kind()})
case Complex64:
*(*complex64)(v.ptr) = complex64(x)
case Complex128:
*(*complex128)(v.ptr) = x
}
}
func (v Value) SetFloat(x float64) {
v.mustBeAssignable()
switch k := v.kind(); k {
default:
panic(&ValueError{"reflect.Value.SetFloat", v.kind()})
case Float32:
*(*float32)(v.ptr) = float32(x)
case Float64:
*(*float64)(v.ptr) = x
}
}
func (v Value) SetInt(x int64) {
v.mustBeAssignable()
switch k := v.kind(); k {
default:
panic(&ValueError{"reflect.Value.SetInt", v.kind()})
case Int:
*(*int)(v.ptr) = int(x)
case Int8:
*(*int8)(v.ptr) = int8(x)
case Int16:
*(*int16)(v.ptr) = int16(x)
case Int32:
*(*int32)(v.ptr) = int32(x)
case Int64:
*(*int64)(v.ptr) = x
}
}
func (v Value) SetLen(n int) {
v.mustBeAssignable()
v.mustBe(Slice)
s := (*sliceHeader)(v.ptr)
if uint(n) > uint(s.Cap) {
panic("reflect: slice length out of range in SetLen")
}
s.Len = n
}
func (v Value) SetCap(n int) {
v.mustBeAssignable()
v.mustBe(Slice)
s := (*sliceHeader)(v.ptr)
if n < s.Len || n > s.Cap {
panic("reflect: slice capacity out of range in SetCap")
}
s.Cap = n
}
func (v Value) SetMapIndex(key, val Value) {
v.mustBe(Map)
v.mustBeExported()
key.mustBeExported()
tt := (*mapType)(unsafe.Pointer(v.typ))
key = key.assignTo("reflect.Value.SetMapIndex", tt.key, nil)
var k unsafe.Pointer
if key.flag&flagIndir != 0 {
k = key.ptr
} else {
k = unsafe.Pointer(&key.ptr)
}
if val.typ == nil {
mapdelete(v.typ, v.pointer(), k)
return
}
val.mustBeExported()
val = val.assignTo("reflect.Value.SetMapIndex", tt.elem, nil)
var e unsafe.Pointer
if val.flag&flagIndir != 0 {
e = val.ptr
} else {
e = unsafe.Pointer(&val.ptr)
}
mapassign(v.typ, v.pointer(), k, e)
}
func (v Value) SetUint(x uint64) {
v.mustBeAssignable()
switch k := v.kind(); k {
default:
panic(&ValueError{"reflect.Value.SetUint", v.kind()})
case Uint:
*(*uint)(v.ptr) = uint(x)
case Uint8:
*(*uint8)(v.ptr) = uint8(x)
case Uint16:
*(*uint16)(v.ptr) = uint16(x)
case Uint32:
*(*uint32)(v.ptr) = uint32(x)
case Uint64:
*(*uint64)(v.ptr) = x
case Uintptr:
*(*uintptr)(v.ptr) = uintptr(x)
}
}
func (v Value) SetPointer(x unsafe.Pointer) {
v.mustBeAssignable()
v.mustBe(UnsafePointer)
*(*unsafe.Pointer)(v.ptr) = x
}
func (v Value) SetString(x string) {
v.mustBeAssignable()
v.mustBe(String)
*(*string)(v.ptr) = x
}
func (v Value) Slice(i, j int) Value {
var (
cap int
typ *sliceType
base unsafe.Pointer
)
switch kind := v.kind(); kind {
default:
panic(&ValueError{"reflect.Value.Slice", v.kind()})
case Array:
if v.flag&flagAddr == 0 {
panic("reflect.Value.Slice: slice of unaddressable array")
}
tt := (*arrayType)(unsafe.Pointer(v.typ))
cap = int(tt.len)
typ = (*sliceType)(unsafe.Pointer(tt.slice))
base = v.ptr
case Slice:
typ = (*sliceType)(unsafe.Pointer(v.typ))
s := (*sliceHeader)(v.ptr)
base = s.Data
cap = s.Cap
case String:
s := (*stringHeader)(v.ptr)
if i < 0 || j < i || j > s.Len {
panic("reflect.Value.Slice: string slice index out of bounds")
}
var t stringHeader
if i < s.Len {
t = stringHeader{arrayAt(s.Data, i, 1, "i < s.Len"), j - i}
}
return Value{v.typ, unsafe.Pointer(&t), v.flag}
}
if i < 0 || j < i || j > cap {
panic("reflect.Value.Slice: slice index out of bounds")
}
var x []unsafe.Pointer
s := (*sliceHeader)(unsafe.Pointer(&x))
s.Len = j - i
s.Cap = cap - i
if cap-i > 0 {
s.Data = arrayAt(base, i, typ.elem.Size(), "i < cap")
} else {
s.Data = base
}
fl := v.flag.ro() | flagIndir | flag(Slice)
return Value{typ.common(), unsafe.Pointer(&x), fl}
}
func (v Value) Slice3(i, j, k int) Value {
var (
cap int
typ *sliceType
base unsafe.Pointer
)
switch kind := v.kind(); kind {
default:
panic(&ValueError{"reflect.Value.Slice3", v.kind()})
case Array:
if v.flag&flagAddr == 0 {
panic("reflect.Value.Slice3: slice of unaddressable array")
}
tt := (*arrayType)(unsafe.Pointer(v.typ))
cap = int(tt.len)
typ = (*sliceType)(unsafe.Pointer(tt.slice))
base = v.ptr
case Slice:
typ = (*sliceType)(unsafe.Pointer(v.typ))
s := (*sliceHeader)(v.ptr)
base = s.Data
cap = s.Cap
}
if i < 0 || j < i || k < j || k > cap {
panic("reflect.Value.Slice3: slice index out of bounds")
}
var x []unsafe.Pointer
s := (*sliceHeader)(unsafe.Pointer(&x))
s.Len = j - i
s.Cap = k - i
if k-i > 0 {
s.Data = arrayAt(base, i, typ.elem.Size(), "i < k <= cap")
} else {
s.Data = base
}
fl := v.flag.ro() | flagIndir | flag(Slice)
return Value{typ.common(), unsafe.Pointer(&x), fl}
}
func (v Value) String() string {
switch k := v.kind(); k {
case Invalid:
return "<invalid Value>"
case String:
return *(*string)(v.ptr)
}
return "<" + v.Type().String() + " Value>"
}
func (v Value) TryRecv() (x Value, ok bool) {
v.mustBe(Chan)
v.mustBeExported()
return v.recv(true)
}
func (v Value) TrySend(x Value) bool {
v.mustBe(Chan)
v.mustBeExported()
return v.send(x, true)
}
func (v Value) Type() Type {
f := v.flag
if f == 0 {
panic(&ValueError{"reflect.Value.Type", Invalid})
}
if f&flagMethod == 0 {
return v.typ
}
i := int(v.flag) >> flagMethodShift
if v.typ.Kind() == Interface {
tt := (*interfaceType)(unsafe.Pointer(v.typ))
if uint(i) >= uint(len(tt.methods)) {
panic("reflect: internal error: invalid method index")
}
m := &tt.methods[i]
return v.typ.typeOff(m.typ)
}
ms := v.typ.exportedMethods()
if uint(i) >= uint(len(ms)) {
panic("reflect: internal error: invalid method index")
}
m := ms[i]
return v.typ.typeOff(m.mtyp)
}
func (v Value) Uint() uint64 {
k := v.kind()
p := v.ptr
switch k {
case Uint:
return uint64(*(*uint)(p))
case Uint8:
return uint64(*(*uint8)(p))
case Uint16:
return uint64(*(*uint16)(p))
case Uint32:
return uint64(*(*uint32)(p))
case Uint64:
return *(*uint64)(p)
case Uintptr:
return uint64(*(*uintptr)(p))
}
panic(&ValueError{"reflect.Value.Uint", v.kind()})
}
func (v Value) UnsafeAddr() uintptr {
if v.typ == nil {
panic(&ValueError{"reflect.Value.UnsafeAddr", Invalid})
}
if v.flag&flagAddr == 0 {
panic("reflect.Value.UnsafeAddr of unaddressable value")
}
return uintptr(v.ptr)
}
type StringHeader struct {
Data uintptr
Len int
}
type stringHeader struct {
Data unsafe.Pointer
Len int
}
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
type sliceHeader struct {
Data unsafe.Pointer
Len int
Cap int
}
func typesMustMatch(what string, t1, t2 Type) {
if t1 != t2 {
panic(what + ": " + t1.String() + " != " + t2.String())
}
}
func arrayAt(p unsafe.Pointer, i int, eltSize uintptr, whySafe string) unsafe.Pointer {
return add(p, uintptr(i)*eltSize, "i < len")
}
func grow(s Value, extra int) (Value, int, int) {
i0 := s.Len()
i1 := i0 + extra
if i1 < i0 {
panic("reflect.Append: slice overflow")
}
m := s.Cap()
if i1 <= m {
return s.Slice(0, i1), i0, i1
}
if m == 0 {
m = extra
} else {
for m < i1 {
if i0 < 1024 {
m += m
} else {
m += m / 4
}
}
}
t := MakeSlice(s.Type(), i1, m)
Copy(t, s)
return t, i0, i1
}
func Append(s Value, x ...Value) Value {
s.mustBe(Slice)
s, i0, i1 := grow(s, len(x))
for i, j := i0, 0; i < i1; i, j = i+1, j+1 {
s.Index(i).Set(x[j])
}
return s
}
func AppendSlice(s, t Value) Value {
s.mustBe(Slice)
t.mustBe(Slice)
typesMustMatch("reflect.AppendSlice", s.Type().Elem(), t.Type().Elem())
s, i0, i1 := grow(s, t.Len())
Copy(s.Slice(i0, i1), t)
return s
}
func Copy(dst, src Value) int {
dk := dst.kind()
if dk != Array && dk != Slice {
panic(&ValueError{"reflect.Copy", dk})
}
if dk == Array {
dst.mustBeAssignable()
}
dst.mustBeExported()
sk := src.kind()
var stringCopy bool
if sk != Array && sk != Slice {
stringCopy = sk == String && dst.typ.Elem().Kind() == Uint8
if !stringCopy {
panic(&ValueError{"reflect.Copy", sk})
}
}
src.mustBeExported()
de := dst.typ.Elem()
if !stringCopy {
se := src.typ.Elem()
typesMustMatch("reflect.Copy", de, se)
}
var ds, ss sliceHeader
if dk == Array {
ds.Data = dst.ptr
ds.Len = dst.Len()
ds.Cap = ds.Len
} else {
ds = *(*sliceHeader)(dst.ptr)
}
if sk == Array {
ss.Data = src.ptr
ss.Len = src.Len()
ss.Cap = ss.Len
} else if sk == Slice {
ss = *(*sliceHeader)(src.ptr)
} else {
sh := *(*stringHeader)(src.ptr)
ss.Data = sh.Data
ss.Len = sh.Len
ss.Cap = sh.Len
}
return typedslicecopy(de.common(), ds, ss)
}
type runtimeSelect struct {
dir SelectDir
typ *rtype
ch unsafe.Pointer
val unsafe.Pointer
}
func rselect([]runtimeSelect) (chosen int, recvOK bool)
type SelectDir int
const (
_ SelectDir = iota
SelectSend
SelectRecv
SelectDefault
)
type SelectCase struct {
Dir SelectDir
Chan Value
Send Value
}
func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) {
runcases := make([]runtimeSelect, len(cases))
haveDefault := false
for i, c := range cases {
rc := &runcases[i]
rc.dir = c.Dir
switch c.Dir {
default:
panic("reflect.Select: invalid Dir")
case SelectDefault:
if haveDefault {
panic("reflect.Select: multiple default cases")
}
haveDefault = true
if c.Chan.IsValid() {
panic("reflect.Select: default case has Chan value")
}
if c.Send.IsValid() {
panic("reflect.Select: default case has Send value")
}
case SelectSend:
ch := c.Chan
if !ch.IsValid() {
break
}
ch.mustBe(Chan)
ch.mustBeExported()
tt := (*chanType)(unsafe.Pointer(ch.typ))
if ChanDir(tt.dir)&SendDir == 0 {
panic("reflect.Select: SendDir case using recv-only channel")
}
rc.ch = ch.pointer()
rc.typ = &tt.rtype
v := c.Send
if !v.IsValid() {
panic("reflect.Select: SendDir case missing Send value")
}
v.mustBeExported()
v = v.assignTo("reflect.Select", tt.elem, nil)
if v.flag&flagIndir != 0 {
rc.val = v.ptr
} else {
rc.val = unsafe.Pointer(&v.ptr)
}
case SelectRecv:
if c.Send.IsValid() {
panic("reflect.Select: RecvDir case has Send value")
}
ch := c.Chan
if !ch.IsValid() {
break
}
ch.mustBe(Chan)
ch.mustBeExported()
tt := (*chanType)(unsafe.Pointer(ch.typ))
if ChanDir(tt.dir)&RecvDir == 0 {
panic("reflect.Select: RecvDir case using send-only channel")
}
rc.ch = ch.pointer()
rc.typ = &tt.rtype
rc.val = unsafe_New(tt.elem)
}
}
chosen, recvOK = rselect(runcases)
if runcases[chosen].dir == SelectRecv {
tt := (*chanType)(unsafe.Pointer(runcases[chosen].typ))
t := tt.elem
p := runcases[chosen].val
fl := flag(t.Kind())
if ifaceIndir(t) {
recv = Value{t, p, fl | flagIndir}
} else {
recv = Value{t, *(*unsafe.Pointer)(p), fl}
}
}
return chosen, recv, recvOK
}
func unsafe_New(*rtype) unsafe.Pointer
func unsafe_NewArray(*rtype, int) unsafe.Pointer
func MakeSlice(typ Type, len, cap int) Value {
if typ.Kind() != Slice {
panic("reflect.MakeSlice of non-slice type")
}
if len < 0 {
panic("reflect.MakeSlice: negative len")
}
if cap < 0 {
panic("reflect.MakeSlice: negative cap")
}
if len > cap {
panic("reflect.MakeSlice: len > cap")
}
s := sliceHeader{unsafe_NewArray(typ.Elem().(*rtype), cap), len, cap}
return Value{typ.common(), unsafe.Pointer(&s), flagIndir | flag(Slice)}
}
func MakeChan(typ Type, buffer int) Value {
if typ.Kind() != Chan {
panic("reflect.MakeChan of non-chan type")
}
if buffer < 0 {
panic("reflect.MakeChan: negative buffer size")
}
if typ.ChanDir() != BothDir {
panic("reflect.MakeChan: unidirectional channel type")
}
ch := makechan(typ.(*rtype), buffer)
return Value{typ.common(), ch, flag(Chan)}
}
func MakeMap(typ Type) Value {
return MakeMapWithSize(typ, 0)
}
func MakeMapWithSize(typ Type, n int) Value {
if typ.Kind() != Map {
panic("reflect.MakeMapWithSize of non-map type")
}
m := makemap(typ.(*rtype), n)
return Value{typ.common(), m, flag(Map)}
}
func Indirect(v Value) Value {
if v.Kind() != Ptr {
return v
}
return v.Elem()
}
func ValueOf(i interface{}) Value {
if i == nil {
return Value{}
}
escapes(i)
return unpackEface(i)
}
func Zero(typ Type) Value {
if typ == nil {
panic("reflect: Zero(nil)")
}
t := typ.common()
fl := flag(t.Kind())
if ifaceIndir(t) {
return Value{t, unsafe_New(typ.(*rtype)), fl | flagIndir}
}
return Value{t, nil, fl}
}
func New(typ Type) Value {
if typ == nil {
panic("reflect: New(nil)")
}
ptr := unsafe_New(typ.(*rtype))
fl := flag(Ptr)
return Value{typ.common().ptrTo(), ptr, fl}
}
func NewAt(typ Type, p unsafe.Pointer) Value {
fl := flag(Ptr)
return Value{typ.common().ptrTo(), p, fl}
}
func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value {
if v.flag&flagMethod != 0 {
v = makeMethodValue(context, v)
}
switch {
case directlyAssignable(dst, v.typ):
fl := v.flag&(flagAddr|flagIndir) | v.flag.ro()
fl |= flag(dst.Kind())
return Value{dst, v.ptr, fl}
case implements(dst, v.typ):
if target == nil {
target = unsafe_New(dst)
}
if v.Kind() == Interface && v.IsNil() {
return Value{dst, nil, flag(Interface)}
}
x := valueInterface(v, false)
if dst.NumMethod() == 0 {
*(*interface{})(target) = x
} else {
ifaceE2I(dst, x, target)
}
return Value{dst, target, flagIndir | flag(Interface)}
}
panic(context + ": value of type " + v.typ.String() + " is not assignable to type " + dst.String())
}
func (v Value) Convert(t Type) Value {
if v.flag&flagMethod != 0 {
v = makeMethodValue("Convert", v)
}
op := convertOp(t.common(), v.typ)
if op == nil {
panic("reflect.Value.Convert: value of type " + v.typ.String() + " cannot be converted to type " + t.String())
}
return op(v, t)
}
func convertOp(dst, src *rtype) func(Value, Type) Value {
switch src.Kind() {
case Int, Int8, Int16, Int32, Int64:
switch dst.Kind() {
case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
return cvtInt
case Float32, Float64:
return cvtIntFloat
case String:
return cvtIntString
}
case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
switch dst.Kind() {
case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
return cvtUint
case Float32, Float64:
return cvtUintFloat
case String:
return cvtUintString
}
case Float32, Float64:
switch dst.Kind() {
case Int, Int8, Int16, Int32, Int64:
return cvtFloatInt
case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
return cvtFloatUint
case Float32, Float64:
return cvtFloat
}
case Complex64, Complex128:
switch dst.Kind() {
case Complex64, Complex128:
return cvtComplex
}
case String:
if dst.Kind() == Slice && dst.Elem().PkgPath() == "" {
switch dst.Elem().Kind() {
case Uint8:
return cvtStringBytes
case Int32:
return cvtStringRunes
}
}
case Slice:
if dst.Kind() == String && src.Elem().PkgPath() == "" {
switch src.Elem().Kind() {
case Uint8:
return cvtBytesString
case Int32:
return cvtRunesString
}
}
}
if haveIdenticalUnderlyingType(dst, src, false) {
return cvtDirect
}
if dst.Kind() == Ptr && dst.Name() == "" &&
src.Kind() == Ptr && src.Name() == "" &&
haveIdenticalUnderlyingType(dst.Elem().common(), src.Elem().common(), false) {
return cvtDirect
}
if implements(dst, src) {
if src.Kind() == Interface {
return cvtI2I
}
return cvtT2I
}
return nil
}
func makeInt(f flag, bits uint64, t Type) Value {
typ := t.common()
ptr := unsafe_New(typ)
switch typ.size {
case 1:
*(*uint8)(ptr) = uint8(bits)
case 2:
*(*uint16)(ptr) = uint16(bits)
case 4:
*(*uint32)(ptr) = uint32(bits)
case 8:
*(*uint64)(ptr) = bits
}
return Value{typ, ptr, f | flagIndir | flag(typ.Kind())}
}
func makeFloat(f flag, v float64, t Type) Value {
typ := t.common()
ptr := unsafe_New(typ)
switch typ.size {
case 4:
*(*float32)(ptr) = float32(v)
case 8:
*(*float64)(ptr) = v
}
return Value{typ, ptr, f | flagIndir | flag(typ.Kind())}
}
func makeComplex(f flag, v complex128, t Type) Value {
typ := t.common()
ptr := unsafe_New(typ)
switch typ.size {
case 8:
*(*complex64)(ptr) = complex64(v)
case 16:
*(*complex128)(ptr) = v
}
return Value{typ, ptr, f | flagIndir | flag(typ.Kind())}
}
func makeString(f flag, v string, t Type) Value {
ret := New(t).Elem()
ret.SetString(v)
ret.flag = ret.flag&^flagAddr | f
return ret
}
func makeBytes(f flag, v []byte, t Type) Value {
ret := New(t).Elem()
ret.SetBytes(v)
ret.flag = ret.flag&^flagAddr | f
return ret
}
func makeRunes(f flag, v []rune, t Type) Value {
ret := New(t).Elem()
ret.setRunes(v)
ret.flag = ret.flag&^flagAddr | f
return ret
}
func cvtInt(v Value, t Type) Value {
return makeInt(v.flag.ro(), uint64(v.Int()), t)
}
func cvtUint(v Value, t Type) Value {
return makeInt(v.flag.ro(), v.Uint(), t)
}
func cvtFloatInt(v Value, t Type) Value {
return makeInt(v.flag.ro(), uint64(int64(v.Float())), t)
}
func cvtFloatUint(v Value, t Type) Value {
return makeInt(v.flag.ro(), uint64(v.Float()), t)
}
func cvtIntFloat(v Value, t Type) Value {
return makeFloat(v.flag.ro(), float64(v.Int()), t)
}
func cvtUintFloat(v Value, t Type) Value {
return makeFloat(v.flag.ro(), float64(v.Uint()), t)
}
func cvtFloat(v Value, t Type) Value {
return makeFloat(v.flag.ro(), v.Float(), t)
}
func cvtComplex(v Value, t Type) Value {
return makeComplex(v.flag.ro(), v.Complex(), t)
}
func cvtIntString(v Value, t Type) Value {
return makeString(v.flag.ro(), string(v.Int()), t)
}
func cvtUintString(v Value, t Type) Value {
return makeString(v.flag.ro(), string(v.Uint()), t)
}
func cvtBytesString(v Value, t Type) Value {
return makeString(v.flag.ro(), string(v.Bytes()), t)
}
func cvtStringBytes(v Value, t Type) Value {
return makeBytes(v.flag.ro(), []byte(v.String()), t)
}
func cvtRunesString(v Value, t Type) Value {
return makeString(v.flag.ro(), string(v.runes()), t)
}
func cvtStringRunes(v Value, t Type) Value {
return makeRunes(v.flag.ro(), []rune(v.String()), t)
}
func cvtDirect(v Value, typ Type) Value {
f := v.flag
t := typ.common()
ptr := v.ptr
if f&flagAddr != 0 {
c := unsafe_New(t)
typedmemmove(t, c, ptr)
ptr = c
f &^= flagAddr
}
return Value{t, ptr, v.flag.ro() | f}
}
func cvtT2I(v Value, typ Type) Value {
target := unsafe_New(typ.common())
x := valueInterface(v, false)
if typ.NumMethod() == 0 {
*(*interface{})(target) = x
} else {
ifaceE2I(typ.(*rtype), x, target)
}
return Value{typ.common(), target, v.flag.ro() | flagIndir | flag(Interface)}
}
func cvtI2I(v Value, typ Type) Value {
if v.IsNil() {
ret := Zero(typ)
ret.flag |= v.flag.ro()
return ret
}
return cvtT2I(v.Elem(), typ)
}
func chancap(ch unsafe.Pointer) int
func chanclose(ch unsafe.Pointer)
func chanlen(ch unsafe.Pointer) int
func chanrecv(ch unsafe.Pointer, nb bool, val unsafe.Pointer) (selected, received bool)
func chansend(ch unsafe.Pointer, val unsafe.Pointer, nb bool) bool
func makechan(typ *rtype, size int) (ch unsafe.Pointer)
func makemap(t *rtype, cap int) (m unsafe.Pointer)
func mapaccess(t *rtype, m unsafe.Pointer, key unsafe.Pointer) (val unsafe.Pointer)
func mapassign(t *rtype, m unsafe.Pointer, key, val unsafe.Pointer)
func mapdelete(t *rtype, m unsafe.Pointer, key unsafe.Pointer)
func mapiterinit(t *rtype, m unsafe.Pointer) unsafe.Pointer
func mapiterkey(it unsafe.Pointer) (key unsafe.Pointer)
func mapiternext(it unsafe.Pointer)
func maplen(m unsafe.Pointer) int
func call(argtype *rtype, fn, arg unsafe.Pointer, n uint32, retoffset uint32)
func ifaceE2I(t *rtype, src interface{}, dst unsafe.Pointer)
func typedmemmove(t *rtype, dst, src unsafe.Pointer)
func typedmemmovepartial(t *rtype, dst, src unsafe.Pointer, off, size uintptr)
func typedslicecopy(elemType *rtype, dst, src sliceHeader) int
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
func escapes(x interface{}) {
if dummy.b {
dummy.x = x
}
}
var dummy struct {
b bool
x interface{}
}
View as plain text