gob: beginning of support for GobEncoder/GobDecoder interfaces.

This allows a data item that can marshal itself to be transmitted by its
own encoding, enabling some types to be handled that cannot be
normally, plus providing a way to use gobs on data with unexported
fields.

In this CL, the necessary methods are protected by leading _, so only
package gob can use the facilities (in its tests, of course); this
code is not ready for real use yet.  I could be talked into enabling
it for experimentation, though.  The main drawback is that the
methods must be implemented by the actual type passed through,
not by an indirection from it.  For instance, if *T implements
GobEncoder, you must send a *T, not a T.  This will be addressed
in due course.

Also there is improved commentary and a couple of unrelated
minor bug fixes.

R=rsc
CC=golang-dev
https://golang.org/cl/4243056
This commit is contained in:
Rob Pike 2011-03-04 12:25:18 -08:00
parent 7b563be516
commit c91daefb24
9 changed files with 939 additions and 178 deletions

View file

@ -24,9 +24,9 @@ var (
errRange = os.ErrorString("gob: internal error: field numbers out of bounds")
)
// The execution state of an instance of the decoder. A new state
// decoderState is the execution state of an instance of the decoder. A new state
// is created for nested objects.
type decodeState struct {
type decoderState 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).
@ -37,8 +37,8 @@ type decodeState struct {
// We pass the bytes.Buffer separately for easier testing of the infrastructure
// without requiring a full Decoder.
func newDecodeState(dec *Decoder, buf *bytes.Buffer) *decodeState {
d := new(decodeState)
func newDecodeState(dec *Decoder, buf *bytes.Buffer) *decoderState {
d := new(decoderState)
d.dec = dec
d.b = buf
d.buf = make([]byte, uint64Size)
@ -85,7 +85,7 @@ func decodeUintReader(r io.Reader, buf []byte) (x uint64, width int, err os.Erro
// decodeUint reads an encoded unsigned integer from state.r.
// Does not check for overflow.
func (state *decodeState) decodeUint() (x uint64) {
func (state *decoderState) decodeUint() (x uint64) {
b, err := state.b.ReadByte()
if err != nil {
error(err)
@ -112,7 +112,7 @@ func (state *decodeState) decodeUint() (x uint64) {
// decodeInt reads an encoded signed integer from state.r.
// Does not check for overflow.
func (state *decodeState) decodeInt() int64 {
func (state *decoderState) decodeInt() int64 {
x := state.decodeUint()
if x&1 != 0 {
return ^int64(x >> 1)
@ -120,7 +120,8 @@ func (state *decodeState) decodeInt() int64 {
return int64(x >> 1)
}
type decOp func(i *decInstr, state *decodeState, p unsafe.Pointer)
// decOp is the signature of a decoding operator for a given type.
type decOp func(i *decInstr, state *decoderState, p unsafe.Pointer)
// The 'instructions' of the decoding machine
type decInstr struct {
@ -150,26 +151,31 @@ func decIndirect(p unsafe.Pointer, indir int) unsafe.Pointer {
return p
}
func ignoreUint(i *decInstr, state *decodeState, p unsafe.Pointer) {
// ignoreUint discards a uint value with no destination.
func ignoreUint(i *decInstr, state *decoderState, p unsafe.Pointer) {
state.decodeUint()
}
func ignoreTwoUints(i *decInstr, state *decodeState, p unsafe.Pointer) {
// ignoreTwoUints discards a uint value with no destination. It's used to skip
// complex values.
func ignoreTwoUints(i *decInstr, state *decoderState, p unsafe.Pointer) {
state.decodeUint()
state.decodeUint()
}
func decBool(i *decInstr, state *decodeState, p unsafe.Pointer) {
// decBool decodes a uiint and stores it as a boolean through p.
func decBool(i *decInstr, state *decoderState, p unsafe.Pointer) {
if i.indir > 0 {
if *(*unsafe.Pointer)(p) == nil {
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(bool))
}
p = *(*unsafe.Pointer)(p)
}
*(*bool)(p) = state.decodeInt() != 0
*(*bool)(p) = state.decodeUint() != 0
}
func decInt8(i *decInstr, state *decodeState, p unsafe.Pointer) {
// decInt8 decodes an integer and stores it as an int8 through p.
func decInt8(i *decInstr, state *decoderState, p unsafe.Pointer) {
if i.indir > 0 {
if *(*unsafe.Pointer)(p) == nil {
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int8))
@ -184,7 +190,8 @@ func decInt8(i *decInstr, state *decodeState, p unsafe.Pointer) {
}
}
func decUint8(i *decInstr, state *decodeState, p unsafe.Pointer) {
// decUint8 decodes an unsigned integer and stores it as a uint8 through p.
func decUint8(i *decInstr, state *decoderState, p unsafe.Pointer) {
if i.indir > 0 {
if *(*unsafe.Pointer)(p) == nil {
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint8))
@ -199,7 +206,8 @@ func decUint8(i *decInstr, state *decodeState, p unsafe.Pointer) {
}
}
func decInt16(i *decInstr, state *decodeState, p unsafe.Pointer) {
// decInt16 decodes an integer and stores it as an int16 through p.
func decInt16(i *decInstr, state *decoderState, p unsafe.Pointer) {
if i.indir > 0 {
if *(*unsafe.Pointer)(p) == nil {
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int16))
@ -214,7 +222,8 @@ func decInt16(i *decInstr, state *decodeState, p unsafe.Pointer) {
}
}
func decUint16(i *decInstr, state *decodeState, p unsafe.Pointer) {
// decUint16 decodes an unsigned integer and stores it as a uint16 through p.
func decUint16(i *decInstr, state *decoderState, p unsafe.Pointer) {
if i.indir > 0 {
if *(*unsafe.Pointer)(p) == nil {
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint16))
@ -229,7 +238,8 @@ func decUint16(i *decInstr, state *decodeState, p unsafe.Pointer) {
}
}
func decInt32(i *decInstr, state *decodeState, p unsafe.Pointer) {
// decInt32 decodes an integer and stores it as an int32 through p.
func decInt32(i *decInstr, state *decoderState, p unsafe.Pointer) {
if i.indir > 0 {
if *(*unsafe.Pointer)(p) == nil {
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int32))
@ -244,7 +254,8 @@ func decInt32(i *decInstr, state *decodeState, p unsafe.Pointer) {
}
}
func decUint32(i *decInstr, state *decodeState, p unsafe.Pointer) {
// decUint32 decodes an unsigned integer and stores it as a uint32 through p.
func decUint32(i *decInstr, state *decoderState, p unsafe.Pointer) {
if i.indir > 0 {
if *(*unsafe.Pointer)(p) == nil {
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint32))
@ -259,7 +270,8 @@ func decUint32(i *decInstr, state *decodeState, p unsafe.Pointer) {
}
}
func decInt64(i *decInstr, state *decodeState, p unsafe.Pointer) {
// decInt64 decodes an integer and stores it as an int64 through p.
func decInt64(i *decInstr, state *decoderState, p unsafe.Pointer) {
if i.indir > 0 {
if *(*unsafe.Pointer)(p) == nil {
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int64))
@ -269,7 +281,8 @@ func decInt64(i *decInstr, state *decodeState, p unsafe.Pointer) {
*(*int64)(p) = int64(state.decodeInt())
}
func decUint64(i *decInstr, state *decodeState, p unsafe.Pointer) {
// decUint64 decodes an unsigned integer and stores it as a uint64 through p.
func decUint64(i *decInstr, state *decoderState, p unsafe.Pointer) {
if i.indir > 0 {
if *(*unsafe.Pointer)(p) == nil {
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint64))
@ -294,7 +307,9 @@ func floatFromBits(u uint64) float64 {
return math.Float64frombits(v)
}
func storeFloat32(i *decInstr, state *decodeState, p unsafe.Pointer) {
// storeFloat32 decodes an unsigned integer, treats it as a 32-bit floating-point
// number, and stores it through p. It's a helper function for float32 and complex64.
func storeFloat32(i *decInstr, state *decoderState, p unsafe.Pointer) {
v := floatFromBits(state.decodeUint())
av := v
if av < 0 {
@ -308,7 +323,9 @@ func storeFloat32(i *decInstr, state *decodeState, p unsafe.Pointer) {
}
}
func decFloat32(i *decInstr, state *decodeState, p unsafe.Pointer) {
// decFloat32 decodes an unsigned integer, treats it as a 32-bit floating-point
// number, and stores it through p.
func decFloat32(i *decInstr, state *decoderState, p unsafe.Pointer) {
if i.indir > 0 {
if *(*unsafe.Pointer)(p) == nil {
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(float32))
@ -318,7 +335,9 @@ func decFloat32(i *decInstr, state *decodeState, p unsafe.Pointer) {
storeFloat32(i, state, p)
}
func decFloat64(i *decInstr, state *decodeState, p unsafe.Pointer) {
// decFloat64 decodes an unsigned integer, treats it as a 64-bit floating-point
// number, and stores it through p.
func decFloat64(i *decInstr, state *decoderState, p unsafe.Pointer) {
if i.indir > 0 {
if *(*unsafe.Pointer)(p) == nil {
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(float64))
@ -328,8 +347,10 @@ func decFloat64(i *decInstr, state *decodeState, p unsafe.Pointer) {
*(*float64)(p) = floatFromBits(uint64(state.decodeUint()))
}
// Complex numbers are just a pair of floating-point numbers, real part first.
func decComplex64(i *decInstr, state *decodeState, p unsafe.Pointer) {
// decComplex64 decodes a pair of unsigned integers, treats them as a
// pair of floating point numbers, and stores them as a complex64 through p.
// The real part comes first.
func decComplex64(i *decInstr, state *decoderState, p unsafe.Pointer) {
if i.indir > 0 {
if *(*unsafe.Pointer)(p) == nil {
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(complex64))
@ -340,7 +361,10 @@ func decComplex64(i *decInstr, state *decodeState, p unsafe.Pointer) {
storeFloat32(i, state, unsafe.Pointer(uintptr(p)+uintptr(unsafe.Sizeof(float32(0)))))
}
func decComplex128(i *decInstr, state *decodeState, p unsafe.Pointer) {
// decComplex128 decodes a pair of unsigned integers, treats them as a
// pair of floating point numbers, and stores them as a complex128 through p.
// The real part comes first.
func decComplex128(i *decInstr, state *decoderState, p unsafe.Pointer) {
if i.indir > 0 {
if *(*unsafe.Pointer)(p) == nil {
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(complex128))
@ -352,8 +376,10 @@ func decComplex128(i *decInstr, state *decodeState, p unsafe.Pointer) {
*(*complex128)(p) = complex(real, imag)
}
// decUint8Array decodes byte array and stores through p a slice header
// describing the data.
// uint8 arrays are encoded as an unsigned count followed by the raw bytes.
func decUint8Array(i *decInstr, state *decodeState, p unsafe.Pointer) {
func decUint8Array(i *decInstr, state *decoderState, p unsafe.Pointer) {
if i.indir > 0 {
if *(*unsafe.Pointer)(p) == nil {
*(*unsafe.Pointer)(p) = unsafe.Pointer(new([]uint8))
@ -365,8 +391,10 @@ func decUint8Array(i *decInstr, state *decodeState, p unsafe.Pointer) {
*(*[]uint8)(p) = b
}
// decString decodes byte array and stores through p a string header
// describing the data.
// Strings are encoded as an unsigned count followed by the raw bytes.
func decString(i *decInstr, state *decodeState, p unsafe.Pointer) {
func decString(i *decInstr, state *decoderState, p unsafe.Pointer) {
if i.indir > 0 {
if *(*unsafe.Pointer)(p) == nil {
*(*unsafe.Pointer)(p) = unsafe.Pointer(new([]byte))
@ -378,7 +406,8 @@ func decString(i *decInstr, state *decodeState, p unsafe.Pointer) {
*(*string)(p) = string(b)
}
func ignoreUint8Array(i *decInstr, state *decodeState, p unsafe.Pointer) {
// ignoreUint8Array skips over the data for a byte slice value with no destination.
func ignoreUint8Array(i *decInstr, state *decoderState, p unsafe.Pointer) {
b := make([]byte, state.decodeUint())
state.b.Read(b)
}
@ -409,8 +438,15 @@ func allocate(rtyp reflect.Type, p uintptr, indir int) uintptr {
return *(*uintptr)(up)
}
// decodeSingle decodes a top-level value that is not a struct and stores it through p.
// Such values are preceded by a zero, making them have the memory layout of a
// struct field (although with an illegal field number).
func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, p uintptr) (err os.Error) {
p = allocate(ut.base, p, ut.indir)
indir := ut.indir
if ut.isGobDecoder {
indir = int(ut.decIndir)
}
p = allocate(ut.base, p, indir)
state := newDecodeState(dec, &dec.buf)
state.fieldnum = singletonField
basep := p
@ -427,6 +463,7 @@ func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, p uintptr)
return nil
}
// decodeSingle decodes a top-level struct and stores it through p.
// Indir is for the value, not the type. At the time of the call it may
// differ from ut.indir, which was computed when the engine was built.
// This state cannot arise for decodeSingle, which is called directly
@ -460,6 +497,7 @@ func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p uintptr,
return nil
}
// ignoreStruct discards the data for a struct with no destination.
func (dec *Decoder) ignoreStruct(engine *decEngine) (err os.Error) {
state := newDecodeState(dec, &dec.buf)
state.fieldnum = -1
@ -482,6 +520,8 @@ func (dec *Decoder) ignoreStruct(engine *decEngine) (err os.Error) {
return nil
}
// ignoreSingle discards the data for a top-level non-struct value with no
// destination. It's used when calling Decode with a nil value.
func (dec *Decoder) ignoreSingle(engine *decEngine) (err os.Error) {
state := newDecodeState(dec, &dec.buf)
state.fieldnum = singletonField
@ -494,7 +534,8 @@ func (dec *Decoder) ignoreSingle(engine *decEngine) (err os.Error) {
return nil
}
func (dec *Decoder) decodeArrayHelper(state *decodeState, p uintptr, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl os.ErrorString) {
// decodeArrayHelper does the work for decoding arrays and slices.
func (dec *Decoder) decodeArrayHelper(state *decoderState, 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)
@ -506,7 +547,10 @@ func (dec *Decoder) decodeArrayHelper(state *decodeState, p uintptr, elemOp decO
}
}
func (dec *Decoder) decodeArray(atyp *reflect.ArrayType, state *decodeState, p uintptr, elemOp decOp, elemWid uintptr, length, indir, elemIndir int, ovfl os.ErrorString) {
// decodeArray decodes an array and stores it through p, that is, p points to the zeroth element.
// The length is an unsigned integer preceding the elements. Even though the length is redundant
// (it's part of the type), it's a useful check and is included in the encoding.
func (dec *Decoder) decodeArray(atyp *reflect.ArrayType, state *decoderState, 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
}
@ -516,7 +560,9 @@ func (dec *Decoder) decodeArray(atyp *reflect.ArrayType, state *decodeState, p u
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 {
// decodeIntoValue is a helper for map decoding. Since maps are decoded using reflection,
// unlike the other items we can't use a pointer directly.
func decodeIntoValue(state *decoderState, op decOp, indir int, v reflect.Value, ovfl os.ErrorString) reflect.Value {
instr := &decInstr{op, 0, indir, 0, ovfl}
up := unsafe.Pointer(v.UnsafeAddr())
if indir > 1 {
@ -526,7 +572,11 @@ func decodeIntoValue(state *decodeState, op decOp, indir int, v reflect.Value, o
return v
}
func (dec *Decoder) decodeMap(mtyp *reflect.MapType, state *decodeState, p uintptr, keyOp, elemOp decOp, indir, keyIndir, elemIndir int, ovfl os.ErrorString) {
// decodeMap decodes a map and stores its header through p.
// Maps are encoded as a length followed by key:value pairs.
// Because the internals of maps are not visible to us, we must
// use reflection rather than pointer magic.
func (dec *Decoder) decodeMap(mtyp *reflect.MapType, state *decoderState, 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
}
@ -538,7 +588,7 @@ func (dec *Decoder) decodeMap(mtyp *reflect.MapType, state *decodeState, p uintp
// Maps cannot be accessed by moving addresses around the way
// that slices etc. can. We must recover a full reflection value for
// the iteration.
v := reflect.NewValue(unsafe.Unreflect(mtyp, unsafe.Pointer((p)))).(*reflect.MapValue)
v := reflect.NewValue(unsafe.Unreflect(mtyp, unsafe.Pointer(p))).(*reflect.MapValue)
n := int(state.decodeUint())
for i := 0; i < n; i++ {
key := decodeIntoValue(state, keyOp, keyIndir, reflect.MakeZero(mtyp.Key()), ovfl)
@ -547,21 +597,24 @@ func (dec *Decoder) decodeMap(mtyp *reflect.MapType, state *decodeState, p uintp
}
}
func (dec *Decoder) ignoreArrayHelper(state *decodeState, elemOp decOp, length int) {
// ignoreArrayHelper does the work for discarding arrays and slices.
func (dec *Decoder) ignoreArrayHelper(state *decoderState, 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 (dec *Decoder) ignoreArray(state *decodeState, elemOp decOp, length int) {
// ignoreArray discards the data for an array value with no destination.
func (dec *Decoder) ignoreArray(state *decoderState, elemOp decOp, length int) {
if n := state.decodeUint(); n != uint64(length) {
errorf("gob: length mismatch in ignoreArray")
}
dec.ignoreArrayHelper(state, elemOp, length)
}
func (dec *Decoder) ignoreMap(state *decodeState, keyOp, elemOp decOp) {
// ignoreMap discards the data for a map value with no destination.
func (dec *Decoder) ignoreMap(state *decoderState, keyOp, elemOp decOp) {
n := int(state.decodeUint())
keyInstr := &decInstr{keyOp, 0, 0, 0, os.ErrorString("no error")}
elemInstr := &decInstr{elemOp, 0, 0, 0, os.ErrorString("no error")}
@ -571,7 +624,9 @@ func (dec *Decoder) ignoreMap(state *decodeState, keyOp, elemOp decOp) {
}
}
func (dec *Decoder) decodeSlice(atyp *reflect.SliceType, state *decodeState, p uintptr, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl os.ErrorString) {
// decodeSlice decodes a slice and stores the slice header through p.
// Slices are encoded as an unsigned length followed by the elements.
func (dec *Decoder) decodeSlice(atyp *reflect.SliceType, state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl os.ErrorString) {
n := int(uintptr(state.decodeUint()))
if indir > 0 {
up := unsafe.Pointer(p)
@ -590,7 +645,8 @@ func (dec *Decoder) decodeSlice(atyp *reflect.SliceType, state *decodeState, p u
dec.decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, n, elemIndir, ovfl)
}
func (dec *Decoder) ignoreSlice(state *decodeState, elemOp decOp) {
// ignoreSlice skips over the data for a slice value with no destination.
func (dec *Decoder) ignoreSlice(state *decoderState, elemOp decOp) {
dec.ignoreArrayHelper(state, elemOp, int(state.decodeUint()))
}
@ -609,9 +665,10 @@ func setInterfaceValue(ivalue *reflect.InterfaceValue, value reflect.Value) {
ivalue.Set(value)
}
// decodeInterface receives the name of a concrete type followed by its value.
// decodeInterface decodes an interface value and stores it through p.
// Interfaces are encoded as the name of a concrete type followed by a value.
// If the name is empty, the value is nil and no value is sent.
func (dec *Decoder) decodeInterface(ityp *reflect.InterfaceType, state *decodeState, p uintptr, indir int) {
func (dec *Decoder) decodeInterface(ityp *reflect.InterfaceType, state *decoderState, p uintptr, indir int) {
// Create an interface reflect.Value. We need one even for the nil case.
ivalue := reflect.MakeZero(ityp).(*reflect.InterfaceValue)
// Read the name of the concrete type.
@ -655,7 +712,8 @@ func (dec *Decoder) decodeInterface(ityp *reflect.InterfaceType, state *decodeSt
*(*[2]uintptr)(unsafe.Pointer(p)) = ivalue.Get()
}
func (dec *Decoder) ignoreInterface(state *decodeState) {
// ignoreInterface discards the data for an interface value with no destination.
func (dec *Decoder) ignoreInterface(state *decoderState) {
// Read the name of the concrete type.
b := make([]byte, state.decodeUint())
_, err := state.b.Read(b)
@ -670,6 +728,32 @@ func (dec *Decoder) ignoreInterface(state *decodeState) {
state.b.Next(int(state.decodeUint()))
}
// decodeGobDecoder decodes something implementing the GobDecoder interface.
// The data is encoded as a byte slice.
func (dec *Decoder) decodeGobDecoder(state *decoderState, v reflect.Value, index int) {
// Read the bytes for the value.
b := make([]byte, state.decodeUint())
_, err := state.b.Read(b)
if err != nil {
error(err)
}
// We know it's a GobDecoder, so just call the method directly.
err = v.Interface().(_GobDecoder)._GobDecode(b)
if err != nil {
error(err)
}
}
// ignoreGobDecoder discards the data for a GobDecoder value with no destination.
func (dec *Decoder) ignoreGobDecoder(state *decoderState) {
// Read the bytes for the value.
b := make([]byte, state.decodeUint())
_, err := state.b.Read(b)
if err != nil {
error(err)
}
}
// Index by Go types.
var decOpTable = [...]decOp{
reflect.Bool: decBool,
@ -699,10 +783,14 @@ var decIgnoreOpMap = map[typeId]decOp{
tComplex: ignoreTwoUints,
}
// Return the decoding op for the base type under rt and
// decOpFor returns the decoding op for the base type under rt and
// the indirection count to reach it.
func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProgress map[reflect.Type]*decOp) (*decOp, int) {
ut := userType(rt)
// If the type implements GobEncoder, we handle it without further processing.
if ut.isGobDecoder {
return dec.gobDecodeOpFor(ut)
}
// If this type is already in progress, it's a recursive type (e.g. map[string]*T).
// Return the pointer to the op we're already building.
if opPtr := inProgress[rt]; opPtr != nil {
@ -724,7 +812,7 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
elemId := dec.wireType[wireId].ArrayT.Elem
elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress)
ovfl := overflow(name)
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
state.dec.decodeArray(t, state, uintptr(p), *elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl)
}
@ -735,7 +823,7 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
keyOp, keyIndir := dec.decOpFor(keyId, t.Key(), name, inProgress)
elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress)
ovfl := overflow(name)
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
up := unsafe.Pointer(p)
state.dec.decodeMap(t, state, uintptr(up), *keyOp, *elemOp, i.indir, keyIndir, elemIndir, ovfl)
}
@ -754,17 +842,17 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
}
elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress)
ovfl := overflow(name)
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
state.dec.decodeSlice(t, state, uintptr(p), *elemOp, t.Elem().Size(), i.indir, elemIndir, ovfl)
}
case *reflect.StructType:
// Generate a closure that calls out to the engine for the nested type.
enginePtr, err := dec.getDecEnginePtr(wireId, typ)
enginePtr, err := dec.getDecEnginePtr(wireId, userType(typ))
if err != nil {
error(err)
}
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
// indirect through enginePtr to delay evaluation for recursive structs.
err = dec.decodeStruct(*enginePtr, userType(typ), uintptr(p), i.indir)
if err != nil {
@ -772,8 +860,8 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
}
}
case *reflect.InterfaceType:
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
dec.decodeInterface(t, state, uintptr(p), i.indir)
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
state.dec.decodeInterface(t, state, uintptr(p), i.indir)
}
}
}
@ -783,15 +871,15 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
return &op, indir
}
// Return the decoding op for a field that has no destination.
// decIgnoreOpFor returns the decoding op for a field that has no destination.
func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
op, ok := decIgnoreOpMap[wireId]
if !ok {
if wireId == tInterface {
// Special case because it's a method: the ignored item might
// define types and we need to record their state in the decoder.
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
dec.ignoreInterface(state)
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
state.dec.ignoreInterface(state)
}
return op
}
@ -803,7 +891,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
case wire.ArrayT != nil:
elemId := wire.ArrayT.Elem
elemOp := dec.decIgnoreOpFor(elemId)
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
state.dec.ignoreArray(state, elemOp, wire.ArrayT.Len)
}
@ -812,14 +900,14 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
elemId := dec.wireType[wireId].MapT.Elem
keyOp := dec.decIgnoreOpFor(keyId)
elemOp := dec.decIgnoreOpFor(elemId)
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
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) {
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
state.dec.ignoreSlice(state, elemOp)
}
@ -829,10 +917,15 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
if err != nil {
error(err)
}
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
// indirect through enginePtr to delay evaluation for recursive structs
state.dec.ignoreStruct(*enginePtr)
}
case wire.GobEncoderT != nil:
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
state.dec.ignoreGobDecoder(state)
}
}
}
if op == nil {
@ -841,16 +934,56 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
return op
}
// Are these two gob Types compatible?
// Answers the question for basic types, arrays, and slices.
// gobDecodeOpFor returns the op for a type that is known to implement
// GobDecoder.
func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) (*decOp, int) {
rt := ut.user
if ut.decIndir != 0 {
errorf("gob: TODO: can't handle indirection to reach GobDecoder")
}
index := -1
for i := 0; i < rt.NumMethod(); i++ {
if rt.Method(i).Name == gobDecodeMethodName {
index = i
break
}
}
if index < 0 {
panic("can't find GobDecode method")
}
var op decOp
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
// Allocate the underlying data, but hold on to the address we have,
// since it's known to be the receiver's address.
// TODO: fix this up when decIndir can be non-zero.
allocate(ut.base, uintptr(p), ut.indir)
v := reflect.NewValue(unsafe.Unreflect(rt, p))
state.dec.decodeGobDecoder(state, v, index)
}
return &op, int(ut.decIndir)
}
// compatibleType asks: Are these two gob Types compatible?
// Answers the question for basic types, arrays, maps and slices, plus
// GobEncoder/Decoder pairs.
// Structs are considered ok; fields will be checked later.
func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId, inProgress map[reflect.Type]typeId) bool {
if rhs, ok := inProgress[fr]; ok {
return rhs == fw
}
inProgress[fr] = fw
fr = userType(fr).base
switch t := fr.(type) {
ut := userType(fr)
wire, ok := dec.wireType[fw]
// If fr is a GobDecoder, the wire type must be GobEncoder.
// And if fr is not a GobDecoder, the wire type must not be either.
if ut.isGobDecoder != (ok && wire.GobEncoderT != nil) { // the parentheses look odd but are correct.
return false
}
if ut.isGobDecoder { // This test trumps all others.
return true
}
switch t := ut.base.(type) {
default:
// chan, etc: cannot handle.
return false
@ -869,14 +1002,12 @@ func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId, inProgress map[re
case *reflect.InterfaceType:
return fw == tInterface
case *reflect.ArrayType:
wire, ok := dec.wireType[fw]
if !ok || wire.ArrayT == nil {
return false
}
array := wire.ArrayT
return t.Len() == array.Len && dec.compatibleType(t.Elem(), array.Elem, inProgress)
case *reflect.MapType:
wire, ok := dec.wireType[fw]
if !ok || wire.MapT == nil {
return false
}
@ -911,8 +1042,13 @@ func (dec *Decoder) typeString(remoteId typeId) string {
return dec.wireType[remoteId].string()
}
func (dec *Decoder) compileSingle(remoteId typeId, rt reflect.Type) (engine *decEngine, err os.Error) {
// compileSingle compiles the decoder engine for a non-struct top-level value, including
// GobDecoders.
func (dec *Decoder) compileSingle(remoteId typeId, ut *userTypeInfo) (engine *decEngine, err os.Error) {
rt := ut.base
if ut.isGobDecoder {
rt = ut.user
}
engine = new(decEngine)
engine.instr = make([]decInstr, 1) // one item
name := rt.String() // best we can do
@ -926,6 +1062,7 @@ func (dec *Decoder) compileSingle(remoteId typeId, rt reflect.Type) (engine *dec
return
}
// compileIgnoreSingle compiles the decoder engine for a non-struct top-level value that will be discarded.
func (dec *Decoder) compileIgnoreSingle(remoteId typeId) (engine *decEngine, err os.Error) {
engine = new(decEngine)
engine.instr = make([]decInstr, 1) // one item
@ -936,16 +1073,19 @@ func (dec *Decoder) compileIgnoreSingle(remoteId typeId) (engine *decEngine, err
return
}
// Is this an exported - upper case - name?
// isExported reports whether this is an exported - upper case - name.
func isExported(name string) bool {
rune, _ := utf8.DecodeRuneInString(name)
return unicode.IsUpper(rune)
}
func (dec *Decoder) compileDec(remoteId typeId, rt reflect.Type) (engine *decEngine, err os.Error) {
// compileDec compiles the decoder engine for a value. If the value is not a struct,
// it calls out to compileSingle.
func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEngine, err os.Error) {
rt := ut.base
srt, ok := rt.(*reflect.StructType)
if !ok {
return dec.compileSingle(remoteId, rt)
if !ok || ut.isGobDecoder {
return dec.compileSingle(remoteId, ut)
}
var wireStruct *structType
// Builtin types can come from global pool; the rest must be defined by the decoder.
@ -990,7 +1130,9 @@ func (dec *Decoder) compileDec(remoteId typeId, rt reflect.Type) (engine *decEng
return
}
func (dec *Decoder) getDecEnginePtr(remoteId typeId, rt reflect.Type) (enginePtr **decEngine, err os.Error) {
// getDecEnginePtr returns the engine for the specified type.
func (dec *Decoder) getDecEnginePtr(remoteId typeId, ut *userTypeInfo) (enginePtr **decEngine, err os.Error) {
rt := ut.base
decoderMap, ok := dec.decoderCache[rt]
if !ok {
decoderMap = make(map[typeId]**decEngine)
@ -1000,7 +1142,7 @@ func (dec *Decoder) getDecEnginePtr(remoteId typeId, rt reflect.Type) (enginePtr
// To handle recursive types, mark this engine as underway before compiling.
enginePtr = new(*decEngine)
decoderMap[remoteId] = enginePtr
*enginePtr, err = dec.compileDec(remoteId, rt)
*enginePtr, err = dec.compileDec(remoteId, ut)
if err != nil {
decoderMap[remoteId] = nil, false
}
@ -1008,11 +1150,12 @@ func (dec *Decoder) getDecEnginePtr(remoteId typeId, rt reflect.Type) (enginePtr
return
}
// When ignoring struct data, in effect we compile it into this type
// emptyStruct is the type we compile into when ignoring a struct value.
type emptyStruct struct{}
var emptyStructType = reflect.Typeof(emptyStruct{})
// getDecEnginePtr returns the engine for the specified type when the value is to be discarded.
func (dec *Decoder) getIgnoreEnginePtr(wireId typeId) (enginePtr **decEngine, err os.Error) {
var ok bool
if enginePtr, ok = dec.ignorerCache[wireId]; !ok {
@ -1021,7 +1164,7 @@ func (dec *Decoder) getIgnoreEnginePtr(wireId typeId) (enginePtr **decEngine, er
dec.ignorerCache[wireId] = enginePtr
wire := dec.wireType[wireId]
if wire != nil && wire.StructT != nil {
*enginePtr, err = dec.compileDec(wireId, emptyStructType)
*enginePtr, err = dec.compileDec(wireId, userType(emptyStructType))
} else {
*enginePtr, err = dec.compileIgnoreSingle(wireId)
}
@ -1032,6 +1175,7 @@ func (dec *Decoder) getIgnoreEnginePtr(wireId typeId) (enginePtr **decEngine, er
return
}
// decodeValue decodes the data stream representing a value and stores it in val.
func (dec *Decoder) decodeValue(wireId typeId, val reflect.Value) (err os.Error) {
defer catchError(&err)
// If the value is nil, it means we should just ignore this item.
@ -1042,12 +1186,18 @@ func (dec *Decoder) decodeValue(wireId typeId, val reflect.Value) (err os.Error)
ut := userType(val.Type())
base := ut.base
indir := ut.indir
enginePtr, err := dec.getDecEnginePtr(wireId, base)
if ut.isGobDecoder {
indir = int(ut.decIndir)
if indir != 0 {
errorf("TODO: can't handle indirection in GobDecoder value")
}
}
enginePtr, err := dec.getDecEnginePtr(wireId, ut)
if err != nil {
return err
}
engine := *enginePtr
if st, ok := base.(*reflect.StructType); ok {
if st, ok := base.(*reflect.StructType); ok && !ut.isGobDecoder {
if engine.numInstr == 0 && st.NumField() > 0 && len(dec.wireType[wireId].StructT.Field) > 0 {
name := base.Name()
return os.ErrorString("gob: type mismatch: no fields matched compiling decoder for " + name)
@ -1057,6 +1207,7 @@ func (dec *Decoder) decodeValue(wireId typeId, val reflect.Value) (err os.Error)
return dec.decodeSingle(engine, ut, uintptr(val.UnsafeAddr()))
}
// decodeIgnoredValue decodes the data stream representing a value of the specified type and discards it.
func (dec *Decoder) decodeIgnoredValue(wireId typeId) os.Error {
enginePtr, err := dec.getIgnoreEnginePtr(wireId)
if err != nil {