]> Cypherpunks repositories - gostls13.git/commitdiff
gob: several fixes.
authorRob Pike <r@golang.org>
Sun, 31 Oct 2010 20:41:30 +0000 (13:41 -0700)
committerRob Pike <r@golang.org>
Sun, 31 Oct 2010 20:41:30 +0000 (13:41 -0700)
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

src/pkg/gob/codec_test.go
src/pkg/gob/debug.go
src/pkg/gob/decode.go
src/pkg/gob/decoder.go
src/pkg/gob/encode.go
src/pkg/gob/encoder.go
src/pkg/gob/type.go

index 1d9ac843889cc11488bd1d2fa4523cfb02175467..426cc80edf3fc5ba69170c153871cb80ceb116a4 100644 (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)
index cbd662d1c9bfb662c92b20e04adb3aca41d29393..1daf3b914c2f615895209c3e0b32f722234df8fc 100644 (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))
index 791b231a498bce5a014704ff570c200fac879238..5a19b781971627c8abe733b332b914531b7b9064 100644 (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)
-               }
+               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() {
index c28185f16cb32741f8ce9b294106e5304d88c6fc..af3e78a6d28829e48ff83ba6abd42dc993f49e8e 100644 (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
 }
 
index 4d9718d01bf69775ba4f1328ace16576898fb6cb..694cddbcc90b756b053e65fec64bd21784b52baa 100644 (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
 }
index 5d12d920b4164aca40a198be6ef9f5db0b74cd35..340a60241062c9c3ddaf05e102dff9dfb327f9b9 100644 (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
 }
 
index 6b0ee40521fafa99820ea85a7ca549ebf63e6de7..a72a392cb04105ef5f3e46d5e46cf1dc6da70b22 100644 (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 {