From 505c19580e0f43fe5224431459cacb7c21edd93d Mon Sep 17 00:00:00 2001 From: Ondřej Surý Date: Fri, 6 Apr 2012 15:14:11 +0200 Subject: Imported Upstream version 1 --- src/pkg/gob/Makefile | 25 - src/pkg/gob/codec_test.go | 1406 ----------------------------------------- src/pkg/gob/debug.go | 686 -------------------- src/pkg/gob/decode.go | 1275 ------------------------------------- src/pkg/gob/decoder.go | 202 ------ src/pkg/gob/doc.go | 363 ----------- src/pkg/gob/dump.go | 22 - src/pkg/gob/encode.go | 717 --------------------- src/pkg/gob/encoder.go | 243 ------- src/pkg/gob/encoder_test.go | 580 ----------------- src/pkg/gob/error.go | 42 -- src/pkg/gob/gobencdec_test.go | 490 -------------- src/pkg/gob/timing_test.go | 94 --- src/pkg/gob/type.go | 786 ----------------------- src/pkg/gob/type_test.go | 153 ----- 15 files changed, 7084 deletions(-) delete mode 100644 src/pkg/gob/Makefile delete mode 100644 src/pkg/gob/codec_test.go delete mode 100644 src/pkg/gob/debug.go delete mode 100644 src/pkg/gob/decode.go delete mode 100644 src/pkg/gob/decoder.go delete mode 100644 src/pkg/gob/doc.go delete mode 100644 src/pkg/gob/dump.go delete mode 100644 src/pkg/gob/encode.go delete mode 100644 src/pkg/gob/encoder.go delete mode 100644 src/pkg/gob/encoder_test.go delete mode 100644 src/pkg/gob/error.go delete mode 100644 src/pkg/gob/gobencdec_test.go delete mode 100644 src/pkg/gob/timing_test.go delete mode 100644 src/pkg/gob/type.go delete mode 100644 src/pkg/gob/type_test.go (limited to 'src/pkg/gob') diff --git a/src/pkg/gob/Makefile b/src/pkg/gob/Makefile deleted file mode 100644 index 68007c189..000000000 --- a/src/pkg/gob/Makefile +++ /dev/null @@ -1,25 +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. - -include ../../Make.inc - -TARG=gob -GOFILES=\ - decode.go\ - decoder.go\ - doc.go\ - encode.go\ - encoder.go\ - error.go\ - type.go\ - -include ../../Make.pkg - -# Help for debugging. Requires adding debug.go to the gob package as well. - -dump: dump.$O - $(LD) -o dump $< - -dump.$O: dump.go - $(GC) $< diff --git a/src/pkg/gob/codec_test.go b/src/pkg/gob/codec_test.go deleted file mode 100644 index a5fb91cda..000000000 --- a/src/pkg/gob/codec_test.go +++ /dev/null @@ -1,1406 +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" - "math" - "os" - "reflect" - "strings" - "testing" - "unsafe" -) - -// 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).Error) // 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 := os.NewError("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{decUint8Array, 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 os.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.String() != `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.String() != `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.String() != `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.String() != `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.String() != `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.String() != `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.String() != `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.String() != `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.String() != `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.String() != `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.String() != `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.String(), "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 Bad0 struct { - CH chan int - C float64 -} - -func TestInvalidField(t *testing.T) { - var bad0 Bad0 - bad0.CH = make(chan int) - b := new(bytes.Buffer) - dummyEncoder := new(Encoder) // sufficient for this purpose. - dummyEncoder.encode(b, reflect.ValueOf(&bad0), userType(reflect.TypeOf(&bad0))) - if err := dummyEncoder.err; err == nil { - t.Error("expected error; got none") - } else if strings.Index(err.String(), "type") < 0 { - t.Error("expected type error; got", err) - } -} - -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) - } - continue - 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 TestDebugStruct(t *testing.T) { - if debugFunc == nil { - return - } - Register(OnTheFly{}) - 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"} - 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) -} diff --git a/src/pkg/gob/debug.go b/src/pkg/gob/debug.go deleted file mode 100644 index ce8a6ff5e..000000000 --- a/src/pkg/gob/debug.go +++ /dev/null @@ -1,686 +0,0 @@ -package gob - -// This file is not normally included in the gob package. Used only for debugging the package itself. -// Add debug.go to the files listed in the Makefile to add Debug to the gob package. -// Except for reading uints, it is an implementation of a reader that is independent of -// the one implemented by Decoder. - -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(": \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 os.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 os.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 = os.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. -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 os.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 == os.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} - 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/gob/decode.go b/src/pkg/gob/decode.go deleted file mode 100644 index bf7cb95f2..000000000 --- a/src/pkg/gob/decode.go +++ /dev/null @@ -1,1275 +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" - "io" - "math" - "os" - "reflect" - "unsafe" -) - -var ( - errBadUint = os.NewError("gob: encoded unsigned integer out of range") - errBadType = os.NewError("gob: unknown type id or corrupted data") - errRange = os.NewError("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) os.Error { - return os.NewError(`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 os.Error) { - width = 1 - _, err = r.Read(buf[0:width]) - if err != nil { - return - } - b := buf[0] - if b <= 0x7f { - return uint64(b), width, nil - } - nb := -int(int8(b)) - if nb > uint64Size { - err = errBadUint - return - } - var n int - n, err = io.ReadFull(r, buf[0:nb]) - if err != nil { - if err == os.EOF { - err = io.ErrUnexpectedEOF - } - return - } - // Could check that the high byte is zero but it's not worth it. - for i := 0; i < n; i++ { - x <<= 8 - x |= uint64(buf[i]) - width++ - } - 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) - } - nb := -int(int8(b)) - if nb > uint64Size { - error(errBadUint) - } - n, err := state.b.Read(state.buf[0:nb]) - 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 i := 0; i < n; i++ { - x <<= 8 - x |= uint64(state.buf[i]) - } - 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 os.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) -} - -// decUint8Array decodes byte array and stores through p a slice header -// describing the data. -// uint8 arrays are encoded as an unsigned count followed by the raw bytes. -func decUint8Array(i *decInstr, state *decoderState, p unsafe.Pointer) { - if i.indir > 0 { - if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new([]uint8)) - } - p = *(*unsafe.Pointer)(p) - } - b := make([]uint8, state.decodeUint()) - state.b.Read(b) - *(*[]uint8)(p) = b -} - -// decString decodes byte array and stores through p a string header -// describing the data. -// Strings are encoded as an unsigned count followed by the raw bytes. -func decString(i *decInstr, state *decoderState, p unsafe.Pointer) { - if i.indir > 0 { - if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(string)) - } - p = *(*unsafe.Pointer)(p) - } - b := make([]byte, state.decodeUint()) - 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 uintptr, indir int) uintptr { - if indir == 0 { - return p - } - up := unsafe.Pointer(p) - if indir > 1 { - up = decIndirect(up, indir) - } - if *(*unsafe.Pointer)(up) == nil { - // Allocate object. - *(*unsafe.Pointer)(up) = unsafe.New(rtyp) - } - return *(*uintptr)(up) -} - -// decodeSingle decodes a top-level value that is not a struct and stores it through p. -// Such values are preceded by a zero, making them have the memory layout of a -// struct field (although with an illegal field number). -func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, p uintptr) (err os.Error) { - indir := ut.indir - if ut.isGobDecoder { - indir = int(ut.decIndir) - } - p = allocate(ut.base, p, indir) - state := dec.newDecoderState(&dec.buf) - state.fieldnum = singletonField - basep := p - delta := int(state.decodeUint()) - if delta != 0 { - errorf("decode: corrupted data: non-zero delta for singleton") - } - instr := &engine.instr[singletonField] - ptr := unsafe.Pointer(basep) // offset will be zero - if instr.indir > 1 { - ptr = decIndirect(ptr, instr.indir) - } - instr.op(instr, state, ptr) - dec.freeDecoderState(state) - return nil -} - -// decodeSingle decodes a top-level struct and stores it through p. -// Indir is for the value, not the type. At the time of the call it may -// differ from ut.indir, which was computed when the engine was built. -// This state cannot arise for decodeSingle, which is called directly -// from the user's value, not from the innards of an engine. -func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p uintptr, 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(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 uintptr, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl os.Error) { - instr := &decInstr{elemOp, 0, elemIndir, 0, ovfl} - for i := 0; i < length; i++ { - up := unsafe.Pointer(p) - if elemIndir > 1 { - up = decIndirect(up, elemIndir) - } - elemOp(instr, state, up) - p += uintptr(elemWid) - } -} - -// decodeArray decodes an array and stores it through p, that is, p points to the zeroth element. -// The length is an unsigned integer preceding the elements. Even though the length is redundant -// (it's part of the type), it's a useful check and is included in the encoding. -func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, length, indir, elemIndir int, ovfl os.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 os.Error) reflect.Value { - instr := &decInstr{op, 0, indir, 0, ovfl} - up := unsafe.Pointer(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 uintptr, keyOp, elemOp decOp, indir, keyIndir, elemIndir int, ovfl os.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.ValueOf(unsafe.Unreflect(mtyp, unsafe.Pointer(p))) - 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, os.NewError("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, os.NewError("no error")} - elemInstr := &decInstr{elemOp, 0, 0, 0, os.NewError("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 uintptr, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl os.Error) { - n := int(uintptr(state.decodeUint())) - if indir > 0 { - up := unsafe.Pointer(p) - if *(*unsafe.Pointer)(up) == nil { - // Allocate the slice header. - *(*unsafe.Pointer)(up) = unsafe.Pointer(new([]unsafe.Pointer)) - } - p = *(*uintptr)(up) - } - // Allocate storage for the slice elements, that is, the underlying array. - // Always write a header at p. - hdrp := (*reflect.SliceHeader)(unsafe.Pointer(p)) - hdrp.Data = uintptr(unsafe.NewArray(atyp.Elem(), n)) - hdrp.Len = n - hdrp.Cap = n - dec.decodeArrayHelper(state, 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("cannot assign value of type %s to %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 uintptr, 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. - b := make([]byte, state.decodeUint()) - 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. - *(*[2]uintptr)(unsafe.Pointer(p)) = ivalue.InterfaceData() - return - } - // The concrete type must be registered. - typ, ok := nameToConcreteType[name] - 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(state *decoderState, v reflect.Value) { - // Read the bytes for the value. - b := make([]byte, state.decodeUint()) - _, err := state.b.Read(b) - if err != nil { - error(err) - } - // We know it's a GobDecoder, so just call the method directly. - err = v.Interface().(GobDecoder).GobDecode(b) - 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.isGobDecoder { - return dec.gobDecodeOpFor(ut) - } - // If this type is already in progress, it's a recursive type (e.g. map[string]*T). - // Return the pointer to the op we're already building. - if opPtr := inProgress[rt]; opPtr != nil { - 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, uintptr(p), *elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl) - } - - case reflect.Map: - name = "element of " + name - keyId := dec.wireType[wireId].MapT.Key - elemId := dec.wireType[wireId].MapT.Elem - keyOp, keyIndir := dec.decOpFor(keyId, t.Key(), name, inProgress) - elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress) - ovfl := overflow(name) - op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { - up := unsafe.Pointer(p) - state.dec.decodeMap(t, state, uintptr(up), *keyOp, *elemOp, i.indir, keyIndir, elemIndir, ovfl) - } - - case reflect.Slice: - name = "element of " + name - if t.Elem().Kind() == reflect.Uint8 { - op = decUint8Array - 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, uintptr(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), uintptr(p), i.indir) - } - case reflect.Interface: - op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { - state.dec.decodeInterface(t, state, uintptr(p), i.indir) - } - } - } - if op == nil { - errorf("decode can't handle type %s", rt.String()) - } - 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: - 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.New(ut.base) - } - } - // 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.ValueOf(unsafe.Unreflect(rcvrType, unsafe.Pointer(&p))) - } else { - v = reflect.ValueOf(unsafe.Unreflect(rcvrType, p)) - } - state.dec.decodeGobDecoder(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 fr is a GobDecoder, the wire type must be GobEncoder. - // And if fr is not a GobDecoder, the wire type must not be either. - if ut.isGobDecoder != (ok && wire.GobEncoderT != nil) { // the parentheses look odd but are correct. - return false - } - if ut.isGobDecoder { // This test trumps all others. - return true - } - switch t := ut.base; 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 { - sw = dec.wireType[fw].SliceT - } - elem := userType(t.Elem()).base - return sw != nil && dec.compatibleType(elem, sw.Elem, inProgress) - case reflect.Struct: - return true - } - 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 os.Error) { - rt := ut.base - if ut.isGobDecoder { - rt = ut.user - } - engine = new(decEngine) - engine.instr = make([]decInstr, 1) // one item - name := rt.String() // best we can do - if !dec.compatibleType(rt, remoteId, make(map[reflect.Type]typeId)) { - return nil, os.NewError("gob: wrong type received for local value " + name + ": " + dec.typeString(remoteId)) - } - op, indir := dec.decOpFor(remoteId, rt, name, make(map[reflect.Type]*decOp)) - ovfl := os.NewError(`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 os.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 os.Error) { - rt := ut.base - srt := rt - if srt.Kind() != reflect.Struct || - ut.isGobDecoder { - return dec.compileSingle(remoteId, ut) - } - var wireStruct *structType - // Builtin types can come from global pool; the rest must be defined by the decoder. - // 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.String()) - } - 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 os.Error) { - rt := ut.base - 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 { - decoderMap[remoteId] = nil, false - } - } - 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 os.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 { - dec.ignorerCache[wireId] = nil, false - } - } - 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 struct 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.isGobDecoder { - if engine.numInstr == 0 && st.NumField() > 0 && len(dec.wireType[wireId].StructT.Field) > 0 { - name := base.Name() - errorf("type mismatch: no fields matched compiling decoder for %s", name) - } - dec.decodeStruct(engine, ut, uintptr(unsafeAddr(val)), ut.indir) - } else { - dec.decodeSingle(engine, ut, uintptr(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) uintptr { - if v.CanAddr() { - return v.UnsafeAddr() - } - x := reflect.New(v.Type()).Elem() - x.Set(v) - return 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/gob/decoder.go b/src/pkg/gob/decoder.go deleted file mode 100644 index 281947132..000000000 --- a/src/pkg/gob/decoder.go +++ /dev/null @@ -1,202 +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" - "io" - "os" - "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 os.Error -} - -// NewDecoder returns a new decoder that reads from the io.Reader. -func NewDecoder(r io.Reader) *Decoder { - dec := new(Decoder) - dec.r = bufio.NewReader(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 = os.NewError("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 -} - -// 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 - } - 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 buffer. - if cap(dec.tmp) < nbytes { - dec.tmp = make([]byte, nbytes+100) // room to grow - } - dec.tmp = dec.tmp[:nbytes] - - // Read the data - _, dec.err = io.ReadFull(dec.r, dec.tmp) - if dec.err != nil { - if dec.err == os.EOF { - dec.err = io.ErrUnexpectedEOF - } - return - } - dec.buf.Write(dec.tmp) -} - -// 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 -// simply 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 = os.NewError("extra data in buffer") - break - } - dec.nextUint() - } - } - return -1 -} - -// Decode reads the next value from the connection 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. -func (dec *Decoder) Decode(e interface{}) os.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 = os.NewError("gob: attempt to decode into a non-pointer") - return dec.err - } - return dec.DecodeValue(value) -} - -// DecodeValue reads the next value from the connection. -// 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()) -func (dec *Decoder) DecodeValue(v reflect.Value) os.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 os.NewError("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/gob/doc.go b/src/pkg/gob/doc.go deleted file mode 100644 index a9284ced7..000000000 --- a/src/pkg/gob/doc.go +++ /dev/null @@ -1,363 +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". - -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. - -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. Strings and arrays of bytes are -supported with a special, efficient representation (see below). - -Functions and channels cannot be sent in a gob. Attempting -to encode a value that contains one will fail. - -The rest of this comment 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 man 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 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://blog.golang.org/2011/03/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[0].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/gob/dump.go b/src/pkg/gob/dump.go deleted file mode 100644 index 1555f0fbb..000000000 --- a/src/pkg/gob/dump.go +++ /dev/null @@ -1,22 +0,0 @@ -package main - -// Need to compile package gob with debug.go to build this program. - -import ( - "fmt" - "gob" - "os" -) - -func main() { - var err os.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/gob/encode.go b/src/pkg/gob/encode.go deleted file mode 100644 index 317014efd..000000000 --- a/src/pkg/gob/encode.go +++ /dev/null @@ -1,717 +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" - "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 - } - var n, m int - m = uint64Size - for n = 1; x > 0; n++ { - state.buf[m] = uint8(x) - x >>= 8 - m-- - } - state.buf[m] = uint8(-(n - 1)) - n, err := state.b.Write(state.buf[m : 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 uintptr) { - 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 := unsafe.Pointer(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 uintptr) { - state := enc.newEncoderState(b) - state.fieldnum = -1 - for i := 0; i < len(engine.instr); i++ { - instr := &engine.instr[i] - p := unsafe.Pointer(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 uintptr, 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 - up := unsafe.Pointer(elemp) - if elemIndir > 0 { - if up = encIndirect(up, elemIndir); up == nil { - errorf("encodeArray: nil element") - } - elemp = uintptr(up) - } - op(nil, state, unsafe.Pointer(elemp)) - p += uintptr(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, unsafe.Pointer(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) { - state := enc.newEncoderState(b) - state.fieldnum = -1 - state.sendZero = true - if iv.IsNil() { - state.encodeUint(0) - return - } - - ut := userType(iv.Elem().Type()) - name, ok := concreteTypeToName[ut.base] - 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) - enc.encode(data, iv.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 returns whether the value is the zero of its type. -func isZero(val reflect.Value) bool { - switch val.Kind() { - case reflect.Array, 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.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 - } - 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, v reflect.Value) { - // TODO: should we catch panics from the called method? - // We know it's a GobEncoder, so just call the method directly. - data, err := v.Interface().(GobEncoder).GobEncode() - 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.isGobEncoder { - 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, indir := 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, slice.Data, *elemOp, t.Elem().Size(), indir, int(slice.Len)) - } - case reflect.Array: - // True arrays have size in the type. - elemOp, indir := enc.encOpFor(t.Elem(), inProgress) - op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { - state.update(i) - state.enc.encodeArray(state.b, uintptr(p), *elemOp, t.Elem().Size(), indir, 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.ValueOf(unsafe.Unreflect(t, unsafe.Pointer(p))) - 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, uintptr(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.ValueOf(unsafe.Unreflect(t, unsafe.Pointer(p))) - 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.String()) - } - 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.ValueOf(unsafe.Unreflect(rt, unsafe.Pointer(&p))) - } else { - v = reflect.ValueOf(unsafe.Unreflect(rt, p)) - } - if !state.sendZero && isZero(v) { - return - } - state.update(i) - state.enc.encodeGobEncoder(state.b, 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.isGobEncoder { - rt = ut.user - } - if !ut.isGobEncoder && - srt.Kind() == reflect.Struct { - for fieldNum, wireFieldNum := 0, 0; fieldNum < srt.NumField(); fieldNum++ { - f := srt.Field(fieldNum) - if !isExported(f.Name) { - 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 { - // mark this engine as underway before compiling to handle recursive types. - info.encoder = new(encEngine) - info.encoder = enc.compileEnc(ut) - } - 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.isGobEncoder { - indir = int(ut.encIndir) - } - for i := 0; i < indir; i++ { - value = reflect.Indirect(value) - } - if !ut.isGobEncoder && value.Type().Kind() == reflect.Struct { - enc.encodeStruct(b, engine, unsafeAddr(value)) - } else { - enc.encodeSingle(b, engine, unsafeAddr(value)) - } -} diff --git a/src/pkg/gob/encoder.go b/src/pkg/gob/encoder.go deleted file mode 100644 index 96101d92b..000000000 --- a/src/pkg/gob/encoder.go +++ /dev/null @@ -1,243 +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" - "os" - "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 - buf []byte // for collecting the output. - byteBuf bytes.Buffer // buffer for top-level encoderState - err os.Error -} - -// 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) badType(rt reflect.Type) { - enc.setError(os.NewError("gob: can't encode type " + rt.String())) -} - -func (enc *Encoder) setError(err os.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) { - enc.countState.encodeUint(uint64(b.Len())) - // Build the buffer. - countLen := enc.countState.b.Len() - total := countLen + b.Len() - if total > len(enc.buf) { - enc.buf = make([]byte, total+1000) // extra for growth - } - // Place the length before the data. - // TODO(r): avoid the extra copy here. - enc.countState.b.Read(enc.buf[0:countLen]) - // Now the data. - b.Read(enc.buf[countLen:total]) - // Write the data. - _, err := w.Write(enc.buf[0:total]) - 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++ { - 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.isGobEncoder { - // The rules are different: regardless of the underlying type's representation, - // we need to tell the other side that this exact type is a GobEncoder. - return enc.sendActualType(w, state, ut, ut.user) - } - - // 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: - // Probably a bad field in a struct. - enc.badType(rt) - 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{}) os.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.isGobEncoder { - 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) os.Error { - // 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() - 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/gob/encoder_test.go b/src/pkg/gob/encoder_test.go deleted file mode 100644 index f5ee423cb..000000000 --- a/src/pkg/gob/encoder_test.go +++ /dev/null @@ -1,580 +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" - "os" - "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 os.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("", os.EOF, t) - corruptDataCheck("\x7Fhi", io.ErrUnexpectedEOF, t) - corruptDataCheck("\x03now is the time for all good men", errBadType, t) -} - -// Types not supported 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{}) os.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.String(), "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, "wrong 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.String(), 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.String(), "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.String(), "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) os.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"}, - } - buf := bytes.NewBuffer(nil) - enc := NewEncoder(buf) - err := enc.Encode(m) - if err != nil { - t.Errorf("gob.Encode map: %s", err) - } -} diff --git a/src/pkg/gob/error.go b/src/pkg/gob/error.go deleted file mode 100644 index bfd38fc16..000000000 --- a/src/pkg/gob/error.go +++ /dev/null @@ -1,42 +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" - "os" -) - -// 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 os.Error returns. Encoding and -// decoding functions and methods that do not return an os.Error either use -// panic to report an error or are guaranteed error-free. - -// A gobError wraps an os.Error and is used to distinguish errors (panics) generated in this package. -type gobError struct { - os.Error -} - -// errorf is like error but takes Printf-style arguments to construct an os.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 os.Error) { - panic(gobError{Error: err}) -} - -// catchError is meant to be used as a deferred function to turn a panic(gobError) into a -// plain os.Error. It overwrites the error return of the function that deferred its call. -func catchError(err *os.Error) { - if e := recover(); e != nil { - *err = e.(gobError).Error // Will re-panic if not one of our errors, such as a runtime error. - } - return -} diff --git a/src/pkg/gob/gobencdec_test.go b/src/pkg/gob/gobencdec_test.go deleted file mode 100644 index 371a43c8f..000000000 --- a/src/pkg/gob/gobencdec_test.go +++ /dev/null @@ -1,490 +0,0 @@ -// Copyright 20011 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" - "fmt" - "os" - "strings" - "testing" -) - -// 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. - -// The relevant methods - -func (g *ByteStruct) GobEncode() ([]byte, os.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) os.Error { - if g == nil { - return os.NewError("NIL RECEIVER") - } - // Expect N sequential-valued bytes. - if len(data) == 0 { - return os.EOF - } - g.a = data[0] - for i, c := range data { - if c != g.a+byte(i) { - return os.NewError("invalid data sequence") - } - } - return nil -} - -func (g *StringStruct) GobEncode() ([]byte, os.Error) { - return []byte(g.s), nil -} - -func (g *StringStruct) GobDecode(data []byte) os.Error { - // Expect N sequential-valued bytes. - if len(data) == 0 { - return os.EOF - } - a := data[0] - for i, c := range data { - if c != a+byte(i) { - return os.NewError("invalid data sequence") - } - } - g.s = string(data) - return nil -} - -func (a *ArrayStruct) GobEncode() ([]byte, os.Error) { - return a.a[:], nil -} - -func (a *ArrayStruct) GobDecode(data []byte) os.Error { - if len(data) != len(a.a) { - return os.NewError("wrong length in array decode") - } - copy(a.a[:], data) - return nil -} - -func (g *Gobber) GobEncode() ([]byte, os.Error) { - return []byte(fmt.Sprintf("VALUE=%d", *g)), nil -} - -func (g *Gobber) GobDecode(data []byte) os.Error { - _, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g)) - return err -} - -func (v ValueGobber) GobEncode() ([]byte, os.Error) { - return []byte(fmt.Sprintf("VALUE=%s", v)), nil -} - -func (v *ValueGobber) GobDecode(data []byte) os.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 -} - -type GobTest4 struct { - X int // guarantee we have something in common with GobTest* - V ValueGobber -} - -type GobTest5 struct { - X int // guarantee we have something in common with GobTest* - V *ValueGobber -} - -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) - err = enc.Encode(GobTest3{17, &gobber}) - 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 { - 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 %c", 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")}) - 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" { - t.Errorf("expected `hello` got %s", x.V) - } -} - -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.String(), "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.String(), "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 %c", 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) - err := enc.Encode(GobTest3{17, &gobber}) - 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) - } -} diff --git a/src/pkg/gob/timing_test.go b/src/pkg/gob/timing_test.go deleted file mode 100644 index 2a2be7336..000000000 --- a/src/pkg/gob/timing_test.go +++ /dev/null @@ -1,94 +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" - "fmt" - "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 { - panic("can't get pipe:" + err.String()) - } - benchmarkEndToEnd(r, w, b) -} - -func BenchmarkEndToEndByteBuffer(b *testing.B) { - var buf bytes.Buffer - benchmarkEndToEnd(&buf, &buf, b) -} - -func TestCountEncodeMallocs(t *testing.T) { - var buf bytes.Buffer - enc := NewEncoder(&buf) - bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")} - runtime.UpdateMemStats() - mallocs := 0 - runtime.MemStats.Mallocs - const count = 1000 - for i := 0; i < count; i++ { - err := enc.Encode(bench) - if err != nil { - t.Fatal("encode:", err) - } - } - runtime.UpdateMemStats() - mallocs += runtime.MemStats.Mallocs - fmt.Printf("mallocs per encode of type Bench: %d\n", mallocs/count) -} - -func TestCountDecodeMallocs(t *testing.T) { - var buf bytes.Buffer - enc := NewEncoder(&buf) - bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")} - const count = 1000 - for i := 0; i < count; i++ { - err := enc.Encode(bench) - if err != nil { - t.Fatal("encode:", err) - } - } - dec := NewDecoder(&buf) - runtime.UpdateMemStats() - mallocs := 0 - runtime.MemStats.Mallocs - for i := 0; i < count; i++ { - *bench = Bench{} - err := dec.Decode(&bench) - if err != nil { - t.Fatal("decode:", err) - } - } - runtime.UpdateMemStats() - mallocs += runtime.MemStats.Mallocs - fmt.Printf("mallocs per decode of type Bench: %d\n", mallocs/count) -} diff --git a/src/pkg/gob/type.go b/src/pkg/gob/type.go deleted file mode 100644 index b2f716c4b..000000000 --- a/src/pkg/gob/type.go +++ /dev/null @@ -1,786 +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" - "os" - "reflect" - "sync" - "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 - isGobEncoder bool // does the type implement GobEncoder? - isGobDecoder bool // does the type implement GobDecoder? - 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 -} - -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 os.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, os.NewError("can't represent recursive pointer type " + ut.base.String()) - } - if ut.indir%2 == 0 { - slowpoke = slowpoke.Elem() - } - ut.indir++ - } - ut.isGobEncoder, ut.encIndir = implementsInterface(ut.user, gobEncoderInterfaceType) - ut.isGobDecoder, ut.decIndir = implementsInterface(ut.user, gobDecoderInterfaceType) - userTypeCache[rt] = ut - return -} - -var ( - gobEncoderInterfaceType = reflect.TypeOf((*GobEncoder)(nil)).Elem() - gobDecoderInterfaceType = reflect.TypeOf((*GobDecoder)(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) { - 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 "" - } - 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 "" - } - return t.gobType().name() -} - -// Common elements of all types. -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) - 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 "" - } - 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, os.Error) { - // Does this type implement GobEncoder? - if ut.isGobEncoder { - return newGobEncoderType(name), nil - } - var err os.Error - var type0, type1 gobType - defer func() { - if err != nil { - types[rt] = nil, false - } - }() - // 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 !isExported(f.Name) { - 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 - } - st.Field = append(st.Field, &fieldType{f.Name, gt.id()}) - } - return st, nil - - default: - return nil, os.NewError("gob NewTypeObject can't handle type: " + rt.String()) - } - return nil, nil -} - -// isExported reports whether this is an exported - upper case - name. -func isExported(name string) bool { - rune, _ := utf8.DecodeRuneInString(name) - return unicode.IsUpper(rune) -} - -// 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, os.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, os.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 -} - -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 - } - 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, os.Error) { - rt := ut.base - if ut.isGobEncoder { - // 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.isGobEncoder { - userType, err := getType(rt.Name(), ut, rt) - if err != nil { - return nil, err - } - info.wire = &wireType{GobEncoderT: userType.id().gobType().(*gobEncoderType)} - 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.String()) - } - 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, os.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) os.Error -} - -var ( - 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") - } - base := userType(reflect.TypeOf(value)).base - // Check for incompatible duplicates. - if t, ok := nameToConcreteType[name]; ok && t != base { - panic("gob: registering duplicate types for " + name) - } - if n, ok := concreteTypeToName[base]; ok && n != name { - panic("gob: registering duplicate names for " + base.String()) - } - // 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[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. - // Dereference one pointer looking for a named type. - star := "" - if rt.Name() == "" { - if pt := rt; pt.Kind() == reflect.Ptr { - star = "*" - 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/gob/type_test.go b/src/pkg/gob/type_test.go deleted file mode 100644 index 411ffb797..000000000 --- a/src/pkg/gob/type_test.go +++ /dev/null @@ -1,153 +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 ( - "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.String()) - } - 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) - } -} -- cgit v1.2.3