aboutsummaryrefslogtreecommitdiff
path: root/src/encoding/gob/decode.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/encoding/gob/decode.go')
-rw-r--r--src/encoding/gob/decode.go33
1 files changed, 21 insertions, 12 deletions
diff --git a/src/encoding/gob/decode.go b/src/encoding/gob/decode.go
index 6a9213fb3c..f44838e4cf 100644
--- a/src/encoding/gob/decode.go
+++ b/src/encoding/gob/decode.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+//go:generate go run decgen.go -output dec_helpers.go
+
package gob
import (
@@ -19,6 +21,8 @@ var (
errRange = errors.New("gob: bad data: field numbers out of bounds")
)
+type decHelper func(state *decoderState, v reflect.Value, length int, ovfl error) bool
+
// decoderState is the execution state of an instance of the decoder. A new state
// is created for nested objects.
type decoderState struct {
@@ -257,7 +261,7 @@ func float64FromBits(u uint64) float64 {
// number, and returns it. It's a helper function for float32 and complex64.
// It returns a float64 because that's what reflection needs, but its return
// value is known to be accurately representable in a float32.
-func float32FromBits(i *decInstr, u uint64) float64 {
+func float32FromBits(u uint64, ovfl error) float64 {
v := float64FromBits(u)
av := v
if av < 0 {
@@ -265,7 +269,7 @@ func float32FromBits(i *decInstr, u uint64) float64 {
}
// +Inf is OK in both 32- and 64-bit floats. Underflow is always OK.
if math.MaxFloat32 < av && av <= math.MaxFloat64 {
- error_(i.ovfl)
+ error_(ovfl)
}
return v
}
@@ -273,7 +277,7 @@ func float32FromBits(i *decInstr, u uint64) float64 {
// decFloat32 decodes an unsigned integer, treats it as a 32-bit floating-point
// number, and stores it in value.
func decFloat32(i *decInstr, state *decoderState, value reflect.Value) {
- value.SetFloat(float32FromBits(i, state.decodeUint()))
+ value.SetFloat(float32FromBits(state.decodeUint(), i.ovfl))
}
// decFloat64 decodes an unsigned integer, treats it as a 64-bit floating-point
@@ -286,8 +290,8 @@ func decFloat64(i *decInstr, state *decoderState, value reflect.Value) {
// pair of floating point numbers, and stores them as a complex64 in value.
// The real part comes first.
func decComplex64(i *decInstr, state *decoderState, value reflect.Value) {
- real := float32FromBits(i, state.decodeUint())
- imag := float32FromBits(i, state.decodeUint())
+ real := float32FromBits(state.decodeUint(), i.ovfl)
+ imag := float32FromBits(state.decodeUint(), i.ovfl)
value.SetComplex(complex(real, imag))
}
@@ -450,7 +454,10 @@ func (dec *Decoder) ignoreSingle(engine *decEngine) {
}
// decodeArrayHelper does the work for decoding arrays and slices.
-func (dec *Decoder) decodeArrayHelper(state *decoderState, value reflect.Value, elemOp decOp, length int, ovfl error) {
+func (dec *Decoder) decodeArrayHelper(state *decoderState, value reflect.Value, elemOp decOp, length int, ovfl error, helper decHelper) {
+ if helper != nil && helper(state, value, length, ovfl) {
+ return
+ }
instr := &decInstr{elemOp, 0, nil, ovfl}
isPtr := value.Type().Elem().Kind() == reflect.Ptr
for i := 0; i < length; i++ {
@@ -468,11 +475,11 @@ func (dec *Decoder) decodeArrayHelper(state *decoderState, value reflect.Value,
// decodeArray decodes an array and stores it in value.
// 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, value reflect.Value, elemOp decOp, length int, ovfl error) {
+func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, value reflect.Value, elemOp decOp, length int, ovfl error, helper decHelper) {
if n := state.decodeUint(); n != uint64(length) {
errorf("length mismatch in decodeArray")
}
- dec.decodeArrayHelper(state, value, elemOp, length, ovfl)
+ dec.decodeArrayHelper(state, value, elemOp, length, ovfl, helper)
}
// decodeIntoValue is a helper for map decoding.
@@ -534,7 +541,7 @@ func (dec *Decoder) ignoreMap(state *decoderState, keyOp, elemOp decOp) {
// decodeSlice decodes a slice and stores it in value.
// Slices are encoded as an unsigned length followed by the elements.
-func (dec *Decoder) decodeSlice(state *decoderState, value reflect.Value, elemOp decOp, ovfl error) {
+func (dec *Decoder) decodeSlice(state *decoderState, value reflect.Value, elemOp decOp, ovfl error, helper decHelper) {
u := state.decodeUint()
typ := value.Type()
size := uint64(typ.Elem().Size())
@@ -551,7 +558,7 @@ func (dec *Decoder) decodeSlice(state *decoderState, value reflect.Value, elemOp
} else {
value.Set(value.Slice(0, n))
}
- dec.decodeArrayHelper(state, value, elemOp, n, ovfl)
+ dec.decodeArrayHelper(state, value, elemOp, n, ovfl, helper)
}
// ignoreSlice skips over the data for a slice value with no destination.
@@ -720,8 +727,9 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
elemId := dec.wireType[wireId].ArrayT.Elem
elemOp := dec.decOpFor(elemId, t.Elem(), name, inProgress)
ovfl := overflow(name)
+ helper := decArrayHelper[t.Elem().Kind()]
op = func(i *decInstr, state *decoderState, value reflect.Value) {
- state.dec.decodeArray(t, state, value, *elemOp, t.Len(), ovfl)
+ state.dec.decodeArray(t, state, value, *elemOp, t.Len(), ovfl, helper)
}
case reflect.Map:
@@ -748,8 +756,9 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
}
elemOp := dec.decOpFor(elemId, t.Elem(), name, inProgress)
ovfl := overflow(name)
+ helper := decSliceHelper[t.Elem().Kind()]
op = func(i *decInstr, state *decoderState, value reflect.Value) {
- state.dec.decodeSlice(state, value, *elemOp, ovfl)
+ state.dec.decodeSlice(state, value, *elemOp, ovfl, helper)
}
case reflect.Struct: