diff options
Diffstat (limited to 'src/pkg/encoding/gob/decode.go')
-rw-r--r-- | src/pkg/encoding/gob/decode.go | 89 |
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 |