Commit 7f7cb166 authored by Rob Pike's avatar Rob Pike

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
parent f62772b1
......@@ -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)
......
......@@ -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))
......
This diff is collapsed.
......@@ -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
}
......
......@@ -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
}
......@@ -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
}
......
......@@ -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 {
......
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