1
0
mirror of https://github.com/golang/go synced 2024-11-24 23:47:55 -07:00

gob: several fixes.

1) Be sure to use the eval-time encoder/decoder rather than
the compile-time decoder.  In a few cases the receiver for
the compiling encoder was being pickled incorrectly into a
closure.
(This is the fix for issue 1238).

2) Get the innermost name right when given a pointer to an
unnamed type.

3) Use a count to delineate interface values, making it
possible to ignore values without having a concrete type
to encode into.  This is a protocol change but only for the
new feature, so it shouldn't affect anyone.  The old test
worked because, amazingly, it depended on bug #1.

Fixes #1238.

R=rsc, albert.strasheim
CC=golang-dev
https://golang.org/cl/2806041
This commit is contained in:
Rob Pike 2010-10-31 13:41:30 -07:00
parent f62772b1e5
commit 7f7cb166c8
7 changed files with 104 additions and 77 deletions

View File

@ -50,7 +50,7 @@ func testError(t *testing.T) {
func TestUintCodec(t *testing.T) {
defer testError(t)
b := new(bytes.Buffer)
encState := newEncoderState(b)
encState := newEncoderState(nil, b)
for _, tt := range encodeT {
b.Reset()
encodeUint(encState, tt.x)
@ -58,7 +58,7 @@ func TestUintCodec(t *testing.T) {
t.Errorf("encodeUint: %#x encode: expected % x got % x", tt.x, tt.b, b.Bytes())
}
}
decState := newDecodeState(&b)
decState := newDecodeState(nil, &b)
for u := uint64(0); ; u = (u + 1) * 7 {
b.Reset()
encodeUint(encState, u)
@ -75,9 +75,9 @@ func TestUintCodec(t *testing.T) {
func verifyInt(i int64, t *testing.T) {
defer testError(t)
var b = new(bytes.Buffer)
encState := newEncoderState(b)
encState := newEncoderState(nil, b)
encodeInt(encState, i)
decState := newDecodeState(&b)
decState := newDecodeState(nil, &b)
decState.buf = make([]byte, 8)
j := decodeInt(decState)
if i != j {
@ -113,7 +113,7 @@ var bytesResult = []byte{0x07, 0x05, 'h', 'e', 'l', 'l', 'o'}
func newencoderState(b *bytes.Buffer) *encoderState {
b.Reset()
state := newEncoderState(b)
state := newEncoderState(nil, b)
state.fieldnum = -1
return state
}
@ -327,7 +327,7 @@ func execDec(typ string, instr *decInstr, state *decodeState, t *testing.T, p un
func newDecodeStateFromData(data []byte) *decodeState {
b := bytes.NewBuffer(data)
state := newDecodeState(&b)
state := newDecodeState(nil, &b)
state.fieldnum = -1
return state
}
@ -1125,6 +1125,14 @@ func (v Vector) Square() int {
return sum
}
type Point struct {
a, b int
}
func (p Point) Square() int {
return p.a*p.a + p.b*p.b
}
// A struct with interfaces in it.
type InterfaceItem struct {
i int
@ -1243,15 +1251,15 @@ func TestInterfaceBasic(t *testing.T) {
func TestIgnoreInterface(t *testing.T) {
iVal := Int(3)
fVal := Float(5)
// Sending a Vector will require that the receiver define a type in the middle of
// Sending a Point will require that the receiver define a type in the middle of
// receiving the value for item2.
vVal := Vector{1, 2, 3}
pVal := Point{2, 3}
b := new(bytes.Buffer)
item1 := &InterfaceItem{1, iVal, fVal, vVal, 11.5, nil}
item1 := &InterfaceItem{1, iVal, fVal, pVal, 11.5, nil}
// Register the types.
Register(Int(0))
Register(Float(0))
Register(Vector{})
Register(Point{})
err := NewEncoder(b).Encode(item1)
if err != nil {
t.Error("expected no encode error; got", err)

View File

@ -78,13 +78,13 @@ func (dec *Decoder) debug() {
if dec.err != nil {
return
}
dec.debugFromBuffer(0)
dec.debugFromBuffer(0, false)
}
// printFromBuffer prints the next value. The buffer contains data, but it may
// be a type descriptor and we may need to load more data to see the value;
// printType takes care of that.
func (dec *Decoder) debugFromBuffer(indent int) {
func (dec *Decoder) debugFromBuffer(indent int, countPresent bool) {
for dec.state.b.Len() > 0 {
// Receive a type id.
id := typeId(decodeInt(dec.state))
@ -106,6 +106,9 @@ func (dec *Decoder) debugFromBuffer(indent int) {
dec.err = errBadType
break
}
if countPresent {
decodeUint(dec.state)
}
dec.debugPrint(indent, id)
break
}
@ -261,7 +264,7 @@ func (dec *Decoder) printBuiltin(indent int, id typeId) {
fmt.Printf("nil interface")
} else {
fmt.Printf("interface value; type %q\n", b)
dec.debugFromBuffer(indent)
dec.debugFromBuffer(indent, true)
}
default:
fmt.Print("unknown\n")
@ -272,7 +275,7 @@ func (dec *Decoder) debugStruct(indent int, id typeId, wire *wireType) {
tab(indent)
fmt.Printf("%s struct {\n", id.Name())
strct := wire.structT
state := newDecodeState(dec.state.b)
state := newDecodeState(dec, dec.state.b)
state.fieldnum = -1
for dec.err == nil {
delta := int(decodeUint(state))

View File

@ -25,6 +25,7 @@ var (
// The execution state of an instance of the decoder. A new state
// is created for nested objects.
type decodeState struct {
dec *Decoder
// The buffer is stored with an extra indirection because it may be replaced
// if we load a type during decode (when reading an interface value).
b **bytes.Buffer
@ -32,8 +33,9 @@ type decodeState struct {
buf []byte
}
func newDecodeState(b **bytes.Buffer) *decodeState {
func newDecodeState(dec *Decoder, b **bytes.Buffer) *decodeState {
d := new(decodeState)
d.dec = dec
d.b = b
d.buf = make([]byte, uint64Size)
return d
@ -401,10 +403,10 @@ func allocate(rtyp reflect.Type, p uintptr, indir int) uintptr {
return *(*uintptr)(up)
}
func decodeSingle(engine *decEngine, rtyp reflect.Type, b **bytes.Buffer, p uintptr, indir int) (err os.Error) {
func (dec *Decoder) decodeSingle(engine *decEngine, rtyp reflect.Type, b **bytes.Buffer, p uintptr, indir int) (err os.Error) {
defer catchError(&err)
p = allocate(rtyp, p, indir)
state := newDecodeState(b)
state := newDecodeState(dec, b)
state.fieldnum = singletonField
basep := p
delta := int(decodeUint(state))
@ -423,7 +425,7 @@ func decodeSingle(engine *decEngine, rtyp reflect.Type, b **bytes.Buffer, p uint
func (dec *Decoder) decodeStruct(engine *decEngine, rtyp *reflect.StructType, b **bytes.Buffer, p uintptr, indir int) (err os.Error) {
defer catchError(&err)
p = allocate(rtyp, p, indir)
state := newDecodeState(b)
state := newDecodeState(dec, b)
state.fieldnum = -1
basep := p
for state.b.Len() > 0 {
@ -450,9 +452,9 @@ func (dec *Decoder) decodeStruct(engine *decEngine, rtyp *reflect.StructType, b
return nil
}
func ignoreStruct(engine *decEngine, b **bytes.Buffer) (err os.Error) {
func (dec *Decoder) ignoreStruct(engine *decEngine, b **bytes.Buffer) (err os.Error) {
defer catchError(&err)
state := newDecodeState(b)
state := newDecodeState(dec, b)
state.fieldnum = -1
for state.b.Len() > 0 {
delta := int(decodeUint(state))
@ -473,7 +475,7 @@ func ignoreStruct(engine *decEngine, b **bytes.Buffer) (err os.Error) {
return nil
}
func decodeArrayHelper(state *decodeState, p uintptr, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl os.ErrorString) {
func (dec *Decoder) decodeArrayHelper(state *decodeState, p uintptr, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl os.ErrorString) {
instr := &decInstr{elemOp, 0, elemIndir, 0, ovfl}
for i := 0; i < length; i++ {
up := unsafe.Pointer(p)
@ -485,14 +487,14 @@ func decodeArrayHelper(state *decodeState, p uintptr, elemOp decOp, elemWid uint
}
}
func decodeArray(atyp *reflect.ArrayType, state *decodeState, p uintptr, elemOp decOp, elemWid uintptr, length, indir, elemIndir int, ovfl os.ErrorString) {
func (dec *Decoder) decodeArray(atyp *reflect.ArrayType, state *decodeState, p uintptr, elemOp decOp, elemWid uintptr, length, indir, elemIndir int, ovfl os.ErrorString) {
if indir > 0 {
p = allocate(atyp, p, 1) // All but the last level has been allocated by dec.Indirect
}
if n := decodeUint(state); n != uint64(length) {
errorf("gob: length mismatch in decodeArray")
}
decodeArrayHelper(state, p, elemOp, elemWid, length, elemIndir, ovfl)
dec.decodeArrayHelper(state, p, elemOp, elemWid, length, elemIndir, ovfl)
}
func decodeIntoValue(state *decodeState, op decOp, indir int, v reflect.Value, ovfl os.ErrorString) reflect.Value {
@ -505,7 +507,7 @@ func decodeIntoValue(state *decodeState, op decOp, indir int, v reflect.Value, o
return v
}
func decodeMap(mtyp *reflect.MapType, state *decodeState, p uintptr, keyOp, elemOp decOp, indir, keyIndir, elemIndir int, ovfl os.ErrorString) {
func (dec *Decoder) decodeMap(mtyp *reflect.MapType, state *decodeState, p uintptr, keyOp, elemOp decOp, indir, keyIndir, elemIndir int, ovfl os.ErrorString) {
if indir > 0 {
p = allocate(mtyp, p, 1) // All but the last level has been allocated by dec.Indirect
}
@ -526,21 +528,21 @@ func decodeMap(mtyp *reflect.MapType, state *decodeState, p uintptr, keyOp, elem
}
}
func ignoreArrayHelper(state *decodeState, elemOp decOp, length int) {
func (dec *Decoder) ignoreArrayHelper(state *decodeState, elemOp decOp, length int) {
instr := &decInstr{elemOp, 0, 0, 0, os.ErrorString("no error")}
for i := 0; i < length; i++ {
elemOp(instr, state, nil)
}
}
func ignoreArray(state *decodeState, elemOp decOp, length int) {
func (dec *Decoder) ignoreArray(state *decodeState, elemOp decOp, length int) {
if n := decodeUint(state); n != uint64(length) {
errorf("gob: length mismatch in ignoreArray")
}
ignoreArrayHelper(state, elemOp, length)
dec.ignoreArrayHelper(state, elemOp, length)
}
func ignoreMap(state *decodeState, keyOp, elemOp decOp) {
func (dec *Decoder) ignoreMap(state *decodeState, keyOp, elemOp decOp) {
n := int(decodeUint(state))
keyInstr := &decInstr{keyOp, 0, 0, 0, os.ErrorString("no error")}
elemInstr := &decInstr{elemOp, 0, 0, 0, os.ErrorString("no error")}
@ -550,7 +552,7 @@ func ignoreMap(state *decodeState, keyOp, elemOp decOp) {
}
}
func decodeSlice(atyp *reflect.SliceType, state *decodeState, p uintptr, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl os.ErrorString) {
func (dec *Decoder) decodeSlice(atyp *reflect.SliceType, state *decodeState, p uintptr, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl os.ErrorString) {
n := int(uintptr(decodeUint(state)))
if indir > 0 {
up := unsafe.Pointer(p)
@ -566,11 +568,11 @@ func decodeSlice(atyp *reflect.SliceType, state *decodeState, p uintptr, elemOp
hdrp.Data = uintptr(unsafe.NewArray(atyp.Elem(), n))
hdrp.Len = n
hdrp.Cap = n
decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, n, elemIndir, ovfl)
dec.decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, n, elemIndir, ovfl)
}
func ignoreSlice(state *decodeState, elemOp decOp) {
ignoreArrayHelper(state, elemOp, int(decodeUint(state)))
func (dec *Decoder) ignoreSlice(state *decodeState, elemOp decOp) {
dec.ignoreArrayHelper(state, elemOp, int(decodeUint(state)))
}
// setInterfaceValue sets an interface value to a concrete value through
@ -610,7 +612,7 @@ func (dec *Decoder) decodeInterface(ityp *reflect.InterfaceType, state *decodeSt
}
// Read the concrete value.
value := reflect.MakeZero(typ)
dec.decodeValueFromBuffer(value, false)
dec.decodeValueFromBuffer(value, false, true)
if dec.err != nil {
error(dec.err)
}
@ -631,10 +633,11 @@ func (dec *Decoder) ignoreInterface(state *decodeState) {
b := make([]byte, decodeUint(state))
_, err := state.b.Read(b)
if err != nil {
dec.decodeValueFromBuffer(nil, true)
if dec.err != nil {
error(err)
}
dec.decodeValueFromBuffer(nil, true, true)
if dec.err != nil {
error(err)
}
}
@ -685,7 +688,7 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string) (decOp
elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name)
ovfl := overflow(name)
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
decodeArray(t, state, uintptr(p), elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl)
state.dec.decodeArray(t, state, uintptr(p), elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl)
}
case *reflect.MapType:
@ -697,7 +700,7 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string) (decOp
ovfl := overflow(name)
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
up := unsafe.Pointer(p)
decodeMap(t, state, uintptr(up), keyOp, elemOp, i.indir, keyIndir, elemIndir, ovfl)
state.dec.decodeMap(t, state, uintptr(up), keyOp, elemOp, i.indir, keyIndir, elemIndir, ovfl)
}
case *reflect.SliceType:
@ -715,7 +718,7 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string) (decOp
elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name)
ovfl := overflow(name)
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
decodeSlice(t, state, uintptr(p), elemOp, t.Elem().Size(), i.indir, elemIndir, ovfl)
state.dec.decodeSlice(t, state, uintptr(p), elemOp, t.Elem().Size(), i.indir, elemIndir, ovfl)
}
case *reflect.StructType:
@ -764,7 +767,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
elemId := wire.arrayT.Elem
elemOp := dec.decIgnoreOpFor(elemId)
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
ignoreArray(state, elemOp, wire.arrayT.Len)
state.dec.ignoreArray(state, elemOp, wire.arrayT.Len)
}
case wire.mapT != nil:
@ -773,14 +776,14 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
keyOp := dec.decIgnoreOpFor(keyId)
elemOp := dec.decIgnoreOpFor(elemId)
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
ignoreMap(state, keyOp, elemOp)
state.dec.ignoreMap(state, keyOp, elemOp)
}
case wire.sliceT != nil:
elemId := wire.sliceT.Elem
elemOp := dec.decIgnoreOpFor(elemId)
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
ignoreSlice(state, elemOp)
state.dec.ignoreSlice(state, elemOp)
}
case wire.structT != nil:
@ -791,7 +794,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
}
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
// indirect through enginePtr to delay evaluation for recursive structs
ignoreStruct(*enginePtr, state.b)
state.dec.ignoreStruct(*enginePtr, state.b)
}
}
}
@ -931,7 +934,7 @@ func (dec *Decoder) getDecEnginePtr(remoteId typeId, rt reflect.Type) (enginePtr
return
}
// When ignoring data, in effect we compile it into this type
// When ignoring struct data, in effect we compile it into this type
type emptyStruct struct{}
var emptyStructType = reflect.Typeof(emptyStruct{})
@ -965,7 +968,7 @@ func (dec *Decoder) decode(wireId typeId, val reflect.Value) os.Error {
}
return dec.decodeStruct(engine, st, dec.state.b, uintptr(val.Addr()), indir)
}
return decodeSingle(engine, rt, dec.state.b, uintptr(val.Addr()), indir)
return dec.decodeSingle(engine, rt, dec.state.b, uintptr(val.Addr()), indir)
}
func init() {

View File

@ -33,7 +33,7 @@ func NewDecoder(r io.Reader) *Decoder {
dec := new(Decoder)
dec.r = r
dec.wireType = make(map[typeId]*wireType)
dec.state = newDecodeState(&dec.byteBuffer) // buffer set in Decode()
dec.state = newDecodeState(dec, &dec.byteBuffer) // buffer set in Decode()
dec.decoderCache = make(map[reflect.Type]map[typeId]**decEngine)
dec.ignorerCache = make(map[typeId]**decEngine)
@ -104,7 +104,7 @@ func (dec *Decoder) recv() {
// decodeValueFromBuffer grabs the next value from the input. The Decoder's
// buffer already contains data. If the next item in the buffer is a type
// descriptor, it may be necessary to reload the buffer, but recvType does that.
func (dec *Decoder) decodeValueFromBuffer(value reflect.Value, ignore bool) {
func (dec *Decoder) decodeValueFromBuffer(value reflect.Value, ignoreInterfaceValue, countPresent bool) {
for dec.state.b.Len() > 0 {
// Receive a type id.
id := typeId(decodeInt(dec.state))
@ -119,17 +119,22 @@ func (dec *Decoder) decodeValueFromBuffer(value reflect.Value, ignore bool) {
continue
}
// No, it's a value.
if ignore {
dec.byteBuffer.Reset()
break
}
// Make sure the type has been defined already or is a builtin type (for
// top-level singleton values).
if dec.wireType[id] == nil && builtinIdToType[id] == nil {
dec.err = errBadType
break
}
// An interface value is preceded by a byte count.
if countPresent {
count := int(decodeUint(dec.state))
if ignoreInterfaceValue {
// An interface value is preceded by a byte count. Just skip that many bytes.
dec.state.b.Next(int(count))
break
}
// Otherwise fall through and decode it.
}
dec.err = dec.decode(id, value)
break
}
@ -149,7 +154,7 @@ func (dec *Decoder) DecodeValue(value reflect.Value) os.Error {
if dec.err != nil {
return dec.err
}
dec.decodeValueFromBuffer(value, false)
dec.decodeValueFromBuffer(value, false, false)
return dec.err
}

View File

@ -20,14 +20,15 @@ const uint64Size = unsafe.Sizeof(uint64(0))
// number is initialized to -1 so 0 comes out as delta(1). A delta of
// 0 terminates the structure.
type encoderState struct {
enc *Encoder
b *bytes.Buffer
sendZero bool // encoding an array element or map key/value pair; send zero values
fieldnum int // the last field number written.
buf [1 + uint64Size]byte // buffer used by the encoder; here to avoid allocation.
}
func newEncoderState(b *bytes.Buffer) *encoderState {
return &encoderState{b: b}
func newEncoderState(enc *Encoder, b *bytes.Buffer) *encoderState {
return &encoderState{enc: enc, b: b}
}
// Unsigned integers have a two-state encoding. If the number is less
@ -318,8 +319,8 @@ type encEngine struct {
const singletonField = 0
func encodeSingle(engine *encEngine, b *bytes.Buffer, basep uintptr) {
state := newEncoderState(b)
func (enc *Encoder) encodeSingle(b *bytes.Buffer, engine *encEngine, basep uintptr) {
state := newEncoderState(enc, b)
state.fieldnum = singletonField
// There is no surrounding struct to frame the transmission, so we must
// generate data even if the item is zero. To do this, set sendZero.
@ -334,8 +335,8 @@ func encodeSingle(engine *encEngine, b *bytes.Buffer, basep uintptr) {
instr.op(instr, state, p)
}
func encodeStruct(engine *encEngine, b *bytes.Buffer, basep uintptr) {
state := newEncoderState(b)
func (enc *Encoder) encodeStruct(b *bytes.Buffer, engine *encEngine, basep uintptr) {
state := newEncoderState(enc, b)
state.fieldnum = -1
for i := 0; i < len(engine.instr); i++ {
instr := &engine.instr[i]
@ -349,8 +350,8 @@ func encodeStruct(engine *encEngine, b *bytes.Buffer, basep uintptr) {
}
}
func encodeArray(b *bytes.Buffer, p uintptr, op encOp, elemWid uintptr, elemIndir int, length int) {
state := newEncoderState(b)
func (enc *Encoder) encodeArray(b *bytes.Buffer, p uintptr, op encOp, elemWid uintptr, elemIndir int, length int) {
state := newEncoderState(enc, b)
state.fieldnum = -1
state.sendZero = true
encodeUint(state, uint64(length))
@ -378,8 +379,8 @@ func encodeReflectValue(state *encoderState, v reflect.Value, op encOp, indir in
op(nil, state, unsafe.Pointer(v.Addr()))
}
func encodeMap(b *bytes.Buffer, mv *reflect.MapValue, keyOp, elemOp encOp, keyIndir, elemIndir int) {
state := newEncoderState(b)
func (enc *Encoder) encodeMap(b *bytes.Buffer, mv *reflect.MapValue, keyOp, elemOp encOp, keyIndir, elemIndir int) {
state := newEncoderState(enc, b)
state.fieldnum = -1
state.sendZero = true
keys := mv.Keys()
@ -395,7 +396,7 @@ func encodeMap(b *bytes.Buffer, mv *reflect.MapValue, keyOp, elemOp encOp, keyIn
// by the concrete value. A nil value gets sent as the empty string for the name,
// followed by no value.
func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv *reflect.InterfaceValue) {
state := newEncoderState(b)
state := newEncoderState(enc, b)
state.fieldnum = -1
state.sendZero = true
if iv.IsNil() {
@ -416,8 +417,14 @@ func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv *reflect.InterfaceValue)
}
// Send (and maybe first define) the type id.
enc.sendTypeDescriptor(typ)
// Send the value.
err = enc.encode(state.b, iv.Elem())
// Encode the value into a new buffer.
data := new(bytes.Buffer)
err = enc.encode(data, iv.Elem())
if err != nil {
error(err)
}
encodeUint(state, uint64(data.Len()))
_, err = state.b.Write(data.Bytes())
if err != nil {
error(err)
}
@ -470,14 +477,14 @@ func (enc *Encoder) encOpFor(rt reflect.Type) (encOp, int) {
return
}
state.update(i)
encodeArray(state.b, slice.Data, elemOp, t.Elem().Size(), indir, int(slice.Len))
state.enc.encodeArray(state.b, slice.Data, elemOp, t.Elem().Size(), indir, int(slice.Len))
}
case *reflect.ArrayType:
// True arrays have size in the type.
elemOp, indir := enc.encOpFor(t.Elem())
op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
state.update(i)
encodeArray(state.b, uintptr(p), elemOp, t.Elem().Size(), indir, t.Len())
state.enc.encodeArray(state.b, uintptr(p), elemOp, t.Elem().Size(), indir, t.Len())
}
case *reflect.MapType:
keyOp, keyIndir := enc.encOpFor(t.Key())
@ -492,7 +499,7 @@ func (enc *Encoder) encOpFor(rt reflect.Type) (encOp, int) {
return
}
state.update(i)
encodeMap(state.b, mv, keyOp, elemOp, keyIndir, elemIndir)
state.enc.encodeMap(state.b, mv, keyOp, elemOp, keyIndir, elemIndir)
}
case *reflect.StructType:
// Generate a closure that calls out to the engine for the nested type.
@ -501,7 +508,7 @@ func (enc *Encoder) encOpFor(rt reflect.Type) (encOp, int) {
op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
state.update(i)
// indirect through info to delay evaluation for recursive structs
encodeStruct(info.encoder, state.b, uintptr(p))
state.enc.encodeStruct(state.b, info.encoder, uintptr(p))
}
case *reflect.InterfaceType:
op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
@ -513,7 +520,7 @@ func (enc *Encoder) encOpFor(rt reflect.Type) (encOp, int) {
return
}
state.update(i)
enc.encodeInterface(state.b, iv)
state.enc.encodeInterface(state.b, iv)
}
}
}
@ -574,9 +581,9 @@ func (enc *Encoder) encode(b *bytes.Buffer, value reflect.Value) (err os.Error)
}
engine := enc.lockAndGetEncEngine(rt)
if value.Type().Kind() == reflect.Struct {
encodeStruct(engine, b, value.Addr())
enc.encodeStruct(b, engine, value.Addr())
} else {
encodeSingle(engine, b, value.Addr())
enc.encodeSingle(b, engine, value.Addr())
}
return nil
}

View File

@ -29,8 +29,8 @@ func NewEncoder(w io.Writer) *Encoder {
enc := new(Encoder)
enc.w = w
enc.sent = make(map[reflect.Type]typeId)
enc.state = newEncoderState(new(bytes.Buffer))
enc.countState = newEncoderState(new(bytes.Buffer))
enc.state = newEncoderState(enc, new(bytes.Buffer))
enc.countState = newEncoderState(enc, new(bytes.Buffer))
return enc
}

View File

@ -320,7 +320,8 @@ func newTypeObject(name string, rt reflect.Type) (gobType, os.Error) {
typ, _ := indirect(f.Type)
tname := typ.Name()
if tname == "" {
tname = f.Type.String()
t, _ := indirect(f.Type)
tname = t.String()
}
gt, err := getType(tname, f.Type)
if err != nil {