Commit 87783933 authored by Russ Cox's avatar Russ Cox

gob: use new reflect

R=r
DELTA=242  (68 added, 69 deleted, 105 changed)
OCL=31239
CL=31289
parent e37f81b4
...@@ -278,7 +278,7 @@ type decEngine struct { ...@@ -278,7 +278,7 @@ type decEngine struct {
instr []decInstr instr []decInstr
} }
func decodeStruct(engine *decEngine, rtyp reflect.StructType, r io.Reader, p uintptr, indir int) os.Error { func decodeStruct(engine *decEngine, rtyp *reflect.StructType, r io.Reader, p uintptr, indir int) os.Error {
if indir > 0 { if indir > 0 {
up := unsafe.Pointer(p); up := unsafe.Pointer(p);
if *(*unsafe.Pointer)(up) == nil { if *(*unsafe.Pointer)(up) == nil {
...@@ -317,7 +317,7 @@ func decodeStruct(engine *decEngine, rtyp reflect.StructType, r io.Reader, p uin ...@@ -317,7 +317,7 @@ func decodeStruct(engine *decEngine, rtyp reflect.StructType, r io.Reader, p uin
return state.err return state.err
} }
func decodeArrayHelper(state *DecState, p uintptr, elemOp decOp, elemWid, length, elemIndir int) os.Error { func decodeArrayHelper(state *DecState, p uintptr, elemOp decOp, elemWid uintptr, length, elemIndir int) os.Error {
instr := &decInstr{elemOp, 0, elemIndir, 0}; instr := &decInstr{elemOp, 0, elemIndir, 0};
for i := 0; i < length && state.err == nil; i++ { for i := 0; i < length && state.err == nil; i++ {
up := unsafe.Pointer(p); up := unsafe.Pointer(p);
...@@ -330,7 +330,7 @@ func decodeArrayHelper(state *DecState, p uintptr, elemOp decOp, elemWid, length ...@@ -330,7 +330,7 @@ func decodeArrayHelper(state *DecState, p uintptr, elemOp decOp, elemWid, length
return state.err return state.err
} }
func decodeArray(atyp reflect.ArrayType, state *DecState, p uintptr, elemOp decOp, elemWid, length, indir, elemIndir int) os.Error { func decodeArray(atyp *reflect.ArrayType, state *DecState, p uintptr, elemOp decOp, elemWid uintptr, length, indir, elemIndir int) os.Error {
if indir > 0 { if indir > 0 {
up := unsafe.Pointer(p); up := unsafe.Pointer(p);
if *(*unsafe.Pointer)(up) == nil { if *(*unsafe.Pointer)(up) == nil {
...@@ -341,14 +341,14 @@ func decodeArray(atyp reflect.ArrayType, state *DecState, p uintptr, elemOp decO ...@@ -341,14 +341,14 @@ func decodeArray(atyp reflect.ArrayType, state *DecState, p uintptr, elemOp decO
} }
p = *(*uintptr)(up); p = *(*uintptr)(up);
} }
if DecodeUint(state) != uint64(length) { if n := DecodeUint(state); n != uint64(length) {
return os.ErrorString("length mismatch in decodeArray"); return os.ErrorString("length mismatch in decodeArray");
} }
return decodeArrayHelper(state, p, elemOp, elemWid, length, elemIndir); return decodeArrayHelper(state, p, elemOp, elemWid, length, elemIndir);
} }
func decodeSlice(atyp reflect.ArrayType, state *DecState, p uintptr, elemOp decOp, elemWid, indir, elemIndir int) os.Error { func decodeSlice(atyp *reflect.SliceType, state *DecState, p uintptr, elemOp decOp, elemWid uintptr, indir, elemIndir int) os.Error {
length := int(DecodeUint(state)); length := uintptr(DecodeUint(state));
if indir > 0 { if indir > 0 {
up := unsafe.Pointer(p); up := unsafe.Pointer(p);
if *(*unsafe.Pointer)(up) == nil { if *(*unsafe.Pointer)(up) == nil {
...@@ -364,59 +364,58 @@ func decodeSlice(atyp reflect.ArrayType, state *DecState, p uintptr, elemOp decO ...@@ -364,59 +364,58 @@ func decodeSlice(atyp reflect.ArrayType, state *DecState, p uintptr, elemOp decO
hdrp.Data = uintptr(unsafe.Pointer(&data[0])); hdrp.Data = uintptr(unsafe.Pointer(&data[0]));
hdrp.Len = uint32(length); hdrp.Len = uint32(length);
hdrp.Cap = uint32(length); hdrp.Cap = uint32(length);
return decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, length, elemIndir); return decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, int(length), elemIndir);
} }
var decEngineMap = make(map[reflect.Type] *decEngine) var decEngineMap = make(map[reflect.Type] *decEngine)
var decOpMap = map[int] decOp { var decOpMap = map[reflect.Type] decOp {
reflect.BoolKind: decBool, reflect.Typeof((*reflect.BoolType)(nil)): decBool,
reflect.IntKind: decInt, reflect.Typeof((*reflect.IntType)(nil)): decInt,
reflect.Int8Kind: decInt8, reflect.Typeof((*reflect.Int8Type)(nil)): decInt8,
reflect.Int16Kind: decInt16, reflect.Typeof((*reflect.Int16Type)(nil)): decInt16,
reflect.Int32Kind: decInt32, reflect.Typeof((*reflect.Int32Type)(nil)): decInt32,
reflect.Int64Kind: decInt64, reflect.Typeof((*reflect.Int64Type)(nil)): decInt64,
reflect.UintKind: decUint, reflect.Typeof((*reflect.UintType)(nil)): decUint,
reflect.Uint8Kind: decUint8, reflect.Typeof((*reflect.Uint8Type)(nil)): decUint8,
reflect.Uint16Kind: decUint16, reflect.Typeof((*reflect.Uint16Type)(nil)): decUint16,
reflect.Uint32Kind: decUint32, reflect.Typeof((*reflect.Uint32Type)(nil)): decUint32,
reflect.Uint64Kind: decUint64, reflect.Typeof((*reflect.Uint64Type)(nil)): decUint64,
reflect.FloatKind: decFloat, reflect.Typeof((*reflect.FloatType)(nil)): decFloat,
reflect.Float32Kind: decFloat32, reflect.Typeof((*reflect.Float32Type)(nil)): decFloat32,
reflect.Float64Kind: decFloat64, reflect.Typeof((*reflect.Float64Type)(nil)): decFloat64,
reflect.StringKind: decString, reflect.Typeof((*reflect.StringType)(nil)): decString,
} }
func getDecEngine(rt reflect.Type) *decEngine func getDecEngine(rt reflect.Type) *decEngine
func decOpFor(typ reflect.Type) decOp { func decOpFor(typ reflect.Type) decOp {
op, ok := decOpMap[typ.Kind()]; op, ok := decOpMap[reflect.Typeof(typ)];
if !ok { if !ok {
// Special cases // Special cases
if typ.Kind() == reflect.ArrayKind { switch t := typ.(type) {
atyp := typ.(reflect.ArrayType); case *reflect.SliceType:
switch { if _, ok := t.Elem().(*reflect.Uint8Type); ok {
case atyp.Elem().Kind() == reflect.Uint8Kind: op = decUint8Array;
op = decUint8Array break;
case atyp.IsSlice():
elemOp := decOpFor(atyp.Elem());
_, elemIndir := indirect(atyp.Elem());
op = func(i *decInstr, state *DecState, p unsafe.Pointer) {
state.err = decodeSlice(atyp, state, uintptr(p), elemOp, atyp.Elem().Size(), i.indir, elemIndir);
};
case !atyp.IsSlice():
elemOp := decOpFor(atyp.Elem());
_, elemIndir := indirect(atyp.Elem());
op = func(i *decInstr, state *DecState, p unsafe.Pointer) {
state.err = decodeArray(atyp, state, uintptr(p), elemOp, atyp.Elem().Size(), atyp.Len(), i.indir, elemIndir);
};
} }
} elemOp := decOpFor(t.Elem());
if typ.Kind() == reflect.StructKind { _, elemIndir := indirect(t.Elem());
op = func(i *decInstr, state *DecState, p unsafe.Pointer) {
state.err = decodeSlice(t, state, uintptr(p), elemOp, t.Elem().Size(), i.indir, elemIndir);
};
case *reflect.ArrayType:
elemOp := decOpFor(t.Elem());
_, elemIndir := indirect(t.Elem());
op = func(i *decInstr, state *DecState, p unsafe.Pointer) {
state.err = decodeArray(t, state, uintptr(p), elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir);
};
case *reflect.StructType:
// Generate a closure that calls out to the engine for the nested type. // Generate a closure that calls out to the engine for the nested type.
engine := getDecEngine(typ); engine := getDecEngine(typ);
styp := typ.(reflect.StructType);
op = func(i *decInstr, state *DecState, p unsafe.Pointer) { op = func(i *decInstr, state *DecState, p unsafe.Pointer) {
state.err = decodeStruct(engine, styp, state.r, uintptr(p), i.indir) state.err = decodeStruct(engine, t, state.r, uintptr(p), i.indir)
}; };
} }
} }
...@@ -427,7 +426,7 @@ func decOpFor(typ reflect.Type) decOp { ...@@ -427,7 +426,7 @@ func decOpFor(typ reflect.Type) decOp {
} }
func compileDec(rt reflect.Type, typ Type) *decEngine { func compileDec(rt reflect.Type, typ Type) *decEngine {
srt, ok1 := rt.(reflect.StructType); srt, ok1 := rt.(*reflect.StructType);
styp, ok2 := typ.(*structType); styp, ok2 := typ.(*structType);
if !ok1 || !ok2 { if !ok1 || !ok2 {
panicln("TODO: can't handle non-structs"); panicln("TODO: can't handle non-structs");
...@@ -438,19 +437,10 @@ func compileDec(rt reflect.Type, typ Type) *decEngine { ...@@ -438,19 +437,10 @@ func compileDec(rt reflect.Type, typ Type) *decEngine {
field := styp.field[fieldnum]; field := styp.field[fieldnum];
// TODO(r): verify compatibility with corresponding field of data. // TODO(r): verify compatibility with corresponding field of data.
// For now, assume perfect correspondence between struct and gob. // For now, assume perfect correspondence between struct and gob.
_name, ftyp, _tag, offset := srt.Field(fieldnum); f := srt.Field(fieldnum);
// How many indirections to the underlying data? ftyp, indir := indirect(f.Type);
indir := 0;
for {
pt, ok := ftyp.(reflect.PtrType);
if !ok {
break
}
ftyp = pt.Sub();
indir++;
}
op := decOpFor(ftyp); op := decOpFor(ftyp);
engine.instr[fieldnum] = decInstr{op, fieldnum, indir, uintptr(offset)}; engine.instr[fieldnum] = decInstr{op, fieldnum, indir, uintptr(f.Offset)};
} }
return engine; return engine;
} }
...@@ -459,7 +449,8 @@ func compileDec(rt reflect.Type, typ Type) *decEngine { ...@@ -459,7 +449,8 @@ func compileDec(rt reflect.Type, typ Type) *decEngine {
func getDecEngine(rt reflect.Type) *decEngine { func getDecEngine(rt reflect.Type) *decEngine {
engine, ok := decEngineMap[rt]; engine, ok := decEngineMap[rt];
if !ok { if !ok {
return compileDec(rt, newType(rt.Name(), rt)); pkg, name := rt.Name();
engine = compileDec(rt, newType(name, rt));
decEngineMap[rt] = engine; decEngineMap[rt] = engine;
} }
return engine; return engine;
...@@ -472,11 +463,11 @@ func Decode(r io.Reader, e interface{}) os.Error { ...@@ -472,11 +463,11 @@ func Decode(r io.Reader, e interface{}) os.Error {
for i := 0; i < indir; i++ { for i := 0; i < indir; i++ {
v = reflect.Indirect(v); v = reflect.Indirect(v);
} }
if rt.Kind() != reflect.StructKind { if _, ok := v.(*reflect.StructValue); !ok {
return os.ErrorString("decode can't handle " + rt.String()) return os.ErrorString("decode can't handle " + rt.String())
} }
typeLock.Lock(); typeLock.Lock();
engine := getDecEngine(rt); engine := getDecEngine(rt);
typeLock.Unlock(); typeLock.Unlock();
return decodeStruct(engine, rt.(reflect.StructType), r, uintptr(v.Addr()), 0); return decodeStruct(engine, rt.(*reflect.StructType), r, uintptr(v.Addr()), 0);
} }
...@@ -14,21 +14,6 @@ import ( ...@@ -14,21 +14,6 @@ import (
"unsafe"; "unsafe";
) )
// Step through the indirections on a type to discover the base type.
// Return the number of indirections.
func indirect(t reflect.Type) (rt reflect.Type, count int) {
rt = t;
for {
pt, ok := rt.(reflect.PtrType);
if !ok {
break
}
rt = pt.Sub();
count++;
}
return;
}
// The global execution state of an instance of the encoder. // The global execution state of an instance of the encoder.
// Field numbers are delta encoded and always increase. The field // Field numbers are delta encoded and always increase. The field
// number is initialized to -1 so 0 comes out as delta(1). A delta of // number is initialized to -1 so 0 comes out as delta(1). A delta of
...@@ -295,7 +280,7 @@ func encodeStruct(engine *encEngine, w io.Writer, basep uintptr) os.Error { ...@@ -295,7 +280,7 @@ func encodeStruct(engine *encEngine, w io.Writer, basep uintptr) os.Error {
return state.err return state.err
} }
func encodeArray(w io.Writer, p uintptr, op encOp, elemWid int, length int, elemIndir int) os.Error { func encodeArray(w io.Writer, p uintptr, op encOp, elemWid uintptr, length int, elemIndir int) os.Error {
state := new(EncState); state := new(EncState);
state.w = w; state.w = w;
state.fieldnum = -1; state.fieldnum = -1;
...@@ -316,58 +301,56 @@ func encodeArray(w io.Writer, p uintptr, op encOp, elemWid int, length int, elem ...@@ -316,58 +301,56 @@ func encodeArray(w io.Writer, p uintptr, op encOp, elemWid int, length int, elem
} }
var encEngineMap = make(map[reflect.Type] *encEngine) var encEngineMap = make(map[reflect.Type] *encEngine)
var encOpMap = map[int] encOp { var encOpMap = map[reflect.Type] encOp {
reflect.BoolKind: encBool, reflect.Typeof((*reflect.BoolType)(nil)): encBool,
reflect.IntKind: encInt, reflect.Typeof((*reflect.IntType)(nil)): encInt,
reflect.Int8Kind: encInt8, reflect.Typeof((*reflect.Int8Type)(nil)): encInt8,
reflect.Int16Kind: encInt16, reflect.Typeof((*reflect.Int16Type)(nil)): encInt16,
reflect.Int32Kind: encInt32, reflect.Typeof((*reflect.Int32Type)(nil)): encInt32,
reflect.Int64Kind: encInt64, reflect.Typeof((*reflect.Int64Type)(nil)): encInt64,
reflect.UintKind: encUint, reflect.Typeof((*reflect.UintType)(nil)): encUint,
reflect.Uint8Kind: encUint8, reflect.Typeof((*reflect.Uint8Type)(nil)): encUint8,
reflect.Uint16Kind: encUint16, reflect.Typeof((*reflect.Uint16Type)(nil)): encUint16,
reflect.Uint32Kind: encUint32, reflect.Typeof((*reflect.Uint32Type)(nil)): encUint32,
reflect.Uint64Kind: encUint64, reflect.Typeof((*reflect.Uint64Type)(nil)): encUint64,
reflect.FloatKind: encFloat, reflect.Typeof((*reflect.FloatType)(nil)): encFloat,
reflect.Float32Kind: encFloat32, reflect.Typeof((*reflect.Float32Type)(nil)): encFloat32,
reflect.Float64Kind: encFloat64, reflect.Typeof((*reflect.Float64Type)(nil)): encFloat64,
reflect.StringKind: encString, reflect.Typeof((*reflect.StringType)(nil)): encString,
} }
func getEncEngine(rt reflect.Type) *encEngine func getEncEngine(rt reflect.Type) *encEngine
func encOpFor(typ reflect.Type) encOp { func encOpFor(typ reflect.Type) encOp {
op, ok := encOpMap[typ.Kind()]; op, ok := encOpMap[reflect.Typeof(typ)];
if !ok { if !ok {
// Special cases // Special cases
if typ.Kind() == reflect.ArrayKind { switch t := typ.(type) {
atyp := typ.(reflect.ArrayType); case *reflect.SliceType:
switch { if _, ok := t.Elem().(*reflect.Uint8Type); ok {
case atyp.Elem().Kind() == reflect.Uint8Kind: op = encUint8Array;
op = encUint8Array break;
case atyp.IsSlice():
// Slices have a header; we decode it to find the underlying array.
elemOp := encOpFor(atyp.Elem());
_, indir := indirect(atyp.Elem());
op = func(i *encInstr, state *EncState, p unsafe.Pointer) {
slice := *(*reflect.SliceHeader)(p);
if slice.Len == 0 {
return
}
state.update(i);
state.err = encodeArray(state.w, slice.Data, elemOp, atyp.Elem().Size(), int(slice.Len), indir);
};
case !atyp.IsSlice():
// True arrays have size in the type.
elemOp := encOpFor(atyp.Elem());
_, indir := indirect(atyp.Elem());
op = func(i *encInstr, state *EncState, p unsafe.Pointer) {
state.update(i);
state.err = encodeArray(state.w, uintptr(p), elemOp, atyp.Elem().Size(), atyp.Len(), indir);
};
} }
} // Slices have a header; we decode it to find the underlying array.
if typ.Kind() == reflect.StructKind { elemOp := encOpFor(t.Elem());
_, indir := indirect(t.Elem());
op = func(i *encInstr, state *EncState, p unsafe.Pointer) {
slice := (*reflect.SliceHeader)(p);
if slice.Len == 0 {
return
}
state.update(i);
state.err = encodeArray(state.w, slice.Data, elemOp, t.Elem().Size(), int(slice.Len), indir);
};
case *reflect.ArrayType:
// True arrays have size in the type.
elemOp := encOpFor(t.Elem());
_, indir := indirect(t.Elem());
op = func(i *encInstr, state *EncState, p unsafe.Pointer) {
state.update(i);
state.err = encodeArray(state.w, uintptr(p), elemOp, t.Elem().Size(), t.Len(), indir);
};
case *reflect.StructType:
// Generate a closure that calls out to the engine for the nested type. // Generate a closure that calls out to the engine for the nested type.
engine := getEncEngine(typ); engine := getEncEngine(typ);
op = func(i *encInstr, state *EncState, p unsafe.Pointer) { op = func(i *encInstr, state *EncState, p unsafe.Pointer) {
...@@ -386,28 +369,19 @@ func encOpFor(typ reflect.Type) encOp { ...@@ -386,28 +369,19 @@ func encOpFor(typ reflect.Type) encOp {
// it's compatible. // it's compatible.
// TODO(r): worth checking? typ is unused here. // TODO(r): worth checking? typ is unused here.
func compileEnc(rt reflect.Type, typ Type) *encEngine { func compileEnc(rt reflect.Type, typ Type) *encEngine {
srt, ok := rt.(reflect.StructType); srt, ok := rt.(*reflect.StructType);
if !ok { if !ok {
panicln("TODO: can't handle non-structs"); panicln("TODO: can't handle non-structs");
} }
engine := new(encEngine); engine := new(encEngine);
engine.instr = make([]encInstr, srt.Len()+1); // +1 for terminator engine.instr = make([]encInstr, srt.NumField()+1); // +1 for terminator
for fieldnum := 0; fieldnum < srt.Len(); fieldnum++ { for fieldnum := 0; fieldnum < srt.NumField(); fieldnum++ {
_name, ftyp, _tag, offset := srt.Field(fieldnum); f := srt.Field(fieldnum);
// How many indirections to the underlying data? ftyp, indir := indirect(f.Type);
indir := 0;
for {
pt, ok := ftyp.(reflect.PtrType);
if !ok {
break
}
ftyp = pt.Sub();
indir++;
}
op := encOpFor(ftyp); op := encOpFor(ftyp);
engine.instr[fieldnum] = encInstr{op, fieldnum, indir, uintptr(offset)}; engine.instr[fieldnum] = encInstr{op, fieldnum, indir, uintptr(f.Offset)};
} }
engine.instr[srt.Len()] = encInstr{encStructTerminator, 0, 0, 0}; engine.instr[srt.NumField()] = encInstr{encStructTerminator, 0, 0, 0};
return engine; return engine;
} }
...@@ -415,7 +389,8 @@ func compileEnc(rt reflect.Type, typ Type) *encEngine { ...@@ -415,7 +389,8 @@ func compileEnc(rt reflect.Type, typ Type) *encEngine {
func getEncEngine(rt reflect.Type) *encEngine { func getEncEngine(rt reflect.Type) *encEngine {
engine, ok := encEngineMap[rt]; engine, ok := encEngineMap[rt];
if !ok { if !ok {
engine = compileEnc(rt, newType(rt.Name(), rt)); pkg, name := rt.Name();
engine = compileEnc(rt, newType(name, rt));
encEngineMap[rt] = engine; encEngineMap[rt] = engine;
} }
return engine return engine
...@@ -428,11 +403,11 @@ func Encode(w io.Writer, e interface{}) os.Error { ...@@ -428,11 +403,11 @@ func Encode(w io.Writer, e interface{}) os.Error {
for i := 0; i < indir; i++ { for i := 0; i < indir; i++ {
v = reflect.Indirect(v); v = reflect.Indirect(v);
} }
if v.Kind() != reflect.StructKind { if _, ok := v.(*reflect.StructValue); !ok {
return os.ErrorString("encode can't handle " + v.Type().String()) return os.ErrorString("encode can't handle " + v.Type().String())
} }
typeLock.Lock(); typeLock.Lock();
engine := getEncEngine(rt); engine := getEncEngine(rt);
typeLock.Unlock(); typeLock.Unlock();
return encodeStruct(engine, w, uintptr(v.(reflect.StructValue).Addr())); return encodeStruct(engine, w, v.Addr());
} }
...@@ -141,50 +141,79 @@ func newStructType(name string) *structType { ...@@ -141,50 +141,79 @@ func newStructType(name string) *structType {
// Construction // Construction
func newType(name string, rt reflect.Type) Type func newType(name string, rt reflect.Type) Type
// Step through the indirections on a type to discover the base type.
// Return the number of indirections.
func indirect(t reflect.Type) (rt reflect.Type, count int) {
rt = t;
for {
pt, ok := rt.(*reflect.PtrType);
if !ok {
break;
}
rt = pt.Elem();
count++;
}
return;
}
func newTypeObject(name string, rt reflect.Type) Type { func newTypeObject(name string, rt reflect.Type) Type {
switch rt.Kind() { switch t := rt.(type) {
// All basic types are easy: they are predefined. // All basic types are easy: they are predefined.
case reflect.BoolKind: case *reflect.BoolType:
return tBool return tBool
case reflect.IntKind, reflect.Int32Kind, reflect.Int64Kind:
case *reflect.IntType:
return tInt return tInt
case reflect.UintKind, reflect.Uint32Kind, reflect.Uint64Kind: case *reflect.Int32Type:
return tInt
case *reflect.Int64Type:
return tInt
case *reflect.UintType:
return tUint
case *reflect.Uint32Type:
return tUint
case *reflect.Uint64Type:
return tUint return tUint
case reflect.FloatKind, reflect.Float32Kind, reflect.Float64Kind:
case *reflect.FloatType:
return tFloat
case *reflect.Float32Type:
return tFloat
case *reflect.Float64Type:
return tFloat return tFloat
case reflect.StringKind:
case *reflect.StringType:
return tString return tString
case reflect.ArrayKind:
at := rt.(reflect.ArrayType); case *reflect.ArrayType:
if at.IsSlice() { return newArrayType(name, newType("", t.Elem()), t.Len());
// []byte == []uint8 is a special case
if at.Elem().Kind() == reflect.Uint8Kind { case *reflect.SliceType:
return tBytes // []byte == []uint8 is a special case
} if _, ok := t.Elem().(*reflect.Uint8Type); ok {
return newSliceType(name, newType("", at.Elem())); return tBytes
} else {
return newArrayType(name, newType("", at.Elem()), at.Len());
} }
case reflect.StructKind: return newSliceType(name, newType("", t.Elem()));
case *reflect.StructType:
// Install the struct type itself before the fields so recursive // Install the struct type itself before the fields so recursive
// structures can be constructed safely. // structures can be constructed safely.
strType := newStructType(name); strType := newStructType(name);
types[rt] = strType; types[rt] = strType;
st := rt.(reflect.StructType); field := make([]*fieldType, t.NumField());
field := make([]*fieldType, st.Len()); for i := 0; i < t.NumField(); i++ {
for i := 0; i < st.Len(); i++ { f := t.Field(i);
name, typ, _tag, _offset := st.Field(i); typ, _indir := indirect(f.Type);
// Find trailing name in type, e.g. from "*gob.Bar" want "Bar", which _pkg, tname := typ.Name();
// is defined as the word after the period (there is at most one period). if tname == "" {
typestring := typ.String(); tname = f.Type.String();
period := strings.Index(typestring, ".");
if period >= 0 {
typestring = typestring[period+1:len(typestring)]
} }
field[i] = &fieldType{ name, newType(typestring, typ) }; field[i] = &fieldType{ f.Name, newType(tname, f.Type) };
} }
strType.field = field; strType.field = field;
return strType; return strType;
default: default:
panicln("gob NewTypeObject can't handle type", rt.String()); // TODO(r): panic? panicln("gob NewTypeObject can't handle type", rt.String()); // TODO(r): panic?
} }
...@@ -193,8 +222,12 @@ func newTypeObject(name string, rt reflect.Type) Type { ...@@ -193,8 +222,12 @@ func newTypeObject(name string, rt reflect.Type) Type {
func newType(name string, rt reflect.Type) Type { func newType(name string, rt reflect.Type) Type {
// Flatten the data structure by collapsing out pointers // Flatten the data structure by collapsing out pointers
for rt.Kind() == reflect.PtrKind { for {
rt = rt.(reflect.PtrType).Sub(); pt, ok := rt.(*reflect.PtrType);
if !ok {
break;
}
rt = pt.Elem();
} }
typ, present := types[rt]; typ, present := types[rt];
if present { if present {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment