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)
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)
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 {
func newencoderState(b *bytes.Buffer) *encoderState {
b.Reset()
- state := newEncoderState(b)
+ state := newEncoderState(nil, b)
state.fieldnum = -1
return state
}
func newDecodeStateFromData(data []byte) *decodeState {
b := bytes.NewBuffer(data)
- state := newDecodeState(&b)
+ state := newDecodeState(nil, &b)
state.fieldnum = -1
return state
}
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
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)
// 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
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
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))
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 {
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))
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)
}
}
-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 {
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
}
}
}
-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")}
}
}
-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)
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
}
// Read the concrete value.
value := reflect.MakeZero(typ)
- dec.decodeValueFromBuffer(value, false)
+ dec.decodeValueFromBuffer(value, false, true)
if dec.err != nil {
error(dec.err)
}
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)
}
}
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:
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:
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:
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:
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:
}
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)
}
}
}
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{})
}
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() {
// 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
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.
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]
}
}
-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))
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()
// 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() {
}
// 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)
}
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())
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.
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) {
return
}
state.update(i)
- enc.encodeInterface(state.b, iv)
+ state.enc.encodeInterface(state.b, iv)
}
}
}
}
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
}