summaryrefslogtreecommitdiff
path: root/src/pkg/encoding/gob/decode.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/encoding/gob/decode.go')
-rw-r--r--src/pkg/encoding/gob/decode.go89
1 files changed, 51 insertions, 38 deletions
diff --git a/src/pkg/encoding/gob/decode.go b/src/pkg/encoding/gob/decode.go
index 7cc756540..3e76f4c90 100644
--- a/src/pkg/encoding/gob/decode.go
+++ b/src/pkg/encoding/gob/decode.go
@@ -9,6 +9,7 @@ package gob
import (
"bytes"
+ "encoding"
"errors"
"io"
"math"
@@ -450,11 +451,11 @@ type decEngine struct {
// allocate makes sure storage is available for an object of underlying type rtyp
// that is indir levels of indirection through p.
-func allocate(rtyp reflect.Type, p uintptr, indir int) uintptr {
+func allocate(rtyp reflect.Type, p unsafe.Pointer, indir int) unsafe.Pointer {
if indir == 0 {
return p
}
- up := unsafe.Pointer(p)
+ up := p
if indir > 1 {
up = decIndirect(up, indir)
}
@@ -462,13 +463,13 @@ func allocate(rtyp reflect.Type, p uintptr, indir int) uintptr {
// Allocate object.
*(*unsafe.Pointer)(up) = unsafe.Pointer(reflect.New(rtyp).Pointer())
}
- return *(*uintptr)(up)
+ return *(*unsafe.Pointer)(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, basep uintptr) {
+func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep unsafe.Pointer) {
state := dec.newDecoderState(&dec.buf)
state.fieldnum = singletonField
delta := int(state.decodeUint())
@@ -479,7 +480,7 @@ func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep uint
if instr.indir != ut.indir {
errorf("internal error: inconsistent indirection instr %d ut %d", instr.indir, ut.indir)
}
- ptr := unsafe.Pointer(basep) // offset will be zero
+ ptr := basep // offset will be zero
if instr.indir > 1 {
ptr = decIndirect(ptr, instr.indir)
}
@@ -492,7 +493,7 @@ func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep uint
// differ from ut.indir, which was computed when the engine was built.
// This state cannot arise for decodeSingle, which is called directly
// from the user's value, not from the innards of an engine.
-func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p uintptr, indir int) {
+func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p unsafe.Pointer, indir int) {
p = allocate(ut.base, p, indir)
state := dec.newDecoderState(&dec.buf)
state.fieldnum = -1
@@ -511,7 +512,7 @@ func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p uintptr,
break
}
instr := &engine.instr[fieldnum]
- p := unsafe.Pointer(basep + instr.offset)
+ p := unsafe.Pointer(uintptr(basep) + instr.offset)
if instr.indir > 1 {
p = decIndirect(p, instr.indir)
}
@@ -559,25 +560,25 @@ func (dec *Decoder) ignoreSingle(engine *decEngine) {
}
// 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 error) {
+func (dec *Decoder) decodeArrayHelper(state *decoderState, p unsafe.Pointer, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl error) {
instr := &decInstr{elemOp, 0, elemIndir, 0, ovfl}
for i := 0; i < length; i++ {
if state.b.Len() == 0 {
errorf("decoding array or slice: length exceeds input size (%d elements)", length)
}
- up := unsafe.Pointer(p)
+ up := p
if elemIndir > 1 {
up = decIndirect(up, elemIndir)
}
elemOp(instr, state, up)
- p += uintptr(elemWid)
+ p = unsafe.Pointer(uintptr(p) + elemWid)
}
}
// 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.Type, state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, length, indir, elemIndir int, ovfl error) {
+func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, p unsafe.Pointer, elemOp decOp, elemWid uintptr, length, indir, elemIndir int, ovfl error) {
if indir > 0 {
p = allocate(atyp, p, 1) // All but the last level has been allocated by dec.Indirect
}
@@ -591,7 +592,7 @@ func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, p uintpt
// unlike the other items we can't use a pointer directly.
func decodeIntoValue(state *decoderState, op decOp, indir int, v reflect.Value, ovfl error) reflect.Value {
instr := &decInstr{op, 0, indir, 0, ovfl}
- up := unsafe.Pointer(unsafeAddr(v))
+ up := unsafeAddr(v)
if indir > 1 {
up = decIndirect(up, indir)
}
@@ -603,7 +604,7 @@ func decodeIntoValue(state *decoderState, op decOp, indir int, v reflect.Value,
// 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.Type, state *decoderState, p uintptr, keyOp, elemOp decOp, indir, keyIndir, elemIndir int, ovfl error) {
+func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, p unsafe.Pointer, keyOp, elemOp decOp, indir, keyIndir, elemIndir int, ovfl error) {
if indir > 0 {
p = allocate(mtyp, p, 1) // All but the last level has been allocated by dec.Indirect
}
@@ -673,7 +674,7 @@ func (dec *Decoder) decodeSlice(atyp reflect.Type, state *decoderState, p uintpt
hdrp.Cap = n
}
hdrp.Len = n
- dec.decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, n, elemIndir, ovfl)
+ dec.decodeArrayHelper(state, unsafe.Pointer(hdrp.Data), elemOp, elemWid, n, elemIndir, ovfl)
}
// ignoreSlice skips over the data for a slice value with no destination.
@@ -693,7 +694,7 @@ func setInterfaceValue(ivalue reflect.Value, value reflect.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.Type, state *decoderState, p uintptr, indir int) {
+func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p unsafe.Pointer, indir int) {
// Create a writable interface reflect.Value. We need one even for the nil case.
ivalue := allocValue(ityp)
// Read the name of the concrete type.
@@ -767,15 +768,22 @@ func (dec *Decoder) ignoreInterface(state *decoderState) {
// decodeGobDecoder decodes something implementing the GobDecoder interface.
// The data is encoded as a byte slice.
-func (dec *Decoder) decodeGobDecoder(state *decoderState, v reflect.Value) {
+func (dec *Decoder) decodeGobDecoder(ut *userTypeInfo, state *decoderState, v reflect.Value) {
// 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)
+ // We know it's one of these.
+ switch ut.externalDec {
+ case xGob:
+ err = v.Interface().(GobDecoder).GobDecode(b)
+ case xBinary:
+ err = v.Interface().(encoding.BinaryUnmarshaler).UnmarshalBinary(b)
+ case xText:
+ err = v.Interface().(encoding.TextUnmarshaler).UnmarshalText(b)
+ }
if err != nil {
error_(err)
}
@@ -825,9 +833,10 @@ var decIgnoreOpMap = map[typeId]decOp{
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 {
+ if ut.externalDec != 0 {
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 {
@@ -850,7 +859,7 @@ 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 *decoderState, p unsafe.Pointer) {
- state.dec.decodeArray(t, state, uintptr(p), *elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl)
+ state.dec.decodeArray(t, state, p, *elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl)
}
case reflect.Map:
@@ -860,8 +869,7 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), "element of "+name, inProgress)
ovfl := overflow(name)
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)
+ state.dec.decodeMap(t, state, p, *keyOp, *elemOp, i.indir, keyIndir, elemIndir, ovfl)
}
case reflect.Slice:
@@ -890,11 +898,11 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
}
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
// indirect through enginePtr to delay evaluation for recursive structs.
- dec.decodeStruct(*enginePtr, userType(typ), uintptr(p), i.indir)
+ dec.decodeStruct(*enginePtr, userType(typ), p, i.indir)
}
case reflect.Interface:
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
- state.dec.decodeInterface(t, state, uintptr(p), i.indir)
+ state.dec.decodeInterface(t, state, p, i.indir)
}
}
}
@@ -955,7 +963,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
state.dec.ignoreStruct(*enginePtr)
}
- case wire.GobEncoderT != nil:
+ case wire.GobEncoderT != nil, wire.BinaryMarshalerT != nil, wire.TextMarshalerT != nil:
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
state.dec.ignoreGobDecoder(state)
}
@@ -994,7 +1002,7 @@ func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) (*decOp, int) {
} else {
v = reflect.NewAt(rcvrType, p).Elem()
}
- state.dec.decodeGobDecoder(state, v)
+ state.dec.decodeGobDecoder(ut, state, v)
}
return &op, int(ut.indir)
@@ -1011,12 +1019,18 @@ func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId, inProgress map[re
inProgress[fr] = fw
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.
+ // If wire was encoded with an encoding method, fr must have that method.
+ // And if not, it must not.
+ // At most one of the booleans in ut is set.
+ // We could possibly relax this constraint in the future in order to
+ // choose the decoding method using the data in the wireType.
+ // The parentheses look odd but are correct.
+ if (ut.externalDec == xGob) != (ok && wire.GobEncoderT != nil) ||
+ (ut.externalDec == xBinary) != (ok && wire.BinaryMarshalerT != nil) ||
+ (ut.externalDec == xText) != (ok && wire.TextMarshalerT != nil) {
return false
}
- if ut.isGobDecoder { // This test trumps all others.
+ if ut.externalDec != 0 { // This test trumps all others.
return true
}
switch t := ut.base; t.Kind() {
@@ -1115,8 +1129,7 @@ func (dec *Decoder) compileIgnoreSingle(remoteId typeId) (engine *decEngine, err
func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEngine, err error) {
rt := ut.base
srt := rt
- if srt.Kind() != reflect.Struct ||
- ut.isGobDecoder {
+ if srt.Kind() != reflect.Struct || ut.externalDec != 0 {
return dec.compileSingle(remoteId, ut)
}
var wireStruct *structType
@@ -1224,14 +1237,14 @@ func (dec *Decoder) decodeValue(wireId typeId, val reflect.Value) {
return
}
engine := *enginePtr
- if st := base; st.Kind() == reflect.Struct && !ut.isGobDecoder {
+ if st := base; st.Kind() == reflect.Struct && ut.externalDec == 0 {
if engine.numInstr == 0 && st.NumField() > 0 && len(dec.wireType[wireId].StructT.Field) > 0 {
name := base.Name()
errorf("type mismatch: no fields matched compiling decoder for %s", name)
}
- dec.decodeStruct(engine, ut, uintptr(unsafeAddr(val)), ut.indir)
+ dec.decodeStruct(engine, ut, unsafeAddr(val), ut.indir)
} else {
- dec.decodeSingle(engine, ut, uintptr(unsafeAddr(val)))
+ dec.decodeSingle(engine, ut, unsafeAddr(val))
}
}
@@ -1283,13 +1296,13 @@ func init() {
// into existing structs or slices cannot be addressed,
// so simulate it by returning a pointer to a copy.
// Each call allocates once.
-func unsafeAddr(v reflect.Value) uintptr {
+func unsafeAddr(v reflect.Value) unsafe.Pointer {
if v.CanAddr() {
- return v.UnsafeAddr()
+ return unsafe.Pointer(v.UnsafeAddr())
}
x := reflect.New(v.Type()).Elem()
x.Set(v)
- return x.UnsafeAddr()
+ return unsafe.Pointer(x.UnsafeAddr())
}
// Gob depends on being able to take the address