diff options
Diffstat (limited to 'src/pkg/encoding/gob')
-rw-r--r-- | src/pkg/encoding/gob/codec_test.go | 1506 | ||||
-rw-r--r-- | src/pkg/encoding/gob/debug.go | 705 | ||||
-rw-r--r-- | src/pkg/encoding/gob/decode.go | 1317 | ||||
-rw-r--r-- | src/pkg/encoding/gob/decoder.go | 237 | ||||
-rw-r--r-- | src/pkg/encoding/gob/doc.go | 386 | ||||
-rw-r--r-- | src/pkg/encoding/gob/dump.go | 29 | ||||
-rw-r--r-- | src/pkg/encoding/gob/encode.go | 760 | ||||
-rw-r--r-- | src/pkg/encoding/gob/encoder.go | 253 | ||||
-rw-r--r-- | src/pkg/encoding/gob/encoder_test.go | 862 | ||||
-rw-r--r-- | src/pkg/encoding/gob/error.go | 43 | ||||
-rw-r--r-- | src/pkg/encoding/gob/example_encdec_test.go | 61 | ||||
-rw-r--r-- | src/pkg/encoding/gob/example_interface_test.go | 81 | ||||
-rw-r--r-- | src/pkg/encoding/gob/example_test.go | 60 | ||||
-rw-r--r-- | src/pkg/encoding/gob/gobencdec_test.go | 797 | ||||
-rw-r--r-- | src/pkg/encoding/gob/timing_test.go | 109 | ||||
-rw-r--r-- | src/pkg/encoding/gob/type.go | 893 | ||||
-rw-r--r-- | src/pkg/encoding/gob/type_test.go | 222 |
17 files changed, 0 insertions, 8321 deletions
diff --git a/src/pkg/encoding/gob/codec_test.go b/src/pkg/encoding/gob/codec_test.go deleted file mode 100644 index fa57f3761..000000000 --- a/src/pkg/encoding/gob/codec_test.go +++ /dev/null @@ -1,1506 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gob - -import ( - "bytes" - "errors" - "flag" - "math" - "math/rand" - "reflect" - "strings" - "testing" - "time" - "unsafe" -) - -var doFuzzTests = flag.Bool("gob.fuzz", false, "run the fuzz tests, which are large and very slow") - -// Guarantee encoding format by comparing some encodings to hand-written values -type EncodeT struct { - x uint64 - b []byte -} - -var encodeT = []EncodeT{ - {0x00, []byte{0x00}}, - {0x0F, []byte{0x0F}}, - {0xFF, []byte{0xFF, 0xFF}}, - {0xFFFF, []byte{0xFE, 0xFF, 0xFF}}, - {0xFFFFFF, []byte{0xFD, 0xFF, 0xFF, 0xFF}}, - {0xFFFFFFFF, []byte{0xFC, 0xFF, 0xFF, 0xFF, 0xFF}}, - {0xFFFFFFFFFF, []byte{0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}, - {0xFFFFFFFFFFFF, []byte{0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}, - {0xFFFFFFFFFFFFFF, []byte{0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}, - {0xFFFFFFFFFFFFFFFF, []byte{0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}, - {0x1111, []byte{0xFE, 0x11, 0x11}}, - {0x1111111111111111, []byte{0xF8, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}}, - {0x8888888888888888, []byte{0xF8, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88}}, - {1 << 63, []byte{0xF8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, -} - -// testError is meant to be used as a deferred function to turn a panic(gobError) into a -// plain test.Error call. -func testError(t *testing.T) { - if e := recover(); e != nil { - t.Error(e.(gobError).err) // Will re-panic if not one of our errors, such as a runtime error. - } - return -} - -// Test basic encode/decode routines for unsigned integers -func TestUintCodec(t *testing.T) { - defer testError(t) - b := new(bytes.Buffer) - encState := newEncoderState(b) - for _, tt := range encodeT { - b.Reset() - encState.encodeUint(tt.x) - if !bytes.Equal(tt.b, b.Bytes()) { - t.Errorf("encodeUint: %#x encode: expected % x got % x", tt.x, tt.b, b.Bytes()) - } - } - decState := newDecodeState(b) - for u := uint64(0); ; u = (u + 1) * 7 { - b.Reset() - encState.encodeUint(u) - v := decState.decodeUint() - if u != v { - t.Errorf("Encode/Decode: sent %#x received %#x", u, v) - } - if u&(1<<63) != 0 { - break - } - } -} - -func verifyInt(i int64, t *testing.T) { - defer testError(t) - var b = new(bytes.Buffer) - encState := newEncoderState(b) - encState.encodeInt(i) - decState := newDecodeState(b) - decState.buf = make([]byte, 8) - j := decState.decodeInt() - if i != j { - t.Errorf("Encode/Decode: sent %#x received %#x", uint64(i), uint64(j)) - } -} - -// Test basic encode/decode routines for signed integers -func TestIntCodec(t *testing.T) { - for u := uint64(0); ; u = (u + 1) * 7 { - // Do positive and negative values - i := int64(u) - verifyInt(i, t) - verifyInt(-i, t) - verifyInt(^i, t) - if u&(1<<63) != 0 { - break - } - } - verifyInt(-1<<63, t) // a tricky case -} - -// The result of encoding a true boolean with field number 7 -var boolResult = []byte{0x07, 0x01} - -// The result of encoding a number 17 with field number 7 -var signedResult = []byte{0x07, 2 * 17} -var unsignedResult = []byte{0x07, 17} -var floatResult = []byte{0x07, 0xFE, 0x31, 0x40} - -// The result of encoding a number 17+19i with field number 7 -var complexResult = []byte{0x07, 0xFE, 0x31, 0x40, 0xFE, 0x33, 0x40} - -// The result of encoding "hello" with field number 7 -var bytesResult = []byte{0x07, 0x05, 'h', 'e', 'l', 'l', 'o'} - -func newDecodeState(buf *bytes.Buffer) *decoderState { - d := new(decoderState) - d.b = buf - d.buf = make([]byte, uint64Size) - return d -} - -func newEncoderState(b *bytes.Buffer) *encoderState { - b.Reset() - state := &encoderState{enc: nil, b: b} - state.fieldnum = -1 - return state -} - -// Test instruction execution for encoding. -// Do not run the machine yet; instead do individual instructions crafted by hand. -func TestScalarEncInstructions(t *testing.T) { - var b = new(bytes.Buffer) - - // bool - { - data := struct{ a bool }{true} - instr := &encInstr{encBool, 6, 0, 0} - state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) - if !bytes.Equal(boolResult, b.Bytes()) { - t.Errorf("bool enc instructions: expected % x got % x", boolResult, b.Bytes()) - } - } - - // int - { - b.Reset() - data := struct{ a int }{17} - instr := &encInstr{encInt, 6, 0, 0} - state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) - if !bytes.Equal(signedResult, b.Bytes()) { - t.Errorf("int enc instructions: expected % x got % x", signedResult, b.Bytes()) - } - } - - // uint - { - b.Reset() - data := struct{ a uint }{17} - instr := &encInstr{encUint, 6, 0, 0} - state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) - if !bytes.Equal(unsignedResult, b.Bytes()) { - t.Errorf("uint enc instructions: expected % x got % x", unsignedResult, b.Bytes()) - } - } - - // int8 - { - b.Reset() - data := struct{ a int8 }{17} - instr := &encInstr{encInt8, 6, 0, 0} - state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) - if !bytes.Equal(signedResult, b.Bytes()) { - t.Errorf("int8 enc instructions: expected % x got % x", signedResult, b.Bytes()) - } - } - - // uint8 - { - b.Reset() - data := struct{ a uint8 }{17} - instr := &encInstr{encUint8, 6, 0, 0} - state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) - if !bytes.Equal(unsignedResult, b.Bytes()) { - t.Errorf("uint8 enc instructions: expected % x got % x", unsignedResult, b.Bytes()) - } - } - - // int16 - { - b.Reset() - data := struct{ a int16 }{17} - instr := &encInstr{encInt16, 6, 0, 0} - state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) - if !bytes.Equal(signedResult, b.Bytes()) { - t.Errorf("int16 enc instructions: expected % x got % x", signedResult, b.Bytes()) - } - } - - // uint16 - { - b.Reset() - data := struct{ a uint16 }{17} - instr := &encInstr{encUint16, 6, 0, 0} - state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) - if !bytes.Equal(unsignedResult, b.Bytes()) { - t.Errorf("uint16 enc instructions: expected % x got % x", unsignedResult, b.Bytes()) - } - } - - // int32 - { - b.Reset() - data := struct{ a int32 }{17} - instr := &encInstr{encInt32, 6, 0, 0} - state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) - if !bytes.Equal(signedResult, b.Bytes()) { - t.Errorf("int32 enc instructions: expected % x got % x", signedResult, b.Bytes()) - } - } - - // uint32 - { - b.Reset() - data := struct{ a uint32 }{17} - instr := &encInstr{encUint32, 6, 0, 0} - state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) - if !bytes.Equal(unsignedResult, b.Bytes()) { - t.Errorf("uint32 enc instructions: expected % x got % x", unsignedResult, b.Bytes()) - } - } - - // int64 - { - b.Reset() - data := struct{ a int64 }{17} - instr := &encInstr{encInt64, 6, 0, 0} - state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) - if !bytes.Equal(signedResult, b.Bytes()) { - t.Errorf("int64 enc instructions: expected % x got % x", signedResult, b.Bytes()) - } - } - - // uint64 - { - b.Reset() - data := struct{ a uint64 }{17} - instr := &encInstr{encUint64, 6, 0, 0} - state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) - if !bytes.Equal(unsignedResult, b.Bytes()) { - t.Errorf("uint64 enc instructions: expected % x got % x", unsignedResult, b.Bytes()) - } - } - - // float32 - { - b.Reset() - data := struct{ a float32 }{17} - instr := &encInstr{encFloat32, 6, 0, 0} - state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) - if !bytes.Equal(floatResult, b.Bytes()) { - t.Errorf("float32 enc instructions: expected % x got % x", floatResult, b.Bytes()) - } - } - - // float64 - { - b.Reset() - data := struct{ a float64 }{17} - instr := &encInstr{encFloat64, 6, 0, 0} - state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) - if !bytes.Equal(floatResult, b.Bytes()) { - t.Errorf("float64 enc instructions: expected % x got % x", floatResult, b.Bytes()) - } - } - - // bytes == []uint8 - { - b.Reset() - data := struct{ a []byte }{[]byte("hello")} - instr := &encInstr{encUint8Array, 6, 0, 0} - state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) - if !bytes.Equal(bytesResult, b.Bytes()) { - t.Errorf("bytes enc instructions: expected % x got % x", bytesResult, b.Bytes()) - } - } - - // string - { - b.Reset() - data := struct{ a string }{"hello"} - instr := &encInstr{encString, 6, 0, 0} - state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) - if !bytes.Equal(bytesResult, b.Bytes()) { - t.Errorf("string enc instructions: expected % x got % x", bytesResult, b.Bytes()) - } - } -} - -func execDec(typ string, instr *decInstr, state *decoderState, t *testing.T, p unsafe.Pointer) { - defer testError(t) - v := int(state.decodeUint()) - if v+state.fieldnum != 6 { - t.Fatalf("decoding field number %d, got %d", 6, v+state.fieldnum) - } - instr.op(instr, state, decIndirect(p, instr.indir)) - state.fieldnum = 6 -} - -func newDecodeStateFromData(data []byte) *decoderState { - b := bytes.NewBuffer(data) - state := newDecodeState(b) - state.fieldnum = -1 - return state -} - -// Test instruction execution for decoding. -// Do not run the machine yet; instead do individual instructions crafted by hand. -func TestScalarDecInstructions(t *testing.T) { - ovfl := errors.New("overflow") - - // bool - { - var data struct { - a bool - } - instr := &decInstr{decBool, 6, 0, 0, ovfl} - state := newDecodeStateFromData(boolResult) - execDec("bool", instr, state, t, unsafe.Pointer(&data)) - if data.a != true { - t.Errorf("bool a = %v not true", data.a) - } - } - // int - { - var data struct { - a int - } - instr := &decInstr{decOpTable[reflect.Int], 6, 0, 0, ovfl} - state := newDecodeStateFromData(signedResult) - execDec("int", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("int a = %v not 17", data.a) - } - } - - // uint - { - var data struct { - a uint - } - instr := &decInstr{decOpTable[reflect.Uint], 6, 0, 0, ovfl} - state := newDecodeStateFromData(unsignedResult) - execDec("uint", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("uint a = %v not 17", data.a) - } - } - - // int8 - { - var data struct { - a int8 - } - instr := &decInstr{decInt8, 6, 0, 0, ovfl} - state := newDecodeStateFromData(signedResult) - execDec("int8", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("int8 a = %v not 17", data.a) - } - } - - // uint8 - { - var data struct { - a uint8 - } - instr := &decInstr{decUint8, 6, 0, 0, ovfl} - state := newDecodeStateFromData(unsignedResult) - execDec("uint8", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("uint8 a = %v not 17", data.a) - } - } - - // int16 - { - var data struct { - a int16 - } - instr := &decInstr{decInt16, 6, 0, 0, ovfl} - state := newDecodeStateFromData(signedResult) - execDec("int16", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("int16 a = %v not 17", data.a) - } - } - - // uint16 - { - var data struct { - a uint16 - } - instr := &decInstr{decUint16, 6, 0, 0, ovfl} - state := newDecodeStateFromData(unsignedResult) - execDec("uint16", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("uint16 a = %v not 17", data.a) - } - } - - // int32 - { - var data struct { - a int32 - } - instr := &decInstr{decInt32, 6, 0, 0, ovfl} - state := newDecodeStateFromData(signedResult) - execDec("int32", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("int32 a = %v not 17", data.a) - } - } - - // uint32 - { - var data struct { - a uint32 - } - instr := &decInstr{decUint32, 6, 0, 0, ovfl} - state := newDecodeStateFromData(unsignedResult) - execDec("uint32", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("uint32 a = %v not 17", data.a) - } - } - - // uintptr - { - var data struct { - a uintptr - } - instr := &decInstr{decOpTable[reflect.Uintptr], 6, 0, 0, ovfl} - state := newDecodeStateFromData(unsignedResult) - execDec("uintptr", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("uintptr a = %v not 17", data.a) - } - } - - // int64 - { - var data struct { - a int64 - } - instr := &decInstr{decInt64, 6, 0, 0, ovfl} - state := newDecodeStateFromData(signedResult) - execDec("int64", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("int64 a = %v not 17", data.a) - } - } - - // uint64 - { - var data struct { - a uint64 - } - instr := &decInstr{decUint64, 6, 0, 0, ovfl} - state := newDecodeStateFromData(unsignedResult) - execDec("uint64", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("uint64 a = %v not 17", data.a) - } - } - - // float32 - { - var data struct { - a float32 - } - instr := &decInstr{decFloat32, 6, 0, 0, ovfl} - state := newDecodeStateFromData(floatResult) - execDec("float32", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("float32 a = %v not 17", data.a) - } - } - - // float64 - { - var data struct { - a float64 - } - instr := &decInstr{decFloat64, 6, 0, 0, ovfl} - state := newDecodeStateFromData(floatResult) - execDec("float64", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("float64 a = %v not 17", data.a) - } - } - - // complex64 - { - var data struct { - a complex64 - } - instr := &decInstr{decOpTable[reflect.Complex64], 6, 0, 0, ovfl} - state := newDecodeStateFromData(complexResult) - execDec("complex", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17+19i { - t.Errorf("complex a = %v not 17+19i", data.a) - } - } - - // complex128 - { - var data struct { - a complex128 - } - instr := &decInstr{decOpTable[reflect.Complex128], 6, 0, 0, ovfl} - state := newDecodeStateFromData(complexResult) - execDec("complex", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17+19i { - t.Errorf("complex a = %v not 17+19i", data.a) - } - } - - // bytes == []uint8 - { - var data struct { - a []byte - } - instr := &decInstr{decUint8Slice, 6, 0, 0, ovfl} - state := newDecodeStateFromData(bytesResult) - execDec("bytes", instr, state, t, unsafe.Pointer(&data)) - if string(data.a) != "hello" { - t.Errorf(`bytes a = %q not "hello"`, string(data.a)) - } - } - - // string - { - var data struct { - a string - } - instr := &decInstr{decString, 6, 0, 0, ovfl} - state := newDecodeStateFromData(bytesResult) - execDec("bytes", instr, state, t, unsafe.Pointer(&data)) - if data.a != "hello" { - t.Errorf(`bytes a = %q not "hello"`, data.a) - } - } -} - -func TestEndToEnd(t *testing.T) { - type T2 struct { - T string - } - s1 := "string1" - s2 := "string2" - type T1 struct { - A, B, C int - M map[string]*float64 - EmptyMap map[string]int // to check that we receive a non-nil map. - N *[3]float64 - Strs *[2]string - Int64s *[]int64 - RI complex64 - S string - Y []byte - T *T2 - } - pi := 3.14159 - e := 2.71828 - t1 := &T1{ - A: 17, - B: 18, - C: -5, - M: map[string]*float64{"pi": &pi, "e": &e}, - EmptyMap: make(map[string]int), - N: &[3]float64{1.5, 2.5, 3.5}, - Strs: &[2]string{s1, s2}, - Int64s: &[]int64{77, 89, 123412342134}, - RI: 17 - 23i, - S: "Now is the time", - Y: []byte("hello, sailor"), - T: &T2{"this is T2"}, - } - b := new(bytes.Buffer) - err := NewEncoder(b).Encode(t1) - if err != nil { - t.Error("encode:", err) - } - var _t1 T1 - err = NewDecoder(b).Decode(&_t1) - if err != nil { - t.Fatal("decode:", err) - } - if !reflect.DeepEqual(t1, &_t1) { - t.Errorf("encode expected %v got %v", *t1, _t1) - } - // Be absolutely sure the received map is non-nil. - if t1.EmptyMap == nil { - t.Errorf("nil map sent") - } - if _t1.EmptyMap == nil { - t.Errorf("nil map received") - } -} - -func TestOverflow(t *testing.T) { - type inputT struct { - Maxi int64 - Mini int64 - Maxu uint64 - Maxf float64 - Minf float64 - Maxc complex128 - Minc complex128 - } - var it inputT - var err error - b := new(bytes.Buffer) - enc := NewEncoder(b) - dec := NewDecoder(b) - - // int8 - b.Reset() - it = inputT{ - Maxi: math.MaxInt8 + 1, - } - type outi8 struct { - Maxi int8 - Mini int8 - } - var o1 outi8 - enc.Encode(it) - err = dec.Decode(&o1) - if err == nil || err.Error() != `value for "Maxi" out of range` { - t.Error("wrong overflow error for int8:", err) - } - it = inputT{ - Mini: math.MinInt8 - 1, - } - b.Reset() - enc.Encode(it) - err = dec.Decode(&o1) - if err == nil || err.Error() != `value for "Mini" out of range` { - t.Error("wrong underflow error for int8:", err) - } - - // int16 - b.Reset() - it = inputT{ - Maxi: math.MaxInt16 + 1, - } - type outi16 struct { - Maxi int16 - Mini int16 - } - var o2 outi16 - enc.Encode(it) - err = dec.Decode(&o2) - if err == nil || err.Error() != `value for "Maxi" out of range` { - t.Error("wrong overflow error for int16:", err) - } - it = inputT{ - Mini: math.MinInt16 - 1, - } - b.Reset() - enc.Encode(it) - err = dec.Decode(&o2) - if err == nil || err.Error() != `value for "Mini" out of range` { - t.Error("wrong underflow error for int16:", err) - } - - // int32 - b.Reset() - it = inputT{ - Maxi: math.MaxInt32 + 1, - } - type outi32 struct { - Maxi int32 - Mini int32 - } - var o3 outi32 - enc.Encode(it) - err = dec.Decode(&o3) - if err == nil || err.Error() != `value for "Maxi" out of range` { - t.Error("wrong overflow error for int32:", err) - } - it = inputT{ - Mini: math.MinInt32 - 1, - } - b.Reset() - enc.Encode(it) - err = dec.Decode(&o3) - if err == nil || err.Error() != `value for "Mini" out of range` { - t.Error("wrong underflow error for int32:", err) - } - - // uint8 - b.Reset() - it = inputT{ - Maxu: math.MaxUint8 + 1, - } - type outu8 struct { - Maxu uint8 - } - var o4 outu8 - enc.Encode(it) - err = dec.Decode(&o4) - if err == nil || err.Error() != `value for "Maxu" out of range` { - t.Error("wrong overflow error for uint8:", err) - } - - // uint16 - b.Reset() - it = inputT{ - Maxu: math.MaxUint16 + 1, - } - type outu16 struct { - Maxu uint16 - } - var o5 outu16 - enc.Encode(it) - err = dec.Decode(&o5) - if err == nil || err.Error() != `value for "Maxu" out of range` { - t.Error("wrong overflow error for uint16:", err) - } - - // uint32 - b.Reset() - it = inputT{ - Maxu: math.MaxUint32 + 1, - } - type outu32 struct { - Maxu uint32 - } - var o6 outu32 - enc.Encode(it) - err = dec.Decode(&o6) - if err == nil || err.Error() != `value for "Maxu" out of range` { - t.Error("wrong overflow error for uint32:", err) - } - - // float32 - b.Reset() - it = inputT{ - Maxf: math.MaxFloat32 * 2, - } - type outf32 struct { - Maxf float32 - Minf float32 - } - var o7 outf32 - enc.Encode(it) - err = dec.Decode(&o7) - if err == nil || err.Error() != `value for "Maxf" out of range` { - t.Error("wrong overflow error for float32:", err) - } - - // complex64 - b.Reset() - it = inputT{ - Maxc: complex(math.MaxFloat32*2, math.MaxFloat32*2), - } - type outc64 struct { - Maxc complex64 - Minc complex64 - } - var o8 outc64 - enc.Encode(it) - err = dec.Decode(&o8) - if err == nil || err.Error() != `value for "Maxc" out of range` { - t.Error("wrong overflow error for complex64:", err) - } -} - -func TestNesting(t *testing.T) { - type RT struct { - A string - Next *RT - } - rt := new(RT) - rt.A = "level1" - rt.Next = new(RT) - rt.Next.A = "level2" - b := new(bytes.Buffer) - NewEncoder(b).Encode(rt) - var drt RT - dec := NewDecoder(b) - err := dec.Decode(&drt) - if err != nil { - t.Fatal("decoder error:", err) - } - if drt.A != rt.A { - t.Errorf("nesting: encode expected %v got %v", *rt, drt) - } - if drt.Next == nil { - t.Errorf("nesting: recursion failed") - } - if drt.Next.A != rt.Next.A { - t.Errorf("nesting: encode expected %v got %v", *rt.Next, *drt.Next) - } -} - -// These three structures have the same data with different indirections -type T0 struct { - A int - B int - C int - D int -} -type T1 struct { - A int - B *int - C **int - D ***int -} -type T2 struct { - A ***int - B **int - C *int - D int -} - -func TestAutoIndirection(t *testing.T) { - // First transfer t1 into t0 - var t1 T1 - t1.A = 17 - t1.B = new(int) - *t1.B = 177 - t1.C = new(*int) - *t1.C = new(int) - **t1.C = 1777 - t1.D = new(**int) - *t1.D = new(*int) - **t1.D = new(int) - ***t1.D = 17777 - b := new(bytes.Buffer) - enc := NewEncoder(b) - enc.Encode(t1) - dec := NewDecoder(b) - var t0 T0 - dec.Decode(&t0) - if t0.A != 17 || t0.B != 177 || t0.C != 1777 || t0.D != 17777 { - t.Errorf("t1->t0: expected {17 177 1777 17777}; got %v", t0) - } - - // Now transfer t2 into t0 - var t2 T2 - t2.D = 17777 - t2.C = new(int) - *t2.C = 1777 - t2.B = new(*int) - *t2.B = new(int) - **t2.B = 177 - t2.A = new(**int) - *t2.A = new(*int) - **t2.A = new(int) - ***t2.A = 17 - b.Reset() - enc.Encode(t2) - t0 = T0{} - dec.Decode(&t0) - if t0.A != 17 || t0.B != 177 || t0.C != 1777 || t0.D != 17777 { - t.Errorf("t2->t0 expected {17 177 1777 17777}; got %v", t0) - } - - // Now transfer t0 into t1 - t0 = T0{17, 177, 1777, 17777} - b.Reset() - enc.Encode(t0) - t1 = T1{} - dec.Decode(&t1) - if t1.A != 17 || *t1.B != 177 || **t1.C != 1777 || ***t1.D != 17777 { - t.Errorf("t0->t1 expected {17 177 1777 17777}; got {%d %d %d %d}", t1.A, *t1.B, **t1.C, ***t1.D) - } - - // Now transfer t0 into t2 - b.Reset() - enc.Encode(t0) - t2 = T2{} - dec.Decode(&t2) - if ***t2.A != 17 || **t2.B != 177 || *t2.C != 1777 || t2.D != 17777 { - t.Errorf("t0->t2 expected {17 177 1777 17777}; got {%d %d %d %d}", ***t2.A, **t2.B, *t2.C, t2.D) - } - - // Now do t2 again but without pre-allocated pointers. - b.Reset() - enc.Encode(t0) - ***t2.A = 0 - **t2.B = 0 - *t2.C = 0 - t2.D = 0 - dec.Decode(&t2) - if ***t2.A != 17 || **t2.B != 177 || *t2.C != 1777 || t2.D != 17777 { - t.Errorf("t0->t2 expected {17 177 1777 17777}; got {%d %d %d %d}", ***t2.A, **t2.B, *t2.C, t2.D) - } -} - -type RT0 struct { - A int - B string - C float64 -} -type RT1 struct { - C float64 - B string - A int - NotSet string -} - -func TestReorderedFields(t *testing.T) { - var rt0 RT0 - rt0.A = 17 - rt0.B = "hello" - rt0.C = 3.14159 - b := new(bytes.Buffer) - NewEncoder(b).Encode(rt0) - dec := NewDecoder(b) - var rt1 RT1 - // Wire type is RT0, local type is RT1. - err := dec.Decode(&rt1) - if err != nil { - t.Fatal("decode error:", err) - } - if rt0.A != rt1.A || rt0.B != rt1.B || rt0.C != rt1.C { - t.Errorf("rt1->rt0: expected %v; got %v", rt0, rt1) - } -} - -// Like an RT0 but with fields we'll ignore on the decode side. -type IT0 struct { - A int64 - B string - Ignore_d []int - Ignore_e [3]float64 - Ignore_f bool - Ignore_g string - Ignore_h []byte - Ignore_i *RT1 - Ignore_m map[string]int - C float64 -} - -func TestIgnoredFields(t *testing.T) { - var it0 IT0 - it0.A = 17 - it0.B = "hello" - it0.C = 3.14159 - it0.Ignore_d = []int{1, 2, 3} - it0.Ignore_e[0] = 1.0 - it0.Ignore_e[1] = 2.0 - it0.Ignore_e[2] = 3.0 - it0.Ignore_f = true - it0.Ignore_g = "pay no attention" - it0.Ignore_h = []byte("to the curtain") - it0.Ignore_i = &RT1{3.1, "hi", 7, "hello"} - it0.Ignore_m = map[string]int{"one": 1, "two": 2} - - b := new(bytes.Buffer) - NewEncoder(b).Encode(it0) - dec := NewDecoder(b) - var rt1 RT1 - // Wire type is IT0, local type is RT1. - err := dec.Decode(&rt1) - if err != nil { - t.Error("error: ", err) - } - if int(it0.A) != rt1.A || it0.B != rt1.B || it0.C != rt1.C { - t.Errorf("rt0->rt1: expected %v; got %v", it0, rt1) - } -} - -func TestBadRecursiveType(t *testing.T) { - type Rec ***Rec - var rec Rec - b := new(bytes.Buffer) - err := NewEncoder(b).Encode(&rec) - if err == nil { - t.Error("expected error; got none") - } else if strings.Index(err.Error(), "recursive") < 0 { - t.Error("expected recursive type error; got", err) - } - // Can't test decode easily because we can't encode one, so we can't pass one to a Decoder. -} - -type Indirect struct { - A ***[3]int - S ***[]int - M ****map[string]int -} - -type Direct struct { - A [3]int - S []int - M map[string]int -} - -func TestIndirectSliceMapArray(t *testing.T) { - // Marshal indirect, unmarshal to direct. - i := new(Indirect) - i.A = new(**[3]int) - *i.A = new(*[3]int) - **i.A = new([3]int) - ***i.A = [3]int{1, 2, 3} - i.S = new(**[]int) - *i.S = new(*[]int) - **i.S = new([]int) - ***i.S = []int{4, 5, 6} - i.M = new(***map[string]int) - *i.M = new(**map[string]int) - **i.M = new(*map[string]int) - ***i.M = new(map[string]int) - ****i.M = map[string]int{"one": 1, "two": 2, "three": 3} - b := new(bytes.Buffer) - NewEncoder(b).Encode(i) - dec := NewDecoder(b) - var d Direct - err := dec.Decode(&d) - if err != nil { - t.Error("error: ", err) - } - if len(d.A) != 3 || d.A[0] != 1 || d.A[1] != 2 || d.A[2] != 3 { - t.Errorf("indirect to direct: d.A is %v not %v", d.A, ***i.A) - } - if len(d.S) != 3 || d.S[0] != 4 || d.S[1] != 5 || d.S[2] != 6 { - t.Errorf("indirect to direct: d.S is %v not %v", d.S, ***i.S) - } - if len(d.M) != 3 || d.M["one"] != 1 || d.M["two"] != 2 || d.M["three"] != 3 { - t.Errorf("indirect to direct: d.M is %v not %v", d.M, ***i.M) - } - // Marshal direct, unmarshal to indirect. - d.A = [3]int{11, 22, 33} - d.S = []int{44, 55, 66} - d.M = map[string]int{"four": 4, "five": 5, "six": 6} - i = new(Indirect) - b.Reset() - NewEncoder(b).Encode(d) - dec = NewDecoder(b) - err = dec.Decode(&i) - if err != nil { - t.Fatal("error: ", err) - } - if len(***i.A) != 3 || (***i.A)[0] != 11 || (***i.A)[1] != 22 || (***i.A)[2] != 33 { - t.Errorf("direct to indirect: ***i.A is %v not %v", ***i.A, d.A) - } - if len(***i.S) != 3 || (***i.S)[0] != 44 || (***i.S)[1] != 55 || (***i.S)[2] != 66 { - t.Errorf("direct to indirect: ***i.S is %v not %v", ***i.S, ***i.S) - } - if len(****i.M) != 3 || (****i.M)["four"] != 4 || (****i.M)["five"] != 5 || (****i.M)["six"] != 6 { - t.Errorf("direct to indirect: ****i.M is %v not %v", ****i.M, d.M) - } -} - -// An interface with several implementations -type Squarer interface { - Square() int -} - -type Int int - -func (i Int) Square() int { - return int(i * i) -} - -type Float float64 - -func (f Float) Square() int { - return int(f * f) -} - -type Vector []int - -func (v Vector) Square() int { - sum := 0 - for _, x := range v { - sum += x * x - } - return sum -} - -type Point struct { - X, Y int -} - -func (p Point) Square() int { - return p.X*p.X + p.Y*p.Y -} - -// A struct with interfaces in it. -type InterfaceItem struct { - I int - Sq1, Sq2, Sq3 Squarer - F float64 - Sq []Squarer -} - -// The same struct without interfaces -type NoInterfaceItem struct { - I int - F float64 -} - -func TestInterface(t *testing.T) { - iVal := Int(3) - fVal := Float(5) - // Sending a Vector will require that the receiver define a type in the middle of - // receiving the value for item2. - vVal := Vector{1, 2, 3} - b := new(bytes.Buffer) - item1 := &InterfaceItem{1, iVal, fVal, vVal, 11.5, []Squarer{iVal, fVal, nil, vVal}} - // Register the types. - Register(Int(0)) - Register(Float(0)) - Register(Vector{}) - err := NewEncoder(b).Encode(item1) - if err != nil { - t.Error("expected no encode error; got", err) - } - - item2 := InterfaceItem{} - err = NewDecoder(b).Decode(&item2) - if err != nil { - t.Fatal("decode:", err) - } - if item2.I != item1.I { - t.Error("normal int did not decode correctly") - } - if item2.Sq1 == nil || item2.Sq1.Square() != iVal.Square() { - t.Error("Int did not decode correctly") - } - if item2.Sq2 == nil || item2.Sq2.Square() != fVal.Square() { - t.Error("Float did not decode correctly") - } - if item2.Sq3 == nil || item2.Sq3.Square() != vVal.Square() { - t.Error("Vector did not decode correctly") - } - if item2.F != item1.F { - t.Error("normal float did not decode correctly") - } - // Now check that we received a slice of Squarers correctly, including a nil element - if len(item1.Sq) != len(item2.Sq) { - t.Fatalf("[]Squarer length wrong: got %d; expected %d", len(item2.Sq), len(item1.Sq)) - } - for i, v1 := range item1.Sq { - v2 := item2.Sq[i] - if v1 == nil || v2 == nil { - if v1 != nil || v2 != nil { - t.Errorf("item %d inconsistent nils", i) - } - } else if v1.Square() != v2.Square() { - t.Errorf("item %d inconsistent values: %v %v", i, v1, v2) - } - } -} - -// A struct with all basic types, stored in interfaces. -type BasicInterfaceItem struct { - Int, Int8, Int16, Int32, Int64 interface{} - Uint, Uint8, Uint16, Uint32, Uint64 interface{} - Float32, Float64 interface{} - Complex64, Complex128 interface{} - Bool interface{} - String interface{} - Bytes interface{} -} - -func TestInterfaceBasic(t *testing.T) { - b := new(bytes.Buffer) - item1 := &BasicInterfaceItem{ - int(1), int8(1), int16(1), int32(1), int64(1), - uint(1), uint8(1), uint16(1), uint32(1), uint64(1), - float32(1), 1.0, - complex64(1i), complex128(1i), - true, - "hello", - []byte("sailor"), - } - err := NewEncoder(b).Encode(item1) - if err != nil { - t.Error("expected no encode error; got", err) - } - - item2 := &BasicInterfaceItem{} - err = NewDecoder(b).Decode(&item2) - if err != nil { - t.Fatal("decode:", err) - } - if !reflect.DeepEqual(item1, item2) { - t.Errorf("encode expected %v got %v", item1, item2) - } - // Hand check a couple for correct types. - if v, ok := item2.Bool.(bool); !ok || !v { - t.Error("boolean should be true") - } - if v, ok := item2.String.(string); !ok || v != item1.String.(string) { - t.Errorf("string should be %v is %v", item1.String, v) - } -} - -type String string - -type PtrInterfaceItem struct { - Str1 interface{} // basic - Str2 interface{} // derived -} - -// We'll send pointers; should receive values. -// Also check that we can register T but send *T. -func TestInterfacePointer(t *testing.T) { - b := new(bytes.Buffer) - str1 := "howdy" - str2 := String("kiddo") - item1 := &PtrInterfaceItem{ - &str1, - &str2, - } - // Register the type. - Register(str2) - err := NewEncoder(b).Encode(item1) - if err != nil { - t.Error("expected no encode error; got", err) - } - - item2 := &PtrInterfaceItem{} - err = NewDecoder(b).Decode(&item2) - if err != nil { - t.Fatal("decode:", err) - } - // Hand test for correct types and values. - if v, ok := item2.Str1.(string); !ok || v != str1 { - t.Errorf("basic string failed: %q should be %q", v, str1) - } - if v, ok := item2.Str2.(String); !ok || v != str2 { - t.Errorf("derived type String failed: %q should be %q", v, str2) - } -} - -func TestIgnoreInterface(t *testing.T) { - iVal := Int(3) - fVal := Float(5) - // Sending a Point will require that the receiver define a type in the middle of - // receiving the value for item2. - pVal := Point{2, 3} - b := new(bytes.Buffer) - item1 := &InterfaceItem{1, iVal, fVal, pVal, 11.5, nil} - // Register the types. - Register(Int(0)) - Register(Float(0)) - Register(Point{}) - err := NewEncoder(b).Encode(item1) - if err != nil { - t.Error("expected no encode error; got", err) - } - - item2 := NoInterfaceItem{} - err = NewDecoder(b).Decode(&item2) - if err != nil { - t.Fatal("decode:", err) - } - if item2.I != item1.I { - t.Error("normal int did not decode correctly") - } - if item2.F != item2.F { - t.Error("normal float did not decode correctly") - } -} - -type U struct { - A int - B string - c float64 - D uint -} - -func TestUnexportedFields(t *testing.T) { - var u0 U - u0.A = 17 - u0.B = "hello" - u0.c = 3.14159 - u0.D = 23 - b := new(bytes.Buffer) - NewEncoder(b).Encode(u0) - dec := NewDecoder(b) - var u1 U - u1.c = 1234. - err := dec.Decode(&u1) - if err != nil { - t.Fatal("decode error:", err) - } - if u0.A != u0.A || u0.B != u1.B || u0.D != u1.D { - t.Errorf("u1->u0: expected %v; got %v", u0, u1) - } - if u1.c != 1234. { - t.Error("u1.c modified") - } -} - -var singletons = []interface{}{ - true, - 7, - 3.2, - "hello", - [3]int{11, 22, 33}, - []float32{0.5, 0.25, 0.125}, - map[string]int{"one": 1, "two": 2}, -} - -func TestDebugSingleton(t *testing.T) { - if debugFunc == nil { - return - } - b := new(bytes.Buffer) - // Accumulate a number of values and print them out all at once. - for _, x := range singletons { - err := NewEncoder(b).Encode(x) - if err != nil { - t.Fatal("encode:", err) - } - } - debugFunc(b) -} - -// A type that won't be defined in the gob until we send it in an interface value. -type OnTheFly struct { - A int -} - -type DT struct { - // X OnTheFly - A int - B string - C float64 - I interface{} - J interface{} - I_nil interface{} - M map[string]int - T [3]int - S []string -} - -func newDT() DT { - var dt DT - dt.A = 17 - dt.B = "hello" - dt.C = 3.14159 - dt.I = 271828 - dt.J = OnTheFly{3} - dt.I_nil = nil - dt.M = map[string]int{"one": 1, "two": 2} - dt.T = [3]int{11, 22, 33} - dt.S = []string{"hi", "joe"} - return dt -} - -func TestDebugStruct(t *testing.T) { - if debugFunc == nil { - return - } - Register(OnTheFly{}) - dt := newDT() - b := new(bytes.Buffer) - err := NewEncoder(b).Encode(dt) - if err != nil { - t.Fatal("encode:", err) - } - debugBuffer := bytes.NewBuffer(b.Bytes()) - dt2 := &DT{} - err = NewDecoder(b).Decode(&dt2) - if err != nil { - t.Error("decode:", err) - } - debugFunc(debugBuffer) -} - -func encFuzzDec(rng *rand.Rand, in interface{}) error { - buf := new(bytes.Buffer) - enc := NewEncoder(buf) - if err := enc.Encode(&in); err != nil { - return err - } - - b := buf.Bytes() - for i, bi := range b { - if rng.Intn(10) < 3 { - b[i] = bi + uint8(rng.Intn(256)) - } - } - - dec := NewDecoder(buf) - var e interface{} - if err := dec.Decode(&e); err != nil { - return err - } - return nil -} - -// This does some "fuzz testing" by attempting to decode a sequence of random bytes. -func TestFuzz(t *testing.T) { - if !*doFuzzTests { - t.Logf("disabled; run with -gob.fuzz to enable") - return - } - - // all possible inputs - input := []interface{}{ - new(int), - new(float32), - new(float64), - new(complex128), - &ByteStruct{255}, - &ArrayStruct{}, - &StringStruct{"hello"}, - &GobTest1{0, &StringStruct{"hello"}}, - } - testFuzz(t, time.Now().UnixNano(), 100, input...) -} - -func TestFuzzRegressions(t *testing.T) { - if !*doFuzzTests { - t.Logf("disabled; run with -gob.fuzz to enable") - return - } - - // An instance triggering a type name of length ~102 GB. - testFuzz(t, 1328492090837718000, 100, new(float32)) - // An instance triggering a type name of 1.6 GB. - // Note: can take several minutes to run. - testFuzz(t, 1330522872628565000, 100, new(int)) -} - -func testFuzz(t *testing.T, seed int64, n int, input ...interface{}) { - for _, e := range input { - t.Logf("seed=%d n=%d e=%T", seed, n, e) - rng := rand.New(rand.NewSource(seed)) - for i := 0; i < n; i++ { - encFuzzDec(rng, e) - } - } -} - -// TestFuzzOneByte tries to decode corrupted input sequences -// and checks that no panic occurs. -func TestFuzzOneByte(t *testing.T) { - buf := new(bytes.Buffer) - Register(OnTheFly{}) - dt := newDT() - if err := NewEncoder(buf).Encode(dt); err != nil { - t.Fatal(err) - } - s := buf.String() - - indices := make([]int, 0, len(s)) - for i := 0; i < len(s); i++ { - switch i { - case 14, 167, 231, 265: // a slice length, corruptions are not handled yet. - continue - } - indices = append(indices, i) - } - if testing.Short() { - indices = []int{1, 111, 178} // known fixed panics - } - for _, i := range indices { - for j := 0; j < 256; j += 3 { - b := []byte(s) - b[i] ^= byte(j) - var e DT - func() { - defer func() { - if p := recover(); p != nil { - t.Errorf("crash for b[%d] ^= 0x%x", i, j) - panic(p) - } - }() - err := NewDecoder(bytes.NewReader(b)).Decode(&e) - _ = err - }() - } - } -} diff --git a/src/pkg/encoding/gob/debug.go b/src/pkg/encoding/gob/debug.go deleted file mode 100644 index 6117eb083..000000000 --- a/src/pkg/encoding/gob/debug.go +++ /dev/null @@ -1,705 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Delete the next line to include in the gob package. -// +build ignore - -package gob - -// This file is not normally included in the gob package. Used only for debugging the package itself. -// Except for reading uints, it is an implementation of a reader that is independent of -// the one implemented by Decoder. -// To enable the Debug function, delete the +build ignore line above and do -// go install - -import ( - "bytes" - "fmt" - "io" - "os" - "strings" - "sync" -) - -var dumpBytes = false // If true, print the remaining bytes in the input buffer at each item. - -// Init installs the debugging facility. If this file is not compiled in the -// package, the tests in codec_test.go are no-ops. -func init() { - debugFunc = Debug -} - -var ( - blanks = bytes.Repeat([]byte{' '}, 3*10) - empty = []byte(": <empty>\n") - tabs = strings.Repeat("\t", 100) -) - -// tab indents itself when printed. -type tab int - -func (t tab) String() string { - n := int(t) - if n > len(tabs) { - n = len(tabs) - } - return tabs[0:n] -} - -func (t tab) print() { - fmt.Fprint(os.Stderr, t) -} - -// A peekReader wraps an io.Reader, allowing one to peek ahead to see -// what's coming without stealing the data from the client of the Reader. -type peekReader struct { - r io.Reader - data []byte // read-ahead data -} - -// newPeekReader returns a peekReader that wraps r. -func newPeekReader(r io.Reader) *peekReader { - return &peekReader{r: r} -} - -// Read is the usual method. It will first take data that has been read ahead. -func (p *peekReader) Read(b []byte) (n int, err error) { - if len(p.data) == 0 { - return p.r.Read(b) - } - // Satisfy what's possible from the read-ahead data. - n = copy(b, p.data) - // Move data down to beginning of slice, to avoid endless growth - copy(p.data, p.data[n:]) - p.data = p.data[:len(p.data)-n] - return -} - -// peek returns as many bytes as possible from the unread -// portion of the stream, up to the length of b. -func (p *peekReader) peek(b []byte) (n int, err error) { - if len(p.data) > 0 { - n = copy(b, p.data) - if n == len(b) { - return - } - b = b[n:] - } - if len(b) == 0 { - return - } - m, e := io.ReadFull(p.r, b) - if m > 0 { - p.data = append(p.data, b[:m]...) - } - n += m - if e == io.ErrUnexpectedEOF { - // That means m > 0 but we reached EOF. If we got data - // we won't complain about not being able to peek enough. - if n > 0 { - e = nil - } else { - e = io.EOF - } - } - return n, e -} - -type debugger struct { - mutex sync.Mutex - remain int // the number of bytes known to remain in the input - remainingKnown bool // the value of 'remain' is valid - r *peekReader - wireType map[typeId]*wireType - tmp []byte // scratch space for decoding uints. -} - -// dump prints the next nBytes of the input. -// It arranges to print the output aligned from call to -// call, to make it easy to see what has been consumed. -func (deb *debugger) dump(format string, args ...interface{}) { - if !dumpBytes { - return - } - fmt.Fprintf(os.Stderr, format+" ", args...) - if !deb.remainingKnown { - return - } - if deb.remain < 0 { - fmt.Fprintf(os.Stderr, "remaining byte count is negative! %d\n", deb.remain) - return - } - data := make([]byte, deb.remain) - n, _ := deb.r.peek(data) - if n == 0 { - os.Stderr.Write(empty) - return - } - b := new(bytes.Buffer) - fmt.Fprintf(b, "[%d]{\n", deb.remain) - // Blanks until first byte - lineLength := 0 - if n := len(data); n%10 != 0 { - lineLength = 10 - n%10 - fmt.Fprintf(b, "\t%s", blanks[:lineLength*3]) - } - // 10 bytes per line - for len(data) > 0 { - if lineLength == 0 { - fmt.Fprint(b, "\t") - } - m := 10 - lineLength - lineLength = 0 - if m > len(data) { - m = len(data) - } - fmt.Fprintf(b, "% x\n", data[:m]) - data = data[m:] - } - fmt.Fprint(b, "}\n") - os.Stderr.Write(b.Bytes()) -} - -// Debug prints a human-readable representation of the gob data read from r. -// It is a no-op unless debugging was enabled when the package was built. -func Debug(r io.Reader) { - err := debug(r) - if err != nil { - fmt.Fprintf(os.Stderr, "gob debug: %s\n", err) - } -} - -// debug implements Debug, but catches panics and returns -// them as errors to be printed by Debug. -func debug(r io.Reader) (err error) { - defer catchError(&err) - fmt.Fprintln(os.Stderr, "Start of debugging") - deb := &debugger{ - r: newPeekReader(r), - wireType: make(map[typeId]*wireType), - tmp: make([]byte, 16), - } - if b, ok := r.(*bytes.Buffer); ok { - deb.remain = b.Len() - deb.remainingKnown = true - } - deb.gobStream() - return -} - -// note that we've consumed some bytes -func (deb *debugger) consumed(n int) { - if deb.remainingKnown { - deb.remain -= n - } -} - -// int64 decodes and returns the next integer, which must be present. -// Don't call this if you could be at EOF. -func (deb *debugger) int64() int64 { - return toInt(deb.uint64()) -} - -// uint64 returns and decodes the next unsigned integer, which must be present. -// Don't call this if you could be at EOF. -// TODO: handle errors better. -func (deb *debugger) uint64() uint64 { - n, w, err := decodeUintReader(deb.r, deb.tmp) - if err != nil { - errorf("debug: read error: %s", err) - } - deb.consumed(w) - return n -} - -// GobStream: -// DelimitedMessage* (until EOF) -func (deb *debugger) gobStream() { - // Make sure we're single-threaded through here. - deb.mutex.Lock() - defer deb.mutex.Unlock() - - for deb.delimitedMessage(0) { - } -} - -// DelimitedMessage: -// uint(lengthOfMessage) Message -func (deb *debugger) delimitedMessage(indent tab) bool { - for { - n := deb.loadBlock(true) - if n < 0 { - return false - } - deb.dump("Delimited message of length %d", n) - deb.message(indent) - } - return true -} - -// loadBlock preps us to read a message -// of the length specified next in the input. It returns -// the length of the block. The argument tells whether -// an EOF is acceptable now. If it is and one is found, -// the return value is negative. -func (deb *debugger) loadBlock(eofOK bool) int { - n64, w, err := decodeUintReader(deb.r, deb.tmp) // deb.uint64 will error at EOF - if err != nil { - if eofOK && err == io.EOF { - return -1 - } - errorf("debug: unexpected error: %s", err) - } - deb.consumed(w) - n := int(n64) - if n < 0 { - errorf("huge value for message length: %d", n64) - } - return int(n) -} - -// Message: -// TypeSequence TypedValue -// TypeSequence -// (TypeDefinition DelimitedTypeDefinition*)? -// DelimitedTypeDefinition: -// uint(lengthOfTypeDefinition) TypeDefinition -// TypedValue: -// int(typeId) Value -func (deb *debugger) message(indent tab) bool { - for { - // Convert the uint64 to a signed integer typeId - uid := deb.int64() - id := typeId(uid) - deb.dump("type id=%d", id) - if id < 0 { - deb.typeDefinition(indent, -id) - n := deb.loadBlock(false) - deb.dump("Message of length %d", n) - continue - } else { - deb.value(indent, id) - break - } - } - return true -} - -// Helper methods to make it easy to scan a type descriptor. - -// common returns the CommonType at the input point. -func (deb *debugger) common() CommonType { - fieldNum := -1 - name := "" - id := typeId(0) - for { - delta := deb.delta(-1) - if delta == 0 { - break - } - fieldNum += delta - switch fieldNum { - case 0: - name = deb.string() - case 1: - // Id typeId - id = deb.typeId() - default: - errorf("corrupted CommonType") - } - } - return CommonType{name, id} -} - -// uint returns the unsigned int at the input point, as a uint (not uint64). -func (deb *debugger) uint() uint { - return uint(deb.uint64()) -} - -// int returns the signed int at the input point, as an int (not int64). -func (deb *debugger) int() int { - return int(deb.int64()) -} - -// typeId returns the type id at the input point. -func (deb *debugger) typeId() typeId { - return typeId(deb.int64()) -} - -// string returns the string at the input point. -func (deb *debugger) string() string { - x := int(deb.uint64()) - b := make([]byte, x) - nb, _ := deb.r.Read(b) - if nb != x { - errorf("corrupted type") - } - deb.consumed(nb) - return string(b) -} - -// delta returns the field delta at the input point. The expect argument, -// if non-negative, identifies what the value should be. -func (deb *debugger) delta(expect int) int { - delta := int(deb.uint64()) - if delta < 0 || (expect >= 0 && delta != expect) { - errorf("decode: corrupted type: delta %d expected %d", delta, expect) - } - return delta -} - -// TypeDefinition: -// [int(-typeId) (already read)] encodingOfWireType -func (deb *debugger) typeDefinition(indent tab, id typeId) { - deb.dump("type definition for id %d", id) - // Encoding is of a wireType. Decode the structure as usual - fieldNum := -1 - wire := new(wireType) - // A wireType defines a single field. - delta := deb.delta(-1) - fieldNum += delta - switch fieldNum { - case 0: // array type, one field of {{Common}, elem, length} - // Field number 0 is CommonType - deb.delta(1) - com := deb.common() - // Field number 1 is type Id of elem - deb.delta(1) - id := deb.typeId() - // Field number 3 is length - deb.delta(1) - length := deb.int() - wire.ArrayT = &arrayType{com, id, length} - - case 1: // slice type, one field of {{Common}, elem} - // Field number 0 is CommonType - deb.delta(1) - com := deb.common() - // Field number 1 is type Id of elem - deb.delta(1) - id := deb.typeId() - wire.SliceT = &sliceType{com, id} - - case 2: // struct type, one field of {{Common}, []fieldType} - // Field number 0 is CommonType - deb.delta(1) - com := deb.common() - // Field number 1 is slice of FieldType - deb.delta(1) - numField := int(deb.uint()) - field := make([]*fieldType, numField) - for i := 0; i < numField; i++ { - field[i] = new(fieldType) - deb.delta(1) // field 0 of fieldType: name - field[i].Name = deb.string() - deb.delta(1) // field 1 of fieldType: id - field[i].Id = deb.typeId() - deb.delta(0) // end of fieldType - } - wire.StructT = &structType{com, field} - - case 3: // map type, one field of {{Common}, key, elem} - // Field number 0 is CommonType - deb.delta(1) - com := deb.common() - // Field number 1 is type Id of key - deb.delta(1) - keyId := deb.typeId() - // Field number 2 is type Id of elem - deb.delta(1) - elemId := deb.typeId() - wire.MapT = &mapType{com, keyId, elemId} - case 4: // GobEncoder type, one field of {{Common}} - // Field number 0 is CommonType - deb.delta(1) - com := deb.common() - wire.GobEncoderT = &gobEncoderType{com} - case 5: // BinaryMarshaler type, one field of {{Common}} - // Field number 0 is CommonType - deb.delta(1) - com := deb.common() - wire.BinaryMarshalerT = &gobEncoderType{com} - case 6: // TextMarshaler type, one field of {{Common}} - // Field number 0 is CommonType - deb.delta(1) - com := deb.common() - wire.TextMarshalerT = &gobEncoderType{com} - default: - errorf("bad field in type %d", fieldNum) - } - deb.printWireType(indent, wire) - deb.delta(0) // end inner type (arrayType, etc.) - deb.delta(0) // end wireType - // Remember we've seen this type. - deb.wireType[id] = wire -} - -// Value: -// SingletonValue | StructValue -func (deb *debugger) value(indent tab, id typeId) { - wire, ok := deb.wireType[id] - if ok && wire.StructT != nil { - deb.structValue(indent, id) - } else { - deb.singletonValue(indent, id) - } -} - -// SingletonValue: -// uint(0) FieldValue -func (deb *debugger) singletonValue(indent tab, id typeId) { - deb.dump("Singleton value") - // is it a builtin type? - wire := deb.wireType[id] - _, ok := builtinIdToType[id] - if !ok && wire == nil { - errorf("type id %d not defined", id) - } - m := deb.uint64() - if m != 0 { - errorf("expected zero; got %d", m) - } - deb.fieldValue(indent, id) -} - -// InterfaceValue: -// NilInterfaceValue | NonNilInterfaceValue -func (deb *debugger) interfaceValue(indent tab) { - deb.dump("Start of interface value") - if nameLen := deb.uint64(); nameLen == 0 { - deb.nilInterfaceValue(indent) - } else { - deb.nonNilInterfaceValue(indent, int(nameLen)) - } -} - -// NilInterfaceValue: -// uint(0) [already read] -func (deb *debugger) nilInterfaceValue(indent tab) int { - fmt.Fprintf(os.Stderr, "%snil interface\n", indent) - return 0 -} - -// NonNilInterfaceValue: -// ConcreteTypeName TypeSequence InterfaceContents -// ConcreteTypeName: -// uint(lengthOfName) [already read=n] name -// InterfaceContents: -// int(concreteTypeId) DelimitedValue -// DelimitedValue: -// uint(length) Value -func (deb *debugger) nonNilInterfaceValue(indent tab, nameLen int) { - // ConcreteTypeName - b := make([]byte, nameLen) - deb.r.Read(b) // TODO: CHECK THESE READS!! - deb.consumed(nameLen) - name := string(b) - - for { - id := deb.typeId() - if id < 0 { - deb.typeDefinition(indent, -id) - n := deb.loadBlock(false) - deb.dump("Nested message of length %d", n) - } else { - // DelimitedValue - x := deb.uint64() // in case we want to ignore the value; we don't. - fmt.Fprintf(os.Stderr, "%sinterface value, type %q id=%d; valueLength %d\n", indent, name, id, x) - deb.value(indent, id) - break - } - } -} - -// printCommonType prints a common type; used by printWireType. -func (deb *debugger) printCommonType(indent tab, kind string, common *CommonType) { - indent.print() - fmt.Fprintf(os.Stderr, "%s %q id=%d\n", kind, common.Name, common.Id) -} - -// printWireType prints the contents of a wireType. -func (deb *debugger) printWireType(indent tab, wire *wireType) { - fmt.Fprintf(os.Stderr, "%stype definition {\n", indent) - indent++ - switch { - case wire.ArrayT != nil: - deb.printCommonType(indent, "array", &wire.ArrayT.CommonType) - fmt.Fprintf(os.Stderr, "%slen %d\n", indent+1, wire.ArrayT.Len) - fmt.Fprintf(os.Stderr, "%selemid %d\n", indent+1, wire.ArrayT.Elem) - case wire.MapT != nil: - deb.printCommonType(indent, "map", &wire.MapT.CommonType) - fmt.Fprintf(os.Stderr, "%skey id=%d\n", indent+1, wire.MapT.Key) - fmt.Fprintf(os.Stderr, "%selem id=%d\n", indent+1, wire.MapT.Elem) - case wire.SliceT != nil: - deb.printCommonType(indent, "slice", &wire.SliceT.CommonType) - fmt.Fprintf(os.Stderr, "%selem id=%d\n", indent+1, wire.SliceT.Elem) - case wire.StructT != nil: - deb.printCommonType(indent, "struct", &wire.StructT.CommonType) - for i, field := range wire.StructT.Field { - fmt.Fprintf(os.Stderr, "%sfield %d:\t%s\tid=%d\n", indent+1, i, field.Name, field.Id) - } - case wire.GobEncoderT != nil: - deb.printCommonType(indent, "GobEncoder", &wire.GobEncoderT.CommonType) - } - indent-- - fmt.Fprintf(os.Stderr, "%s}\n", indent) -} - -// fieldValue prints a value of any type, such as a struct field. -// FieldValue: -// builtinValue | ArrayValue | MapValue | SliceValue | StructValue | InterfaceValue -func (deb *debugger) fieldValue(indent tab, id typeId) { - _, ok := builtinIdToType[id] - if ok { - if id == tInterface { - deb.interfaceValue(indent) - } else { - deb.printBuiltin(indent, id) - } - return - } - wire, ok := deb.wireType[id] - if !ok { - errorf("type id %d not defined", id) - } - switch { - case wire.ArrayT != nil: - deb.arrayValue(indent, wire) - case wire.MapT != nil: - deb.mapValue(indent, wire) - case wire.SliceT != nil: - deb.sliceValue(indent, wire) - case wire.StructT != nil: - deb.structValue(indent, id) - case wire.GobEncoderT != nil: - deb.gobEncoderValue(indent, id) - default: - panic("bad wire type for field") - } -} - -// printBuiltin prints a value not of a fundamental type, that is, -// one whose type is known to gobs at bootstrap time. -func (deb *debugger) printBuiltin(indent tab, id typeId) { - switch id { - case tBool: - x := deb.int64() - if x == 0 { - fmt.Fprintf(os.Stderr, "%sfalse\n", indent) - } else { - fmt.Fprintf(os.Stderr, "%strue\n", indent) - } - case tInt: - x := deb.int64() - fmt.Fprintf(os.Stderr, "%s%d\n", indent, x) - case tUint: - x := deb.int64() - fmt.Fprintf(os.Stderr, "%s%d\n", indent, x) - case tFloat: - x := deb.uint64() - fmt.Fprintf(os.Stderr, "%s%g\n", indent, floatFromBits(x)) - case tComplex: - r := deb.uint64() - i := deb.uint64() - fmt.Fprintf(os.Stderr, "%s%g+%gi\n", indent, floatFromBits(r), floatFromBits(i)) - case tBytes: - x := int(deb.uint64()) - b := make([]byte, x) - deb.r.Read(b) - deb.consumed(x) - fmt.Fprintf(os.Stderr, "%s{% x}=%q\n", indent, b, b) - case tString: - x := int(deb.uint64()) - b := make([]byte, x) - deb.r.Read(b) - deb.consumed(x) - fmt.Fprintf(os.Stderr, "%s%q\n", indent, b) - default: - panic("unknown builtin") - } -} - -// ArrayValue: -// uint(n) FieldValue*n -func (deb *debugger) arrayValue(indent tab, wire *wireType) { - elemId := wire.ArrayT.Elem - u := deb.uint64() - length := int(u) - for i := 0; i < length; i++ { - deb.fieldValue(indent, elemId) - } - if length != wire.ArrayT.Len { - fmt.Fprintf(os.Stderr, "%s(wrong length for array: %d should be %d)\n", indent, length, wire.ArrayT.Len) - } -} - -// MapValue: -// uint(n) (FieldValue FieldValue)*n [n (key, value) pairs] -func (deb *debugger) mapValue(indent tab, wire *wireType) { - keyId := wire.MapT.Key - elemId := wire.MapT.Elem - u := deb.uint64() - length := int(u) - for i := 0; i < length; i++ { - deb.fieldValue(indent+1, keyId) - deb.fieldValue(indent+1, elemId) - } -} - -// SliceValue: -// uint(n) (n FieldValue) -func (deb *debugger) sliceValue(indent tab, wire *wireType) { - elemId := wire.SliceT.Elem - u := deb.uint64() - length := int(u) - deb.dump("Start of slice of length %d", length) - - for i := 0; i < length; i++ { - deb.fieldValue(indent, elemId) - } -} - -// StructValue: -// (uint(fieldDelta) FieldValue)* -func (deb *debugger) structValue(indent tab, id typeId) { - deb.dump("Start of struct value of %q id=%d\n<<\n", id.name(), id) - fmt.Fprintf(os.Stderr, "%s%s struct {\n", indent, id.name()) - wire, ok := deb.wireType[id] - if !ok { - errorf("type id %d not defined", id) - } - strct := wire.StructT - fieldNum := -1 - indent++ - for { - delta := deb.uint64() - if delta == 0 { // struct terminator is zero delta fieldnum - break - } - fieldNum += int(delta) - if fieldNum < 0 || fieldNum >= len(strct.Field) { - deb.dump("field number out of range: prevField=%d delta=%d", fieldNum-int(delta), delta) - break - } - fmt.Fprintf(os.Stderr, "%sfield %d:\t%s\n", indent, fieldNum, wire.StructT.Field[fieldNum].Name) - deb.fieldValue(indent+1, strct.Field[fieldNum].Id) - } - indent-- - fmt.Fprintf(os.Stderr, "%s} // end %s struct\n", indent, id.name()) - deb.dump(">> End of struct value of type %d %q", id, id.name()) -} - -// GobEncoderValue: -// uint(n) byte*n -func (deb *debugger) gobEncoderValue(indent tab, id typeId) { - len := deb.uint64() - deb.dump("GobEncoder value of %q id=%d, length %d\n", id.name(), id, len) - fmt.Fprintf(os.Stderr, "%s%s (implements GobEncoder)\n", indent, id.name()) - data := make([]byte, len) - _, err := deb.r.Read(data) - if err != nil { - errorf("gobEncoder data read: %s", err) - } - fmt.Fprintf(os.Stderr, "%s[% .2x]\n", indent+1, data) -} diff --git a/src/pkg/encoding/gob/decode.go b/src/pkg/encoding/gob/decode.go deleted file mode 100644 index d8513148e..000000000 --- a/src/pkg/encoding/gob/decode.go +++ /dev/null @@ -1,1317 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gob - -// TODO(rsc): When garbage collector changes, revisit -// the allocations in this file that use unsafe.Pointer. - -import ( - "bytes" - "encoding" - "errors" - "io" - "math" - "reflect" - "unsafe" -) - -var ( - errBadUint = errors.New("gob: encoded unsigned integer out of range") - errBadType = errors.New("gob: unknown type id or corrupted data") - errRange = errors.New("gob: bad data: field numbers out of bounds") -) - -// decoderState is the execution state of an instance of the decoder. A new state -// is created for nested objects. -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). - b *bytes.Buffer - fieldnum int // the last field number read. - buf []byte - next *decoderState // for free list -} - -// We pass the bytes.Buffer separately for easier testing of the infrastructure -// without requiring a full Decoder. -func (dec *Decoder) newDecoderState(buf *bytes.Buffer) *decoderState { - d := dec.freeList - if d == nil { - d = new(decoderState) - d.dec = dec - d.buf = make([]byte, uint64Size) - } else { - dec.freeList = d.next - } - d.b = buf - return d -} - -func (dec *Decoder) freeDecoderState(d *decoderState) { - d.next = dec.freeList - dec.freeList = d -} - -func overflow(name string) error { - return errors.New(`value for "` + name + `" out of range`) -} - -// decodeUintReader reads an encoded unsigned integer from an io.Reader. -// Used only by the Decoder to read the message length. -func decodeUintReader(r io.Reader, buf []byte) (x uint64, width int, err error) { - width = 1 - n, err := io.ReadFull(r, buf[0:width]) - if n == 0 { - return - } - b := buf[0] - if b <= 0x7f { - return uint64(b), width, nil - } - n = -int(int8(b)) - if n > uint64Size { - err = errBadUint - return - } - width, err = io.ReadFull(r, buf[0:n]) - if err != nil { - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - return - } - // Could check that the high byte is zero but it's not worth it. - for _, b := range buf[0:width] { - x = x<<8 | uint64(b) - } - width++ // +1 for length byte - return -} - -// decodeUint reads an encoded unsigned integer from state.r. -// Does not check for overflow. -func (state *decoderState) decodeUint() (x uint64) { - b, err := state.b.ReadByte() - if err != nil { - error_(err) - } - if b <= 0x7f { - return uint64(b) - } - n := -int(int8(b)) - if n > uint64Size { - error_(errBadUint) - } - width, err := state.b.Read(state.buf[0:n]) - if err != nil { - error_(err) - } - // Don't need to check error; it's safe to loop regardless. - // Could check that the high byte is zero but it's not worth it. - for _, b := range state.buf[0:width] { - x = x<<8 | uint64(b) - } - return x -} - -// decodeInt reads an encoded signed integer from state.r. -// Does not check for overflow. -func (state *decoderState) decodeInt() int64 { - x := state.decodeUint() - if x&1 != 0 { - return ^int64(x >> 1) - } - return int64(x >> 1) -} - -// 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 { - op decOp - field int // field number of the wire type - indir int // how many pointer indirections to reach the value in the struct - offset uintptr // offset in the structure of the field to encode - ovfl error // error message for overflow/underflow (for arrays, of the elements) -} - -// Since the encoder writes no zeros, if we arrive at a decoder we have -// a value to extract and store. The field number has already been read -// (it's how we knew to call this decoder). -// Each decoder is responsible for handling any indirections associated -// with the data structure. If any pointer so reached is nil, allocation must -// be done. - -// Walk the pointer hierarchy, allocating if we find a nil. Stop one before the end. -func decIndirect(p unsafe.Pointer, indir int) unsafe.Pointer { - for ; indir > 1; indir-- { - if *(*unsafe.Pointer)(p) == nil { - // Allocation required - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(unsafe.Pointer)) - } - p = *(*unsafe.Pointer)(p) - } - return p -} - -// ignoreUint discards a uint value with no destination. -func ignoreUint(i *decInstr, state *decoderState, p unsafe.Pointer) { - state.decodeUint() -} - -// 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() -} - -// decBool decodes a uint 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.decodeUint() != 0 -} - -// 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)) - } - p = *(*unsafe.Pointer)(p) - } - v := state.decodeInt() - if v < math.MinInt8 || math.MaxInt8 < v { - error_(i.ovfl) - } else { - *(*int8)(p) = int8(v) - } -} - -// 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)) - } - p = *(*unsafe.Pointer)(p) - } - v := state.decodeUint() - if math.MaxUint8 < v { - error_(i.ovfl) - } else { - *(*uint8)(p) = uint8(v) - } -} - -// 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)) - } - p = *(*unsafe.Pointer)(p) - } - v := state.decodeInt() - if v < math.MinInt16 || math.MaxInt16 < v { - error_(i.ovfl) - } else { - *(*int16)(p) = int16(v) - } -} - -// 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)) - } - p = *(*unsafe.Pointer)(p) - } - v := state.decodeUint() - if math.MaxUint16 < v { - error_(i.ovfl) - } else { - *(*uint16)(p) = uint16(v) - } -} - -// 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)) - } - p = *(*unsafe.Pointer)(p) - } - v := state.decodeInt() - if v < math.MinInt32 || math.MaxInt32 < v { - error_(i.ovfl) - } else { - *(*int32)(p) = int32(v) - } -} - -// 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)) - } - p = *(*unsafe.Pointer)(p) - } - v := state.decodeUint() - if math.MaxUint32 < v { - error_(i.ovfl) - } else { - *(*uint32)(p) = uint32(v) - } -} - -// 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)) - } - p = *(*unsafe.Pointer)(p) - } - *(*int64)(p) = int64(state.decodeInt()) -} - -// 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)) - } - p = *(*unsafe.Pointer)(p) - } - *(*uint64)(p) = uint64(state.decodeUint()) -} - -// Floating-point numbers are transmitted as uint64s holding the bits -// of the underlying representation. They are sent byte-reversed, with -// the exponent end coming out first, so integer floating point numbers -// (for example) transmit more compactly. This routine does the -// unswizzling. -func floatFromBits(u uint64) float64 { - var v uint64 - for i := 0; i < 8; i++ { - v <<= 8 - v |= u & 0xFF - u >>= 8 - } - return math.Float64frombits(v) -} - -// 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 { - av = -av - } - // +Inf is OK in both 32- and 64-bit floats. Underflow is always OK. - if math.MaxFloat32 < av && av <= math.MaxFloat64 { - error_(i.ovfl) - } else { - *(*float32)(p) = float32(v) - } -} - -// 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)) - } - p = *(*unsafe.Pointer)(p) - } - storeFloat32(i, state, p) -} - -// 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)) - } - p = *(*unsafe.Pointer)(p) - } - *(*float64)(p) = floatFromBits(uint64(state.decodeUint())) -} - -// 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)) - } - p = *(*unsafe.Pointer)(p) - } - storeFloat32(i, state, p) - storeFloat32(i, state, unsafe.Pointer(uintptr(p)+unsafe.Sizeof(float32(0)))) -} - -// 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)) - } - p = *(*unsafe.Pointer)(p) - } - real := floatFromBits(uint64(state.decodeUint())) - imag := floatFromBits(uint64(state.decodeUint())) - *(*complex128)(p) = complex(real, imag) -} - -// decUint8Slice decodes a byte slice and stores through p a slice header -// describing the data. -// uint8 slices are encoded as an unsigned count followed by the raw bytes. -func decUint8Slice(i *decInstr, state *decoderState, p unsafe.Pointer) { - if i.indir > 0 { - if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new([]uint8)) - } - p = *(*unsafe.Pointer)(p) - } - n := state.decodeUint() - if n > uint64(state.b.Len()) { - errorf("length of []byte exceeds input size (%d bytes)", n) - } - slice := (*[]uint8)(p) - if uint64(cap(*slice)) < n { - *slice = make([]uint8, n) - } else { - *slice = (*slice)[0:n] - } - if _, err := state.b.Read(*slice); err != nil { - errorf("error decoding []byte: %s", err) - } -} - -// 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 *decoderState, p unsafe.Pointer) { - if i.indir > 0 { - if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(string)) - } - p = *(*unsafe.Pointer)(p) - } - n := state.decodeUint() - if n > uint64(state.b.Len()) { - errorf("string length exceeds input size (%d bytes)", n) - } - b := make([]byte, n) - state.b.Read(b) - // It would be a shame to do the obvious thing here, - // *(*string)(p) = string(b) - // because we've already allocated the storage and this would - // allocate again and copy. So we do this ugly hack, which is even - // even more unsafe than it looks as it depends the memory - // representation of a string matching the beginning of the memory - // representation of a byte slice (a byte slice is longer). - *(*string)(p) = *(*string)(unsafe.Pointer(&b)) -} - -// 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) -} - -// Execution engine - -// The encoder engine is an array of instructions indexed by field number of the incoming -// decoder. It is executed with random access according to field number. -type decEngine struct { - instr []decInstr - numInstr int // the number of active instructions -} - -// 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 unsafe.Pointer, indir int) unsafe.Pointer { - if indir == 0 { - return p - } - up := p - if indir > 1 { - up = decIndirect(up, indir) - } - if *(*unsafe.Pointer)(up) == nil { - // Allocate object. - *(*unsafe.Pointer)(up) = unsafe.Pointer(reflect.New(rtyp).Pointer()) - } - 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 unsafe.Pointer) { - state := dec.newDecoderState(&dec.buf) - state.fieldnum = singletonField - delta := int(state.decodeUint()) - if delta != 0 { - errorf("decode: corrupted data: non-zero delta for singleton") - } - instr := &engine.instr[singletonField] - if instr.indir != ut.indir { - errorf("internal error: inconsistent indirection instr %d ut %d", instr.indir, ut.indir) - } - ptr := basep // offset will be zero - if instr.indir > 1 { - ptr = decIndirect(ptr, instr.indir) - } - instr.op(instr, state, ptr) - dec.freeDecoderState(state) -} - -// decodeStruct 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 -// from the user's value, not from the innards of an engine. -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 - basep := p - for state.b.Len() > 0 { - delta := int(state.decodeUint()) - if delta < 0 { - errorf("decode: corrupted data: negative delta") - } - if delta == 0 { // struct terminator is zero delta fieldnum - break - } - fieldnum := state.fieldnum + delta - if fieldnum >= len(engine.instr) { - error_(errRange) - break - } - instr := &engine.instr[fieldnum] - p := unsafe.Pointer(uintptr(basep) + instr.offset) - if instr.indir > 1 { - p = decIndirect(p, instr.indir) - } - instr.op(instr, state, p) - state.fieldnum = fieldnum - } - dec.freeDecoderState(state) -} - -// ignoreStruct discards the data for a struct with no destination. -func (dec *Decoder) ignoreStruct(engine *decEngine) { - state := dec.newDecoderState(&dec.buf) - state.fieldnum = -1 - for state.b.Len() > 0 { - delta := int(state.decodeUint()) - if delta < 0 { - errorf("ignore decode: corrupted data: negative delta") - } - if delta == 0 { // struct terminator is zero delta fieldnum - break - } - fieldnum := state.fieldnum + delta - if fieldnum >= len(engine.instr) { - error_(errRange) - } - instr := &engine.instr[fieldnum] - instr.op(instr, state, unsafe.Pointer(nil)) - state.fieldnum = fieldnum - } - dec.freeDecoderState(state) -} - -// 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) { - state := dec.newDecoderState(&dec.buf) - state.fieldnum = singletonField - delta := int(state.decodeUint()) - if delta != 0 { - errorf("decode: corrupted data: non-zero delta for singleton") - } - instr := &engine.instr[singletonField] - instr.op(instr, state, unsafe.Pointer(nil)) - dec.freeDecoderState(state) -} - -// decodeArrayHelper does the work for decoding arrays and slices. -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 := p - if elemIndir > 1 { - up = decIndirect(up, elemIndir) - } - elemOp(instr, state, up) - 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 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 - } - if n := state.decodeUint(); n != uint64(length) { - errorf("length mismatch in decodeArray") - } - dec.decodeArrayHelper(state, p, elemOp, elemWid, length, elemIndir, ovfl) -} - -// 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 error) reflect.Value { - instr := &decInstr{op, 0, indir, 0, ovfl} - up := unsafeAddr(v) - if indir > 1 { - up = decIndirect(up, indir) - } - op(instr, state, up) - return v -} - -// 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.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 - } - up := unsafe.Pointer(p) - if *(*unsafe.Pointer)(up) == nil { // maps are represented as a pointer in the runtime - // Allocate map. - *(*unsafe.Pointer)(up) = unsafe.Pointer(reflect.MakeMap(mtyp).Pointer()) - } - // 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.NewAt(mtyp, unsafe.Pointer(p)).Elem() - n := int(state.decodeUint()) - for i := 0; i < n; i++ { - key := decodeIntoValue(state, keyOp, keyIndir, allocValue(mtyp.Key()), ovfl) - elem := decodeIntoValue(state, elemOp, elemIndir, allocValue(mtyp.Elem()), ovfl) - v.SetMapIndex(key, elem) - } -} - -// 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, errors.New("no error")} - for i := 0; i < length; i++ { - elemOp(instr, state, nil) - } -} - -// 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("length mismatch in ignoreArray") - } - dec.ignoreArrayHelper(state, elemOp, length) -} - -// 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, errors.New("no error")} - elemInstr := &decInstr{elemOp, 0, 0, 0, errors.New("no error")} - for i := 0; i < n; i++ { - keyOp(keyInstr, state, nil) - elemOp(elemInstr, state, nil) - } -} - -// 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.Type, state *decoderState, p unsafe.Pointer, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl error) { - nr := state.decodeUint() - n := int(nr) - if indir > 0 { - if *(*unsafe.Pointer)(p) == nil { - // Allocate the slice header. - *(*unsafe.Pointer)(p) = unsafe.Pointer(new([]unsafe.Pointer)) - } - p = *(*unsafe.Pointer)(p) - } - // Allocate storage for the slice elements, that is, the underlying array, - // if the existing slice does not have the capacity. - // Always write a header at p. - hdrp := (*reflect.SliceHeader)(p) - if hdrp.Cap < n { - hdrp.Data = reflect.MakeSlice(atyp, n, n).Pointer() - hdrp.Cap = n - } - hdrp.Len = n - dec.decodeArrayHelper(state, unsafe.Pointer(hdrp.Data), elemOp, elemWid, n, elemIndir, ovfl) -} - -// 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())) -} - -// setInterfaceValue sets an interface value to a concrete value, -// but first it checks that the assignment will succeed. -func setInterfaceValue(ivalue reflect.Value, value reflect.Value) { - if !value.Type().AssignableTo(ivalue.Type()) { - errorf("%s is not assignable to type %s", value.Type(), ivalue.Type()) - } - ivalue.Set(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 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. - nr := state.decodeUint() - if nr < 0 || nr > 1<<31 { // zero is permissible for anonymous types - errorf("invalid type name length %d", nr) - } - if nr > uint64(state.b.Len()) { - errorf("invalid type name length %d: exceeds input size", nr) - } - b := make([]byte, nr) - state.b.Read(b) - name := string(b) - if name == "" { - // Copy the representation of the nil interface value to the target. - // This is horribly unsafe and special. - if indir > 0 { - p = allocate(ityp, p, 1) // All but the last level has been allocated by dec.Indirect - } - *(*[2]uintptr)(unsafe.Pointer(p)) = ivalue.InterfaceData() - return - } - if len(name) > 1024 { - errorf("name too long (%d bytes): %.20q...", len(name), name) - } - // The concrete type must be registered. - registerLock.RLock() - typ, ok := nameToConcreteType[name] - registerLock.RUnlock() - if !ok { - errorf("name not registered for interface: %q", name) - } - // Read the type id of the concrete value. - concreteId := dec.decodeTypeSequence(true) - if concreteId < 0 { - error_(dec.err) - } - // Byte count of value is next; we don't care what it is (it's there - // in case we want to ignore the value by skipping it completely). - state.decodeUint() - // Read the concrete value. - value := allocValue(typ) - dec.decodeValue(concreteId, value) - if dec.err != nil { - error_(dec.err) - } - // Allocate the destination interface value. - if indir > 0 { - p = allocate(ityp, p, 1) // All but the last level has been allocated by dec.Indirect - } - // Assign the concrete value to the interface. - // Tread carefully; it might not satisfy the interface. - setInterfaceValue(ivalue, value) - // Copy the representation of the interface value to the target. - // This is horribly unsafe and special. - *(*[2]uintptr)(unsafe.Pointer(p)) = ivalue.InterfaceData() -} - -// 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) - if err != nil { - error_(err) - } - id := dec.decodeTypeSequence(true) - if id < 0 { - error_(dec.err) - } - // At this point, the decoder buffer contains a delimited value. Just toss it. - 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(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 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) - } -} - -// 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, - reflect.Int8: decInt8, - reflect.Int16: decInt16, - reflect.Int32: decInt32, - reflect.Int64: decInt64, - reflect.Uint8: decUint8, - reflect.Uint16: decUint16, - reflect.Uint32: decUint32, - reflect.Uint64: decUint64, - reflect.Float32: decFloat32, - reflect.Float64: decFloat64, - reflect.Complex64: decComplex64, - reflect.Complex128: decComplex128, - reflect.String: decString, -} - -// Indexed by gob types. tComplex will be added during type.init(). -var decIgnoreOpMap = map[typeId]decOp{ - tBool: ignoreUint, - tInt: ignoreUint, - tUint: ignoreUint, - tFloat: ignoreUint, - tBytes: ignoreUint8Array, - tString: ignoreUint8Array, - tComplex: ignoreTwoUints, -} - -// 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.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 { - return opPtr, ut.indir - } - typ := ut.base - indir := ut.indir - var op decOp - k := typ.Kind() - if int(k) < len(decOpTable) { - op = decOpTable[k] - } - if op == nil { - inProgress[rt] = &op - // Special cases - switch t := typ; t.Kind() { - case reflect.Array: - name = "element of " + name - elemId := dec.wireType[wireId].ArrayT.Elem - 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, p, *elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl) - } - - case reflect.Map: - keyId := dec.wireType[wireId].MapT.Key - elemId := dec.wireType[wireId].MapT.Elem - keyOp, keyIndir := dec.decOpFor(keyId, t.Key(), "key of "+name, inProgress) - elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), "element of "+name, inProgress) - ovfl := overflow(name) - op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { - state.dec.decodeMap(t, state, p, *keyOp, *elemOp, i.indir, keyIndir, elemIndir, ovfl) - } - - case reflect.Slice: - name = "element of " + name - if t.Elem().Kind() == reflect.Uint8 { - op = decUint8Slice - break - } - var elemId typeId - if tt, ok := builtinIdToType[wireId]; ok { - elemId = tt.(*sliceType).Elem - } else { - elemId = dec.wireType[wireId].SliceT.Elem - } - elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress) - ovfl := overflow(name) - op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { - state.dec.decodeSlice(t, state, p, *elemOp, t.Elem().Size(), i.indir, elemIndir, ovfl) - } - - case reflect.Struct: - // Generate a closure that calls out to the engine for the nested type. - enginePtr, err := dec.getDecEnginePtr(wireId, userType(typ)) - if err != nil { - error_(err) - } - op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { - // indirect through enginePtr to delay evaluation for recursive structs. - 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, p, i.indir) - } - } - } - if op == nil { - errorf("decode can't handle type %s", rt) - } - return &op, indir -} - -// 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 *decoderState, p unsafe.Pointer) { - state.dec.ignoreInterface(state) - } - return op - } - // Special cases - wire := dec.wireType[wireId] - switch { - case wire == nil: - errorf("bad data: undefined type %s", wireId.string()) - case wire.ArrayT != nil: - elemId := wire.ArrayT.Elem - elemOp := dec.decIgnoreOpFor(elemId) - op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { - state.dec.ignoreArray(state, elemOp, wire.ArrayT.Len) - } - - case wire.MapT != nil: - keyId := dec.wireType[wireId].MapT.Key - elemId := dec.wireType[wireId].MapT.Elem - keyOp := dec.decIgnoreOpFor(keyId) - elemOp := dec.decIgnoreOpFor(elemId) - 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 *decoderState, p unsafe.Pointer) { - state.dec.ignoreSlice(state, elemOp) - } - - case wire.StructT != nil: - // Generate a closure that calls out to the engine for the nested type. - enginePtr, err := dec.getIgnoreEnginePtr(wireId) - if err != nil { - error_(err) - } - 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, wire.BinaryMarshalerT != nil, wire.TextMarshalerT != nil: - op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { - state.dec.ignoreGobDecoder(state) - } - } - } - if op == nil { - errorf("bad data: ignore can't handle type %s", wireId.string()) - } - return op -} - -// gobDecodeOpFor returns the op for a type that is known to implement -// GobDecoder. -func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) (*decOp, int) { - rcvrType := ut.user - if ut.decIndir == -1 { - rcvrType = reflect.PtrTo(rcvrType) - } else if ut.decIndir > 0 { - for i := int8(0); i < ut.decIndir; i++ { - rcvrType = rcvrType.Elem() - } - } - var op decOp - op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { - // Caller has gotten us to within one indirection of our value. - if i.indir > 0 { - if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(reflect.New(ut.base).Pointer()) - } - } - // Now p is a pointer to the base type. Do we need to climb out to - // get to the receiver type? - var v reflect.Value - if ut.decIndir == -1 { - v = reflect.NewAt(rcvrType, unsafe.Pointer(&p)).Elem() - } else { - v = reflect.NewAt(rcvrType, p).Elem() - } - state.dec.decodeGobDecoder(ut, state, v) - } - return &op, int(ut.indir) - -} - -// 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 - ut := userType(fr) - wire, ok := dec.wireType[fw] - // 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.externalDec != 0 { // This test trumps all others. - return true - } - switch t := ut.base; t.Kind() { - default: - // chan, etc: cannot handle. - return false - case reflect.Bool: - return fw == tBool - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return fw == tInt - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return fw == tUint - case reflect.Float32, reflect.Float64: - return fw == tFloat - case reflect.Complex64, reflect.Complex128: - return fw == tComplex - case reflect.String: - return fw == tString - case reflect.Interface: - return fw == tInterface - case reflect.Array: - if !ok || wire.ArrayT == nil { - return false - } - array := wire.ArrayT - return t.Len() == array.Len && dec.compatibleType(t.Elem(), array.Elem, inProgress) - case reflect.Map: - if !ok || wire.MapT == nil { - return false - } - MapType := wire.MapT - return dec.compatibleType(t.Key(), MapType.Key, inProgress) && dec.compatibleType(t.Elem(), MapType.Elem, inProgress) - case reflect.Slice: - // Is it an array of bytes? - if t.Elem().Kind() == reflect.Uint8 { - return fw == tBytes - } - // Extract and compare element types. - var sw *sliceType - if tt, ok := builtinIdToType[fw]; ok { - sw, _ = tt.(*sliceType) - } else if wire != nil { - sw = wire.SliceT - } - elem := userType(t.Elem()).base - return sw != nil && dec.compatibleType(elem, sw.Elem, inProgress) - case reflect.Struct: - return true - } -} - -// typeString returns a human-readable description of the type identified by remoteId. -func (dec *Decoder) typeString(remoteId typeId) string { - if t := idToType[remoteId]; t != nil { - // globally known type. - return t.string() - } - return dec.wireType[remoteId].string() -} - -// 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 error) { - rt := ut.user - engine = new(decEngine) - engine.instr = make([]decInstr, 1) // one item - name := rt.String() // best we can do - if !dec.compatibleType(rt, remoteId, make(map[reflect.Type]typeId)) { - remoteType := dec.typeString(remoteId) - // Common confusing case: local interface type, remote concrete type. - if ut.base.Kind() == reflect.Interface && remoteId != tInterface { - return nil, errors.New("gob: local interface type " + name + " can only be decoded from remote interface type; received concrete type " + remoteType) - } - return nil, errors.New("gob: decoding into local type " + name + ", received remote type " + remoteType) - } - op, indir := dec.decOpFor(remoteId, rt, name, make(map[reflect.Type]*decOp)) - ovfl := errors.New(`value for "` + name + `" out of range`) - engine.instr[singletonField] = decInstr{*op, singletonField, indir, 0, ovfl} - engine.numInstr = 1 - 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 error) { - engine = new(decEngine) - engine.instr = make([]decInstr, 1) // one item - op := dec.decIgnoreOpFor(remoteId) - ovfl := overflow(dec.typeString(remoteId)) - engine.instr[0] = decInstr{op, 0, 0, 0, ovfl} - engine.numInstr = 1 - return -} - -// 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 error) { - rt := ut.base - srt := rt - if srt.Kind() != reflect.Struct || ut.externalDec != 0 { - return dec.compileSingle(remoteId, ut) - } - var wireStruct *structType - // Builtin types can come from global pool; the rest must be defined by the decoder. - // Also we know we're decoding a struct now, so the client must have sent one. - if t, ok := builtinIdToType[remoteId]; ok { - wireStruct, _ = t.(*structType) - } else { - wire := dec.wireType[remoteId] - if wire == nil { - error_(errBadType) - } - wireStruct = wire.StructT - } - if wireStruct == nil { - errorf("type mismatch in decoder: want struct type %s; got non-struct", rt) - } - engine = new(decEngine) - engine.instr = make([]decInstr, len(wireStruct.Field)) - seen := make(map[reflect.Type]*decOp) - // Loop over the fields of the wire type. - for fieldnum := 0; fieldnum < len(wireStruct.Field); fieldnum++ { - wireField := wireStruct.Field[fieldnum] - if wireField.Name == "" { - errorf("empty name for remote field of type %s", wireStruct.Name) - } - ovfl := overflow(wireField.Name) - // Find the field of the local type with the same name. - localField, present := srt.FieldByName(wireField.Name) - // TODO(r): anonymous names - if !present || !isExported(wireField.Name) { - op := dec.decIgnoreOpFor(wireField.Id) - engine.instr[fieldnum] = decInstr{op, fieldnum, 0, 0, ovfl} - continue - } - if !dec.compatibleType(localField.Type, wireField.Id, make(map[reflect.Type]typeId)) { - errorf("wrong type (%s) for received field %s.%s", localField.Type, wireStruct.Name, wireField.Name) - } - op, indir := dec.decOpFor(wireField.Id, localField.Type, localField.Name, seen) - engine.instr[fieldnum] = decInstr{*op, fieldnum, indir, uintptr(localField.Offset), ovfl} - engine.numInstr++ - } - return -} - -// getDecEnginePtr returns the engine for the specified type. -func (dec *Decoder) getDecEnginePtr(remoteId typeId, ut *userTypeInfo) (enginePtr **decEngine, err error) { - rt := ut.user - decoderMap, ok := dec.decoderCache[rt] - if !ok { - decoderMap = make(map[typeId]**decEngine) - dec.decoderCache[rt] = decoderMap - } - if enginePtr, ok = decoderMap[remoteId]; !ok { - // To handle recursive types, mark this engine as underway before compiling. - enginePtr = new(*decEngine) - decoderMap[remoteId] = enginePtr - *enginePtr, err = dec.compileDec(remoteId, ut) - if err != nil { - delete(decoderMap, remoteId) - } - } - return -} - -// 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 error) { - var ok bool - if enginePtr, ok = dec.ignorerCache[wireId]; !ok { - // To handle recursive types, mark this engine as underway before compiling. - enginePtr = new(*decEngine) - dec.ignorerCache[wireId] = enginePtr - wire := dec.wireType[wireId] - if wire != nil && wire.StructT != nil { - *enginePtr, err = dec.compileDec(wireId, userType(emptyStructType)) - } else { - *enginePtr, err = dec.compileIgnoreSingle(wireId) - } - if err != nil { - delete(dec.ignorerCache, wireId) - } - } - return -} - -// decodeValue decodes the data stream representing a value and stores it in val. -func (dec *Decoder) decodeValue(wireId typeId, val reflect.Value) { - defer catchError(&dec.err) - // If the value is nil, it means we should just ignore this item. - if !val.IsValid() { - dec.decodeIgnoredValue(wireId) - return - } - // Dereference down to the underlying type. - ut := userType(val.Type()) - base := ut.base - var enginePtr **decEngine - enginePtr, dec.err = dec.getDecEnginePtr(wireId, ut) - if dec.err != nil { - return - } - engine := *enginePtr - if st := base; st.Kind() == reflect.Struct && ut.externalDec == 0 { - if engine.numInstr == 0 && st.NumField() > 0 && - dec.wireType[wireId] != nil && 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, unsafeAddr(val), ut.indir) - } else { - dec.decodeSingle(engine, ut, unsafeAddr(val)) - } -} - -// decodeIgnoredValue decodes the data stream representing a value of the specified type and discards it. -func (dec *Decoder) decodeIgnoredValue(wireId typeId) { - var enginePtr **decEngine - enginePtr, dec.err = dec.getIgnoreEnginePtr(wireId) - if dec.err != nil { - return - } - wire := dec.wireType[wireId] - if wire != nil && wire.StructT != nil { - dec.ignoreStruct(*enginePtr) - } else { - dec.ignoreSingle(*enginePtr) - } -} - -func init() { - var iop, uop decOp - switch reflect.TypeOf(int(0)).Bits() { - case 32: - iop = decInt32 - uop = decUint32 - case 64: - iop = decInt64 - uop = decUint64 - default: - panic("gob: unknown size of int/uint") - } - decOpTable[reflect.Int] = iop - decOpTable[reflect.Uint] = uop - - // Finally uintptr - switch reflect.TypeOf(uintptr(0)).Bits() { - case 32: - uop = decUint32 - case 64: - uop = decUint64 - default: - panic("gob: unknown size of uintptr") - } - decOpTable[reflect.Uintptr] = uop -} - -// Gob assumes it can call UnsafeAddr on any Value -// in order to get a pointer it can copy data from. -// Values that have just been created and do not point -// 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) unsafe.Pointer { - if v.CanAddr() { - return unsafe.Pointer(v.UnsafeAddr()) - } - x := reflect.New(v.Type()).Elem() - x.Set(v) - return unsafe.Pointer(x.UnsafeAddr()) -} - -// Gob depends on being able to take the address -// of zeroed Values it creates, so use this wrapper instead -// of the standard reflect.Zero. -// Each call allocates once. -func allocValue(t reflect.Type) reflect.Value { - return reflect.New(t).Elem() -} diff --git a/src/pkg/encoding/gob/decoder.go b/src/pkg/encoding/gob/decoder.go deleted file mode 100644 index 3a769ec12..000000000 --- a/src/pkg/encoding/gob/decoder.go +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gob - -import ( - "bufio" - "bytes" - "errors" - "io" - "reflect" - "sync" -) - -// A Decoder manages the receipt of type and data information read from the -// remote side of a connection. -type Decoder struct { - mutex sync.Mutex // each item must be received atomically - r io.Reader // source of the data - buf bytes.Buffer // buffer for more efficient i/o from r - wireType map[typeId]*wireType // map from remote ID to local description - decoderCache map[reflect.Type]map[typeId]**decEngine // cache of compiled engines - ignorerCache map[typeId]**decEngine // ditto for ignored objects - freeList *decoderState // list of free decoderStates; avoids reallocation - countBuf []byte // used for decoding integers while parsing messages - tmp []byte // temporary storage for i/o; saves reallocating - err error -} - -// NewDecoder returns a new decoder that reads from the io.Reader. -// If r does not also implement io.ByteReader, it will be wrapped in a -// bufio.Reader. -func NewDecoder(r io.Reader) *Decoder { - dec := new(Decoder) - // We use the ability to read bytes as a plausible surrogate for buffering. - if _, ok := r.(io.ByteReader); !ok { - r = bufio.NewReader(r) - } - dec.r = r - dec.wireType = make(map[typeId]*wireType) - dec.decoderCache = make(map[reflect.Type]map[typeId]**decEngine) - dec.ignorerCache = make(map[typeId]**decEngine) - dec.countBuf = make([]byte, 9) // counts may be uint64s (unlikely!), require 9 bytes - - return dec -} - -// recvType loads the definition of a type. -func (dec *Decoder) recvType(id typeId) { - // Have we already seen this type? That's an error - if id < firstUserId || dec.wireType[id] != nil { - dec.err = errors.New("gob: duplicate type received") - return - } - - // Type: - wire := new(wireType) - dec.decodeValue(tWireType, reflect.ValueOf(wire)) - if dec.err != nil { - return - } - // Remember we've seen this type. - dec.wireType[id] = wire -} - -var errBadCount = errors.New("invalid message length") - -// recvMessage reads the next count-delimited item from the input. It is the converse -// of Encoder.writeMessage. It returns false on EOF or other error reading the message. -func (dec *Decoder) recvMessage() bool { - // Read a count. - nbytes, _, err := decodeUintReader(dec.r, dec.countBuf) - if err != nil { - dec.err = err - return false - } - // Upper limit of 1GB, allowing room to grow a little without overflow. - // TODO: We might want more control over this limit. - if nbytes >= 1<<30 { - dec.err = errBadCount - return false - } - dec.readMessage(int(nbytes)) - return dec.err == nil -} - -// readMessage reads the next nbytes bytes from the input. -func (dec *Decoder) readMessage(nbytes int) { - // Allocate the dec.tmp buffer, up to 10KB. - const maxBuf = 10 * 1024 - nTmp := nbytes - if nTmp > maxBuf { - nTmp = maxBuf - } - if cap(dec.tmp) < nTmp { - nAlloc := nTmp + 100 // A little extra for growth. - if nAlloc > maxBuf { - nAlloc = maxBuf - } - dec.tmp = make([]byte, nAlloc) - } - dec.tmp = dec.tmp[:nTmp] - - // Read the data - dec.buf.Grow(nbytes) - for nbytes > 0 { - if nbytes < nTmp { - dec.tmp = dec.tmp[:nbytes] - } - var nRead int - nRead, dec.err = io.ReadFull(dec.r, dec.tmp) - if dec.err != nil { - if dec.err == io.EOF { - dec.err = io.ErrUnexpectedEOF - } - return - } - dec.buf.Write(dec.tmp) - nbytes -= nRead - } -} - -// toInt turns an encoded uint64 into an int, according to the marshaling rules. -func toInt(x uint64) int64 { - i := int64(x >> 1) - if x&1 != 0 { - i = ^i - } - return i -} - -func (dec *Decoder) nextInt() int64 { - n, _, err := decodeUintReader(&dec.buf, dec.countBuf) - if err != nil { - dec.err = err - } - return toInt(n) -} - -func (dec *Decoder) nextUint() uint64 { - n, _, err := decodeUintReader(&dec.buf, dec.countBuf) - if err != nil { - dec.err = err - } - return n -} - -// decodeTypeSequence parses: -// TypeSequence -// (TypeDefinition DelimitedTypeDefinition*)? -// and returns the type id of the next value. It returns -1 at -// EOF. Upon return, the remainder of dec.buf is the value to be -// decoded. If this is an interface value, it can be ignored by -// resetting that buffer. -func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId { - for dec.err == nil { - if dec.buf.Len() == 0 { - if !dec.recvMessage() { - break - } - } - // Receive a type id. - id := typeId(dec.nextInt()) - if id >= 0 { - // Value follows. - return id - } - // Type definition for (-id) follows. - dec.recvType(-id) - // When decoding an interface, after a type there may be a - // DelimitedValue still in the buffer. Skip its count. - // (Alternatively, the buffer is empty and the byte count - // will be absorbed by recvMessage.) - if dec.buf.Len() > 0 { - if !isInterface { - dec.err = errors.New("extra data in buffer") - break - } - dec.nextUint() - } - } - return -1 -} - -// Decode reads the next value from the input stream and stores -// it in the data represented by the empty interface value. -// If e is nil, the value will be discarded. Otherwise, -// the value underlying e must be a pointer to the -// correct type for the next data item received. -// If the input is at EOF, Decode returns io.EOF and -// does not modify e. -func (dec *Decoder) Decode(e interface{}) error { - if e == nil { - return dec.DecodeValue(reflect.Value{}) - } - value := reflect.ValueOf(e) - // If e represents a value as opposed to a pointer, the answer won't - // get back to the caller. Make sure it's a pointer. - if value.Type().Kind() != reflect.Ptr { - dec.err = errors.New("gob: attempt to decode into a non-pointer") - return dec.err - } - return dec.DecodeValue(value) -} - -// DecodeValue reads the next value from the input stream. -// If v is the zero reflect.Value (v.Kind() == Invalid), DecodeValue discards the value. -// Otherwise, it stores the value into v. In that case, v must represent -// a non-nil pointer to data or be an assignable reflect.Value (v.CanSet()) -// If the input is at EOF, DecodeValue returns io.EOF and -// does not modify e. -func (dec *Decoder) DecodeValue(v reflect.Value) error { - if v.IsValid() { - if v.Kind() == reflect.Ptr && !v.IsNil() { - // That's okay, we'll store through the pointer. - } else if !v.CanSet() { - return errors.New("gob: DecodeValue of unassignable value") - } - } - // Make sure we're single-threaded through here. - dec.mutex.Lock() - defer dec.mutex.Unlock() - - dec.buf.Reset() // In case data lingers from previous invocation. - dec.err = nil - id := dec.decodeTypeSequence(false) - if dec.err == nil { - dec.decodeValue(id, v) - } - return dec.err -} - -// If debug.go is compiled into the program , debugFunc prints a human-readable -// representation of the gob data read from r by calling that file's Debug function. -// Otherwise it is nil. -var debugFunc func(io.Reader) diff --git a/src/pkg/encoding/gob/doc.go b/src/pkg/encoding/gob/doc.go deleted file mode 100644 index d0acaba1a..000000000 --- a/src/pkg/encoding/gob/doc.go +++ /dev/null @@ -1,386 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package gob manages streams of gobs - binary values exchanged between an -Encoder (transmitter) and a Decoder (receiver). A typical use is transporting -arguments and results of remote procedure calls (RPCs) such as those provided by -package "rpc". - -The implementation compiles a custom codec for each data type in the stream and -is most efficient when a single Encoder is used to transmit a stream of values, -amortizing the cost of compilation. - -Basics - -A stream of gobs is self-describing. Each data item in the stream is preceded by -a specification of its type, expressed in terms of a small set of predefined -types. Pointers are not transmitted, but the things they point to are -transmitted; that is, the values are flattened. Recursive types work fine, but -recursive values (data with cycles) are problematic. This may change. - -To use gobs, create an Encoder and present it with a series of data items as -values or addresses that can be dereferenced to values. The Encoder makes sure -all type information is sent before it is needed. At the receive side, a -Decoder retrieves values from the encoded stream and unpacks them into local -variables. - -Types and Values - -The source and destination values/types need not correspond exactly. For structs, -fields (identified by name) that are in the source but absent from the receiving -variable will be ignored. Fields that are in the receiving variable but missing -from the transmitted type or value will be ignored in the destination. If a field -with the same name is present in both, their types must be compatible. Both the -receiver and transmitter will do all necessary indirection and dereferencing to -convert between gobs and actual Go values. For instance, a gob type that is -schematically, - - struct { A, B int } - -can be sent from or received into any of these Go types: - - struct { A, B int } // the same - *struct { A, B int } // extra indirection of the struct - struct { *A, **B int } // extra indirection of the fields - struct { A, B int64 } // different concrete value type; see below - -It may also be received into any of these: - - struct { A, B int } // the same - struct { B, A int } // ordering doesn't matter; matching is by name - struct { A, B, C int } // extra field (C) ignored - struct { B int } // missing field (A) ignored; data will be dropped - struct { B, C int } // missing field (A) ignored; extra field (C) ignored. - -Attempting to receive into these types will draw a decode error: - - struct { A int; B uint } // change of signedness for B - struct { A int; B float } // change of type for B - struct { } // no field names in common - struct { C, D int } // no field names in common - -Integers are transmitted two ways: arbitrary precision signed integers or -arbitrary precision unsigned integers. There is no int8, int16 etc. -discrimination in the gob format; there are only signed and unsigned integers. As -described below, the transmitter sends the value in a variable-length encoding; -the receiver accepts the value and stores it in the destination variable. -Floating-point numbers are always sent using IEEE-754 64-bit precision (see -below). - -Signed integers may be received into any signed integer variable: int, int16, etc.; -unsigned integers may be received into any unsigned integer variable; and floating -point values may be received into any floating point variable. However, -the destination variable must be able to represent the value or the decode -operation will fail. - -Structs, arrays and slices are also supported. Structs encode and decode only -exported fields. Strings and arrays of bytes are supported with a special, -efficient representation (see below). When a slice is decoded, if the existing -slice has capacity the slice will be extended in place; if not, a new array is -allocated. Regardless, the length of the resulting slice reports the number of -elements decoded. - -Functions and channels will not be sent in a gob. Attempting to encode such a value -at top the level will fail. A struct field of chan or func type is treated exactly -like an unexported field and is ignored. - -Gob can encode a value of any type implementing the GobEncoder or -encoding.BinaryMarshaler interfaces by calling the corresponding method, -in that order of preference. - -Gob can decode a value of any type implementing the GobDecoder or -encoding.BinaryUnmarshaler interfaces by calling the corresponding method, -again in that order of preference. - -Encoding Details - -This section documents the encoding, details that are not important for most -users. Details are presented bottom-up. - -An unsigned integer is sent one of two ways. If it is less than 128, it is sent -as a byte with that value. Otherwise it is sent as a minimal-length big-endian -(high byte first) byte stream holding the value, preceded by one byte holding the -byte count, negated. Thus 0 is transmitted as (00), 7 is transmitted as (07) and -256 is transmitted as (FE 01 00). - -A boolean is encoded within an unsigned integer: 0 for false, 1 for true. - -A signed integer, i, is encoded within an unsigned integer, u. Within u, bits 1 -upward contain the value; bit 0 says whether they should be complemented upon -receipt. The encode algorithm looks like this: - - uint u; - if i < 0 { - u = (^i << 1) | 1 // complement i, bit 0 is 1 - } else { - u = (i << 1) // do not complement i, bit 0 is 0 - } - encodeUnsigned(u) - -The low bit is therefore analogous to a sign bit, but making it the complement bit -instead guarantees that the largest negative integer is not a special case. For -example, -129=^128=(^256>>1) encodes as (FE 01 01). - -Floating-point numbers are always sent as a representation of a float64 value. -That value is converted to a uint64 using math.Float64bits. The uint64 is then -byte-reversed and sent as a regular unsigned integer. The byte-reversal means the -exponent and high-precision part of the mantissa go first. Since the low bits are -often zero, this can save encoding bytes. For instance, 17.0 is encoded in only -three bytes (FE 31 40). - -Strings and slices of bytes are sent as an unsigned count followed by that many -uninterpreted bytes of the value. - -All other slices and arrays are sent as an unsigned count followed by that many -elements using the standard gob encoding for their type, recursively. - -Maps are sent as an unsigned count followed by that many key, element -pairs. Empty but non-nil maps are sent, so if the sender has allocated -a map, the receiver will allocate a map even if no elements are -transmitted. - -Structs are sent as a sequence of (field number, field value) pairs. The field -value is sent using the standard gob encoding for its type, recursively. If a -field has the zero value for its type, it is omitted from the transmission. The -field number is defined by the type of the encoded struct: the first field of the -encoded type is field 0, the second is field 1, etc. When encoding a value, the -field numbers are delta encoded for efficiency and the fields are always sent in -order of increasing field number; the deltas are therefore unsigned. The -initialization for the delta encoding sets the field number to -1, so an unsigned -integer field 0 with value 7 is transmitted as unsigned delta = 1, unsigned value -= 7 or (01 07). Finally, after all the fields have been sent a terminating mark -denotes the end of the struct. That mark is a delta=0 value, which has -representation (00). - -Interface types are not checked for compatibility; all interface types are -treated, for transmission, as members of a single "interface" type, analogous to -int or []byte - in effect they're all treated as interface{}. Interface values -are transmitted as a string identifying the concrete type being sent (a name -that must be pre-defined by calling Register), followed by a byte count of the -length of the following data (so the value can be skipped if it cannot be -stored), followed by the usual encoding of concrete (dynamic) value stored in -the interface value. (A nil interface value is identified by the empty string -and transmits no value.) Upon receipt, the decoder verifies that the unpacked -concrete item satisfies the interface of the receiving variable. - -The representation of types is described below. When a type is defined on a given -connection between an Encoder and Decoder, it is assigned a signed integer type -id. When Encoder.Encode(v) is called, it makes sure there is an id assigned for -the type of v and all its elements and then it sends the pair (typeid, encoded-v) -where typeid is the type id of the encoded type of v and encoded-v is the gob -encoding of the value v. - -To define a type, the encoder chooses an unused, positive type id and sends the -pair (-type id, encoded-type) where encoded-type is the gob encoding of a wireType -description, constructed from these types: - - type wireType struct { - ArrayT *ArrayType - SliceT *SliceType - StructT *StructType - MapT *MapType - } - type arrayType struct { - CommonType - Elem typeId - Len int - } - type CommonType struct { - Name string // the name of the struct type - Id int // the id of the type, repeated so it's inside the type - } - type sliceType struct { - CommonType - Elem typeId - } - type structType struct { - CommonType - Field []*fieldType // the fields of the struct. - } - type fieldType struct { - Name string // the name of the field. - Id int // the type id of the field, which must be already defined - } - type mapType struct { - CommonType - Key typeId - Elem typeId - } - -If there are nested type ids, the types for all inner type ids must be defined -before the top-level type id is used to describe an encoded-v. - -For simplicity in setup, the connection is defined to understand these types a -priori, as well as the basic gob types int, uint, etc. Their ids are: - - bool 1 - int 2 - uint 3 - float 4 - []byte 5 - string 6 - complex 7 - interface 8 - // gap for reserved ids. - WireType 16 - ArrayType 17 - CommonType 18 - SliceType 19 - StructType 20 - FieldType 21 - // 22 is slice of fieldType. - MapType 23 - -Finally, each message created by a call to Encode is preceded by an encoded -unsigned integer count of the number of bytes remaining in the message. After -the initial type name, interface values are wrapped the same way; in effect, the -interface value acts like a recursive invocation of Encode. - -In summary, a gob stream looks like - - (byteCount (-type id, encoding of a wireType)* (type id, encoding of a value))* - -where * signifies zero or more repetitions and the type id of a value must -be predefined or be defined before the value in the stream. - -See "Gobs of data" for a design discussion of the gob wire format: -http://golang.org/doc/articles/gobs_of_data.html -*/ -package gob - -/* -Grammar: - -Tokens starting with a lower case letter are terminals; int(n) -and uint(n) represent the signed/unsigned encodings of the value n. - -GobStream: - DelimitedMessage* -DelimitedMessage: - uint(lengthOfMessage) Message -Message: - TypeSequence TypedValue -TypeSequence - (TypeDefinition DelimitedTypeDefinition*)? -DelimitedTypeDefinition: - uint(lengthOfTypeDefinition) TypeDefinition -TypedValue: - int(typeId) Value -TypeDefinition: - int(-typeId) encodingOfWireType -Value: - SingletonValue | StructValue -SingletonValue: - uint(0) FieldValue -FieldValue: - builtinValue | ArrayValue | MapValue | SliceValue | StructValue | InterfaceValue -InterfaceValue: - NilInterfaceValue | NonNilInterfaceValue -NilInterfaceValue: - uint(0) -NonNilInterfaceValue: - ConcreteTypeName TypeSequence InterfaceContents -ConcreteTypeName: - uint(lengthOfName) [already read=n] name -InterfaceContents: - int(concreteTypeId) DelimitedValue -DelimitedValue: - uint(length) Value -ArrayValue: - uint(n) FieldValue*n [n elements] -MapValue: - uint(n) (FieldValue FieldValue)*n [n (key, value) pairs] -SliceValue: - uint(n) FieldValue*n [n elements] -StructValue: - (uint(fieldDelta) FieldValue)* -*/ - -/* -For implementers and the curious, here is an encoded example. Given - type Point struct {X, Y int} -and the value - p := Point{22, 33} -the bytes transmitted that encode p will be: - 1f ff 81 03 01 01 05 50 6f 69 6e 74 01 ff 82 00 - 01 02 01 01 58 01 04 00 01 01 59 01 04 00 00 00 - 07 ff 82 01 2c 01 42 00 -They are determined as follows. - -Since this is the first transmission of type Point, the type descriptor -for Point itself must be sent before the value. This is the first type -we've sent on this Encoder, so it has type id 65 (0 through 64 are -reserved). - - 1f // This item (a type descriptor) is 31 bytes long. - ff 81 // The negative of the id for the type we're defining, -65. - // This is one byte (indicated by FF = -1) followed by - // ^-65<<1 | 1. The low 1 bit signals to complement the - // rest upon receipt. - - // Now we send a type descriptor, which is itself a struct (wireType). - // The type of wireType itself is known (it's built in, as is the type of - // all its components), so we just need to send a *value* of type wireType - // that represents type "Point". - // Here starts the encoding of that value. - // Set the field number implicitly to -1; this is done at the beginning - // of every struct, including nested structs. - 03 // Add 3 to field number; now 2 (wireType.structType; this is a struct). - // structType starts with an embedded CommonType, which appears - // as a regular structure here too. - 01 // add 1 to field number (now 0); start of embedded CommonType. - 01 // add 1 to field number (now 0, the name of the type) - 05 // string is (unsigned) 5 bytes long - 50 6f 69 6e 74 // wireType.structType.CommonType.name = "Point" - 01 // add 1 to field number (now 1, the id of the type) - ff 82 // wireType.structType.CommonType._id = 65 - 00 // end of embedded wiretype.structType.CommonType struct - 01 // add 1 to field number (now 1, the field array in wireType.structType) - 02 // There are two fields in the type (len(structType.field)) - 01 // Start of first field structure; add 1 to get field number 0: field[0].name - 01 // 1 byte - 58 // structType.field[0].name = "X" - 01 // Add 1 to get field number 1: field[0].id - 04 // structType.field[0].typeId is 2 (signed int). - 00 // End of structType.field[0]; start structType.field[1]; set field number to -1. - 01 // Add 1 to get field number 0: field[1].name - 01 // 1 byte - 59 // structType.field[1].name = "Y" - 01 // Add 1 to get field number 1: field[1].id - 04 // struct.Type.field[1].typeId is 2 (signed int). - 00 // End of structType.field[1]; end of structType.field. - 00 // end of wireType.structType structure - 00 // end of wireType structure - -Now we can send the Point value. Again the field number resets to -1: - - 07 // this value is 7 bytes long - ff 82 // the type number, 65 (1 byte (-FF) followed by 65<<1) - 01 // add one to field number, yielding field 0 - 2c // encoding of signed "22" (0x22 = 44 = 22<<1); Point.x = 22 - 01 // add one to field number, yielding field 1 - 42 // encoding of signed "33" (0x42 = 66 = 33<<1); Point.y = 33 - 00 // end of structure - -The type encoding is long and fairly intricate but we send it only once. -If p is transmitted a second time, the type is already known so the -output will be just: - - 07 ff 82 01 2c 01 42 00 - -A single non-struct value at top level is transmitted like a field with -delta tag 0. For instance, a signed integer with value 3 presented as -the argument to Encode will emit: - - 03 04 00 06 - -Which represents: - - 03 // this value is 3 bytes long - 04 // the type number, 2, represents an integer - 00 // tag delta 0 - 06 // value 3 - -*/ diff --git a/src/pkg/encoding/gob/dump.go b/src/pkg/encoding/gob/dump.go deleted file mode 100644 index 17238c98d..000000000 --- a/src/pkg/encoding/gob/dump.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package main - -// Need to compile package gob with debug.go to build this program. -// See comments in debug.go for how to do this. - -import ( - "encoding/gob" - "fmt" - "os" -) - -func main() { - var err error - file := os.Stdin - if len(os.Args) > 1 { - file, err = os.Open(os.Args[1]) - if err != nil { - fmt.Fprintf(os.Stderr, "dump: %s\n", err) - os.Exit(1) - } - } - gob.Debug(file) -} diff --git a/src/pkg/encoding/gob/encode.go b/src/pkg/encoding/gob/encode.go deleted file mode 100644 index 7831c02d1..000000000 --- a/src/pkg/encoding/gob/encode.go +++ /dev/null @@ -1,760 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gob - -import ( - "bytes" - "encoding" - "math" - "reflect" - "unsafe" -) - -const uint64Size = int(unsafe.Sizeof(uint64(0))) - -// encoderState is the global execution state of an instance of the encoder. -// Field numbers are delta encoded and always increase. The field -// 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. - next *encoderState // for free list -} - -func (enc *Encoder) newEncoderState(b *bytes.Buffer) *encoderState { - e := enc.freeList - if e == nil { - e = new(encoderState) - e.enc = enc - } else { - enc.freeList = e.next - } - e.sendZero = false - e.fieldnum = 0 - e.b = b - return e -} - -func (enc *Encoder) freeEncoderState(e *encoderState) { - e.next = enc.freeList - enc.freeList = e -} - -// Unsigned integers have a two-state encoding. If the number is less -// than 128 (0 through 0x7F), its value is written directly. -// Otherwise the value is written in big-endian byte order preceded -// by the byte length, negated. - -// encodeUint writes an encoded unsigned integer to state.b. -func (state *encoderState) encodeUint(x uint64) { - if x <= 0x7F { - err := state.b.WriteByte(uint8(x)) - if err != nil { - error_(err) - } - return - } - i := uint64Size - for x > 0 { - state.buf[i] = uint8(x) - x >>= 8 - i-- - } - state.buf[i] = uint8(i - uint64Size) // = loop count, negated - _, err := state.b.Write(state.buf[i : uint64Size+1]) - if err != nil { - error_(err) - } -} - -// encodeInt writes an encoded signed integer to state.w. -// The low bit of the encoding says whether to bit complement the (other bits of the) -// uint to recover the int. -func (state *encoderState) encodeInt(i int64) { - var x uint64 - if i < 0 { - x = uint64(^i<<1) | 1 - } else { - x = uint64(i << 1) - } - state.encodeUint(uint64(x)) -} - -// encOp is the signature of an encoding operator for a given type. -type encOp func(i *encInstr, state *encoderState, p unsafe.Pointer) - -// The 'instructions' of the encoding machine -type encInstr struct { - op encOp - field int // field number - indir int // how many pointer indirections to reach the value in the struct - offset uintptr // offset in the structure of the field to encode -} - -// update emits a field number and updates the state to record its value for delta encoding. -// If the instruction pointer is nil, it does nothing -func (state *encoderState) update(instr *encInstr) { - if instr != nil { - state.encodeUint(uint64(instr.field - state.fieldnum)) - state.fieldnum = instr.field - } -} - -// Each encoder for a composite is responsible for handling any -// indirections associated with the elements of the data structure. -// If any pointer so reached is nil, no bytes are written. If the -// data item is zero, no bytes are written. Single values - ints, -// strings etc. - are indirected before calling their encoders. -// Otherwise, the output (for a scalar) is the field number, as an -// encoded integer, followed by the field data in its appropriate -// format. - -// encIndirect dereferences p indir times and returns the result. -func encIndirect(p unsafe.Pointer, indir int) unsafe.Pointer { - for ; indir > 0; indir-- { - p = *(*unsafe.Pointer)(p) - if p == nil { - return unsafe.Pointer(nil) - } - } - return p -} - -// encBool encodes the bool with address p as an unsigned 0 or 1. -func encBool(i *encInstr, state *encoderState, p unsafe.Pointer) { - b := *(*bool)(p) - if b || state.sendZero { - state.update(i) - if b { - state.encodeUint(1) - } else { - state.encodeUint(0) - } - } -} - -// encInt encodes the int with address p. -func encInt(i *encInstr, state *encoderState, p unsafe.Pointer) { - v := int64(*(*int)(p)) - if v != 0 || state.sendZero { - state.update(i) - state.encodeInt(v) - } -} - -// encUint encodes the uint with address p. -func encUint(i *encInstr, state *encoderState, p unsafe.Pointer) { - v := uint64(*(*uint)(p)) - if v != 0 || state.sendZero { - state.update(i) - state.encodeUint(v) - } -} - -// encInt8 encodes the int8 with address p. -func encInt8(i *encInstr, state *encoderState, p unsafe.Pointer) { - v := int64(*(*int8)(p)) - if v != 0 || state.sendZero { - state.update(i) - state.encodeInt(v) - } -} - -// encUint8 encodes the uint8 with address p. -func encUint8(i *encInstr, state *encoderState, p unsafe.Pointer) { - v := uint64(*(*uint8)(p)) - if v != 0 || state.sendZero { - state.update(i) - state.encodeUint(v) - } -} - -// encInt16 encodes the int16 with address p. -func encInt16(i *encInstr, state *encoderState, p unsafe.Pointer) { - v := int64(*(*int16)(p)) - if v != 0 || state.sendZero { - state.update(i) - state.encodeInt(v) - } -} - -// encUint16 encodes the uint16 with address p. -func encUint16(i *encInstr, state *encoderState, p unsafe.Pointer) { - v := uint64(*(*uint16)(p)) - if v != 0 || state.sendZero { - state.update(i) - state.encodeUint(v) - } -} - -// encInt32 encodes the int32 with address p. -func encInt32(i *encInstr, state *encoderState, p unsafe.Pointer) { - v := int64(*(*int32)(p)) - if v != 0 || state.sendZero { - state.update(i) - state.encodeInt(v) - } -} - -// encUint encodes the uint32 with address p. -func encUint32(i *encInstr, state *encoderState, p unsafe.Pointer) { - v := uint64(*(*uint32)(p)) - if v != 0 || state.sendZero { - state.update(i) - state.encodeUint(v) - } -} - -// encInt64 encodes the int64 with address p. -func encInt64(i *encInstr, state *encoderState, p unsafe.Pointer) { - v := *(*int64)(p) - if v != 0 || state.sendZero { - state.update(i) - state.encodeInt(v) - } -} - -// encInt64 encodes the uint64 with address p. -func encUint64(i *encInstr, state *encoderState, p unsafe.Pointer) { - v := *(*uint64)(p) - if v != 0 || state.sendZero { - state.update(i) - state.encodeUint(v) - } -} - -// encUintptr encodes the uintptr with address p. -func encUintptr(i *encInstr, state *encoderState, p unsafe.Pointer) { - v := uint64(*(*uintptr)(p)) - if v != 0 || state.sendZero { - state.update(i) - state.encodeUint(v) - } -} - -// floatBits returns a uint64 holding the bits of a floating-point number. -// Floating-point numbers are transmitted as uint64s holding the bits -// of the underlying representation. They are sent byte-reversed, with -// the exponent end coming out first, so integer floating point numbers -// (for example) transmit more compactly. This routine does the -// swizzling. -func floatBits(f float64) uint64 { - u := math.Float64bits(f) - var v uint64 - for i := 0; i < 8; i++ { - v <<= 8 - v |= u & 0xFF - u >>= 8 - } - return v -} - -// encFloat32 encodes the float32 with address p. -func encFloat32(i *encInstr, state *encoderState, p unsafe.Pointer) { - f := *(*float32)(p) - if f != 0 || state.sendZero { - v := floatBits(float64(f)) - state.update(i) - state.encodeUint(v) - } -} - -// encFloat64 encodes the float64 with address p. -func encFloat64(i *encInstr, state *encoderState, p unsafe.Pointer) { - f := *(*float64)(p) - if f != 0 || state.sendZero { - state.update(i) - v := floatBits(f) - state.encodeUint(v) - } -} - -// encComplex64 encodes the complex64 with address p. -// Complex numbers are just a pair of floating-point numbers, real part first. -func encComplex64(i *encInstr, state *encoderState, p unsafe.Pointer) { - c := *(*complex64)(p) - if c != 0+0i || state.sendZero { - rpart := floatBits(float64(real(c))) - ipart := floatBits(float64(imag(c))) - state.update(i) - state.encodeUint(rpart) - state.encodeUint(ipart) - } -} - -// encComplex128 encodes the complex128 with address p. -func encComplex128(i *encInstr, state *encoderState, p unsafe.Pointer) { - c := *(*complex128)(p) - if c != 0+0i || state.sendZero { - rpart := floatBits(real(c)) - ipart := floatBits(imag(c)) - state.update(i) - state.encodeUint(rpart) - state.encodeUint(ipart) - } -} - -// encUint8Array encodes the byte slice whose header has address p. -// Byte arrays are encoded as an unsigned count followed by the raw bytes. -func encUint8Array(i *encInstr, state *encoderState, p unsafe.Pointer) { - b := *(*[]byte)(p) - if len(b) > 0 || state.sendZero { - state.update(i) - state.encodeUint(uint64(len(b))) - state.b.Write(b) - } -} - -// encString encodes the string whose header has address p. -// Strings are encoded as an unsigned count followed by the raw bytes. -func encString(i *encInstr, state *encoderState, p unsafe.Pointer) { - s := *(*string)(p) - if len(s) > 0 || state.sendZero { - state.update(i) - state.encodeUint(uint64(len(s))) - state.b.WriteString(s) - } -} - -// encStructTerminator encodes the end of an encoded struct -// as delta field number of 0. -func encStructTerminator(i *encInstr, state *encoderState, p unsafe.Pointer) { - state.encodeUint(0) -} - -// Execution engine - -// encEngine an array of instructions indexed by field number of the encoding -// data, typically a struct. It is executed top to bottom, walking the struct. -type encEngine struct { - instr []encInstr -} - -const singletonField = 0 - -// encodeSingle encodes a single top-level non-struct value. -func (enc *Encoder) encodeSingle(b *bytes.Buffer, engine *encEngine, basep unsafe.Pointer) { - state := enc.newEncoderState(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. - state.sendZero = true - instr := &engine.instr[singletonField] - p := basep // offset will be zero - if instr.indir > 0 { - if p = encIndirect(p, instr.indir); p == nil { - return - } - } - instr.op(instr, state, p) - enc.freeEncoderState(state) -} - -// encodeStruct encodes a single struct value. -func (enc *Encoder) encodeStruct(b *bytes.Buffer, engine *encEngine, basep unsafe.Pointer) { - state := enc.newEncoderState(b) - state.fieldnum = -1 - for i := 0; i < len(engine.instr); i++ { - instr := &engine.instr[i] - p := unsafe.Pointer(uintptr(basep) + instr.offset) - if instr.indir > 0 { - if p = encIndirect(p, instr.indir); p == nil { - continue - } - } - instr.op(instr, state, p) - } - enc.freeEncoderState(state) -} - -// encodeArray encodes the array whose 0th element is at p. -func (enc *Encoder) encodeArray(b *bytes.Buffer, p unsafe.Pointer, op encOp, elemWid uintptr, elemIndir int, length int) { - state := enc.newEncoderState(b) - state.fieldnum = -1 - state.sendZero = true - state.encodeUint(uint64(length)) - for i := 0; i < length; i++ { - elemp := p - if elemIndir > 0 { - up := encIndirect(elemp, elemIndir) - if up == nil { - errorf("encodeArray: nil element") - } - elemp = up - } - op(nil, state, elemp) - p = unsafe.Pointer(uintptr(p) + elemWid) - } - enc.freeEncoderState(state) -} - -// encodeReflectValue is a helper for maps. It encodes the value v. -func encodeReflectValue(state *encoderState, v reflect.Value, op encOp, indir int) { - for i := 0; i < indir && v.IsValid(); i++ { - v = reflect.Indirect(v) - } - if !v.IsValid() { - errorf("encodeReflectValue: nil element") - } - op(nil, state, unsafeAddr(v)) -} - -// encodeMap encodes a map as unsigned count followed by key:value pairs. -// Because map internals are not exposed, we must use reflection rather than -// addresses. -func (enc *Encoder) encodeMap(b *bytes.Buffer, mv reflect.Value, keyOp, elemOp encOp, keyIndir, elemIndir int) { - state := enc.newEncoderState(b) - state.fieldnum = -1 - state.sendZero = true - keys := mv.MapKeys() - state.encodeUint(uint64(len(keys))) - for _, key := range keys { - encodeReflectValue(state, key, keyOp, keyIndir) - encodeReflectValue(state, mv.MapIndex(key), elemOp, elemIndir) - } - enc.freeEncoderState(state) -} - -// encodeInterface encodes the interface value iv. -// To send an interface, we send a string identifying the concrete type, followed -// by the type identifier (which might require defining that type right now), followed -// 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.Value) { - // Gobs can encode nil interface values but not typed interface - // values holding nil pointers, since nil pointers point to no value. - elem := iv.Elem() - if elem.Kind() == reflect.Ptr && elem.IsNil() { - errorf("gob: cannot encode nil pointer of type %s inside interface", iv.Elem().Type()) - } - state := enc.newEncoderState(b) - state.fieldnum = -1 - state.sendZero = true - if iv.IsNil() { - state.encodeUint(0) - return - } - - ut := userType(iv.Elem().Type()) - registerLock.RLock() - name, ok := concreteTypeToName[ut.base] - registerLock.RUnlock() - if !ok { - errorf("type not registered for interface: %s", ut.base) - } - // Send the name. - state.encodeUint(uint64(len(name))) - _, err := state.b.WriteString(name) - if err != nil { - error_(err) - } - // Define the type id if necessary. - enc.sendTypeDescriptor(enc.writer(), state, ut) - // Send the type id. - enc.sendTypeId(state, ut) - // Encode the value into a new buffer. Any nested type definitions - // should be written to b, before the encoded value. - enc.pushWriter(b) - data := new(bytes.Buffer) - data.Write(spaceForLength) - enc.encode(data, elem, ut) - if enc.err != nil { - error_(enc.err) - } - enc.popWriter() - enc.writeMessage(b, data) - if enc.err != nil { - error_(err) - } - enc.freeEncoderState(state) -} - -// isZero reports whether the value is the zero of its type. -func isZero(val reflect.Value) bool { - switch val.Kind() { - case reflect.Array: - for i := 0; i < val.Len(); i++ { - if !isZero(val.Index(i)) { - return false - } - } - return true - case reflect.Map, reflect.Slice, reflect.String: - return val.Len() == 0 - case reflect.Bool: - return !val.Bool() - case reflect.Complex64, reflect.Complex128: - return val.Complex() == 0 - case reflect.Chan, reflect.Func, reflect.Interface, reflect.Ptr: - return val.IsNil() - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return val.Int() == 0 - case reflect.Float32, reflect.Float64: - return val.Float() == 0 - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return val.Uint() == 0 - case reflect.Struct: - for i := 0; i < val.NumField(); i++ { - if !isZero(val.Field(i)) { - return false - } - } - return true - } - panic("unknown type in isZero " + val.Type().String()) -} - -// encGobEncoder encodes a value that implements the GobEncoder interface. -// The data is sent as a byte array. -func (enc *Encoder) encodeGobEncoder(b *bytes.Buffer, ut *userTypeInfo, v reflect.Value) { - // TODO: should we catch panics from the called method? - - var data []byte - var err error - // We know it's one of these. - switch ut.externalEnc { - case xGob: - data, err = v.Interface().(GobEncoder).GobEncode() - case xBinary: - data, err = v.Interface().(encoding.BinaryMarshaler).MarshalBinary() - case xText: - data, err = v.Interface().(encoding.TextMarshaler).MarshalText() - } - if err != nil { - error_(err) - } - state := enc.newEncoderState(b) - state.fieldnum = -1 - state.encodeUint(uint64(len(data))) - state.b.Write(data) - enc.freeEncoderState(state) -} - -var encOpTable = [...]encOp{ - reflect.Bool: encBool, - reflect.Int: encInt, - reflect.Int8: encInt8, - reflect.Int16: encInt16, - reflect.Int32: encInt32, - reflect.Int64: encInt64, - reflect.Uint: encUint, - reflect.Uint8: encUint8, - reflect.Uint16: encUint16, - reflect.Uint32: encUint32, - reflect.Uint64: encUint64, - reflect.Uintptr: encUintptr, - reflect.Float32: encFloat32, - reflect.Float64: encFloat64, - reflect.Complex64: encComplex64, - reflect.Complex128: encComplex128, - reflect.String: encString, -} - -// encOpFor returns (a pointer to) the encoding op for the base type under rt and -// the indirection count to reach it. -func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp) (*encOp, int) { - ut := userType(rt) - // If the type implements GobEncoder, we handle it without further processing. - if ut.externalEnc != 0 { - return enc.gobEncodeOpFor(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 { - return opPtr, ut.indir - } - typ := ut.base - indir := ut.indir - k := typ.Kind() - var op encOp - if int(k) < len(encOpTable) { - op = encOpTable[k] - } - if op == nil { - inProgress[rt] = &op - // Special cases - switch t := typ; t.Kind() { - case reflect.Slice: - if t.Elem().Kind() == reflect.Uint8 { - op = encUint8Array - break - } - // Slices have a header; we decode it to find the underlying array. - elemOp, elemIndir := enc.encOpFor(t.Elem(), inProgress) - op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { - slice := (*reflect.SliceHeader)(p) - if !state.sendZero && slice.Len == 0 { - return - } - state.update(i) - state.enc.encodeArray(state.b, unsafe.Pointer(slice.Data), *elemOp, t.Elem().Size(), elemIndir, int(slice.Len)) - } - case reflect.Array: - // True arrays have size in the type. - elemOp, elemIndir := enc.encOpFor(t.Elem(), inProgress) - op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { - state.update(i) - state.enc.encodeArray(state.b, p, *elemOp, t.Elem().Size(), elemIndir, t.Len()) - } - case reflect.Map: - keyOp, keyIndir := enc.encOpFor(t.Key(), inProgress) - elemOp, elemIndir := enc.encOpFor(t.Elem(), inProgress) - op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { - // 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.NewAt(t, unsafe.Pointer(p)).Elem() - mv := reflect.Indirect(v) - // We send zero-length (but non-nil) maps because the - // receiver might want to use the map. (Maps don't use append.) - if !state.sendZero && mv.IsNil() { - return - } - state.update(i) - state.enc.encodeMap(state.b, mv, *keyOp, *elemOp, keyIndir, elemIndir) - } - case reflect.Struct: - // Generate a closure that calls out to the engine for the nested type. - enc.getEncEngine(userType(typ)) - info := mustGetTypeInfo(typ) - op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { - state.update(i) - // indirect through info to delay evaluation for recursive structs - state.enc.encodeStruct(state.b, info.encoder, p) - } - case reflect.Interface: - op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { - // Interfaces transmit the name and contents of the concrete - // value they contain. - v := reflect.NewAt(t, unsafe.Pointer(p)).Elem() - iv := reflect.Indirect(v) - if !state.sendZero && (!iv.IsValid() || iv.IsNil()) { - return - } - state.update(i) - state.enc.encodeInterface(state.b, iv) - } - } - } - if op == nil { - errorf("can't happen: encode type %s", rt) - } - return &op, indir -} - -// gobEncodeOpFor returns the op for a type that is known to implement -// GobEncoder. -func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) { - rt := ut.user - if ut.encIndir == -1 { - rt = reflect.PtrTo(rt) - } else if ut.encIndir > 0 { - for i := int8(0); i < ut.encIndir; i++ { - rt = rt.Elem() - } - } - var op encOp - op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { - var v reflect.Value - if ut.encIndir == -1 { - // Need to climb up one level to turn value into pointer. - v = reflect.NewAt(rt, unsafe.Pointer(&p)).Elem() - } else { - v = reflect.NewAt(rt, p).Elem() - } - if !state.sendZero && isZero(v) { - return - } - state.update(i) - state.enc.encodeGobEncoder(state.b, ut, v) - } - return &op, int(ut.encIndir) // encIndir: op will get called with p == address of receiver. -} - -// compileEnc returns the engine to compile the type. -func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine { - srt := ut.base - engine := new(encEngine) - seen := make(map[reflect.Type]*encOp) - rt := ut.base - if ut.externalEnc != 0 { - rt = ut.user - } - if ut.externalEnc == 0 && srt.Kind() == reflect.Struct { - for fieldNum, wireFieldNum := 0, 0; fieldNum < srt.NumField(); fieldNum++ { - f := srt.Field(fieldNum) - if !isSent(&f) { - continue - } - op, indir := enc.encOpFor(f.Type, seen) - engine.instr = append(engine.instr, encInstr{*op, wireFieldNum, indir, uintptr(f.Offset)}) - wireFieldNum++ - } - if srt.NumField() > 0 && len(engine.instr) == 0 { - errorf("type %s has no exported fields", rt) - } - engine.instr = append(engine.instr, encInstr{encStructTerminator, 0, 0, 0}) - } else { - engine.instr = make([]encInstr, 1) - op, indir := enc.encOpFor(rt, seen) - engine.instr[0] = encInstr{*op, singletonField, indir, 0} // offset is zero - } - return engine -} - -// getEncEngine returns the engine to compile the type. -// typeLock must be held (or we're in initialization and guaranteed single-threaded). -func (enc *Encoder) getEncEngine(ut *userTypeInfo) *encEngine { - info, err1 := getTypeInfo(ut) - if err1 != nil { - error_(err1) - } - if info.encoder == nil { - // Assign the encEngine now, so recursive types work correctly. But... - info.encoder = new(encEngine) - // ... if we fail to complete building the engine, don't cache the half-built machine. - // Doing this here means we won't cache a type that is itself OK but - // that contains a nested type that won't compile. The result is consistent - // error behavior when Encode is called multiple times on the top-level type. - ok := false - defer func() { - if !ok { - info.encoder = nil - } - }() - info.encoder = enc.compileEnc(ut) - ok = true - } - return info.encoder -} - -// lockAndGetEncEngine is a function that locks and compiles. -// This lets us hold the lock only while compiling, not when encoding. -func (enc *Encoder) lockAndGetEncEngine(ut *userTypeInfo) *encEngine { - typeLock.Lock() - defer typeLock.Unlock() - return enc.getEncEngine(ut) -} - -func (enc *Encoder) encode(b *bytes.Buffer, value reflect.Value, ut *userTypeInfo) { - defer catchError(&enc.err) - engine := enc.lockAndGetEncEngine(ut) - indir := ut.indir - if ut.externalEnc != 0 { - indir = int(ut.encIndir) - } - for i := 0; i < indir; i++ { - value = reflect.Indirect(value) - } - if ut.externalEnc == 0 && value.Type().Kind() == reflect.Struct { - enc.encodeStruct(b, engine, unsafeAddr(value)) - } else { - enc.encodeSingle(b, engine, unsafeAddr(value)) - } -} diff --git a/src/pkg/encoding/gob/encoder.go b/src/pkg/encoding/gob/encoder.go deleted file mode 100644 index a3301c3bd..000000000 --- a/src/pkg/encoding/gob/encoder.go +++ /dev/null @@ -1,253 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gob - -import ( - "bytes" - "io" - "reflect" - "sync" -) - -// An Encoder manages the transmission of type and data information to the -// other side of a connection. -type Encoder struct { - mutex sync.Mutex // each item must be sent atomically - w []io.Writer // where to send the data - sent map[reflect.Type]typeId // which types we've already sent - countState *encoderState // stage for writing counts - freeList *encoderState // list of free encoderStates; avoids reallocation - byteBuf bytes.Buffer // buffer for top-level encoderState - err error -} - -// Before we encode a message, we reserve space at the head of the -// buffer in which to encode its length. This means we can use the -// buffer to assemble the message without another allocation. -const maxLength = 9 // Maximum size of an encoded length. -var spaceForLength = make([]byte, maxLength) - -// NewEncoder returns a new encoder that will transmit on the io.Writer. -func NewEncoder(w io.Writer) *Encoder { - enc := new(Encoder) - enc.w = []io.Writer{w} - enc.sent = make(map[reflect.Type]typeId) - enc.countState = enc.newEncoderState(new(bytes.Buffer)) - return enc -} - -// writer() returns the innermost writer the encoder is using -func (enc *Encoder) writer() io.Writer { - return enc.w[len(enc.w)-1] -} - -// pushWriter adds a writer to the encoder. -func (enc *Encoder) pushWriter(w io.Writer) { - enc.w = append(enc.w, w) -} - -// popWriter pops the innermost writer. -func (enc *Encoder) popWriter() { - enc.w = enc.w[0 : len(enc.w)-1] -} - -func (enc *Encoder) setError(err error) { - if enc.err == nil { // remember the first. - enc.err = err - } -} - -// writeMessage sends the data item preceded by a unsigned count of its length. -func (enc *Encoder) writeMessage(w io.Writer, b *bytes.Buffer) { - // Space has been reserved for the length at the head of the message. - // This is a little dirty: we grab the slice from the bytes.Buffer and massage - // it by hand. - message := b.Bytes() - messageLen := len(message) - maxLength - // Encode the length. - enc.countState.b.Reset() - enc.countState.encodeUint(uint64(messageLen)) - // Copy the length to be a prefix of the message. - offset := maxLength - enc.countState.b.Len() - copy(message[offset:], enc.countState.b.Bytes()) - // Write the data. - _, err := w.Write(message[offset:]) - // Drain the buffer and restore the space at the front for the count of the next message. - b.Reset() - b.Write(spaceForLength) - if err != nil { - enc.setError(err) - } -} - -// sendActualType sends the requested type, without further investigation, unless -// it's been sent before. -func (enc *Encoder) sendActualType(w io.Writer, state *encoderState, ut *userTypeInfo, actual reflect.Type) (sent bool) { - if _, alreadySent := enc.sent[actual]; alreadySent { - return false - } - typeLock.Lock() - info, err := getTypeInfo(ut) - typeLock.Unlock() - if err != nil { - enc.setError(err) - return - } - // Send the pair (-id, type) - // Id: - state.encodeInt(-int64(info.id)) - // Type: - enc.encode(state.b, reflect.ValueOf(info.wire), wireTypeUserInfo) - enc.writeMessage(w, state.b) - if enc.err != nil { - return - } - - // Remember we've sent this type, both what the user gave us and the base type. - enc.sent[ut.base] = info.id - if ut.user != ut.base { - enc.sent[ut.user] = info.id - } - // Now send the inner types - switch st := actual; st.Kind() { - case reflect.Struct: - for i := 0; i < st.NumField(); i++ { - if isExported(st.Field(i).Name) { - enc.sendType(w, state, st.Field(i).Type) - } - } - case reflect.Array, reflect.Slice: - enc.sendType(w, state, st.Elem()) - case reflect.Map: - enc.sendType(w, state, st.Key()) - enc.sendType(w, state, st.Elem()) - } - return true -} - -// sendType sends the type info to the other side, if necessary. -func (enc *Encoder) sendType(w io.Writer, state *encoderState, origt reflect.Type) (sent bool) { - ut := userType(origt) - if ut.externalEnc != 0 { - // The rules are different: regardless of the underlying type's representation, - // we need to tell the other side that the base type is a GobEncoder. - return enc.sendActualType(w, state, ut, ut.base) - } - - // It's a concrete value, so drill down to the base type. - switch rt := ut.base; rt.Kind() { - default: - // Basic types and interfaces do not need to be described. - return - case reflect.Slice: - // If it's []uint8, don't send; it's considered basic. - if rt.Elem().Kind() == reflect.Uint8 { - return - } - // Otherwise we do send. - break - case reflect.Array: - // arrays must be sent so we know their lengths and element types. - break - case reflect.Map: - // maps must be sent so we know their lengths and key/value types. - break - case reflect.Struct: - // structs must be sent so we know their fields. - break - case reflect.Chan, reflect.Func: - // If we get here, it's a field of a struct; ignore it. - return - } - - return enc.sendActualType(w, state, ut, ut.base) -} - -// Encode transmits the data item represented by the empty interface value, -// guaranteeing that all necessary type information has been transmitted first. -func (enc *Encoder) Encode(e interface{}) error { - return enc.EncodeValue(reflect.ValueOf(e)) -} - -// sendTypeDescriptor makes sure the remote side knows about this type. -// It will send a descriptor if this is the first time the type has been -// sent. -func (enc *Encoder) sendTypeDescriptor(w io.Writer, state *encoderState, ut *userTypeInfo) { - // Make sure the type is known to the other side. - // First, have we already sent this type? - rt := ut.base - if ut.externalEnc != 0 { - rt = ut.user - } - if _, alreadySent := enc.sent[rt]; !alreadySent { - // No, so send it. - sent := enc.sendType(w, state, rt) - if enc.err != nil { - return - } - // If the type info has still not been transmitted, it means we have - // a singleton basic type (int, []byte etc.) at top level. We don't - // need to send the type info but we do need to update enc.sent. - if !sent { - typeLock.Lock() - info, err := getTypeInfo(ut) - typeLock.Unlock() - if err != nil { - enc.setError(err) - return - } - enc.sent[rt] = info.id - } - } -} - -// sendTypeId sends the id, which must have already been defined. -func (enc *Encoder) sendTypeId(state *encoderState, ut *userTypeInfo) { - // Identify the type of this top-level value. - state.encodeInt(int64(enc.sent[ut.base])) -} - -// EncodeValue transmits the data item represented by the reflection value, -// guaranteeing that all necessary type information has been transmitted first. -func (enc *Encoder) EncodeValue(value reflect.Value) error { - // Gobs contain values. They cannot represent nil pointers, which - // have no value to encode. - if value.Kind() == reflect.Ptr && value.IsNil() { - panic("gob: cannot encode nil pointer of type " + value.Type().String()) - } - - // Make sure we're single-threaded through here, so multiple - // goroutines can share an encoder. - enc.mutex.Lock() - defer enc.mutex.Unlock() - - // Remove any nested writers remaining due to previous errors. - enc.w = enc.w[0:1] - - ut, err := validUserType(value.Type()) - if err != nil { - return err - } - - enc.err = nil - enc.byteBuf.Reset() - enc.byteBuf.Write(spaceForLength) - state := enc.newEncoderState(&enc.byteBuf) - - enc.sendTypeDescriptor(enc.writer(), state, ut) - enc.sendTypeId(state, ut) - if enc.err != nil { - return enc.err - } - - // Encode the object. - enc.encode(state.b, value, ut) - if enc.err == nil { - enc.writeMessage(enc.writer(), state.b) - } - - enc.freeEncoderState(state) - return enc.err -} diff --git a/src/pkg/encoding/gob/encoder_test.go b/src/pkg/encoding/gob/encoder_test.go deleted file mode 100644 index 6445ce100..000000000 --- a/src/pkg/encoding/gob/encoder_test.go +++ /dev/null @@ -1,862 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gob - -import ( - "bytes" - "fmt" - "io" - "reflect" - "strings" - "testing" -) - -type ET2 struct { - X string -} - -type ET1 struct { - A int - Et2 *ET2 - Next *ET1 -} - -// Like ET1 but with a different name for a field -type ET3 struct { - A int - Et2 *ET2 - DifferentNext *ET1 -} - -// Like ET1 but with a different type for a field -type ET4 struct { - A int - Et2 float64 - Next int -} - -func TestEncoderDecoder(t *testing.T) { - b := new(bytes.Buffer) - enc := NewEncoder(b) - et1 := new(ET1) - et1.A = 7 - et1.Et2 = new(ET2) - err := enc.Encode(et1) - if err != nil { - t.Error("encoder fail:", err) - } - dec := NewDecoder(b) - newEt1 := new(ET1) - err = dec.Decode(newEt1) - if err != nil { - t.Fatal("error decoding ET1:", err) - } - - if !reflect.DeepEqual(et1, newEt1) { - t.Fatalf("invalid data for et1: expected %+v; got %+v", *et1, *newEt1) - } - if b.Len() != 0 { - t.Error("not at eof;", b.Len(), "bytes left") - } - - enc.Encode(et1) - newEt1 = new(ET1) - err = dec.Decode(newEt1) - if err != nil { - t.Fatal("round 2: error decoding ET1:", err) - } - if !reflect.DeepEqual(et1, newEt1) { - t.Fatalf("round 2: invalid data for et1: expected %+v; got %+v", *et1, *newEt1) - } - if b.Len() != 0 { - t.Error("round 2: not at eof;", b.Len(), "bytes left") - } - - // Now test with a running encoder/decoder pair that we recognize a type mismatch. - err = enc.Encode(et1) - if err != nil { - t.Error("round 3: encoder fail:", err) - } - newEt2 := new(ET2) - err = dec.Decode(newEt2) - if err == nil { - t.Fatal("round 3: expected `bad type' error decoding ET2") - } -} - -// Run one value through the encoder/decoder, but use the wrong type. -// Input is always an ET1; we compare it to whatever is under 'e'. -func badTypeCheck(e interface{}, shouldFail bool, msg string, t *testing.T) { - b := new(bytes.Buffer) - enc := NewEncoder(b) - et1 := new(ET1) - et1.A = 7 - et1.Et2 = new(ET2) - err := enc.Encode(et1) - if err != nil { - t.Error("encoder fail:", err) - } - dec := NewDecoder(b) - err = dec.Decode(e) - if shouldFail && err == nil { - t.Error("expected error for", msg) - } - if !shouldFail && err != nil { - t.Error("unexpected error for", msg, err) - } -} - -// Test that we recognize a bad type the first time. -func TestWrongTypeDecoder(t *testing.T) { - badTypeCheck(new(ET2), true, "no fields in common", t) - badTypeCheck(new(ET3), false, "different name of field", t) - badTypeCheck(new(ET4), true, "different type of field", t) -} - -func corruptDataCheck(s string, err error, t *testing.T) { - b := bytes.NewBufferString(s) - dec := NewDecoder(b) - err1 := dec.Decode(new(ET2)) - if err1 != err { - t.Errorf("from %q expected error %s; got %s", s, err, err1) - } -} - -// Check that we survive bad data. -func TestBadData(t *testing.T) { - corruptDataCheck("", io.EOF, t) - corruptDataCheck("\x7Fhi", io.ErrUnexpectedEOF, t) - corruptDataCheck("\x03now is the time for all good men", errBadType, t) - // issue 6323. - corruptDataCheck("\x04\x24foo", errRange, t) -} - -// Types not supported at top level by the Encoder. -var unsupportedValues = []interface{}{ - make(chan int), - func(a int) bool { return true }, -} - -func TestUnsupported(t *testing.T) { - var b bytes.Buffer - enc := NewEncoder(&b) - for _, v := range unsupportedValues { - err := enc.Encode(v) - if err == nil { - t.Errorf("expected error for %T; got none", v) - } - } -} - -func encAndDec(in, out interface{}) error { - b := new(bytes.Buffer) - enc := NewEncoder(b) - err := enc.Encode(in) - if err != nil { - return err - } - dec := NewDecoder(b) - err = dec.Decode(out) - if err != nil { - return err - } - return nil -} - -func TestTypeToPtrType(t *testing.T) { - // Encode a T, decode a *T - type Type0 struct { - A int - } - t0 := Type0{7} - t0p := new(Type0) - if err := encAndDec(t0, t0p); err != nil { - t.Error(err) - } -} - -func TestPtrTypeToType(t *testing.T) { - // Encode a *T, decode a T - type Type1 struct { - A uint - } - t1p := &Type1{17} - var t1 Type1 - if err := encAndDec(t1, t1p); err != nil { - t.Error(err) - } -} - -func TestTypeToPtrPtrPtrPtrType(t *testing.T) { - type Type2 struct { - A ****float64 - } - t2 := Type2{} - t2.A = new(***float64) - *t2.A = new(**float64) - **t2.A = new(*float64) - ***t2.A = new(float64) - ****t2.A = 27.4 - t2pppp := new(***Type2) - if err := encAndDec(t2, t2pppp); err != nil { - t.Fatal(err) - } - if ****(****t2pppp).A != ****t2.A { - t.Errorf("wrong value after decode: %g not %g", ****(****t2pppp).A, ****t2.A) - } -} - -func TestSlice(t *testing.T) { - type Type3 struct { - A []string - } - t3p := &Type3{[]string{"hello", "world"}} - var t3 Type3 - if err := encAndDec(t3, t3p); err != nil { - t.Error(err) - } -} - -func TestValueError(t *testing.T) { - // Encode a *T, decode a T - type Type4 struct { - A int - } - t4p := &Type4{3} - var t4 Type4 // note: not a pointer. - if err := encAndDec(t4p, t4); err == nil || strings.Index(err.Error(), "pointer") < 0 { - t.Error("expected error about pointer; got", err) - } -} - -func TestArray(t *testing.T) { - type Type5 struct { - A [3]string - B [3]byte - } - type Type6 struct { - A [2]string // can't hold t5.a - } - t5 := Type5{[3]string{"hello", ",", "world"}, [3]byte{1, 2, 3}} - var t5p Type5 - if err := encAndDec(t5, &t5p); err != nil { - t.Error(err) - } - var t6 Type6 - if err := encAndDec(t5, &t6); err == nil { - t.Error("should fail with mismatched array sizes") - } -} - -func TestRecursiveMapType(t *testing.T) { - type recursiveMap map[string]recursiveMap - r1 := recursiveMap{"A": recursiveMap{"B": nil, "C": nil}, "D": nil} - r2 := make(recursiveMap) - if err := encAndDec(r1, &r2); err != nil { - t.Error(err) - } -} - -func TestRecursiveSliceType(t *testing.T) { - type recursiveSlice []recursiveSlice - r1 := recursiveSlice{0: recursiveSlice{0: nil}, 1: nil} - r2 := make(recursiveSlice, 0) - if err := encAndDec(r1, &r2); err != nil { - t.Error(err) - } -} - -// Regression test for bug: must send zero values inside arrays -func TestDefaultsInArray(t *testing.T) { - type Type7 struct { - B []bool - I []int - S []string - F []float64 - } - t7 := Type7{ - []bool{false, false, true}, - []int{0, 0, 1}, - []string{"hi", "", "there"}, - []float64{0, 0, 1}, - } - var t7p Type7 - if err := encAndDec(t7, &t7p); err != nil { - t.Error(err) - } -} - -var testInt int -var testFloat32 float32 -var testString string -var testSlice []string -var testMap map[string]int -var testArray [7]int - -type SingleTest struct { - in interface{} - out interface{} - err string -} - -var singleTests = []SingleTest{ - {17, &testInt, ""}, - {float32(17.5), &testFloat32, ""}, - {"bike shed", &testString, ""}, - {[]string{"bike", "shed", "paint", "color"}, &testSlice, ""}, - {map[string]int{"seven": 7, "twelve": 12}, &testMap, ""}, - {[7]int{4, 55, 0, 0, 0, 0, 0}, &testArray, ""}, // case that once triggered a bug - {[7]int{4, 55, 1, 44, 22, 66, 1234}, &testArray, ""}, - - // Decode errors - {172, &testFloat32, "type"}, -} - -func TestSingletons(t *testing.T) { - b := new(bytes.Buffer) - enc := NewEncoder(b) - dec := NewDecoder(b) - for _, test := range singleTests { - b.Reset() - err := enc.Encode(test.in) - if err != nil { - t.Errorf("error encoding %v: %s", test.in, err) - continue - } - err = dec.Decode(test.out) - switch { - case err != nil && test.err == "": - t.Errorf("error decoding %v: %s", test.in, err) - continue - case err == nil && test.err != "": - t.Errorf("expected error decoding %v: %s", test.in, test.err) - continue - case err != nil && test.err != "": - if strings.Index(err.Error(), test.err) < 0 { - t.Errorf("wrong error decoding %v: wanted %s, got %v", test.in, test.err, err) - } - continue - } - // Get rid of the pointer in the rhs - val := reflect.ValueOf(test.out).Elem().Interface() - if !reflect.DeepEqual(test.in, val) { - t.Errorf("decoding singleton: expected %v got %v", test.in, val) - } - } -} - -func TestStructNonStruct(t *testing.T) { - type Struct struct { - A string - } - type NonStruct string - s := Struct{"hello"} - var sp Struct - if err := encAndDec(s, &sp); err != nil { - t.Error(err) - } - var ns NonStruct - if err := encAndDec(s, &ns); err == nil { - t.Error("should get error for struct/non-struct") - } else if strings.Index(err.Error(), "type") < 0 { - t.Error("for struct/non-struct expected type error; got", err) - } - // Now try the other way - var nsp NonStruct - if err := encAndDec(ns, &nsp); err != nil { - t.Error(err) - } - if err := encAndDec(ns, &s); err == nil { - t.Error("should get error for non-struct/struct") - } else if strings.Index(err.Error(), "type") < 0 { - t.Error("for non-struct/struct expected type error; got", err) - } -} - -type interfaceIndirectTestI interface { - F() bool -} - -type interfaceIndirectTestT struct{} - -func (this *interfaceIndirectTestT) F() bool { - return true -} - -// A version of a bug reported on golang-nuts. Also tests top-level -// slice of interfaces. The issue was registering *T caused T to be -// stored as the concrete type. -func TestInterfaceIndirect(t *testing.T) { - Register(&interfaceIndirectTestT{}) - b := new(bytes.Buffer) - w := []interfaceIndirectTestI{&interfaceIndirectTestT{}} - err := NewEncoder(b).Encode(w) - if err != nil { - t.Fatal("encode error:", err) - } - - var r []interfaceIndirectTestI - err = NewDecoder(b).Decode(&r) - if err != nil { - t.Fatal("decode error:", err) - } -} - -// Now follow various tests that decode into things that can't represent the -// encoded value, all of which should be legal. - -// Also, when the ignored object contains an interface value, it may define -// types. Make sure that skipping the value still defines the types by using -// the encoder/decoder pair to send a value afterwards. If an interface -// is sent, its type in the test is always NewType0, so this checks that the -// encoder and decoder don't skew with respect to type definitions. - -type Struct0 struct { - I interface{} -} - -type NewType0 struct { - S string -} - -type ignoreTest struct { - in, out interface{} -} - -var ignoreTests = []ignoreTest{ - // Decode normal struct into an empty struct - {&struct{ A int }{23}, &struct{}{}}, - // Decode normal struct into a nil. - {&struct{ A int }{23}, nil}, - // Decode singleton string into a nil. - {"hello, world", nil}, - // Decode singleton slice into a nil. - {[]int{1, 2, 3, 4}, nil}, - // Decode struct containing an interface into a nil. - {&Struct0{&NewType0{"value0"}}, nil}, - // Decode singleton slice of interfaces into a nil. - {[]interface{}{"hi", &NewType0{"value1"}, 23}, nil}, -} - -func TestDecodeIntoNothing(t *testing.T) { - Register(new(NewType0)) - for i, test := range ignoreTests { - b := new(bytes.Buffer) - enc := NewEncoder(b) - err := enc.Encode(test.in) - if err != nil { - t.Errorf("%d: encode error %s:", i, err) - continue - } - dec := NewDecoder(b) - err = dec.Decode(test.out) - if err != nil { - t.Errorf("%d: decode error: %s", i, err) - continue - } - // Now see if the encoder and decoder are in a consistent state. - str := fmt.Sprintf("Value %d", i) - err = enc.Encode(&NewType0{str}) - if err != nil { - t.Fatalf("%d: NewType0 encode error: %s", i, err) - } - ns := new(NewType0) - err = dec.Decode(ns) - if err != nil { - t.Fatalf("%d: NewType0 decode error: %s", i, err) - } - if ns.S != str { - t.Fatalf("%d: expected %q got %q", i, str, ns.S) - } - } -} - -// Another bug from golang-nuts, involving nested interfaces. -type Bug0Outer struct { - Bug0Field interface{} -} - -type Bug0Inner struct { - A int -} - -func TestNestedInterfaces(t *testing.T) { - var buf bytes.Buffer - e := NewEncoder(&buf) - d := NewDecoder(&buf) - Register(new(Bug0Outer)) - Register(new(Bug0Inner)) - f := &Bug0Outer{&Bug0Outer{&Bug0Inner{7}}} - var v interface{} = f - err := e.Encode(&v) - if err != nil { - t.Fatal("Encode:", err) - } - err = d.Decode(&v) - if err != nil { - t.Fatal("Decode:", err) - } - // Make sure it decoded correctly. - outer1, ok := v.(*Bug0Outer) - if !ok { - t.Fatalf("v not Bug0Outer: %T", v) - } - outer2, ok := outer1.Bug0Field.(*Bug0Outer) - if !ok { - t.Fatalf("v.Bug0Field not Bug0Outer: %T", outer1.Bug0Field) - } - inner, ok := outer2.Bug0Field.(*Bug0Inner) - if !ok { - t.Fatalf("v.Bug0Field.Bug0Field not Bug0Inner: %T", outer2.Bug0Field) - } - if inner.A != 7 { - t.Fatalf("final value %d; expected %d", inner.A, 7) - } -} - -// The bugs keep coming. We forgot to send map subtypes before the map. - -type Bug1Elem struct { - Name string - Id int -} - -type Bug1StructMap map[string]Bug1Elem - -func bug1EncDec(in Bug1StructMap, out *Bug1StructMap) error { - return nil -} - -func TestMapBug1(t *testing.T) { - in := make(Bug1StructMap) - in["val1"] = Bug1Elem{"elem1", 1} - in["val2"] = Bug1Elem{"elem2", 2} - - b := new(bytes.Buffer) - enc := NewEncoder(b) - err := enc.Encode(in) - if err != nil { - t.Fatal("encode:", err) - } - dec := NewDecoder(b) - out := make(Bug1StructMap) - err = dec.Decode(&out) - if err != nil { - t.Fatal("decode:", err) - } - if !reflect.DeepEqual(in, out) { - t.Errorf("mismatch: %v %v", in, out) - } -} - -func TestGobMapInterfaceEncode(t *testing.T) { - m := map[string]interface{}{ - "up": uintptr(0), - "i0": []int{-1}, - "i1": []int8{-1}, - "i2": []int16{-1}, - "i3": []int32{-1}, - "i4": []int64{-1}, - "u0": []uint{1}, - "u1": []uint8{1}, - "u2": []uint16{1}, - "u3": []uint32{1}, - "u4": []uint64{1}, - "f0": []float32{1}, - "f1": []float64{1}, - "c0": []complex64{complex(2, -2)}, - "c1": []complex128{complex(2, float64(-2))}, - "us": []uintptr{0}, - "bo": []bool{false}, - "st": []string{"s"}, - } - enc := NewEncoder(new(bytes.Buffer)) - err := enc.Encode(m) - if err != nil { - t.Errorf("encode map: %s", err) - } -} - -func TestSliceReusesMemory(t *testing.T) { - buf := new(bytes.Buffer) - // Bytes - { - x := []byte("abcd") - enc := NewEncoder(buf) - err := enc.Encode(x) - if err != nil { - t.Errorf("bytes: encode: %s", err) - } - // Decode into y, which is big enough. - y := []byte("ABCDE") - addr := &y[0] - dec := NewDecoder(buf) - err = dec.Decode(&y) - if err != nil { - t.Fatal("bytes: decode:", err) - } - if !bytes.Equal(x, y) { - t.Errorf("bytes: expected %q got %q\n", x, y) - } - if addr != &y[0] { - t.Errorf("bytes: unnecessary reallocation") - } - } - // general slice - { - x := []rune("abcd") - enc := NewEncoder(buf) - err := enc.Encode(x) - if err != nil { - t.Errorf("ints: encode: %s", err) - } - // Decode into y, which is big enough. - y := []rune("ABCDE") - addr := &y[0] - dec := NewDecoder(buf) - err = dec.Decode(&y) - if err != nil { - t.Fatal("ints: decode:", err) - } - if !reflect.DeepEqual(x, y) { - t.Errorf("ints: expected %q got %q\n", x, y) - } - if addr != &y[0] { - t.Errorf("ints: unnecessary reallocation") - } - } -} - -// Used to crash: negative count in recvMessage. -func TestBadCount(t *testing.T) { - b := []byte{0xfb, 0xa5, 0x82, 0x2f, 0xca, 0x1} - if err := NewDecoder(bytes.NewReader(b)).Decode(nil); err == nil { - t.Error("expected error from bad count") - } else if err.Error() != errBadCount.Error() { - t.Error("expected bad count error; got", err) - } -} - -// Verify that sequential Decoders built on a single input will -// succeed if the input implements ReadByte and there is no -// type information in the stream. -func TestSequentialDecoder(t *testing.T) { - b := new(bytes.Buffer) - enc := NewEncoder(b) - const count = 10 - for i := 0; i < count; i++ { - s := fmt.Sprintf("%d", i) - if err := enc.Encode(s); err != nil { - t.Error("encoder fail:", err) - } - } - for i := 0; i < count; i++ { - dec := NewDecoder(b) - var s string - if err := dec.Decode(&s); err != nil { - t.Fatal("decoder fail:", err) - } - if s != fmt.Sprintf("%d", i) { - t.Fatalf("decode expected %d got %s", i, s) - } - } -} - -// Should be able to have unrepresentable fields (chan, func, *chan etc.); we just ignore them. -type Bug2 struct { - A int - C chan int - CP *chan int - F func() - FPP **func() -} - -func TestChanFuncIgnored(t *testing.T) { - c := make(chan int) - f := func() {} - fp := &f - b0 := Bug2{23, c, &c, f, &fp} - var buf bytes.Buffer - enc := NewEncoder(&buf) - if err := enc.Encode(b0); err != nil { - t.Fatal("error encoding:", err) - } - var b1 Bug2 - err := NewDecoder(&buf).Decode(&b1) - if err != nil { - t.Fatal("decode:", err) - } - if b1.A != b0.A { - t.Fatalf("got %d want %d", b1.A, b0.A) - } - if b1.C != nil || b1.CP != nil || b1.F != nil || b1.FPP != nil { - t.Fatal("unexpected value for chan or func") - } -} - -func TestSliceIncompatibility(t *testing.T) { - var in = []byte{1, 2, 3} - var out []int - if err := encAndDec(in, &out); err == nil { - t.Error("expected compatibility error") - } -} - -// Mutually recursive slices of structs caused problems. -type Bug3 struct { - Num int - Children []*Bug3 -} - -func TestGobPtrSlices(t *testing.T) { - in := []*Bug3{ - {1, nil}, - {2, nil}, - } - b := new(bytes.Buffer) - err := NewEncoder(b).Encode(&in) - if err != nil { - t.Fatal("encode:", err) - } - - var out []*Bug3 - err = NewDecoder(b).Decode(&out) - if err != nil { - t.Fatal("decode:", err) - } - if !reflect.DeepEqual(in, out) { - t.Fatalf("got %v; wanted %v", out, in) - } -} - -// getDecEnginePtr cached engine for ut.base instead of ut.user so we passed -// a *map and then tried to reuse its engine to decode the inner map. -func TestPtrToMapOfMap(t *testing.T) { - Register(make(map[string]interface{})) - subdata := make(map[string]interface{}) - subdata["bar"] = "baz" - data := make(map[string]interface{}) - data["foo"] = subdata - - b := new(bytes.Buffer) - err := NewEncoder(b).Encode(data) - if err != nil { - t.Fatal("encode:", err) - } - var newData map[string]interface{} - err = NewDecoder(b).Decode(&newData) - if err != nil { - t.Fatal("decode:", err) - } - if !reflect.DeepEqual(data, newData) { - t.Fatalf("expected %v got %v", data, newData) - } -} - -// A top-level nil pointer generates a panic with a helpful string-valued message. -func TestTopLevelNilPointer(t *testing.T) { - errMsg := topLevelNilPanic(t) - if errMsg == "" { - t.Fatal("top-level nil pointer did not panic") - } - if !strings.Contains(errMsg, "nil pointer") { - t.Fatal("expected nil pointer error, got:", errMsg) - } -} - -func topLevelNilPanic(t *testing.T) (panicErr string) { - defer func() { - e := recover() - if err, ok := e.(string); ok { - panicErr = err - } - }() - var ip *int - buf := new(bytes.Buffer) - if err := NewEncoder(buf).Encode(ip); err != nil { - t.Fatal("error in encode:", err) - } - return -} - -func TestNilPointerInsideInterface(t *testing.T) { - var ip *int - si := struct { - I interface{} - }{ - I: ip, - } - buf := new(bytes.Buffer) - err := NewEncoder(buf).Encode(si) - if err == nil { - t.Fatal("expected error, got none") - } - errMsg := err.Error() - if !strings.Contains(errMsg, "nil pointer") || !strings.Contains(errMsg, "interface") { - t.Fatal("expected error about nil pointer and interface, got:", errMsg) - } -} - -type Bug4Public struct { - Name string - Secret Bug4Secret -} - -type Bug4Secret struct { - a int // error: no exported fields. -} - -// Test that a failed compilation doesn't leave around an executable encoder. -// Issue 3273. -func TestMutipleEncodingsOfBadType(t *testing.T) { - x := Bug4Public{ - Name: "name", - Secret: Bug4Secret{1}, - } - buf := new(bytes.Buffer) - enc := NewEncoder(buf) - err := enc.Encode(x) - if err == nil { - t.Fatal("first encoding: expected error") - } - buf.Reset() - enc = NewEncoder(buf) - err = enc.Encode(x) - if err == nil { - t.Fatal("second encoding: expected error") - } - if !strings.Contains(err.Error(), "no exported fields") { - t.Errorf("expected error about no exported fields; got %v", err) - } -} - -// There was an error check comparing the length of the input with the -// length of the slice being decoded. It was wrong because the next -// thing in the input might be a type definition, which would lead to -// an incorrect length check. This test reproduces the corner case. - -type Z struct { -} - -func Test29ElementSlice(t *testing.T) { - Register(Z{}) - src := make([]interface{}, 100) // Size needs to be bigger than size of type definition. - for i := range src { - src[i] = Z{} - } - buf := new(bytes.Buffer) - err := NewEncoder(buf).Encode(src) - if err != nil { - t.Fatalf("encode: %v", err) - return - } - - var dst []interface{} - err = NewDecoder(buf).Decode(&dst) - if err != nil { - t.Errorf("decode: %v", err) - return - } -} diff --git a/src/pkg/encoding/gob/error.go b/src/pkg/encoding/gob/error.go deleted file mode 100644 index 92cc0c615..000000000 --- a/src/pkg/encoding/gob/error.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gob - -import "fmt" - -// Errors in decoding and encoding are handled using panic and recover. -// Panics caused by user error (that is, everything except run-time panics -// such as "index out of bounds" errors) do not leave the file that caused -// them, but are instead turned into plain error returns. Encoding and -// decoding functions and methods that do not return an error either use -// panic to report an error or are guaranteed error-free. - -// A gobError is used to distinguish errors (panics) generated in this package. -type gobError struct { - err error -} - -// errorf is like error_ but takes Printf-style arguments to construct an error. -// It always prefixes the message with "gob: ". -func errorf(format string, args ...interface{}) { - error_(fmt.Errorf("gob: "+format, args...)) -} - -// error wraps the argument error and uses it as the argument to panic. -func error_(err error) { - panic(gobError{err}) -} - -// catchError is meant to be used as a deferred function to turn a panic(gobError) into a -// plain error. It overwrites the error return of the function that deferred its call. -func catchError(err *error) { - if e := recover(); e != nil { - ge, ok := e.(gobError) - if !ok { - panic(e) - } - *err = ge.err - } - return -} diff --git a/src/pkg/encoding/gob/example_encdec_test.go b/src/pkg/encoding/gob/example_encdec_test.go deleted file mode 100644 index e45ad4ccf..000000000 --- a/src/pkg/encoding/gob/example_encdec_test.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gob_test - -import ( - "bytes" - "encoding/gob" - "fmt" - "log" -) - -// The Vector type has unexported fields, which the package cannot access. -// We therefore write a BinaryMarshal/BinaryUnmarshal method pair to allow us -// to send and receive the type with the gob package. These interfaces are -// defined in the "encoding" package. -// We could equivalently use the locally defined GobEncode/GobDecoder -// interfaces. -type Vector struct { - x, y, z int -} - -func (v Vector) MarshalBinary() ([]byte, error) { - // A simple encoding: plain text. - var b bytes.Buffer - fmt.Fprintln(&b, v.x, v.y, v.z) - return b.Bytes(), nil -} - -// UnmarshalBinary modifies the receiver so it must take a pointer receiver. -func (v *Vector) UnmarshalBinary(data []byte) error { - // A simple encoding: plain text. - b := bytes.NewBuffer(data) - _, err := fmt.Fscanln(b, &v.x, &v.y, &v.z) - return err -} - -// This example transmits a value that implements the custom encoding and decoding methods. -func Example_encodeDecode() { - var network bytes.Buffer // Stand-in for the network. - - // Create an encoder and send a value. - enc := gob.NewEncoder(&network) - err := enc.Encode(Vector{3, 4, 5}) - if err != nil { - log.Fatal("encode:", err) - } - - // Create a decoder and receive a value. - dec := gob.NewDecoder(&network) - var v Vector - err = dec.Decode(&v) - if err != nil { - log.Fatal("decode:", err) - } - fmt.Println(v) - - // Output: - // {3 4 5} -} diff --git a/src/pkg/encoding/gob/example_interface_test.go b/src/pkg/encoding/gob/example_interface_test.go deleted file mode 100644 index 4681e6307..000000000 --- a/src/pkg/encoding/gob/example_interface_test.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gob_test - -import ( - "bytes" - "encoding/gob" - "fmt" - "log" - "math" -) - -type Point struct { - X, Y int -} - -func (p Point) Hypotenuse() float64 { - return math.Hypot(float64(p.X), float64(p.Y)) -} - -type Pythagoras interface { - Hypotenuse() float64 -} - -// This example shows how to encode an interface value. The key -// distinction from regular types is to register the concrete type that -// implements the interface. -func Example_interface() { - var network bytes.Buffer // Stand-in for the network. - - // We must register the concrete type for the encoder and decoder (which would - // normally be on a separate machine from the encoder). On each end, this tells the - // engine which concrete type is being sent that implements the interface. - gob.Register(Point{}) - - // Create an encoder and send some values. - enc := gob.NewEncoder(&network) - for i := 1; i <= 3; i++ { - interfaceEncode(enc, Point{3 * i, 4 * i}) - } - - // Create a decoder and receive some values. - dec := gob.NewDecoder(&network) - for i := 1; i <= 3; i++ { - result := interfaceDecode(dec) - fmt.Println(result.Hypotenuse()) - } - - // Output: - // 5 - // 10 - // 15 -} - -// interfaceEncode encodes the interface value into the encoder. -func interfaceEncode(enc *gob.Encoder, p Pythagoras) { - // The encode will fail unless the concrete type has been - // registered. We registered it in the calling function. - - // Pass pointer to interface so Encode sees (and hence sends) a value of - // interface type. If we passed p directly it would see the concrete type instead. - // See the blog post, "The Laws of Reflection" for background. - err := enc.Encode(&p) - if err != nil { - log.Fatal("encode:", err) - } -} - -// interfaceDecode decodes the next interface value from the stream and returns it. -func interfaceDecode(dec *gob.Decoder) Pythagoras { - // The decode will fail unless the concrete type on the wire has been - // registered. We registered it in the calling function. - var p Pythagoras - err := dec.Decode(&p) - if err != nil { - log.Fatal("decode:", err) - } - return p -} diff --git a/src/pkg/encoding/gob/example_test.go b/src/pkg/encoding/gob/example_test.go deleted file mode 100644 index 020352cee..000000000 --- a/src/pkg/encoding/gob/example_test.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gob_test - -import ( - "bytes" - "encoding/gob" - "fmt" - "log" -) - -type P struct { - X, Y, Z int - Name string -} - -type Q struct { - X, Y *int32 - Name string -} - -// This example shows the basic usage of the package: Create an encoder, -// transmit some values, receive them with a decoder. -func Example_basic() { - // Initialize the encoder and decoder. Normally enc and dec would be - // bound to network connections and the encoder and decoder would - // run in different processes. - var network bytes.Buffer // Stand-in for a network connection - enc := gob.NewEncoder(&network) // Will write to network. - dec := gob.NewDecoder(&network) // Will read from network. - - // Encode (send) some values. - err := enc.Encode(P{3, 4, 5, "Pythagoras"}) - if err != nil { - log.Fatal("encode error:", err) - } - err = enc.Encode(P{1782, 1841, 1922, "Treehouse"}) - if err != nil { - log.Fatal("encode error:", err) - } - - // Decode (receive) and print the values. - var q Q - err = dec.Decode(&q) - if err != nil { - log.Fatal("decode error 1:", err) - } - fmt.Printf("%q: {%d, %d}\n", q.Name, *q.X, *q.Y) - err = dec.Decode(&q) - if err != nil { - log.Fatal("decode error 2:", err) - } - fmt.Printf("%q: {%d, %d}\n", q.Name, *q.X, *q.Y) - - // Output: - // "Pythagoras": {3, 4} - // "Treehouse": {1782, 1841} -} diff --git a/src/pkg/encoding/gob/gobencdec_test.go b/src/pkg/encoding/gob/gobencdec_test.go deleted file mode 100644 index 157b7723a..000000000 --- a/src/pkg/encoding/gob/gobencdec_test.go +++ /dev/null @@ -1,797 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This file contains tests of the GobEncoder/GobDecoder support. - -package gob - -import ( - "bytes" - "errors" - "fmt" - "io" - "net" - "strings" - "testing" - "time" -) - -// Types that implement the GobEncoder/Decoder interfaces. - -type ByteStruct struct { - a byte // not an exported field -} - -type StringStruct struct { - s string // not an exported field -} - -type ArrayStruct struct { - a [8192]byte // not an exported field -} - -type Gobber int - -type ValueGobber string // encodes with a value, decodes with a pointer. - -type BinaryGobber int - -type BinaryValueGobber string - -type TextGobber int - -type TextValueGobber string - -// The relevant methods - -func (g *ByteStruct) GobEncode() ([]byte, error) { - b := make([]byte, 3) - b[0] = g.a - b[1] = g.a + 1 - b[2] = g.a + 2 - return b, nil -} - -func (g *ByteStruct) GobDecode(data []byte) error { - if g == nil { - return errors.New("NIL RECEIVER") - } - // Expect N sequential-valued bytes. - if len(data) == 0 { - return io.EOF - } - g.a = data[0] - for i, c := range data { - if c != g.a+byte(i) { - return errors.New("invalid data sequence") - } - } - return nil -} - -func (g *StringStruct) GobEncode() ([]byte, error) { - return []byte(g.s), nil -} - -func (g *StringStruct) GobDecode(data []byte) error { - // Expect N sequential-valued bytes. - if len(data) == 0 { - return io.EOF - } - a := data[0] - for i, c := range data { - if c != a+byte(i) { - return errors.New("invalid data sequence") - } - } - g.s = string(data) - return nil -} - -func (a *ArrayStruct) GobEncode() ([]byte, error) { - return a.a[:], nil -} - -func (a *ArrayStruct) GobDecode(data []byte) error { - if len(data) != len(a.a) { - return errors.New("wrong length in array decode") - } - copy(a.a[:], data) - return nil -} - -func (g *Gobber) GobEncode() ([]byte, error) { - return []byte(fmt.Sprintf("VALUE=%d", *g)), nil -} - -func (g *Gobber) GobDecode(data []byte) error { - _, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g)) - return err -} - -func (g *BinaryGobber) MarshalBinary() ([]byte, error) { - return []byte(fmt.Sprintf("VALUE=%d", *g)), nil -} - -func (g *BinaryGobber) UnmarshalBinary(data []byte) error { - _, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g)) - return err -} - -func (g *TextGobber) MarshalText() ([]byte, error) { - return []byte(fmt.Sprintf("VALUE=%d", *g)), nil -} - -func (g *TextGobber) UnmarshalText(data []byte) error { - _, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g)) - return err -} - -func (v ValueGobber) GobEncode() ([]byte, error) { - return []byte(fmt.Sprintf("VALUE=%s", v)), nil -} - -func (v *ValueGobber) GobDecode(data []byte) error { - _, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v)) - return err -} - -func (v BinaryValueGobber) MarshalBinary() ([]byte, error) { - return []byte(fmt.Sprintf("VALUE=%s", v)), nil -} - -func (v *BinaryValueGobber) UnmarshalBinary(data []byte) error { - _, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v)) - return err -} - -func (v TextValueGobber) MarshalText() ([]byte, error) { - return []byte(fmt.Sprintf("VALUE=%s", v)), nil -} - -func (v *TextValueGobber) UnmarshalText(data []byte) error { - _, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v)) - return err -} - -// Structs that include GobEncodable fields. - -type GobTest0 struct { - X int // guarantee we have something in common with GobTest* - G *ByteStruct -} - -type GobTest1 struct { - X int // guarantee we have something in common with GobTest* - G *StringStruct -} - -type GobTest2 struct { - X int // guarantee we have something in common with GobTest* - G string // not a GobEncoder - should give us errors -} - -type GobTest3 struct { - X int // guarantee we have something in common with GobTest* - G *Gobber - B *BinaryGobber - T *TextGobber -} - -type GobTest4 struct { - X int // guarantee we have something in common with GobTest* - V ValueGobber - BV BinaryValueGobber - TV TextValueGobber -} - -type GobTest5 struct { - X int // guarantee we have something in common with GobTest* - V *ValueGobber - BV *BinaryValueGobber - TV *TextValueGobber -} - -type GobTest6 struct { - X int // guarantee we have something in common with GobTest* - V ValueGobber - W *ValueGobber - BV BinaryValueGobber - BW *BinaryValueGobber - TV TextValueGobber - TW *TextValueGobber -} - -type GobTest7 struct { - X int // guarantee we have something in common with GobTest* - V *ValueGobber - W ValueGobber - BV *BinaryValueGobber - BW BinaryValueGobber - TV *TextValueGobber - TW TextValueGobber -} - -type GobTestIgnoreEncoder struct { - X int // guarantee we have something in common with GobTest* -} - -type GobTestValueEncDec struct { - X int // guarantee we have something in common with GobTest* - G StringStruct // not a pointer. -} - -type GobTestIndirectEncDec struct { - X int // guarantee we have something in common with GobTest* - G ***StringStruct // indirections to the receiver. -} - -type GobTestArrayEncDec struct { - X int // guarantee we have something in common with GobTest* - A ArrayStruct // not a pointer. -} - -type GobTestIndirectArrayEncDec struct { - X int // guarantee we have something in common with GobTest* - A ***ArrayStruct // indirections to a large receiver. -} - -func TestGobEncoderField(t *testing.T) { - b := new(bytes.Buffer) - // First a field that's a structure. - enc := NewEncoder(b) - err := enc.Encode(GobTest0{17, &ByteStruct{'A'}}) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTest0) - err = dec.Decode(x) - if err != nil { - t.Fatal("decode error:", err) - } - if x.G.a != 'A' { - t.Errorf("expected 'A' got %c", x.G.a) - } - // Now a field that's not a structure. - b.Reset() - gobber := Gobber(23) - bgobber := BinaryGobber(24) - tgobber := TextGobber(25) - err = enc.Encode(GobTest3{17, &gobber, &bgobber, &tgobber}) - if err != nil { - t.Fatal("encode error:", err) - } - y := new(GobTest3) - err = dec.Decode(y) - if err != nil { - t.Fatal("decode error:", err) - } - if *y.G != 23 || *y.B != 24 || *y.T != 25 { - t.Errorf("expected '23 got %d", *y.G) - } -} - -// Even though the field is a value, we can still take its address -// and should be able to call the methods. -func TestGobEncoderValueField(t *testing.T) { - b := new(bytes.Buffer) - // First a field that's a structure. - enc := NewEncoder(b) - err := enc.Encode(GobTestValueEncDec{17, StringStruct{"HIJKL"}}) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTestValueEncDec) - err = dec.Decode(x) - if err != nil { - t.Fatal("decode error:", err) - } - if x.G.s != "HIJKL" { - t.Errorf("expected `HIJKL` got %s", x.G.s) - } -} - -// GobEncode/Decode should work even if the value is -// more indirect than the receiver. -func TestGobEncoderIndirectField(t *testing.T) { - b := new(bytes.Buffer) - // First a field that's a structure. - enc := NewEncoder(b) - s := &StringStruct{"HIJKL"} - sp := &s - err := enc.Encode(GobTestIndirectEncDec{17, &sp}) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTestIndirectEncDec) - err = dec.Decode(x) - if err != nil { - t.Fatal("decode error:", err) - } - if (***x.G).s != "HIJKL" { - t.Errorf("expected `HIJKL` got %s", (***x.G).s) - } -} - -// Test with a large field with methods. -func TestGobEncoderArrayField(t *testing.T) { - b := new(bytes.Buffer) - enc := NewEncoder(b) - var a GobTestArrayEncDec - a.X = 17 - for i := range a.A.a { - a.A.a[i] = byte(i) - } - err := enc.Encode(a) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTestArrayEncDec) - err = dec.Decode(x) - if err != nil { - t.Fatal("decode error:", err) - } - for i, v := range x.A.a { - if v != byte(i) { - t.Errorf("expected %x got %x", byte(i), v) - break - } - } -} - -// Test an indirection to a large field with methods. -func TestGobEncoderIndirectArrayField(t *testing.T) { - b := new(bytes.Buffer) - enc := NewEncoder(b) - var a GobTestIndirectArrayEncDec - a.X = 17 - var array ArrayStruct - ap := &array - app := &ap - a.A = &app - for i := range array.a { - array.a[i] = byte(i) - } - err := enc.Encode(a) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTestIndirectArrayEncDec) - err = dec.Decode(x) - if err != nil { - t.Fatal("decode error:", err) - } - for i, v := range (***x.A).a { - if v != byte(i) { - t.Errorf("expected %x got %x", byte(i), v) - break - } - } -} - -// As long as the fields have the same name and implement the -// interface, we can cross-connect them. Not sure it's useful -// and may even be bad but it works and it's hard to prevent -// without exposing the contents of the object, which would -// defeat the purpose. -func TestGobEncoderFieldsOfDifferentType(t *testing.T) { - // first, string in field to byte in field - b := new(bytes.Buffer) - enc := NewEncoder(b) - err := enc.Encode(GobTest1{17, &StringStruct{"ABC"}}) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTest0) - err = dec.Decode(x) - if err != nil { - t.Fatal("decode error:", err) - } - if x.G.a != 'A' { - t.Errorf("expected 'A' got %c", x.G.a) - } - // now the other direction, byte in field to string in field - b.Reset() - err = enc.Encode(GobTest0{17, &ByteStruct{'X'}}) - if err != nil { - t.Fatal("encode error:", err) - } - y := new(GobTest1) - err = dec.Decode(y) - if err != nil { - t.Fatal("decode error:", err) - } - if y.G.s != "XYZ" { - t.Fatalf("expected `XYZ` got %q", y.G.s) - } -} - -// Test that we can encode a value and decode into a pointer. -func TestGobEncoderValueEncoder(t *testing.T) { - // first, string in field to byte in field - b := new(bytes.Buffer) - enc := NewEncoder(b) - err := enc.Encode(GobTest4{17, ValueGobber("hello"), BinaryValueGobber("Καλημέρα"), TextValueGobber("こんにちは")}) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTest5) - err = dec.Decode(x) - if err != nil { - t.Fatal("decode error:", err) - } - if *x.V != "hello" || *x.BV != "Καλημέρα" || *x.TV != "こんにちは" { - t.Errorf("expected `hello` got %s", *x.V) - } -} - -// Test that we can use a value then a pointer type of a GobEncoder -// in the same encoded value. Bug 4647. -func TestGobEncoderValueThenPointer(t *testing.T) { - v := ValueGobber("forty-two") - w := ValueGobber("six-by-nine") - bv := BinaryValueGobber("1nanocentury") - bw := BinaryValueGobber("πseconds") - tv := TextValueGobber("gravitationalacceleration") - tw := TextValueGobber("π²ft/s²") - - // this was a bug: encoding a GobEncoder by value before a GobEncoder - // pointer would cause duplicate type definitions to be sent. - - b := new(bytes.Buffer) - enc := NewEncoder(b) - if err := enc.Encode(GobTest6{42, v, &w, bv, &bw, tv, &tw}); err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTest6) - if err := dec.Decode(x); err != nil { - t.Fatal("decode error:", err) - } - - if got, want := x.V, v; got != want { - t.Errorf("v = %q, want %q", got, want) - } - if got, want := x.W, w; got == nil { - t.Errorf("w = nil, want %q", want) - } else if *got != want { - t.Errorf("w = %q, want %q", *got, want) - } - - if got, want := x.BV, bv; got != want { - t.Errorf("bv = %q, want %q", got, want) - } - if got, want := x.BW, bw; got == nil { - t.Errorf("bw = nil, want %q", want) - } else if *got != want { - t.Errorf("bw = %q, want %q", *got, want) - } - - if got, want := x.TV, tv; got != want { - t.Errorf("tv = %q, want %q", got, want) - } - if got, want := x.TW, tw; got == nil { - t.Errorf("tw = nil, want %q", want) - } else if *got != want { - t.Errorf("tw = %q, want %q", *got, want) - } -} - -// Test that we can use a pointer then a value type of a GobEncoder -// in the same encoded value. -func TestGobEncoderPointerThenValue(t *testing.T) { - v := ValueGobber("forty-two") - w := ValueGobber("six-by-nine") - bv := BinaryValueGobber("1nanocentury") - bw := BinaryValueGobber("πseconds") - tv := TextValueGobber("gravitationalacceleration") - tw := TextValueGobber("π²ft/s²") - - b := new(bytes.Buffer) - enc := NewEncoder(b) - if err := enc.Encode(GobTest7{42, &v, w, &bv, bw, &tv, tw}); err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTest7) - if err := dec.Decode(x); err != nil { - t.Fatal("decode error:", err) - } - - if got, want := x.V, v; got == nil { - t.Errorf("v = nil, want %q", want) - } else if *got != want { - t.Errorf("v = %q, want %q", *got, want) - } - if got, want := x.W, w; got != want { - t.Errorf("w = %q, want %q", got, want) - } - - if got, want := x.BV, bv; got == nil { - t.Errorf("bv = nil, want %q", want) - } else if *got != want { - t.Errorf("bv = %q, want %q", *got, want) - } - if got, want := x.BW, bw; got != want { - t.Errorf("bw = %q, want %q", got, want) - } - - if got, want := x.TV, tv; got == nil { - t.Errorf("tv = nil, want %q", want) - } else if *got != want { - t.Errorf("tv = %q, want %q", *got, want) - } - if got, want := x.TW, tw; got != want { - t.Errorf("tw = %q, want %q", got, want) - } -} - -func TestGobEncoderFieldTypeError(t *testing.T) { - // GobEncoder to non-decoder: error - b := new(bytes.Buffer) - enc := NewEncoder(b) - err := enc.Encode(GobTest1{17, &StringStruct{"ABC"}}) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := &GobTest2{} - err = dec.Decode(x) - if err == nil { - t.Fatal("expected decode error for mismatched fields (encoder to non-decoder)") - } - if strings.Index(err.Error(), "type") < 0 { - t.Fatal("expected type error; got", err) - } - // Non-encoder to GobDecoder: error - b.Reset() - err = enc.Encode(GobTest2{17, "ABC"}) - if err != nil { - t.Fatal("encode error:", err) - } - y := &GobTest1{} - err = dec.Decode(y) - if err == nil { - t.Fatal("expected decode error for mismatched fields (non-encoder to decoder)") - } - if strings.Index(err.Error(), "type") < 0 { - t.Fatal("expected type error; got", err) - } -} - -// Even though ByteStruct is a struct, it's treated as a singleton at the top level. -func TestGobEncoderStructSingleton(t *testing.T) { - b := new(bytes.Buffer) - enc := NewEncoder(b) - err := enc.Encode(&ByteStruct{'A'}) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(ByteStruct) - err = dec.Decode(x) - if err != nil { - t.Fatal("decode error:", err) - } - if x.a != 'A' { - t.Errorf("expected 'A' got %c", x.a) - } -} - -func TestGobEncoderNonStructSingleton(t *testing.T) { - b := new(bytes.Buffer) - enc := NewEncoder(b) - err := enc.Encode(Gobber(1234)) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - var x Gobber - err = dec.Decode(&x) - if err != nil { - t.Fatal("decode error:", err) - } - if x != 1234 { - t.Errorf("expected 1234 got %d", x) - } -} - -func TestGobEncoderIgnoreStructField(t *testing.T) { - b := new(bytes.Buffer) - // First a field that's a structure. - enc := NewEncoder(b) - err := enc.Encode(GobTest0{17, &ByteStruct{'A'}}) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTestIgnoreEncoder) - err = dec.Decode(x) - if err != nil { - t.Fatal("decode error:", err) - } - if x.X != 17 { - t.Errorf("expected 17 got %c", x.X) - } -} - -func TestGobEncoderIgnoreNonStructField(t *testing.T) { - b := new(bytes.Buffer) - // First a field that's a structure. - enc := NewEncoder(b) - gobber := Gobber(23) - bgobber := BinaryGobber(24) - tgobber := TextGobber(25) - err := enc.Encode(GobTest3{17, &gobber, &bgobber, &tgobber}) - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTestIgnoreEncoder) - err = dec.Decode(x) - if err != nil { - t.Fatal("decode error:", err) - } - if x.X != 17 { - t.Errorf("expected 17 got %c", x.X) - } -} - -func TestGobEncoderIgnoreNilEncoder(t *testing.T) { - b := new(bytes.Buffer) - // First a field that's a structure. - enc := NewEncoder(b) - err := enc.Encode(GobTest0{X: 18}) // G is nil - if err != nil { - t.Fatal("encode error:", err) - } - dec := NewDecoder(b) - x := new(GobTest0) - err = dec.Decode(x) - if err != nil { - t.Fatal("decode error:", err) - } - if x.X != 18 { - t.Errorf("expected x.X = 18, got %v", x.X) - } - if x.G != nil { - t.Errorf("expected x.G = nil, got %v", x.G) - } -} - -type gobDecoderBug0 struct { - foo, bar string -} - -func (br *gobDecoderBug0) String() string { - return br.foo + "-" + br.bar -} - -func (br *gobDecoderBug0) GobEncode() ([]byte, error) { - return []byte(br.String()), nil -} - -func (br *gobDecoderBug0) GobDecode(b []byte) error { - br.foo = "foo" - br.bar = "bar" - return nil -} - -// This was a bug: the receiver has a different indirection level -// than the variable. -func TestGobEncoderExtraIndirect(t *testing.T) { - gdb := &gobDecoderBug0{"foo", "bar"} - buf := new(bytes.Buffer) - e := NewEncoder(buf) - if err := e.Encode(gdb); err != nil { - t.Fatalf("encode: %v", err) - } - d := NewDecoder(buf) - var got *gobDecoderBug0 - if err := d.Decode(&got); err != nil { - t.Fatalf("decode: %v", err) - } - if got.foo != gdb.foo || got.bar != gdb.bar { - t.Errorf("got = %q, want %q", got, gdb) - } -} - -// Another bug: this caused a crash with the new Go1 Time type. -// We throw in a gob-encoding array, to test another case of isZero, -// and a struct containing an nil interface, to test a third. -type isZeroBug struct { - T time.Time - S string - I int - A isZeroBugArray - F isZeroBugInterface -} - -type isZeroBugArray [2]uint8 - -// Receiver is value, not pointer, to test isZero of array. -func (a isZeroBugArray) GobEncode() (b []byte, e error) { - b = append(b, a[:]...) - return b, nil -} - -func (a *isZeroBugArray) GobDecode(data []byte) error { - if len(data) != len(a) { - return io.EOF - } - a[0] = data[0] - a[1] = data[1] - return nil -} - -type isZeroBugInterface struct { - I interface{} -} - -func (i isZeroBugInterface) GobEncode() (b []byte, e error) { - return []byte{}, nil -} - -func (i *isZeroBugInterface) GobDecode(data []byte) error { - return nil -} - -func TestGobEncodeIsZero(t *testing.T) { - x := isZeroBug{time.Now(), "hello", -55, isZeroBugArray{1, 2}, isZeroBugInterface{}} - b := new(bytes.Buffer) - enc := NewEncoder(b) - err := enc.Encode(x) - if err != nil { - t.Fatal("encode:", err) - } - var y isZeroBug - dec := NewDecoder(b) - err = dec.Decode(&y) - if err != nil { - t.Fatal("decode:", err) - } - if x != y { - t.Fatalf("%v != %v", x, y) - } -} - -func TestGobEncodePtrError(t *testing.T) { - var err error - b := new(bytes.Buffer) - enc := NewEncoder(b) - err = enc.Encode(&err) - if err != nil { - t.Fatal("encode:", err) - } - dec := NewDecoder(b) - err2 := fmt.Errorf("foo") - err = dec.Decode(&err2) - if err != nil { - t.Fatal("decode:", err) - } - if err2 != nil { - t.Fatalf("expected nil, got %v", err2) - } -} - -func TestNetIP(t *testing.T) { - // Encoding of net.IP{1,2,3,4} in Go 1.1. - enc := []byte{0x07, 0x0a, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04} - - var ip net.IP - err := NewDecoder(bytes.NewReader(enc)).Decode(&ip) - if err != nil { - t.Fatalf("decode: %v", err) - } - if ip.String() != "1.2.3.4" { - t.Errorf("decoded to %v, want 1.2.3.4", ip.String()) - } -} diff --git a/src/pkg/encoding/gob/timing_test.go b/src/pkg/encoding/gob/timing_test.go deleted file mode 100644 index 9fbb0ac6d..000000000 --- a/src/pkg/encoding/gob/timing_test.go +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gob - -import ( - "bytes" - "io" - "os" - "runtime" - "testing" -) - -type Bench struct { - A int - B float64 - C string - D []byte -} - -func benchmarkEndToEnd(r io.Reader, w io.Writer, b *testing.B) { - b.StopTimer() - enc := NewEncoder(w) - dec := NewDecoder(r) - bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")} - b.StartTimer() - for i := 0; i < b.N; i++ { - if enc.Encode(bench) != nil { - panic("encode error") - } - if dec.Decode(bench) != nil { - panic("decode error") - } - } -} - -func BenchmarkEndToEndPipe(b *testing.B) { - r, w, err := os.Pipe() - if err != nil { - b.Fatal("can't get pipe:", err) - } - benchmarkEndToEnd(r, w, b) -} - -func BenchmarkEndToEndByteBuffer(b *testing.B) { - var buf bytes.Buffer - benchmarkEndToEnd(&buf, &buf, b) -} - -func TestCountEncodeMallocs(t *testing.T) { - if testing.Short() { - t.Skip("skipping malloc count in short mode") - } - if runtime.GOMAXPROCS(0) > 1 { - t.Skip("skipping; GOMAXPROCS>1") - } - - const N = 1000 - - var buf bytes.Buffer - enc := NewEncoder(&buf) - bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")} - - allocs := testing.AllocsPerRun(N, func() { - err := enc.Encode(bench) - if err != nil { - t.Fatal("encode:", err) - } - }) - if allocs != 0 { - t.Fatalf("mallocs per encode of type Bench: %v; wanted 0\n", allocs) - } -} - -func TestCountDecodeMallocs(t *testing.T) { - if testing.Short() { - t.Skip("skipping malloc count in short mode") - } - if runtime.GOMAXPROCS(0) > 1 { - t.Skip("skipping; GOMAXPROCS>1") - } - - const N = 1000 - - var buf bytes.Buffer - enc := NewEncoder(&buf) - bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")} - - // Fill the buffer with enough to decode - testing.AllocsPerRun(N, func() { - err := enc.Encode(bench) - if err != nil { - t.Fatal("encode:", err) - } - }) - - dec := NewDecoder(&buf) - allocs := testing.AllocsPerRun(N, func() { - *bench = Bench{} - err := dec.Decode(&bench) - if err != nil { - t.Fatal("decode:", err) - } - }) - if allocs != 3 { - t.Fatalf("mallocs per decode of type Bench: %v; wanted 3\n", allocs) - } -} diff --git a/src/pkg/encoding/gob/type.go b/src/pkg/encoding/gob/type.go deleted file mode 100644 index cad145279..000000000 --- a/src/pkg/encoding/gob/type.go +++ /dev/null @@ -1,893 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gob - -import ( - "encoding" - "errors" - "fmt" - "os" - "reflect" - "sync" - "unicode" - "unicode/utf8" -) - -// userTypeInfo stores the information associated with a type the user has handed -// to the package. It's computed once and stored in a map keyed by reflection -// type. -type userTypeInfo struct { - user reflect.Type // the type the user handed us - base reflect.Type // the base type after all indirections - indir int // number of indirections to reach the base type - externalEnc int // xGob, xBinary, or xText - externalDec int // xGob, xBinary or xText - encIndir int8 // number of indirections to reach the receiver type; may be negative - decIndir int8 // number of indirections to reach the receiver type; may be negative -} - -// externalEncoding bits -const ( - xGob = 1 + iota // GobEncoder or GobDecoder - xBinary // encoding.BinaryMarshaler or encoding.BinaryUnmarshaler - xText // encoding.TextMarshaler or encoding.TextUnmarshaler -) - -var ( - // Protected by an RWMutex because we read it a lot and write - // it only when we see a new type, typically when compiling. - userTypeLock sync.RWMutex - userTypeCache = make(map[reflect.Type]*userTypeInfo) -) - -// validType returns, and saves, the information associated with user-provided type rt. -// If the user type is not valid, err will be non-nil. To be used when the error handler -// is not set up. -func validUserType(rt reflect.Type) (ut *userTypeInfo, err error) { - userTypeLock.RLock() - ut = userTypeCache[rt] - userTypeLock.RUnlock() - if ut != nil { - return - } - // Now set the value under the write lock. - userTypeLock.Lock() - defer userTypeLock.Unlock() - if ut = userTypeCache[rt]; ut != nil { - // Lost the race; not a problem. - return - } - ut = new(userTypeInfo) - ut.base = rt - ut.user = rt - // A type that is just a cycle of pointers (such as type T *T) cannot - // be represented in gobs, which need some concrete data. We use a - // cycle detection algorithm from Knuth, Vol 2, Section 3.1, Ex 6, - // pp 539-540. As we step through indirections, run another type at - // half speed. If they meet up, there's a cycle. - slowpoke := ut.base // walks half as fast as ut.base - for { - pt := ut.base - if pt.Kind() != reflect.Ptr { - break - } - ut.base = pt.Elem() - if ut.base == slowpoke { // ut.base lapped slowpoke - // recursive pointer type. - return nil, errors.New("can't represent recursive pointer type " + ut.base.String()) - } - if ut.indir%2 == 0 { - slowpoke = slowpoke.Elem() - } - ut.indir++ - } - - if ok, indir := implementsInterface(ut.user, gobEncoderInterfaceType); ok { - ut.externalEnc, ut.encIndir = xGob, indir - } else if ok, indir := implementsInterface(ut.user, binaryMarshalerInterfaceType); ok { - ut.externalEnc, ut.encIndir = xBinary, indir - } - - // NOTE(rsc): Would like to allow MarshalText here, but results in incompatibility - // with older encodings for net.IP. See golang.org/issue/6760. - // } else if ok, indir := implementsInterface(ut.user, textMarshalerInterfaceType); ok { - // ut.externalEnc, ut.encIndir = xText, indir - // } - - if ok, indir := implementsInterface(ut.user, gobDecoderInterfaceType); ok { - ut.externalDec, ut.decIndir = xGob, indir - } else if ok, indir := implementsInterface(ut.user, binaryUnmarshalerInterfaceType); ok { - ut.externalDec, ut.decIndir = xBinary, indir - } - - // See note above. - // } else if ok, indir := implementsInterface(ut.user, textUnmarshalerInterfaceType); ok { - // ut.externalDec, ut.decIndir = xText, indir - // } - - userTypeCache[rt] = ut - return -} - -var ( - gobEncoderInterfaceType = reflect.TypeOf((*GobEncoder)(nil)).Elem() - gobDecoderInterfaceType = reflect.TypeOf((*GobDecoder)(nil)).Elem() - binaryMarshalerInterfaceType = reflect.TypeOf((*encoding.BinaryMarshaler)(nil)).Elem() - binaryUnmarshalerInterfaceType = reflect.TypeOf((*encoding.BinaryUnmarshaler)(nil)).Elem() - textMarshalerInterfaceType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem() - textUnmarshalerInterfaceType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() -) - -// implementsInterface reports whether the type implements the -// gobEncoder/gobDecoder interface. -// It also returns the number of indirections required to get to the -// implementation. -func implementsInterface(typ, gobEncDecType reflect.Type) (success bool, indir int8) { - if typ == nil { - return - } - rt := typ - // The type might be a pointer and we need to keep - // dereferencing to the base type until we find an implementation. - for { - if rt.Implements(gobEncDecType) { - return true, indir - } - if p := rt; p.Kind() == reflect.Ptr { - indir++ - if indir > 100 { // insane number of indirections - return false, 0 - } - rt = p.Elem() - continue - } - break - } - // No luck yet, but if this is a base type (non-pointer), the pointer might satisfy. - if typ.Kind() != reflect.Ptr { - // Not a pointer, but does the pointer work? - if reflect.PtrTo(typ).Implements(gobEncDecType) { - return true, -1 - } - } - return false, 0 -} - -// userType returns, and saves, the information associated with user-provided type rt. -// If the user type is not valid, it calls error. -func userType(rt reflect.Type) *userTypeInfo { - ut, err := validUserType(rt) - if err != nil { - error_(err) - } - return ut -} - -// A typeId represents a gob Type as an integer that can be passed on the wire. -// Internally, typeIds are used as keys to a map to recover the underlying type info. -type typeId int32 - -var nextId typeId // incremented for each new type we build -var typeLock sync.Mutex // set while building a type -const firstUserId = 64 // lowest id number granted to user - -type gobType interface { - id() typeId - setId(id typeId) - name() string - string() string // not public; only for debugging - safeString(seen map[typeId]bool) string -} - -var types = make(map[reflect.Type]gobType) -var idToType = make(map[typeId]gobType) -var builtinIdToType map[typeId]gobType // set in init() after builtins are established - -func setTypeId(typ gobType) { - // When building recursive types, someone may get there before us. - if typ.id() != 0 { - return - } - nextId++ - typ.setId(nextId) - idToType[nextId] = typ -} - -func (t typeId) gobType() gobType { - if t == 0 { - return nil - } - return idToType[t] -} - -// string returns the string representation of the type associated with the typeId. -func (t typeId) string() string { - if t.gobType() == nil { - return "<nil>" - } - return t.gobType().string() -} - -// Name returns the name of the type associated with the typeId. -func (t typeId) name() string { - if t.gobType() == nil { - return "<nil>" - } - return t.gobType().name() -} - -// CommonType holds elements of all types. -// It is a historical artifact, kept for binary compatibility and exported -// only for the benefit of the package's encoding of type descriptors. It is -// not intended for direct use by clients. -type CommonType struct { - Name string - Id typeId -} - -func (t *CommonType) id() typeId { return t.Id } - -func (t *CommonType) setId(id typeId) { t.Id = id } - -func (t *CommonType) string() string { return t.Name } - -func (t *CommonType) safeString(seen map[typeId]bool) string { - return t.Name -} - -func (t *CommonType) name() string { return t.Name } - -// Create and check predefined types -// The string for tBytes is "bytes" not "[]byte" to signify its specialness. - -var ( - // Primordial types, needed during initialization. - // Always passed as pointers so the interface{} type - // goes through without losing its interfaceness. - tBool = bootstrapType("bool", (*bool)(nil), 1) - tInt = bootstrapType("int", (*int)(nil), 2) - tUint = bootstrapType("uint", (*uint)(nil), 3) - tFloat = bootstrapType("float", (*float64)(nil), 4) - tBytes = bootstrapType("bytes", (*[]byte)(nil), 5) - tString = bootstrapType("string", (*string)(nil), 6) - tComplex = bootstrapType("complex", (*complex128)(nil), 7) - tInterface = bootstrapType("interface", (*interface{})(nil), 8) - // Reserve some Ids for compatible expansion - tReserved7 = bootstrapType("_reserved1", (*struct{ r7 int })(nil), 9) - tReserved6 = bootstrapType("_reserved1", (*struct{ r6 int })(nil), 10) - tReserved5 = bootstrapType("_reserved1", (*struct{ r5 int })(nil), 11) - tReserved4 = bootstrapType("_reserved1", (*struct{ r4 int })(nil), 12) - tReserved3 = bootstrapType("_reserved1", (*struct{ r3 int })(nil), 13) - tReserved2 = bootstrapType("_reserved1", (*struct{ r2 int })(nil), 14) - tReserved1 = bootstrapType("_reserved1", (*struct{ r1 int })(nil), 15) -) - -// Predefined because it's needed by the Decoder -var tWireType = mustGetTypeInfo(reflect.TypeOf(wireType{})).id -var wireTypeUserInfo *userTypeInfo // userTypeInfo of (*wireType) - -func init() { - // Some magic numbers to make sure there are no surprises. - checkId(16, tWireType) - checkId(17, mustGetTypeInfo(reflect.TypeOf(arrayType{})).id) - checkId(18, mustGetTypeInfo(reflect.TypeOf(CommonType{})).id) - checkId(19, mustGetTypeInfo(reflect.TypeOf(sliceType{})).id) - checkId(20, mustGetTypeInfo(reflect.TypeOf(structType{})).id) - checkId(21, mustGetTypeInfo(reflect.TypeOf(fieldType{})).id) - checkId(23, mustGetTypeInfo(reflect.TypeOf(mapType{})).id) - - builtinIdToType = make(map[typeId]gobType) - for k, v := range idToType { - builtinIdToType[k] = v - } - - // Move the id space upwards to allow for growth in the predefined world - // without breaking existing files. - if nextId > firstUserId { - panic(fmt.Sprintln("nextId too large:", nextId)) - } - nextId = firstUserId - registerBasics() - wireTypeUserInfo = userType(reflect.TypeOf((*wireType)(nil))) -} - -// Array type -type arrayType struct { - CommonType - Elem typeId - Len int -} - -func newArrayType(name string) *arrayType { - a := &arrayType{CommonType{Name: name}, 0, 0} - return a -} - -func (a *arrayType) init(elem gobType, len int) { - // Set our type id before evaluating the element's, in case it's our own. - setTypeId(a) - a.Elem = elem.id() - a.Len = len -} - -func (a *arrayType) safeString(seen map[typeId]bool) string { - if seen[a.Id] { - return a.Name - } - seen[a.Id] = true - return fmt.Sprintf("[%d]%s", a.Len, a.Elem.gobType().safeString(seen)) -} - -func (a *arrayType) string() string { return a.safeString(make(map[typeId]bool)) } - -// GobEncoder type (something that implements the GobEncoder interface) -type gobEncoderType struct { - CommonType -} - -func newGobEncoderType(name string) *gobEncoderType { - g := &gobEncoderType{CommonType{Name: name}} - setTypeId(g) - return g -} - -func (g *gobEncoderType) safeString(seen map[typeId]bool) string { - return g.Name -} - -func (g *gobEncoderType) string() string { return g.Name } - -// Map type -type mapType struct { - CommonType - Key typeId - Elem typeId -} - -func newMapType(name string) *mapType { - m := &mapType{CommonType{Name: name}, 0, 0} - return m -} - -func (m *mapType) init(key, elem gobType) { - // Set our type id before evaluating the element's, in case it's our own. - setTypeId(m) - m.Key = key.id() - m.Elem = elem.id() -} - -func (m *mapType) safeString(seen map[typeId]bool) string { - if seen[m.Id] { - return m.Name - } - seen[m.Id] = true - key := m.Key.gobType().safeString(seen) - elem := m.Elem.gobType().safeString(seen) - return fmt.Sprintf("map[%s]%s", key, elem) -} - -func (m *mapType) string() string { return m.safeString(make(map[typeId]bool)) } - -// Slice type -type sliceType struct { - CommonType - Elem typeId -} - -func newSliceType(name string) *sliceType { - s := &sliceType{CommonType{Name: name}, 0} - return s -} - -func (s *sliceType) init(elem gobType) { - // Set our type id before evaluating the element's, in case it's our own. - setTypeId(s) - // See the comments about ids in newTypeObject. Only slices and - // structs have mutual recursion. - if elem.id() == 0 { - setTypeId(elem) - } - s.Elem = elem.id() -} - -func (s *sliceType) safeString(seen map[typeId]bool) string { - if seen[s.Id] { - return s.Name - } - seen[s.Id] = true - return fmt.Sprintf("[]%s", s.Elem.gobType().safeString(seen)) -} - -func (s *sliceType) string() string { return s.safeString(make(map[typeId]bool)) } - -// Struct type -type fieldType struct { - Name string - Id typeId -} - -type structType struct { - CommonType - Field []*fieldType -} - -func (s *structType) safeString(seen map[typeId]bool) string { - if s == nil { - return "<nil>" - } - if _, ok := seen[s.Id]; ok { - return s.Name - } - seen[s.Id] = true - str := s.Name + " = struct { " - for _, f := range s.Field { - str += fmt.Sprintf("%s %s; ", f.Name, f.Id.gobType().safeString(seen)) - } - str += "}" - return str -} - -func (s *structType) string() string { return s.safeString(make(map[typeId]bool)) } - -func newStructType(name string) *structType { - s := &structType{CommonType{Name: name}, nil} - // For historical reasons we set the id here rather than init. - // See the comment in newTypeObject for details. - setTypeId(s) - return s -} - -// newTypeObject allocates a gobType for the reflection type rt. -// Unless ut represents a GobEncoder, rt should be the base type -// of ut. -// This is only called from the encoding side. The decoding side -// works through typeIds and userTypeInfos alone. -func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, error) { - // Does this type implement GobEncoder? - if ut.externalEnc != 0 { - return newGobEncoderType(name), nil - } - var err error - var type0, type1 gobType - defer func() { - if err != nil { - delete(types, rt) - } - }() - // Install the top-level type before the subtypes (e.g. struct before - // fields) so recursive types can be constructed safely. - switch t := rt; t.Kind() { - // All basic types are easy: they are predefined. - case reflect.Bool: - return tBool.gobType(), nil - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return tInt.gobType(), nil - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return tUint.gobType(), nil - - case reflect.Float32, reflect.Float64: - return tFloat.gobType(), nil - - case reflect.Complex64, reflect.Complex128: - return tComplex.gobType(), nil - - case reflect.String: - return tString.gobType(), nil - - case reflect.Interface: - return tInterface.gobType(), nil - - case reflect.Array: - at := newArrayType(name) - types[rt] = at - type0, err = getBaseType("", t.Elem()) - if err != nil { - return nil, err - } - // Historical aside: - // For arrays, maps, and slices, we set the type id after the elements - // are constructed. This is to retain the order of type id allocation after - // a fix made to handle recursive types, which changed the order in - // which types are built. Delaying the setting in this way preserves - // type ids while allowing recursive types to be described. Structs, - // done below, were already handling recursion correctly so they - // assign the top-level id before those of the field. - at.init(type0, t.Len()) - return at, nil - - case reflect.Map: - mt := newMapType(name) - types[rt] = mt - type0, err = getBaseType("", t.Key()) - if err != nil { - return nil, err - } - type1, err = getBaseType("", t.Elem()) - if err != nil { - return nil, err - } - mt.init(type0, type1) - return mt, nil - - case reflect.Slice: - // []byte == []uint8 is a special case - if t.Elem().Kind() == reflect.Uint8 { - return tBytes.gobType(), nil - } - st := newSliceType(name) - types[rt] = st - type0, err = getBaseType(t.Elem().Name(), t.Elem()) - if err != nil { - return nil, err - } - st.init(type0) - return st, nil - - case reflect.Struct: - st := newStructType(name) - types[rt] = st - idToType[st.id()] = st - for i := 0; i < t.NumField(); i++ { - f := t.Field(i) - if !isSent(&f) { - continue - } - typ := userType(f.Type).base - tname := typ.Name() - if tname == "" { - t := userType(f.Type).base - tname = t.String() - } - gt, err := getBaseType(tname, f.Type) - if err != nil { - return nil, err - } - // Some mutually recursive types can cause us to be here while - // still defining the element. Fix the element type id here. - // We could do this more neatly by setting the id at the start of - // building every type, but that would break binary compatibility. - if gt.id() == 0 { - setTypeId(gt) - } - st.Field = append(st.Field, &fieldType{f.Name, gt.id()}) - } - return st, nil - - default: - return nil, errors.New("gob NewTypeObject can't handle type: " + rt.String()) - } -} - -// isExported reports whether this is an exported - upper case - name. -func isExported(name string) bool { - rune, _ := utf8.DecodeRuneInString(name) - return unicode.IsUpper(rune) -} - -// isSent reports whether this struct field is to be transmitted. -// It will be transmitted only if it is exported and not a chan or func field -// or pointer to chan or func. -func isSent(field *reflect.StructField) bool { - if !isExported(field.Name) { - return false - } - // If the field is a chan or func or pointer thereto, don't send it. - // That is, treat it like an unexported field. - typ := field.Type - for typ.Kind() == reflect.Ptr { - typ = typ.Elem() - } - if typ.Kind() == reflect.Chan || typ.Kind() == reflect.Func { - return false - } - return true -} - -// getBaseType returns the Gob type describing the given reflect.Type's base type. -// typeLock must be held. -func getBaseType(name string, rt reflect.Type) (gobType, error) { - ut := userType(rt) - return getType(name, ut, ut.base) -} - -// getType returns the Gob type describing the given reflect.Type. -// Should be called only when handling GobEncoders/Decoders, -// which may be pointers. All other types are handled through the -// base type, never a pointer. -// typeLock must be held. -func getType(name string, ut *userTypeInfo, rt reflect.Type) (gobType, error) { - typ, present := types[rt] - if present { - return typ, nil - } - typ, err := newTypeObject(name, ut, rt) - if err == nil { - types[rt] = typ - } - return typ, err -} - -func checkId(want, got typeId) { - if want != got { - fmt.Fprintf(os.Stderr, "checkId: %d should be %d\n", int(got), int(want)) - panic("bootstrap type wrong id: " + got.name() + " " + got.string() + " not " + want.string()) - } -} - -// used for building the basic types; called only from init(). the incoming -// interface always refers to a pointer. -func bootstrapType(name string, e interface{}, expect typeId) typeId { - rt := reflect.TypeOf(e).Elem() - _, present := types[rt] - if present { - panic("bootstrap type already present: " + name + ", " + rt.String()) - } - typ := &CommonType{Name: name} - types[rt] = typ - setTypeId(typ) - checkId(expect, nextId) - userType(rt) // might as well cache it now - return nextId -} - -// Representation of the information we send and receive about this type. -// Each value we send is preceded by its type definition: an encoded int. -// However, the very first time we send the value, we first send the pair -// (-id, wireType). -// For bootstrapping purposes, we assume that the recipient knows how -// to decode a wireType; it is exactly the wireType struct here, interpreted -// using the gob rules for sending a structure, except that we assume the -// ids for wireType and structType etc. are known. The relevant pieces -// are built in encode.go's init() function. -// To maintain binary compatibility, if you extend this type, always put -// the new fields last. -type wireType struct { - ArrayT *arrayType - SliceT *sliceType - StructT *structType - MapT *mapType - GobEncoderT *gobEncoderType - BinaryMarshalerT *gobEncoderType - TextMarshalerT *gobEncoderType -} - -func (w *wireType) string() string { - const unknown = "unknown type" - if w == nil { - return unknown - } - switch { - case w.ArrayT != nil: - return w.ArrayT.Name - case w.SliceT != nil: - return w.SliceT.Name - case w.StructT != nil: - return w.StructT.Name - case w.MapT != nil: - return w.MapT.Name - case w.GobEncoderT != nil: - return w.GobEncoderT.Name - case w.BinaryMarshalerT != nil: - return w.BinaryMarshalerT.Name - case w.TextMarshalerT != nil: - return w.TextMarshalerT.Name - } - return unknown -} - -type typeInfo struct { - id typeId - encoder *encEngine - wire *wireType -} - -var typeInfoMap = make(map[reflect.Type]*typeInfo) // protected by typeLock - -// typeLock must be held. -func getTypeInfo(ut *userTypeInfo) (*typeInfo, error) { - rt := ut.base - if ut.externalEnc != 0 { - // We want the user type, not the base type. - rt = ut.user - } - info, ok := typeInfoMap[rt] - if ok { - return info, nil - } - info = new(typeInfo) - gt, err := getBaseType(rt.Name(), rt) - if err != nil { - return nil, err - } - info.id = gt.id() - - if ut.externalEnc != 0 { - userType, err := getType(rt.Name(), ut, rt) - if err != nil { - return nil, err - } - gt := userType.id().gobType().(*gobEncoderType) - switch ut.externalEnc { - case xGob: - info.wire = &wireType{GobEncoderT: gt} - case xBinary: - info.wire = &wireType{BinaryMarshalerT: gt} - case xText: - info.wire = &wireType{TextMarshalerT: gt} - } - typeInfoMap[ut.user] = info - return info, nil - } - - t := info.id.gobType() - switch typ := rt; typ.Kind() { - case reflect.Array: - info.wire = &wireType{ArrayT: t.(*arrayType)} - case reflect.Map: - info.wire = &wireType{MapT: t.(*mapType)} - case reflect.Slice: - // []byte == []uint8 is a special case handled separately - if typ.Elem().Kind() != reflect.Uint8 { - info.wire = &wireType{SliceT: t.(*sliceType)} - } - case reflect.Struct: - info.wire = &wireType{StructT: t.(*structType)} - } - typeInfoMap[rt] = info - return info, nil -} - -// Called only when a panic is acceptable and unexpected. -func mustGetTypeInfo(rt reflect.Type) *typeInfo { - t, err := getTypeInfo(userType(rt)) - if err != nil { - panic("getTypeInfo: " + err.Error()) - } - return t -} - -// GobEncoder is the interface describing data that provides its own -// representation for encoding values for transmission to a GobDecoder. -// A type that implements GobEncoder and GobDecoder has complete -// control over the representation of its data and may therefore -// contain things such as private fields, channels, and functions, -// which are not usually transmissible in gob streams. -// -// Note: Since gobs can be stored permanently, It is good design -// to guarantee the encoding used by a GobEncoder is stable as the -// software evolves. For instance, it might make sense for GobEncode -// to include a version number in the encoding. -type GobEncoder interface { - // GobEncode returns a byte slice representing the encoding of the - // receiver for transmission to a GobDecoder, usually of the same - // concrete type. - GobEncode() ([]byte, error) -} - -// GobDecoder is the interface describing data that provides its own -// routine for decoding transmitted values sent by a GobEncoder. -type GobDecoder interface { - // GobDecode overwrites the receiver, which must be a pointer, - // with the value represented by the byte slice, which was written - // by GobEncode, usually for the same concrete type. - GobDecode([]byte) error -} - -var ( - registerLock sync.RWMutex - nameToConcreteType = make(map[string]reflect.Type) - concreteTypeToName = make(map[reflect.Type]string) -) - -// RegisterName is like Register but uses the provided name rather than the -// type's default. -func RegisterName(name string, value interface{}) { - if name == "" { - // reserved for nil - panic("attempt to register empty name") - } - registerLock.Lock() - defer registerLock.Unlock() - ut := userType(reflect.TypeOf(value)) - // Check for incompatible duplicates. The name must refer to the - // same user type, and vice versa. - if t, ok := nameToConcreteType[name]; ok && t != ut.user { - panic(fmt.Sprintf("gob: registering duplicate types for %q: %s != %s", name, t, ut.user)) - } - if n, ok := concreteTypeToName[ut.base]; ok && n != name { - panic(fmt.Sprintf("gob: registering duplicate names for %s: %q != %q", ut.user, n, name)) - } - // Store the name and type provided by the user.... - nameToConcreteType[name] = reflect.TypeOf(value) - // but the flattened type in the type table, since that's what decode needs. - concreteTypeToName[ut.base] = name -} - -// Register records a type, identified by a value for that type, under its -// internal type name. That name will identify the concrete type of a value -// sent or received as an interface variable. Only types that will be -// transferred as implementations of interface values need to be registered. -// Expecting to be used only during initialization, it panics if the mapping -// between types and names is not a bijection. -func Register(value interface{}) { - // Default to printed representation for unnamed types - rt := reflect.TypeOf(value) - name := rt.String() - - // But for named types (or pointers to them), qualify with import path (but see inner comment). - // Dereference one pointer looking for a named type. - star := "" - if rt.Name() == "" { - if pt := rt; pt.Kind() == reflect.Ptr { - star = "*" - // NOTE: The following line should be rt = pt.Elem() to implement - // what the comment above claims, but fixing it would break compatibility - // with existing gobs. - // - // Given package p imported as "full/p" with these definitions: - // package p - // type T1 struct { ... } - // this table shows the intended and actual strings used by gob to - // name the types: - // - // Type Correct string Actual string - // - // T1 full/p.T1 full/p.T1 - // *T1 *full/p.T1 *p.T1 - // - // The missing full path cannot be fixed without breaking existing gob decoders. - rt = pt - } - } - if rt.Name() != "" { - if rt.PkgPath() == "" { - name = star + rt.Name() - } else { - name = star + rt.PkgPath() + "." + rt.Name() - } - } - - RegisterName(name, value) -} - -func registerBasics() { - Register(int(0)) - Register(int8(0)) - Register(int16(0)) - Register(int32(0)) - Register(int64(0)) - Register(uint(0)) - Register(uint8(0)) - Register(uint16(0)) - Register(uint32(0)) - Register(uint64(0)) - Register(float32(0)) - Register(float64(0)) - Register(complex64(0i)) - Register(complex128(0i)) - Register(uintptr(0)) - Register(false) - Register("") - Register([]byte(nil)) - Register([]int(nil)) - Register([]int8(nil)) - Register([]int16(nil)) - Register([]int32(nil)) - Register([]int64(nil)) - Register([]uint(nil)) - Register([]uint8(nil)) - Register([]uint16(nil)) - Register([]uint32(nil)) - Register([]uint64(nil)) - Register([]float32(nil)) - Register([]float64(nil)) - Register([]complex64(nil)) - Register([]complex128(nil)) - Register([]uintptr(nil)) - Register([]bool(nil)) - Register([]string(nil)) -} diff --git a/src/pkg/encoding/gob/type_test.go b/src/pkg/encoding/gob/type_test.go deleted file mode 100644 index e230d22d4..000000000 --- a/src/pkg/encoding/gob/type_test.go +++ /dev/null @@ -1,222 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gob - -import ( - "bytes" - "reflect" - "testing" -) - -type typeT struct { - id typeId - str string -} - -var basicTypes = []typeT{ - {tBool, "bool"}, - {tInt, "int"}, - {tUint, "uint"}, - {tFloat, "float"}, - {tBytes, "bytes"}, - {tString, "string"}, -} - -func getTypeUnlocked(name string, rt reflect.Type) gobType { - typeLock.Lock() - defer typeLock.Unlock() - t, err := getBaseType(name, rt) - if err != nil { - panic("getTypeUnlocked: " + err.Error()) - } - return t -} - -// Sanity checks -func TestBasic(t *testing.T) { - for _, tt := range basicTypes { - if tt.id.string() != tt.str { - t.Errorf("checkType: expected %q got %s", tt.str, tt.id.string()) - } - if tt.id == 0 { - t.Errorf("id for %q is zero", tt.str) - } - } -} - -// Reregister some basic types to check registration is idempotent. -func TestReregistration(t *testing.T) { - newtyp := getTypeUnlocked("int", reflect.TypeOf(int(0))) - if newtyp != tInt.gobType() { - t.Errorf("reregistration of %s got new type", newtyp.string()) - } - newtyp = getTypeUnlocked("uint", reflect.TypeOf(uint(0))) - if newtyp != tUint.gobType() { - t.Errorf("reregistration of %s got new type", newtyp.string()) - } - newtyp = getTypeUnlocked("string", reflect.TypeOf("hello")) - if newtyp != tString.gobType() { - t.Errorf("reregistration of %s got new type", newtyp.string()) - } -} - -func TestArrayType(t *testing.T) { - var a3 [3]int - a3int := getTypeUnlocked("foo", reflect.TypeOf(a3)) - newa3int := getTypeUnlocked("bar", reflect.TypeOf(a3)) - if a3int != newa3int { - t.Errorf("second registration of [3]int creates new type") - } - var a4 [4]int - a4int := getTypeUnlocked("goo", reflect.TypeOf(a4)) - if a3int == a4int { - t.Errorf("registration of [3]int creates same type as [4]int") - } - var b3 [3]bool - a3bool := getTypeUnlocked("", reflect.TypeOf(b3)) - if a3int == a3bool { - t.Errorf("registration of [3]bool creates same type as [3]int") - } - str := a3bool.string() - expected := "[3]bool" - if str != expected { - t.Errorf("array printed as %q; expected %q", str, expected) - } -} - -func TestSliceType(t *testing.T) { - var s []int - sint := getTypeUnlocked("slice", reflect.TypeOf(s)) - var news []int - newsint := getTypeUnlocked("slice1", reflect.TypeOf(news)) - if sint != newsint { - t.Errorf("second registration of []int creates new type") - } - var b []bool - sbool := getTypeUnlocked("", reflect.TypeOf(b)) - if sbool == sint { - t.Errorf("registration of []bool creates same type as []int") - } - str := sbool.string() - expected := "[]bool" - if str != expected { - t.Errorf("slice printed as %q; expected %q", str, expected) - } -} - -func TestMapType(t *testing.T) { - var m map[string]int - mapStringInt := getTypeUnlocked("map", reflect.TypeOf(m)) - var newm map[string]int - newMapStringInt := getTypeUnlocked("map1", reflect.TypeOf(newm)) - if mapStringInt != newMapStringInt { - t.Errorf("second registration of map[string]int creates new type") - } - var b map[string]bool - mapStringBool := getTypeUnlocked("", reflect.TypeOf(b)) - if mapStringBool == mapStringInt { - t.Errorf("registration of map[string]bool creates same type as map[string]int") - } - str := mapStringBool.string() - expected := "map[string]bool" - if str != expected { - t.Errorf("map printed as %q; expected %q", str, expected) - } -} - -type Bar struct { - X string -} - -// This structure has pointers and refers to itself, making it a good test case. -type Foo struct { - A int - B int32 // will become int - C string - D []byte - E *float64 // will become float64 - F ****float64 // will become float64 - G *Bar - H *Bar // should not interpolate the definition of Bar again - I *Foo // will not explode -} - -func TestStructType(t *testing.T) { - sstruct := getTypeUnlocked("Foo", reflect.TypeOf(Foo{})) - str := sstruct.string() - // If we can print it correctly, we built it correctly. - expected := "Foo = struct { A int; B int; C string; D bytes; E float; F float; G Bar = struct { X string; }; H Bar; I Foo; }" - if str != expected { - t.Errorf("struct printed as %q; expected %q", str, expected) - } -} - -// Should be OK to register the same type multiple times, as long as they're -// at the same level of indirection. -func TestRegistration(t *testing.T) { - type T struct{ a int } - Register(new(T)) - Register(new(T)) -} - -type N1 struct{} -type N2 struct{} - -// See comment in type.go/Register. -func TestRegistrationNaming(t *testing.T) { - testCases := []struct { - t interface{} - name string - }{ - {&N1{}, "*gob.N1"}, - {N2{}, "encoding/gob.N2"}, - } - - for _, tc := range testCases { - Register(tc.t) - - tct := reflect.TypeOf(tc.t) - registerLock.RLock() - ct := nameToConcreteType[tc.name] - registerLock.RUnlock() - if ct != tct { - t.Errorf("nameToConcreteType[%q] = %v, want %v", tc.name, ct, tct) - } - // concreteTypeToName is keyed off the base type. - if tct.Kind() == reflect.Ptr { - tct = tct.Elem() - } - if n := concreteTypeToName[tct]; n != tc.name { - t.Errorf("concreteTypeToName[%v] got %v, want %v", tct, n, tc.name) - } - } -} - -func TestStressParallel(t *testing.T) { - type T2 struct{ A int } - c := make(chan bool) - const N = 10 - for i := 0; i < N; i++ { - go func() { - p := new(T2) - Register(p) - b := new(bytes.Buffer) - enc := NewEncoder(b) - err := enc.Encode(p) - if err != nil { - t.Error("encoder fail:", err) - } - dec := NewDecoder(b) - err = dec.Decode(p) - if err != nil { - t.Error("decoder fail:", err) - } - c <- true - }() - } - for i := 0; i < N; i++ { - <-c - } -} |