package reflect
import (
"runtime"
"strconv"
"unsafe"
)
type commonType struct {
size uintptr
hash uint32
alg uint8
align uint8
fieldAlign uint8
string *string
*uncommonType
}
type method struct {
name *string
pkgPath *string
mtyp *runtime.Type
typ *runtime.Type
ifn unsafe.Pointer
tfn unsafe.Pointer
}
type uncommonType struct {
name *string
pkgPath *string
methods []method
}
type BoolType struct {
commonType
}
type Float32Type struct {
commonType
}
type Float64Type struct {
commonType
}
type FloatType struct {
commonType
}
type Complex64Type struct {
commonType
}
type Complex128Type struct {
commonType
}
type ComplexType struct {
commonType
}
type Int16Type struct {
commonType
}
type Int32Type struct {
commonType
}
type Int64Type struct {
commonType
}
type Int8Type struct {
commonType
}
type IntType struct {
commonType
}
type Uint16Type struct {
commonType
}
type Uint32Type struct {
commonType
}
type Uint64Type struct {
commonType
}
type Uint8Type struct {
commonType
}
type UintType struct {
commonType
}
type StringType struct {
commonType
}
type UintptrType struct {
commonType
}
type UnsafePointerType struct {
commonType
}
type ArrayType struct {
commonType
elem *runtime.Type
len uintptr
}
type ChanDir int
const (
RecvDir ChanDir = 1 << iota
SendDir
BothDir = RecvDir | SendDir
)
type ChanType struct {
commonType
elem *runtime.Type
dir uintptr
}
type FuncType struct {
commonType
dotdotdot bool
in []*runtime.Type
out []*runtime.Type
}
type imethod struct {
name *string
pkgPath *string
typ *runtime.Type
}
type InterfaceType struct {
commonType
methods []imethod
}
type MapType struct {
commonType
key *runtime.Type
elem *runtime.Type
}
type PtrType struct {
commonType
elem *runtime.Type
}
type SliceType struct {
commonType
elem *runtime.Type
}
type structField struct {
name *string
pkgPath *string
typ *runtime.Type
tag *string
offset uintptr
}
type StructType struct {
commonType
fields []structField
}
type Method struct {
PkgPath string
Name string
Type *FuncType
Func *FuncValue
}
type Type interface {
PkgPath() string
Name() string
String() string
Size() uintptr
Align() int
FieldAlign() int
Method(int) Method
NumMethod() int
uncommon() *uncommonType
}
func (t *uncommonType) uncommon() *uncommonType {
return t
}
func (t *uncommonType) PkgPath() string {
if t == nil || t.pkgPath == nil {
return ""
}
return *t.pkgPath
}
func (t *uncommonType) Name() string {
if t == nil || t.name == nil {
return ""
}
return *t.name
}
func (t *commonType) String() string { return *t.string }
func (t *commonType) Size() uintptr { return t.size }
func (t *commonType) Align() int { return int(t.align) }
func (t *commonType) FieldAlign() int { return int(t.fieldAlign) }
func (t *uncommonType) Method(i int) (m Method) {
if t == nil || i < 0 || i >= len(t.methods) {
return
}
p := &t.methods[i]
if p.name != nil {
m.Name = *p.name
}
if p.pkgPath != nil {
m.PkgPath = *p.pkgPath
}
m.Type = toType(*p.typ).(*FuncType)
fn := p.tfn
m.Func = newFuncValue(m.Type, addr(&fn), true)
return
}
func (t *uncommonType) NumMethod() int {
if t == nil {
return 0
}
return len(t.methods)
}
func (t *commonType) NumMethod() int { return t.uncommonType.NumMethod() }
func (t *commonType) Method(i int) (m Method) { return t.uncommonType.Method(i) }
func (t *commonType) PkgPath() string { return t.uncommonType.PkgPath() }
func (t *commonType) Name() string { return t.uncommonType.Name() }
func (t *ArrayType) Len() int { return int(t.len) }
func (t *ArrayType) Elem() Type { return toType(*t.elem) }
func (t *ChanType) Dir() ChanDir { return ChanDir(t.dir) }
func (t *ChanType) Elem() Type { return toType(*t.elem) }
func (d ChanDir) String() string {
switch d {
case SendDir:
return "chan<-"
case RecvDir:
return "<-chan"
case BothDir:
return "chan"
}
return "ChanDir" + strconv.Itoa(int(d))
}
func (t *FuncType) In(i int) Type {
if i < 0 || i >= len(t.in) {
return nil
}
return toType(*t.in[i])
}
func (t *FuncType) DotDotDot() bool { return t.dotdotdot }
func (t *FuncType) NumIn() int { return len(t.in) }
func (t *FuncType) Out(i int) Type {
if i < 0 || i >= len(t.out) {
return nil
}
return toType(*t.out[i])
}
func (t *FuncType) NumOut() int { return len(t.out) }
func (t *InterfaceType) Method(i int) (m Method) {
if i < 0 || i >= len(t.methods) {
return
}
p := &t.methods[i]
m.Name = *p.name
if p.pkgPath != nil {
m.PkgPath = *p.pkgPath
}
m.Type = toType(*p.typ).(*FuncType)
return
}
func (t *InterfaceType) NumMethod() int { return len(t.methods) }
func (t *MapType) Key() Type { return toType(*t.key) }
func (t *MapType) Elem() Type { return toType(*t.elem) }
func (t *PtrType) Elem() Type { return toType(*t.elem) }
func (t *SliceType) Elem() Type { return toType(*t.elem) }
type StructField struct {
PkgPath string
Name string
Type Type
Tag string
Offset uintptr
Index []int
Anonymous bool
}
func (t *StructType) Field(i int) (f StructField) {
if i < 0 || i >= len(t.fields) {
return
}
p := t.fields[i]
f.Type = toType(*p.typ)
if p.name != nil {
f.Name = *p.name
} else {
t := f.Type
if pt, ok := t.(*PtrType); ok {
t = pt.Elem()
}
f.Name = t.Name()
f.Anonymous = true
}
if p.pkgPath != nil {
f.PkgPath = *p.pkgPath
}
if p.tag != nil {
f.Tag = *p.tag
}
f.Offset = p.offset
f.Index = []int{i}
return
}
func (t *StructType) FieldByIndex(index []int) (f StructField) {
for i, x := range index {
if i > 0 {
ft := f.Type
if pt, ok := ft.(*PtrType); ok {
ft = pt.Elem()
}
if st, ok := ft.(*StructType); ok {
t = st
} else {
var f0 StructField
f = f0
return
}
}
f = t.Field(x)
}
return
}
const inf = 1 << 30
func (t *StructType) fieldByName(name string, mark map[*StructType]bool, depth int) (ff StructField, fd int) {
fd = inf
if _, marked := mark[t]; marked {
return
}
mark[t] = true
var fi int
n := 0
L: for i, _ := range t.fields {
f := t.Field(i)
d := inf
switch {
case f.Name == name:
d = depth
case f.Anonymous:
ft := f.Type
if pt, ok := ft.(*PtrType); ok {
ft = pt.Elem()
}
switch {
case ft.Name() == name:
d = depth
case fd > depth:
if st, ok := ft.(*StructType); ok {
f, d = st.fieldByName(name, mark, depth+1)
}
}
}
switch {
case d < fd:
ff, fi, fd = f, i, d
n = 1
case d == fd:
n++
if d == depth {
break L
}
}
}
if n == 1 {
if len(ff.Index) <= depth {
ff.Index = make([]int, depth+1)
}
ff.Index[depth] = fi
} else {
fd = inf
}
mark[t] = false, false
return
}
func (t *StructType) FieldByName(name string) (f StructField, present bool) {
if ff, fd := t.fieldByName(name, make(map[*StructType]bool), 0); fd < inf {
ff.Index = ff.Index[0 : fd+1]
f, present = ff, true
}
return
}
func (t *StructType) NumField() int { return len(t.fields) }
func toType(i interface{}) Type {
switch v := i.(type) {
case nil:
return nil
case *runtime.BoolType:
return (*BoolType)(unsafe.Pointer(v))
case *runtime.FloatType:
return (*FloatType)(unsafe.Pointer(v))
case *runtime.Float32Type:
return (*Float32Type)(unsafe.Pointer(v))
case *runtime.Float64Type:
return (*Float64Type)(unsafe.Pointer(v))
case *runtime.ComplexType:
return (*ComplexType)(unsafe.Pointer(v))
case *runtime.Complex64Type:
return (*Complex64Type)(unsafe.Pointer(v))
case *runtime.Complex128Type:
return (*Complex128Type)(unsafe.Pointer(v))
case *runtime.IntType:
return (*IntType)(unsafe.Pointer(v))
case *runtime.Int8Type:
return (*Int8Type)(unsafe.Pointer(v))
case *runtime.Int16Type:
return (*Int16Type)(unsafe.Pointer(v))
case *runtime.Int32Type:
return (*Int32Type)(unsafe.Pointer(v))
case *runtime.Int64Type:
return (*Int64Type)(unsafe.Pointer(v))
case *runtime.StringType:
return (*StringType)(unsafe.Pointer(v))
case *runtime.UintType:
return (*UintType)(unsafe.Pointer(v))
case *runtime.Uint8Type:
return (*Uint8Type)(unsafe.Pointer(v))
case *runtime.Uint16Type:
return (*Uint16Type)(unsafe.Pointer(v))
case *runtime.Uint32Type:
return (*Uint32Type)(unsafe.Pointer(v))
case *runtime.Uint64Type:
return (*Uint64Type)(unsafe.Pointer(v))
case *runtime.UintptrType:
return (*UintptrType)(unsafe.Pointer(v))
case *runtime.UnsafePointerType:
return (*UnsafePointerType)(unsafe.Pointer(v))
case *runtime.ArrayType:
return (*ArrayType)(unsafe.Pointer(v))
case *runtime.ChanType:
return (*ChanType)(unsafe.Pointer(v))
case *runtime.FuncType:
return (*FuncType)(unsafe.Pointer(v))
case *runtime.InterfaceType:
return (*InterfaceType)(unsafe.Pointer(v))
case *runtime.MapType:
return (*MapType)(unsafe.Pointer(v))
case *runtime.PtrType:
return (*PtrType)(unsafe.Pointer(v))
case *runtime.SliceType:
return (*SliceType)(unsafe.Pointer(v))
case *runtime.StructType:
return (*StructType)(unsafe.Pointer(v))
}
panicln("toType", i)
}
type ArrayOrSliceType interface {
Type
Elem() Type
}
func Typeof(i interface{}) Type { return toType(unsafe.Typeof(i)) }