package reflect
import (
"math"
"runtime"
"unsafe"
)
const ptrSize = 4 << (^uintptr(0) >> 63) const cannotSet = "cannot set value obtained from unexported struct field"
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 (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 link unsafe.Pointer
bad int32
unused int32
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 & flagRO) | 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
addr := unsafe.Pointer(uintptr(args) + off)
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 {
memclr(args, frametype.size)
framePool.Put(args)
} else {
memclr(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)
fl := flagIndir | flag(tv.Kind())
ret[i] = Value{tv.common(), unsafe.Pointer(uintptr(args) + off), fl}
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, len(ftyp.in))
for _, arg := range ftyp.in {
typ := arg
off += -off & uintptr(typ.align-1)
addr := unsafe.Pointer(uintptr(ptr) + off)
v := Value{typ, nil, flag(typ.Kind())}
if ifaceIndir(typ) {
v.ptr = unsafe_New(typ)
typedmemmove(typ, v.ptr, addr)
v.flag |= flagIndir
} else {
v.ptr = *(*unsafe.Pointer)(addr)
}
in = append(in, v)
off += typ.size
}
out := f(in)
if len(out) != len(ftyp.out) {
panic("reflect: wrong return count from function created by MakeFunc")
}
if len(ftyp.out) > 0 {
off += -off & (ptrSize - 1)
if runtime.GOARCH == "amd64p32" {
off = align(off, 8)
}
for i, arg := range ftyp.out {
typ := arg
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)
addr := unsafe.Pointer(uintptr(ptr) + off)
if v.flag&flagIndir != 0 {
typedmemmove(typ, addr, v.ptr)
} else {
*(*unsafe.Pointer)(addr) = v.ptr
}
off += typ.size
}
}
}
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 m.pkgPath != nil {
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 = m.typ
} else {
rcvrtype = v.typ
ut := v.typ.uncommon()
if ut == nil || uint(i) >= uint(len(ut.methods)) {
panic("reflect: internal error: invalid method index")
}
m := &ut.methods[i]
if m.pkgPath != nil {
panic("reflect: " + op + " of unexported method")
}
fn = unsafe.Pointer(&m.ifn)
t = 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)
typedmemmovepartial(frametype, unsafe.Pointer(uintptr(args)+ptrSize), frame, ptrSize, argSize-ptrSize)
call(frametype, fn, args, uint32(frametype.size), uint32(retOffset))
callerRetOffset := retOffset - ptrSize
if runtime.GOARCH == "amd64p32" {
callerRetOffset = align(argSize-ptrSize, 8)
}
typedmemmovepartial(frametype,
unsafe.Pointer(uintptr(frame)+callerRetOffset),
unsafe.Pointer(uintptr(args)+retOffset),
retOffset,
frametype.size-retOffset)
memclr(args, frametype.size)
framePool.Put(args)
}
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 int(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 & flagRO
}
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.pkgPath != nil {
if field.name == nil {
fl |= flagEmbedRO
} else {
fl |= flagStickyRO
}
}
ptr := unsafe.Pointer(uintptr(v.ptr) + field.offset)
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 := unsafe.Pointer(uintptr(v.ptr) + offset)
fl := v.flag&(flagRO|flagIndir|flagAddr) | 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)
fl := flagAddr | flagIndir | v.flag&flagRO | 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)
fl := v.flag&flagRO | 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(*(*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) & flagRO
fl |= flag(typ.Kind())
if ifaceIndir(typ) {
c := unsafe_New(typ)
typedmemmove(typ, c, e)
return Value{typ, c, fl | flagIndir}
} else {
return Value{typ, *(*unsafe.Pointer)(e), fl}
}
}
func (v Value) MapKeys() []Value {
v.mustBe(Map)
tt := (*mapType)(unsafe.Pointer(v.typ))
keyType := tt.key
fl := v.flag&flagRO | 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.typ, 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.typ, 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 < int(s.Len) || n > int(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 = unsafe.Pointer(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")
}
t := stringHeader{arrayAt(s.Data, i, 1), 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())
} else {
s.Data = base
}
fl := v.flag&flagRO | 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())
} else {
s.Data = base
}
fl := v.flag&flagRO | 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 m.typ
}
ut := v.typ.uncommon()
if ut == nil || uint(i) >= uint(len(ut.methods)) {
panic("reflect: internal error: invalid method index")
}
m := &ut.methods[i]
return 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(*(*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) unsafe.Pointer {
return unsafe.Pointer(uintptr(p) + uintptr(i)*eltSize)
}
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()
if sk != Array && sk != Slice {
panic(&ValueError{"reflect.Copy", sk})
}
src.mustBeExported()
de := dst.typ.Elem()
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 {
ss = *(*sliceHeader)(src.ptr)
}
return typedslicecopy(de.common(), ds, ss)
}
type runtimeSelect struct {
dir uintptr 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 = uintptr(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 == uintptr(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), uint64(buffer))
return Value{typ.common(), ch, flag(Chan)}
}
func MakeMap(typ Type) Value {
if typ.Kind() != Map {
panic("reflect.MakeMap of non-map type")
}
m := makemap(typ.(*rtype))
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):
v.typ = dst
fl := v.flag & (flagRO | flagAddr | flagIndir)
fl |= flag(dst.Kind())
return Value{dst, v.ptr, fl}
case implements(dst, v.typ):
if target == nil {
target = unsafe_New(dst)
}
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) {
return cvtDirect
}
if dst.Kind() == Ptr && dst.Name() == "" &&
src.Kind() == Ptr && src.Name() == "" &&
haveIdenticalUnderlyingType(dst.Elem().common(), src.Elem().common()) {
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)(unsafe.Pointer(ptr)) = uint8(bits)
case 2:
*(*uint16)(unsafe.Pointer(ptr)) = uint16(bits)
case 4:
*(*uint32)(unsafe.Pointer(ptr)) = uint32(bits)
case 8:
*(*uint64)(unsafe.Pointer(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)(unsafe.Pointer(ptr)) = float32(v)
case 8:
*(*float64)(unsafe.Pointer(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)(unsafe.Pointer(ptr)) = complex64(v)
case 16:
*(*complex128)(unsafe.Pointer(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&flagRO, uint64(v.Int()), t)
}
func cvtUint(v Value, t Type) Value {
return makeInt(v.flag&flagRO, v.Uint(), t)
}
func cvtFloatInt(v Value, t Type) Value {
return makeInt(v.flag&flagRO, uint64(int64(v.Float())), t)
}
func cvtFloatUint(v Value, t Type) Value {
return makeInt(v.flag&flagRO, uint64(v.Float()), t)
}
func cvtIntFloat(v Value, t Type) Value {
return makeFloat(v.flag&flagRO, float64(v.Int()), t)
}
func cvtUintFloat(v Value, t Type) Value {
return makeFloat(v.flag&flagRO, float64(v.Uint()), t)
}
func cvtFloat(v Value, t Type) Value {
return makeFloat(v.flag&flagRO, v.Float(), t)
}
func cvtComplex(v Value, t Type) Value {
return makeComplex(v.flag&flagRO, v.Complex(), t)
}
func cvtIntString(v Value, t Type) Value {
return makeString(v.flag&flagRO, string(v.Int()), t)
}
func cvtUintString(v Value, t Type) Value {
return makeString(v.flag&flagRO, string(v.Uint()), t)
}
func cvtBytesString(v Value, t Type) Value {
return makeString(v.flag&flagRO, string(v.Bytes()), t)
}
func cvtStringBytes(v Value, t Type) Value {
return makeBytes(v.flag&flagRO, []byte(v.String()), t)
}
func cvtRunesString(v Value, t Type) Value {
return makeString(v.flag&flagRO, string(v.runes()), t)
}
func cvtStringRunes(v Value, t Type) Value {
return makeRunes(v.flag&flagRO, []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&flagRO | 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&flagRO | flagIndir | flag(Interface)}
}
func cvtI2I(v Value, typ Type) Value {
if v.IsNil() {
ret := Zero(typ)
ret.flag |= v.flag & flagRO
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(t *rtype, ch unsafe.Pointer, nb bool, val unsafe.Pointer) (selected, received bool)
func chansend(t *rtype, ch unsafe.Pointer, val unsafe.Pointer, nb bool) bool
func makechan(typ *rtype, size uint64) (ch unsafe.Pointer)
func makemap(t *rtype) (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 memclr(ptr unsafe.Pointer, n uintptr)
func escapes(x interface{}) {
if dummy.b {
dummy.x = x
}
}
var dummy struct {
b bool
x interface{}
}