// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Reflection library. // Handling values. package reflect import ( "reflect"; "unsafe"; ) // Addr is shorthand for unsafe.Pointer and is used to represent the address of Values. type Addr unsafe.Pointer func equalType(a, b Type) bool { return a.String() == b.String() } // Value is the generic interface to reflection values. Once its Kind is known, // such as BoolKind, the Value can be narrowed to the appropriate, more // specific interface, such as BoolValue. Such narrowed values still implement // the Value interface. type Value interface { // The kind of thing described: ArrayKind, BoolKind, etc. Kind() int; // The reflection Type of the value. Type() Type; // The address of the value. Addr() Addr; // The value itself is the dynamic value of an empty interface. Interface() interface {}; } func NewValue(e interface{}) Value; // commonValue fields and functionality for all values type commonValue struct { kind int; typ Type; addr Addr; } func (c *commonValue) Kind() int { return c.kind } func (c *commonValue) Type() Type { return c.typ } func (c *commonValue) Addr() Addr { return c.addr } func (c *commonValue) Interface() interface {} { var i interface {}; switch { case c.typ.Kind() == InterfaceKind: panic("not reached"); // InterfaceValue overrides this method case c.typ.Size() > 8: // TODO(rsc): how do we know it is 8? i = unsafe.Unreflect(uint64(uintptr(c.addr)), c.typ.String(), true); default: if uintptr(c.addr) == 0 { panicln("reflect: address 0 for", c.typ.String()); } i = unsafe.Unreflect(uint64(uintptr(*(*Addr)(c.addr))), c.typ.String(), false); } return i; } func newValueAddr(typ Type, addr Addr) Value type creatorFn func(typ Type, addr Addr) Value // -- Missing // MissingValue represents a value whose type is not known. It usually // indicates an error. type MissingValue interface { Value; } type missingValueStruct struct { commonValue } func missingCreator(typ Type, addr Addr) Value { return &missingValueStruct{ commonValue{MissingKind, typ, addr} } } // -- Int // IntValue represents an int value. type IntValue interface { Value; Get() int; // Get the underlying int. Set(int); // Set the underlying int. } type intValueStruct struct { commonValue } func intCreator(typ Type, addr Addr) Value { return &intValueStruct{ commonValue{IntKind, typ, addr} } } func (v *intValueStruct) Get() int { return *(*int)(v.addr) } func (v *intValueStruct) Set(i int) { *(*int)(v.addr) = i } // -- Int8 // Int8Value represents an int8 value. type Int8Value interface { Value; Get() int8; // Get the underlying int8. Set(int8); // Set the underlying int8. } type int8ValueStruct struct { commonValue } func int8Creator(typ Type, addr Addr) Value { return &int8ValueStruct{ commonValue{Int8Kind, typ, addr} } } func (v *int8ValueStruct) Get() int8 { return *(*int8)(v.addr) } func (v *int8ValueStruct) Set(i int8) { *(*int8)(v.addr) = i } // -- Int16 // Int16Value represents an int16 value. type Int16Value interface { Value; Get() int16; // Get the underlying int16. Set(int16); // Set the underlying int16. } type int16ValueStruct struct { commonValue } func int16Creator(typ Type, addr Addr) Value { return &int16ValueStruct{ commonValue{Int16Kind, typ, addr} } } func (v *int16ValueStruct) Get() int16 { return *(*int16)(v.addr) } func (v *int16ValueStruct) Set(i int16) { *(*int16)(v.addr) = i } // -- Int32 // Int32Value represents an int32 value. type Int32Value interface { Value; Get() int32; // Get the underlying int32. Set(int32); // Set the underlying int32. } type int32ValueStruct struct { commonValue } func int32Creator(typ Type, addr Addr) Value { return &int32ValueStruct{ commonValue{Int32Kind, typ, addr} } } func (v *int32ValueStruct) Get() int32 { return *(*int32)(v.addr) } func (v *int32ValueStruct) Set(i int32) { *(*int32)(v.addr) = i } // -- Int64 // Int64Value represents an int64 value. type Int64Value interface { Value; Get() int64; // Get the underlying int64. Set(int64); // Set the underlying int64. } type int64ValueStruct struct { commonValue } func int64Creator(typ Type, addr Addr) Value { return &int64ValueStruct{ commonValue{Int64Kind, typ, addr} } } func (v *int64ValueStruct) Get() int64 { return *(*int64)(v.addr) } func (v *int64ValueStruct) Set(i int64) { *(*int64)(v.addr) = i } // -- Uint // UintValue represents a uint value. type UintValue interface { Value; Get() uint; // Get the underlying uint. Set(uint); // Set the underlying uint. } type uintValueStruct struct { commonValue } func uintCreator(typ Type, addr Addr) Value { return &uintValueStruct{ commonValue{UintKind, typ, addr} } } func (v *uintValueStruct) Get() uint { return *(*uint)(v.addr) } func (v *uintValueStruct) Set(i uint) { *(*uint)(v.addr) = i } // -- Uint8 // Uint8Value represents a uint8 value. type Uint8Value interface { Value; Get() uint8; // Get the underlying uint8. Set(uint8); // Set the underlying uint8. } type uint8ValueStruct struct { commonValue } func uint8Creator(typ Type, addr Addr) Value { return &uint8ValueStruct{ commonValue{Uint8Kind, typ, addr} } } func (v *uint8ValueStruct) Get() uint8 { return *(*uint8)(v.addr) } func (v *uint8ValueStruct) Set(i uint8) { *(*uint8)(v.addr) = i } // -- Uint16 // Uint16Value represents a uint16 value. type Uint16Value interface { Value; Get() uint16; // Get the underlying uint16. Set(uint16); // Set the underlying uint16. } type uint16ValueStruct struct { commonValue } func uint16Creator(typ Type, addr Addr) Value { return &uint16ValueStruct{ commonValue{Uint16Kind, typ, addr} } } func (v *uint16ValueStruct) Get() uint16 { return *(*uint16)(v.addr) } func (v *uint16ValueStruct) Set(i uint16) { *(*uint16)(v.addr) = i } // -- Uint32 // Uint32Value represents a uint32 value. type Uint32Value interface { Value; Get() uint32; // Get the underlying uint32. Set(uint32); // Set the underlying uint32. } type uint32ValueStruct struct { commonValue } func uint32Creator(typ Type, addr Addr) Value { return &uint32ValueStruct{ commonValue{Uint32Kind, typ, addr} } } func (v *uint32ValueStruct) Get() uint32 { return *(*uint32)(v.addr) } func (v *uint32ValueStruct) Set(i uint32) { *(*uint32)(v.addr) = i } // -- Uint64 // Uint64Value represents a uint64 value. type Uint64Value interface { Value; Get() uint64; // Get the underlying uint64. Set(uint64); // Set the underlying uint64. } type uint64ValueStruct struct { commonValue } func uint64Creator(typ Type, addr Addr) Value { return &uint64ValueStruct{ commonValue{Uint64Kind, typ, addr} } } func (v *uint64ValueStruct) Get() uint64 { return *(*uint64)(v.addr) } func (v *uint64ValueStruct) Set(i uint64) { *(*uint64)(v.addr) = i } // -- Uintptr // UintptrValue represents a uintptr value. type UintptrValue interface { Value; Get() uintptr; // Get the underlying uintptr. Set(uintptr); // Set the underlying uintptr. } type uintptrValueStruct struct { commonValue } func uintptrCreator(typ Type, addr Addr) Value { return &uintptrValueStruct{ commonValue{UintptrKind, typ, addr} } } func (v *uintptrValueStruct) Get() uintptr { return *(*uintptr)(v.addr) } func (v *uintptrValueStruct) Set(i uintptr) { *(*uintptr)(v.addr) = i } // -- Float // FloatValue represents a float value. type FloatValue interface { Value; Get() float; // Get the underlying float. Set(float); // Get the underlying float. } type floatValueStruct struct { commonValue } func floatCreator(typ Type, addr Addr) Value { return &floatValueStruct{ commonValue{FloatKind, typ, addr} } } func (v *floatValueStruct) Get() float { return *(*float)(v.addr) } func (v *floatValueStruct) Set(f float) { *(*float)(v.addr) = f } // -- Float32 // Float32Value represents a float32 value. type Float32Value interface { Value; Get() float32; // Get the underlying float32. Set(float32); // Get the underlying float32. } type float32ValueStruct struct { commonValue } func float32Creator(typ Type, addr Addr) Value { return &float32ValueStruct{ commonValue{Float32Kind, typ, addr} } } func (v *float32ValueStruct) Get() float32 { return *(*float32)(v.addr) } func (v *float32ValueStruct) Set(f float32) { *(*float32)(v.addr) = f } // -- Float64 // Float64Value represents a float64 value. type Float64Value interface { Value; Get() float64; // Get the underlying float64. Set(float64); // Get the underlying float64. } type float64ValueStruct struct { commonValue } func float64Creator(typ Type, addr Addr) Value { return &float64ValueStruct{ commonValue{Float64Kind, typ, addr} } } func (v *float64ValueStruct) Get() float64 { return *(*float64)(v.addr) } func (v *float64ValueStruct) Set(f float64) { *(*float64)(v.addr) = f } // -- String // StringValue represents a string value. type StringValue interface { Value; Get() string; // Get the underlying string value. Set(string); // Set the underlying string value. } type stringValueStruct struct { commonValue } func stringCreator(typ Type, addr Addr) Value { return &stringValueStruct{ commonValue{StringKind, typ, addr} } } func (v *stringValueStruct) Get() string { return *(*string)(v.addr) } func (v *stringValueStruct) Set(s string) { *(*string)(v.addr) = s } // -- Bool // BoolValue represents a bool value. type BoolValue interface { Value; Get() bool; // Get the underlying bool value. Set(bool); // Set the underlying bool value. } type boolValueStruct struct { commonValue } func boolCreator(typ Type, addr Addr) Value { return &boolValueStruct{ commonValue{BoolKind, typ, addr} } } func (v *boolValueStruct) Get() bool { return *(*bool)(v.addr) } func (v *boolValueStruct) Set(b bool) { *(*bool)(v.addr) = b } // -- Pointer // PtrValue represents a pointer value. type PtrValue interface { Value; Sub() Value; // The Value pointed to. Get() Addr; // Get the address stored in the pointer. SetSub(Value); // Set the the pointed-to Value. IsNil() bool; } type ptrValueStruct struct { commonValue } func (v *ptrValueStruct) Get() Addr { return *(*Addr)(v.addr) } func (v *ptrValueStruct) Sub() Value { return newValueAddr(v.typ.(PtrType).Sub(), v.Get()); } func (v *ptrValueStruct) SetSub(subv Value) { a := v.typ.(PtrType).Sub(); b := subv.Type(); if !equalType(a, b) { panicln("reflect: incompatible types in PtrValue.SetSub:", a.String(), b.String()); } *(*Addr)(v.addr) = subv.Addr(); } func (v *ptrValueStruct) IsNil() bool { return uintptr(*(*Addr)(v.addr)) == 0 } func ptrCreator(typ Type, addr Addr) Value { return &ptrValueStruct{ commonValue{PtrKind, typ, addr} }; } // -- Array // Slices and arrays are represented by the same interface. // ArrayValue represents an array or slice value. type ArrayValue interface { Value; IsSlice() bool; // Is this a slice (true) or array (false)? Len() int; // The length of the array/slice. Cap() int; // The capacity of the array/slice (==Len() for arrays). Elem(i int) Value; // The Value of the i'th element. SetLen(len int); // Set the length; slice only. Set(src ArrayValue); // Set the underlying Value; slice only for src and dest both. CopyFrom(src ArrayValue, n int); // Copy the elements from src; lengths must match. IsNil() bool; } func copyArray(dst ArrayValue, src ArrayValue, n int); /* Run-time representation of slices looks like this: struct Slice { byte* array; // actual data uint32 nel; // number of elements uint32 cap; }; */ type runtimeSlice struct { data Addr; len uint32; cap uint32; } type sliceValueStruct struct { commonValue; elemtype Type; elemsize int; slice *runtimeSlice; } func (v *sliceValueStruct) IsSlice() bool { return true } func (v *sliceValueStruct) Len() int { return int(v.slice.len); } func (v *sliceValueStruct) Cap() int { return int(v.slice.cap); } func (v *sliceValueStruct) SetLen(len int) { if len > v.Cap() { panicln("reflect: sliceValueStruct.SetLen", len, v.Cap()); } v.slice.len = uint32(len); } func (v *sliceValueStruct) Set(src ArrayValue) { if !src.IsSlice() { panic("can't set slice from array"); } s := src.(*sliceValueStruct); if !equalType(v.typ, s.typ) { panicln("incompatible types in ArrayValue.Set()"); } *v.slice = *s.slice; } func (v *sliceValueStruct) Elem(i int) Value { data_uint := uintptr(v.slice.data) + uintptr(i * v.elemsize); return newValueAddr(v.elemtype, Addr(data_uint)); } func (v *sliceValueStruct) CopyFrom(src ArrayValue, n int) { copyArray(v, src, n); } func (v *sliceValueStruct) IsNil() bool { return uintptr(v.slice.data) == 0 } type arrayValueStruct struct { commonValue; elemtype Type; elemsize int; len int; } func (v *arrayValueStruct) IsSlice() bool { return false } func (v *arrayValueStruct) Len() int { return v.len } func (v *arrayValueStruct) Cap() int { return v.len } func (v *arrayValueStruct) SetLen(len int) { panicln("can't set len of array"); } func (v *arrayValueStruct) Set(src ArrayValue) { panicln("can't set array"); } func (v *arrayValueStruct) Elem(i int) Value { data_uint := uintptr(v.addr) + uintptr(i * v.elemsize); return newValueAddr(v.elemtype, Addr(data_uint)); } func (v *arrayValueStruct) CopyFrom(src ArrayValue, n int) { copyArray(v, src, n); } func (v *arrayValueStruct) IsNil() bool { return false } func arrayCreator(typ Type, addr Addr) Value { arraytype := typ.(ArrayType); if arraytype.IsSlice() { v := new(sliceValueStruct); v.kind = ArrayKind; v.addr = addr; v.typ = typ; v.elemtype = arraytype.Elem(); v.elemsize = v.elemtype.Size(); v.slice = (*runtimeSlice)(addr); return v; } v := new(arrayValueStruct); v.kind = ArrayKind; v.addr = addr; v.typ = typ; v.elemtype = arraytype.Elem(); v.elemsize = v.elemtype.Size(); v.len = arraytype.Len(); return v; } // -- Map TODO: finish and test // MapValue represents a map value. // Its implementation is incomplete. type MapValue interface { Value; Len() int; // The number of elements; currently always returns 0. Elem(key Value) Value; // The value indexed by key; unimplemented. IsNil() bool; } type mapValueStruct struct { commonValue } func mapCreator(typ Type, addr Addr) Value { return &mapValueStruct{ commonValue{MapKind, typ, addr} } } func (v *mapValueStruct) Len() int { return 0 // TODO: probably want this to be dynamic } func (v *mapValueStruct) IsNil() bool { return false // TODO: implement this properly } func (v *mapValueStruct) Elem(key Value) Value { panic("map value element"); return nil } // -- Chan // ChanValue represents a chan value. // Its implementation is incomplete. type ChanValue interface { Value; IsNil() bool; } type chanValueStruct struct { commonValue } func (v *chanValueStruct) IsNil() bool { return false // TODO: implement this properly } func chanCreator(typ Type, addr Addr) Value { return &chanValueStruct{ commonValue{ChanKind, typ, addr} } } // -- Struct // StructValue represents a struct value. type StructValue interface { Value; Len() int; // The number of fields. Field(i int) Value; // The Value of field i. } type structValueStruct struct { commonValue; field []Value; } func (v *structValueStruct) Len() int { return len(v.field) } func (v *structValueStruct) Field(i int) Value { return v.field[i] } func structCreator(typ Type, addr Addr) Value { t := typ.(StructType); nfield := t.Len(); v := &structValueStruct{ commonValue{StructKind, typ, addr}, make([]Value, nfield) }; for i := 0; i < nfield; i++ { name, ftype, str, offset := t.Field(i); addr_uint := uintptr(addr) + uintptr(offset); v.field[i] = newValueAddr(ftype, Addr(addr_uint)); } v.typ = typ; return v; } // -- Interface // InterfaceValue represents an interface value. type InterfaceValue interface { Value; Get() interface {}; // Get the underlying interface{} value. Value() Value; IsNil() bool; } type interfaceValueStruct struct { commonValue } func (v *interfaceValueStruct) Get() interface{} { // There are two different representations of interface values, // one if the interface type has methods and one if it doesn't. // These two representations require different expressions // to extract correctly. if v.Type().(InterfaceType).Len() == 0 { // Extract as interface value without methods. return *(*interface{})(v.addr) } // Extract from v.addr as interface value with methods. return *(*interface{ m() })(v.addr) } func (v *interfaceValueStruct) Interface() interface{} { return v.Get(); } func (v *interfaceValueStruct) Value() Value { i := v.Get(); if i == nil { return nil; } return NewValue(i); } func (v *interfaceValueStruct) IsNil() bool { return *(*interface{})(v.addr) == nil } func interfaceCreator(typ Type, addr Addr) Value { return &interfaceValueStruct{ commonValue{InterfaceKind, typ, addr} } } // -- Func // FuncValue represents a func value. // Its implementation is incomplete. type FuncValue interface { Value; Get() Addr; // The address of the function. IsNil() bool; } type funcValueStruct struct { commonValue } func (v *funcValueStruct) Get() Addr { return *(*Addr)(v.addr) } func (v *funcValueStruct) IsNil() bool { return *(*Addr)(v.addr) == nil } func funcCreator(typ Type, addr Addr) Value { return &funcValueStruct{ commonValue{FuncKind, typ, addr} } } var creator = map[int] creatorFn { MissingKind : missingCreator, IntKind : intCreator, Int8Kind : int8Creator, Int16Kind : int16Creator, Int32Kind : int32Creator, Int64Kind : int64Creator, UintKind : uintCreator, Uint8Kind : uint8Creator, Uint16Kind : uint16Creator, Uint32Kind : uint32Creator, Uint64Kind : uint64Creator, UintptrKind : uintptrCreator, FloatKind : floatCreator, Float32Kind : float32Creator, Float64Kind : float64Creator, StringKind : stringCreator, BoolKind : boolCreator, PtrKind : ptrCreator, ArrayKind : arrayCreator, MapKind : mapCreator, ChanKind : chanCreator, StructKind : structCreator, InterfaceKind : interfaceCreator, FuncKind : funcCreator, } var typecache = make(map[string] Type); func newValueAddr(typ Type, addr Addr) Value { c, ok := creator[typ.Kind()]; if !ok { panicln("no creator for type" , typ.Kind()); } return c(typ, addr); } // NewZeroValue creates a new, zero-initialized Value for the specified Type. func NewZeroValue(typ Type) Value { size := typ.Size(); if size == 0 { size = 1; } data := make([]uint8, size); return newValueAddr(typ, Addr(&data[0])); } // NewSliceValue creates a new, zero-initialized slice value (ArrayValue) for the specified // slice type (ArrayType), length, and capacity. func NewSliceValue(typ ArrayType, len, cap int) ArrayValue { if !typ.IsSlice() { return nil } array := new(runtimeSlice); size := typ.Elem().Size() * cap; if size == 0 { size = 1; } data := make([]uint8, size); array.data = Addr(&data[0]); array.len = uint32(len); array.cap = uint32(cap); return newValueAddr(typ, Addr(array)).(ArrayValue); } // Works on both slices and arrays func copyArray(dst ArrayValue, src ArrayValue, n int) { if n == 0 { return } dt := dst.Type().(ArrayType).Elem(); st := src.Type().(ArrayType).Elem(); if !equalType(dt, st) { panicln("reflect: incompatible types in CopyArray:", dt.String(), st.String()); } if n < 0 || n > dst.Len() || n > src.Len() { panicln("reflect: CopyArray: invalid count", n); } dstp := uintptr(dst.Elem(0).Addr()); srcp := uintptr(src.Elem(0).Addr()); end := uintptr(n)*uintptr(dt.Size()); if end % 8 == 0 { for i := uintptr(0); i < end; i += 8{ di := Addr(dstp + i); si := Addr(srcp + i); *(*uint64)(di) = *(*uint64)(si); } } else { for i := uintptr(0); i < end; i++ { di := Addr(dstp + i); si := Addr(srcp + i); *(*byte)(di) = *(*byte)(si); } } } // NewValue creates a new Value from the interface{} object provided. func NewValue(e interface {}) Value { value, typestring, indir := unsafe.Reflect(e); typ, ok := typecache[typestring]; if !ok { typ = ParseTypeString("", typestring); typecache[typestring] = typ; } var ap Addr; if indir { // Content of interface is large and didn't // fit, so it's a pointer to the actual content. // We have an address, but we need to // make a copy to avoid letting the caller // edit the content inside the interface. n := uintptr(typ.Size()); data := make([]byte, n); p1 := uintptr(Addr(&data[0])); p2 := uintptr(value); for i := uintptr(0); i < n; i++ { *(*byte)(Addr(p1+i)) = *(*byte)(Addr(p2+i)); } ap = Addr(&data[0]); } else { // Content of interface is small and stored // inside the interface. Make a copy so we // can take its address. x := new(uint64); *x = value; ap = Addr(x); } return newValueAddr(typ, ap); } // Indirect indirects one level through a value, if it is a pointer. // If not a pointer, the value is returned unchanged. // Useful when walking arbitrary data structures. func Indirect(v Value) Value { if v.Kind() == PtrKind { p := v.(PtrValue); if p.Get() == nil { return nil } v = p.Sub() } return v }