diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libgo/go/gob | |
download | cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2 cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'libgo/go/gob')
-rw-r--r-- | libgo/go/gob/codec_test.go | 1355 | ||||
-rw-r--r-- | libgo/go/gob/decode.go | 1020 | ||||
-rw-r--r-- | libgo/go/gob/decoder.go | 164 | ||||
-rw-r--r-- | libgo/go/gob/doc.go | 307 | ||||
-rw-r--r-- | libgo/go/gob/encode.go | 573 | ||||
-rw-r--r-- | libgo/go/gob/encoder.go | 207 | ||||
-rw-r--r-- | libgo/go/gob/encoder_test.go | 385 | ||||
-rw-r--r-- | libgo/go/gob/error.go | 41 | ||||
-rw-r--r-- | libgo/go/gob/type.go | 539 | ||||
-rw-r--r-- | libgo/go/gob/type_test.go | 153 |
10 files changed, 4744 insertions, 0 deletions
diff --git a/libgo/go/gob/codec_test.go b/libgo/go/gob/codec_test.go new file mode 100644 index 000000000..af941c629 --- /dev/null +++ b/libgo/go/gob/codec_test.go @@ -0,0 +1,1355 @@ +// 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(nil, 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(nil, &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(nil, b) + encState.encodeInt(i) + decState := newDecodeState(nil, &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 newencoderState(b *bytes.Buffer) *encoderState { + b.Reset() + state := newEncoderState(nil, 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 *decodeState, 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) *decodeState { + b := bytes.NewBuffer(data) + state := newDecodeState(nil, &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.ErrorString("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{decOpMap[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{decOpMap[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{decOpMap[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{decOpMap[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{decOpMap[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 + 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}, + 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) + } +} + +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) + } +} + +type Bad0 struct { + ch chan int + c float64 +} + +var nilEncoder *Encoder + +func TestInvalidField(t *testing.T) { + var bad0 Bad0 + bad0.ch = make(chan int) + b := new(bytes.Buffer) + err := nilEncoder.encode(b, reflect.NewValue(&bad0)) + if 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 { + a, b int +} + +func (p Point) Square() int { + return p.a*p.a + p.b*p.b +} + +// 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(0i), complex128(0i), + 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") + } +} + +// 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 TestDebug(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/libgo/go/gob/decode.go b/libgo/go/gob/decode.go new file mode 100644 index 000000000..2db75215c --- /dev/null +++ b/libgo/go/gob/decode.go @@ -0,0 +1,1020 @@ +// 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" + "unicode" + "unsafe" + "utf8" +) + +var ( + errBadUint = os.ErrorString("gob: encoded unsigned integer out of range") + errBadType = os.ErrorString("gob: unknown type id or corrupted data") + errRange = os.ErrorString("gob: internal error: field numbers out of bounds") +) + +// The execution state of an instance of the decoder. A new state +// is created for nested objects. +type decodeState 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 +} + +func newDecodeState(dec *Decoder, b **bytes.Buffer) *decodeState { + d := new(decodeState) + d.dec = dec + d.b = b + d.buf = make([]byte, uint64Size) + return d +} + +func overflow(name string) os.ErrorString { + return os.ErrorString(`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, err os.Error) { + _, err = r.Read(buf[0:1]) + if err != nil { + return + } + b := buf[0] + if b <= 0x7f { + return uint64(b), 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]) + } + return +} + +// decodeUint reads an encoded unsigned integer from state.r. +// Does not check for overflow. +func (state *decodeState) 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 *decodeState) decodeInt() int64 { + x := state.decodeUint() + if x&1 != 0 { + return ^int64(x >> 1) + } + return int64(x >> 1) +} + +type decOp func(i *decInstr, state *decodeState, 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.ErrorString // 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 +} + +func ignoreUint(i *decInstr, state *decodeState, p unsafe.Pointer) { + state.decodeUint() +} + +func ignoreTwoUints(i *decInstr, state *decodeState, p unsafe.Pointer) { + state.decodeUint() + state.decodeUint() +} + +func decBool(i *decInstr, state *decodeState, 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.decodeInt() != 0 +} + +func decInt8(i *decInstr, state *decodeState, 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) + } +} + +func decUint8(i *decInstr, state *decodeState, 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) + } +} + +func decInt16(i *decInstr, state *decodeState, 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) + } +} + +func decUint16(i *decInstr, state *decodeState, 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) + } +} + +func decInt32(i *decInstr, state *decodeState, 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) + } +} + +func decUint32(i *decInstr, state *decodeState, 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) + } +} + +func decInt64(i *decInstr, state *decodeState, 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()) +} + +func decUint64(i *decInstr, state *decodeState, 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) +} + +func storeFloat32(i *decInstr, state *decodeState, 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) + } +} + +func decFloat32(i *decInstr, state *decodeState, 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) +} + +func decFloat64(i *decInstr, state *decodeState, 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())) +} + +// Complex numbers are just a pair of floating-point numbers, real part first. +func decComplex64(i *decInstr, state *decodeState, 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)+uintptr(unsafe.Sizeof(float32(0))))) +} + +func decComplex128(i *decInstr, state *decodeState, 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) +} + +// uint8 arrays are encoded as an unsigned count followed by the raw bytes. +func decUint8Array(i *decInstr, state *decodeState, 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 +} + +// Strings are encoded as an unsigned count followed by the raw bytes. +func decString(i *decInstr, state *decodeState, p unsafe.Pointer) { + if i.indir > 0 { + if *(*unsafe.Pointer)(p) == nil { + *(*unsafe.Pointer)(p) = unsafe.Pointer(new([]byte)) + } + p = *(*unsafe.Pointer)(p) + } + b := make([]byte, state.decodeUint()) + state.b.Read(b) + *(*string)(p) = string(b) +} + +func ignoreUint8Array(i *decInstr, state *decodeState, 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) +} + +func (dec *Decoder) decodeSingle(engine *decEngine, rtyp reflect.Type, b **bytes.Buffer, p uintptr, indir int) (err os.Error) { + defer catchError(&err) + p = allocate(rtyp, p, indir) + state := newDecodeState(dec, b) + state.fieldnum = singletonField + basep := p + delta := int(state.decodeUint()) + if delta != 0 { + errorf("gob 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) + return nil +} + +func (dec *Decoder) decodeStruct(engine *decEngine, rtyp *reflect.StructType, b **bytes.Buffer, p uintptr, indir int) (err os.Error) { + defer catchError(&err) + p = allocate(rtyp, p, indir) + state := newDecodeState(dec, b) + state.fieldnum = -1 + basep := p + for state.b.Len() > 0 { + delta := int(state.decodeUint()) + if delta < 0 { + errorf("gob 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 + } + return nil +} + +func (dec *Decoder) ignoreStruct(engine *decEngine, b **bytes.Buffer) (err os.Error) { + defer catchError(&err) + state := newDecodeState(dec, b) + state.fieldnum = -1 + for state.b.Len() > 0 { + delta := int(state.decodeUint()) + if delta < 0 { + errorf("gob 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 + } + return nil +} + +func (dec *Decoder) decodeArrayHelper(state *decodeState, p uintptr, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl os.ErrorString) { + 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) + } +} + +func (dec *Decoder) decodeArray(atyp *reflect.ArrayType, state *decodeState, p uintptr, elemOp decOp, elemWid uintptr, length, indir, elemIndir int, ovfl os.ErrorString) { + 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("gob: length mismatch in decodeArray") + } + dec.decodeArrayHelper(state, p, elemOp, elemWid, length, elemIndir, ovfl) +} + +func decodeIntoValue(state *decodeState, op decOp, indir int, v reflect.Value, ovfl os.ErrorString) reflect.Value { + instr := &decInstr{op, 0, indir, 0, ovfl} + up := unsafe.Pointer(v.Addr()) + if indir > 1 { + up = decIndirect(up, indir) + } + op(instr, state, up) + return v +} + +func (dec *Decoder) decodeMap(mtyp *reflect.MapType, state *decodeState, p uintptr, keyOp, elemOp decOp, indir, keyIndir, elemIndir int, ovfl os.ErrorString) { + 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).Get()) + } + // 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.NewValue(unsafe.Unreflect(mtyp, unsafe.Pointer((p)))).(*reflect.MapValue) + n := int(state.decodeUint()) + for i := 0; i < n; i++ { + key := decodeIntoValue(state, keyOp, keyIndir, reflect.MakeZero(mtyp.Key()), ovfl) + elem := decodeIntoValue(state, elemOp, elemIndir, reflect.MakeZero(mtyp.Elem()), ovfl) + v.SetElem(key, elem) + } +} + +func (dec *Decoder) ignoreArrayHelper(state *decodeState, elemOp decOp, length int) { + instr := &decInstr{elemOp, 0, 0, 0, os.ErrorString("no error")} + for i := 0; i < length; i++ { + elemOp(instr, state, nil) + } +} + +func (dec *Decoder) ignoreArray(state *decodeState, elemOp decOp, length int) { + if n := state.decodeUint(); n != uint64(length) { + errorf("gob: length mismatch in ignoreArray") + } + dec.ignoreArrayHelper(state, elemOp, length) +} + +func (dec *Decoder) ignoreMap(state *decodeState, keyOp, elemOp decOp) { + n := int(state.decodeUint()) + keyInstr := &decInstr{keyOp, 0, 0, 0, os.ErrorString("no error")} + elemInstr := &decInstr{elemOp, 0, 0, 0, os.ErrorString("no error")} + for i := 0; i < n; i++ { + keyOp(keyInstr, state, nil) + elemOp(elemInstr, state, nil) + } +} + +func (dec *Decoder) decodeSlice(atyp *reflect.SliceType, state *decodeState, p uintptr, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl os.ErrorString) { + 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) +} + +func (dec *Decoder) ignoreSlice(state *decodeState, elemOp decOp) { + dec.ignoreArrayHelper(state, elemOp, int(state.decodeUint())) +} + +// setInterfaceValue sets an interface value to a concrete value through +// reflection. If the concrete value does not implement the interface, the +// setting will panic. This routine turns the panic into an error return. +// This dance avoids manually checking that the value satisfies the +// interface. +// TODO(rsc): avoid panic+recover after fixing issue 327. +func setInterfaceValue(ivalue *reflect.InterfaceValue, value reflect.Value) { + defer func() { + if e := recover(); e != nil { + error(e.(os.Error)) + } + }() + ivalue.Set(value) +} + +// decodeInterface receives the name of a concrete type followed by its value. +// If the name is empty, the value is nil and no value is sent. +func (dec *Decoder) decodeInterface(ityp *reflect.InterfaceType, state *decodeState, p uintptr, indir int) { + // Create an interface reflect.Value. We need one even for the nil case. + ivalue := reflect.MakeZero(ityp).(*reflect.InterfaceValue) + // 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.Get() + return + } + // The concrete type must be registered. + typ, ok := nameToConcreteType[name] + if !ok { + errorf("gob: name not registered for interface: %q", name) + } + // Read the concrete value. + value := reflect.MakeZero(typ) + dec.decodeValueFromBuffer(value, false, true) + 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.Get() +} + +func (dec *Decoder) ignoreInterface(state *decodeState) { + // Read the name of the concrete type. + b := make([]byte, state.decodeUint()) + _, err := state.b.Read(b) + if err != nil { + error(err) + } + dec.decodeValueFromBuffer(nil, true, true) + if dec.err != nil { + error(err) + } +} + +// Index by Go types. +var decOpMap = []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, +} + +// Return 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) (decOp, int) { + typ, indir := indirect(rt) + var op decOp + k := typ.Kind() + if int(k) < len(decOpMap) { + op = decOpMap[k] + } + if op == nil { + // Special cases + switch t := typ.(type) { + case *reflect.ArrayType: + name = "element of " + name + elemId := dec.wireType[wireId].ArrayT.Elem + elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name) + ovfl := overflow(name) + op = func(i *decInstr, state *decodeState, p unsafe.Pointer) { + state.dec.decodeArray(t, state, uintptr(p), elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl) + } + + case *reflect.MapType: + name = "element of " + name + keyId := dec.wireType[wireId].MapT.Key + elemId := dec.wireType[wireId].MapT.Elem + keyOp, keyIndir := dec.decOpFor(keyId, t.Key(), name) + elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name) + ovfl := overflow(name) + op = func(i *decInstr, state *decodeState, p unsafe.Pointer) { + up := unsafe.Pointer(p) + state.dec.decodeMap(t, state, uintptr(up), keyOp, elemOp, i.indir, keyIndir, elemIndir, ovfl) + } + + case *reflect.SliceType: + 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) + ovfl := overflow(name) + op = func(i *decInstr, state *decodeState, p unsafe.Pointer) { + state.dec.decodeSlice(t, state, uintptr(p), elemOp, t.Elem().Size(), i.indir, elemIndir, ovfl) + } + + case *reflect.StructType: + // Generate a closure that calls out to the engine for the nested type. + enginePtr, err := dec.getDecEnginePtr(wireId, typ) + if err != nil { + error(err) + } + op = func(i *decInstr, state *decodeState, p unsafe.Pointer) { + // indirect through enginePtr to delay evaluation for recursive structs + err = dec.decodeStruct(*enginePtr, t, state.b, uintptr(p), i.indir) + if err != nil { + error(err) + } + } + case *reflect.InterfaceType: + op = func(i *decInstr, state *decodeState, p unsafe.Pointer) { + dec.decodeInterface(t, state, uintptr(p), i.indir) + } + } + } + if op == nil { + errorf("gob: decode can't handle type %s", rt.String()) + } + return op, indir +} + +// Return 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 *decodeState, p unsafe.Pointer) { + dec.ignoreInterface(state) + } + return op + } + // Special cases + wire := dec.wireType[wireId] + switch { + case wire == nil: + panic("internal error: can't find ignore op for type " + wireId.string()) + case wire.ArrayT != nil: + elemId := wire.ArrayT.Elem + elemOp := dec.decIgnoreOpFor(elemId) + op = func(i *decInstr, state *decodeState, 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 *decodeState, 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 *decodeState, 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 *decodeState, p unsafe.Pointer) { + // indirect through enginePtr to delay evaluation for recursive structs + state.dec.ignoreStruct(*enginePtr, state.b) + } + } + } + if op == nil { + errorf("ignore can't handle type %s", wireId.string()) + } + return op +} + +// Are these two gob Types compatible? +// Answers the question for basic types, arrays, and slices. +// Structs are considered ok; fields will be checked later. +func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId) bool { + fr, _ = indirect(fr) + switch t := fr.(type) { + default: + // map, chan, etc: cannot handle. + return false + case *reflect.BoolType: + return fw == tBool + case *reflect.IntType: + return fw == tInt + case *reflect.UintType: + return fw == tUint + case *reflect.FloatType: + return fw == tFloat + case *reflect.ComplexType: + return fw == tComplex + case *reflect.StringType: + return fw == tString + case *reflect.InterfaceType: + return fw == tInterface + case *reflect.ArrayType: + wire, ok := dec.wireType[fw] + if !ok || wire.ArrayT == nil { + return false + } + array := wire.ArrayT + return t.Len() == array.Len && dec.compatibleType(t.Elem(), array.Elem) + case *reflect.MapType: + wire, ok := dec.wireType[fw] + if !ok || wire.MapT == nil { + return false + } + MapType := wire.MapT + return dec.compatibleType(t.Key(), MapType.Key) && dec.compatibleType(t.Elem(), MapType.Elem) + case *reflect.SliceType: + // 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, _ := indirect(t.Elem()) + return sw != nil && dec.compatibleType(elem, sw.Elem) + case *reflect.StructType: + 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() +} + + +func (dec *Decoder) compileSingle(remoteId typeId, rt reflect.Type) (engine *decEngine, err os.Error) { + engine = new(decEngine) + engine.instr = make([]decInstr, 1) // one item + name := rt.String() // best we can do + if !dec.compatibleType(rt, remoteId) { + return nil, os.ErrorString("gob: wrong type received for local value " + name + ": " + dec.typeString(remoteId)) + } + op, indir := dec.decOpFor(remoteId, rt, name) + ovfl := os.ErrorString(`value for "` + name + `" out of range`) + engine.instr[singletonField] = decInstr{op, singletonField, indir, 0, ovfl} + engine.numInstr = 1 + return +} + +// Is this an exported - upper case - name? +func isExported(name string) bool { + rune, _ := utf8.DecodeRuneInString(name) + return unicode.IsUpper(rune) +} + +func (dec *Decoder) compileDec(remoteId typeId, rt reflect.Type) (engine *decEngine, err os.Error) { + defer catchError(&err) + srt, ok := rt.(*reflect.StructType) + if !ok { + return dec.compileSingle(remoteId, rt) + } + 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 { + wireStruct = dec.wireType[remoteId].StructT + } + if wireStruct == nil { + errorf("gob: type mismatch in decoder: want struct type %s; got non-struct", rt.String()) + } + engine = new(decEngine) + engine.instr = make([]decInstr, len(wireStruct.Field)) + // Loop over the fields of the wire type. + for fieldnum := 0; fieldnum < len(wireStruct.Field); fieldnum++ { + wireField := wireStruct.Field[fieldnum] + if wireField.Name == "" { + errorf("gob: 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) { + errorf("gob: wrong type (%s) for received field %s.%s", localField.Type, wireStruct.Name, wireField.Name) + } + op, indir := dec.decOpFor(wireField.Id, localField.Type, localField.Name) + engine.instr[fieldnum] = decInstr{op, fieldnum, indir, uintptr(localField.Offset), ovfl} + engine.numInstr++ + } + return +} + +func (dec *Decoder) getDecEnginePtr(remoteId typeId, rt reflect.Type) (enginePtr **decEngine, err os.Error) { + 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, rt) + if err != nil { + decoderMap[remoteId] = nil, false + } + } + return +} + +// When ignoring struct data, in effect we compile it into this type +type emptyStruct struct{} + +var emptyStructType = reflect.Typeof(emptyStruct{}) + +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 + *enginePtr, err = dec.compileDec(wireId, emptyStructType) + if err != nil { + dec.ignorerCache[wireId] = nil, false + } + } + return +} + +func (dec *Decoder) decode(wireId typeId, val reflect.Value) os.Error { + // Dereference down to the underlying struct type. + rt, indir := indirect(val.Type()) + enginePtr, err := dec.getDecEnginePtr(wireId, rt) + if err != nil { + return err + } + engine := *enginePtr + if st, ok := rt.(*reflect.StructType); ok { + if engine.numInstr == 0 && st.NumField() > 0 && len(dec.wireType[wireId].StructT.Field) > 0 { + name := rt.Name() + return os.ErrorString("gob: type mismatch: no fields matched compiling decoder for " + name) + } + return dec.decodeStruct(engine, st, dec.state.b, uintptr(val.Addr()), indir) + } + return dec.decodeSingle(engine, rt, dec.state.b, uintptr(val.Addr()), indir) +} + +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") + } + decOpMap[reflect.Int] = iop + decOpMap[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") + } + decOpMap[reflect.Uintptr] = uop +} diff --git a/libgo/go/gob/decoder.go b/libgo/go/gob/decoder.go new file mode 100644 index 000000000..664001a4b --- /dev/null +++ b/libgo/go/gob/decoder.go @@ -0,0 +1,164 @@ +// 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" +) + +// 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 + 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 + state *decodeState // reads data from in-memory buffer + countState *decodeState // reads counts from wire + buf []byte + countBuf [9]byte // counts may be uint64s (unlikely!), require 9 bytes + byteBuffer *bytes.Buffer + 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 = r + dec.wireType = make(map[typeId]*wireType) + dec.state = newDecodeState(dec, &dec.byteBuffer) // buffer set in Decode() + dec.decoderCache = make(map[reflect.Type]map[typeId]**decEngine) + dec.ignorerCache = make(map[typeId]**decEngine) + + return dec +} + +// recvType loads the definition of a type and reloads the Decoder's buffer. +func (dec *Decoder) recvType(id typeId) { + // Have we already seen this type? That's an error + if dec.wireType[id] != nil { + dec.err = os.ErrorString("gob: duplicate type received") + return + } + + // Type: + wire := new(wireType) + dec.err = dec.decode(tWireType, reflect.NewValue(wire)) + if dec.err != nil { + return + } + // Remember we've seen this type. + dec.wireType[id] = wire + + // Load the next parcel. + dec.recv() +} + +// Decode reads the next value from the connection and stores +// it in the data represented by the empty interface value. +// The value underlying e must be the correct type for the next +// data item received, and must be a pointer. +func (dec *Decoder) Decode(e interface{}) os.Error { + value := reflect.NewValue(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.ErrorString("gob: attempt to decode into a non-pointer") + return dec.err + } + return dec.DecodeValue(value) +} + +// recv reads the next count-delimited item from the input. It is the converse +// of Encoder.send. +func (dec *Decoder) recv() { + // Read a count. + var nbytes uint64 + nbytes, dec.err = decodeUintReader(dec.r, dec.countBuf[0:]) + if dec.err != nil { + return + } + // Allocate the buffer. + if nbytes > uint64(len(dec.buf)) { + dec.buf = make([]byte, nbytes+1000) + } + dec.byteBuffer = bytes.NewBuffer(dec.buf[0:nbytes]) + + // Read the data + _, dec.err = io.ReadFull(dec.r, dec.buf[0:nbytes]) + if dec.err != nil { + if dec.err == os.EOF { + dec.err = io.ErrUnexpectedEOF + } + return + } +} + +// decodeValueFromBuffer grabs the next value from the input. The Decoder's +// buffer already contains data. If the next item in the buffer is a type +// descriptor, it may be necessary to reload the buffer, but recvType does that. +func (dec *Decoder) decodeValueFromBuffer(value reflect.Value, ignoreInterfaceValue, countPresent bool) { + for dec.state.b.Len() > 0 { + // Receive a type id. + id := typeId(dec.state.decodeInt()) + + // Is it a new type? + if id < 0 { // 0 is the error state, handled above + // If the id is negative, we have a type. + dec.recvType(-id) + if dec.err != nil { + break + } + continue + } + + // Make sure the type has been defined already or is a builtin type (for + // top-level singleton values). + if dec.wireType[id] == nil && builtinIdToType[id] == nil { + dec.err = errBadType + break + } + // An interface value is preceded by a byte count. + if countPresent { + count := int(dec.state.decodeUint()) + if ignoreInterfaceValue { + // An interface value is preceded by a byte count. Just skip that many bytes. + dec.state.b.Next(int(count)) + break + } + // Otherwise fall through and decode it. + } + dec.err = dec.decode(id, value) + break + } +} + +// DecodeValue reads the next value from the connection and stores +// it in the data represented by the reflection value. +// The value must be the correct type for the next +// data item received. +func (dec *Decoder) DecodeValue(value reflect.Value) os.Error { + // Make sure we're single-threaded through here. + dec.mutex.Lock() + defer dec.mutex.Unlock() + + dec.err = nil + dec.recv() + if dec.err != nil { + return dec.err + } + dec.decodeValueFromBuffer(value, false, false) + 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/libgo/go/gob/doc.go b/libgo/go/gob/doc.go new file mode 100644 index 000000000..31253f16d --- /dev/null +++ b/libgo/go/gob/doc.go @@ -0,0 +1,307 @@ +// 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. + +/* +The gob package 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. + +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 { + 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. +*/ +package gob + +/* +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 78 01 04 00 01 01 79 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 + 78 // 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 + 79 // 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/libgo/go/gob/encode.go b/libgo/go/gob/encode.go new file mode 100644 index 000000000..d286a7e00 --- /dev/null +++ b/libgo/go/gob/encode.go @@ -0,0 +1,573 @@ +// 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" + "math" + "os" + "reflect" + "unsafe" +) + +const uint64Size = unsafe.Sizeof(uint64(0)) + +// 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. +} + +func newEncoderState(enc *Encoder, b *bytes.Buffer) *encoderState { + return &encoderState{enc: enc, b: b} +} + +// 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 & 0xFF) + 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)) +} + +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 +} + +// Emit a field number and update the state to record its value for delta encoding. +// If the instruction pointer is nil, do nothing +func (state *encoderState) update(instr *encInstr) { + if instr != nil { + state.encodeUint(uint64(instr.field - state.fieldnum)) + state.fieldnum = instr.field + } +} + +// Each encoder is responsible for handling any indirections associated +// with the data structure. If any pointer so reached is nil, no bytes are written. +// If the data item is zero, no bytes are written. +// Otherwise, the output (for a scalar) is the field number, as an encoded integer, +// followed by the field data in its appropriate format. + +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 +} + +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) + } + } +} + +func encInt(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := int64(*(*int)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeInt(v) + } +} + +func encUint(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := uint64(*(*uint)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeUint(v) + } +} + +func encInt8(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := int64(*(*int8)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeInt(v) + } +} + +func encUint8(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := uint64(*(*uint8)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeUint(v) + } +} + +func encInt16(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := int64(*(*int16)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeInt(v) + } +} + +func encUint16(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := uint64(*(*uint16)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeUint(v) + } +} + +func encInt32(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := int64(*(*int32)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeInt(v) + } +} + +func encUint32(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := uint64(*(*uint32)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeUint(v) + } +} + +func encInt64(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := *(*int64)(p) + if v != 0 || state.sendZero { + state.update(i) + state.encodeInt(v) + } +} + +func encUint64(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := *(*uint64)(p) + if v != 0 || state.sendZero { + state.update(i) + state.encodeUint(v) + } +} + +func encUintptr(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := uint64(*(*uintptr)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeUint(v) + } +} + +// 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 +} + +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) + } +} + +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) + } +} + +// 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) + } +} + +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) + } +} + +func encNoOp(i *encInstr, state *encoderState, p unsafe.Pointer) { +} + +// 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) + } +} + +// 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))) + io.WriteString(state.b, s) + } +} + +// The end of a struct is marked by a delta field number of 0. +func encStructTerminator(i *encInstr, state *encoderState, p unsafe.Pointer) { + state.encodeUint(0) +} + +// Execution engine + +// The encoder engine is 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 + +func (enc *Encoder) encodeSingle(b *bytes.Buffer, engine *encEngine, basep uintptr) { + state := newEncoderState(enc, 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) +} + +func (enc *Encoder) encodeStruct(b *bytes.Buffer, engine *encEngine, basep uintptr) { + state := newEncoderState(enc, 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) + } +} + +func (enc *Encoder) encodeArray(b *bytes.Buffer, p uintptr, op encOp, elemWid uintptr, elemIndir int, length int) { + state := newEncoderState(enc, 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("gob: encodeArray: nil element") + } + elemp = uintptr(up) + } + op(nil, state, unsafe.Pointer(elemp)) + p += uintptr(elemWid) + } +} + +func encodeReflectValue(state *encoderState, v reflect.Value, op encOp, indir int) { + for i := 0; i < indir && v != nil; i++ { + v = reflect.Indirect(v) + } + if v == nil { + errorf("gob: encodeReflectValue: nil element") + } + op(nil, state, unsafe.Pointer(v.Addr())) +} + +func (enc *Encoder) encodeMap(b *bytes.Buffer, mv *reflect.MapValue, keyOp, elemOp encOp, keyIndir, elemIndir int) { + state := newEncoderState(enc, b) + state.fieldnum = -1 + state.sendZero = true + keys := mv.Keys() + state.encodeUint(uint64(len(keys))) + for _, key := range keys { + encodeReflectValue(state, key, keyOp, keyIndir) + encodeReflectValue(state, mv.Elem(key), elemOp, elemIndir) + } +} + +// 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.InterfaceValue) { + state := newEncoderState(enc, b) + state.fieldnum = -1 + state.sendZero = true + if iv.IsNil() { + state.encodeUint(0) + return + } + + typ, _ := indirect(iv.Elem().Type()) + name, ok := concreteTypeToName[typ] + if !ok { + errorf("gob: type not registered for interface: %s", typ) + } + // Send the name. + state.encodeUint(uint64(len(name))) + _, err := io.WriteString(state.b, name) + if err != nil { + error(err) + } + // Send (and maybe first define) the type id. + enc.sendTypeDescriptor(typ) + // Encode the value into a new buffer. + data := new(bytes.Buffer) + err = enc.encode(data, iv.Elem()) + if err != nil { + error(err) + } + state.encodeUint(uint64(data.Len())) + _, err = state.b.Write(data.Bytes()) + if err != nil { + error(err) + } +} + +var encOpMap = []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, +} + +// Return the encoding op for the base type under rt and +// the indirection count to reach it. +func (enc *Encoder) encOpFor(rt reflect.Type) (encOp, int) { + typ, indir := indirect(rt) + var op encOp + k := typ.Kind() + if int(k) < len(encOpMap) { + op = encOpMap[k] + } + if op == nil { + // Special cases + switch t := typ.(type) { + case *reflect.SliceType: + 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()) + 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.ArrayType: + // True arrays have size in the type. + elemOp, indir := enc.encOpFor(t.Elem()) + 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.MapType: + keyOp, keyIndir := enc.encOpFor(t.Key()) + elemOp, elemIndir := enc.encOpFor(t.Elem()) + 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.NewValue(unsafe.Unreflect(t, unsafe.Pointer((p)))) + mv := reflect.Indirect(v).(*reflect.MapValue) + if !state.sendZero && mv.Len() == 0 { + return + } + state.update(i) + state.enc.encodeMap(state.b, mv, keyOp, elemOp, keyIndir, elemIndir) + } + case *reflect.StructType: + // Generate a closure that calls out to the engine for the nested type. + enc.getEncEngine(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.InterfaceType: + op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { + // Interfaces transmit the name and contents of the concrete + // value they contain. + v := reflect.NewValue(unsafe.Unreflect(t, unsafe.Pointer((p)))) + iv := reflect.Indirect(v).(*reflect.InterfaceValue) + if !state.sendZero && (iv == nil || iv.IsNil()) { + return + } + state.update(i) + state.enc.encodeInterface(state.b, iv) + } + } + } + if op == nil { + errorf("gob enc: can't happen: encode type %s", rt.String()) + } + return op, indir +} + +// The local Type was compiled from the actual value, so we know it's compatible. +func (enc *Encoder) compileEnc(rt reflect.Type) *encEngine { + srt, isStruct := rt.(*reflect.StructType) + engine := new(encEngine) + if isStruct { + engine.instr = make([]encInstr, srt.NumField()+1) // +1 for terminator + for fieldnum := 0; fieldnum < srt.NumField(); fieldnum++ { + f := srt.Field(fieldnum) + op, indir := enc.encOpFor(f.Type) + if !isExported(f.Name) { + op = encNoOp + } + engine.instr[fieldnum] = encInstr{op, fieldnum, indir, uintptr(f.Offset)} + } + engine.instr[srt.NumField()] = encInstr{encStructTerminator, 0, 0, 0} + } else { + engine.instr = make([]encInstr, 1) + op, indir := enc.encOpFor(rt) + engine.instr[0] = encInstr{op, singletonField, indir, 0} // offset is zero + } + return engine +} + +// typeLock must be held (or we're in initialization and guaranteed single-threaded). +// The reflection type must have all its indirections processed out. +func (enc *Encoder) getEncEngine(rt reflect.Type) *encEngine { + info, err1 := getTypeInfo(rt) + 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(rt) + } + return info.encoder +} + +// Put this in a function so we can hold the lock only while compiling, not when encoding. +func (enc *Encoder) lockAndGetEncEngine(rt reflect.Type) *encEngine { + typeLock.Lock() + defer typeLock.Unlock() + return enc.getEncEngine(rt) +} + +func (enc *Encoder) encode(b *bytes.Buffer, value reflect.Value) (err os.Error) { + defer catchError(&err) + // Dereference down to the underlying object. + rt, indir := indirect(value.Type()) + for i := 0; i < indir; i++ { + value = reflect.Indirect(value) + } + engine := enc.lockAndGetEncEngine(rt) + if value.Type().Kind() == reflect.Struct { + enc.encodeStruct(b, engine, value.Addr()) + } else { + enc.encodeSingle(b, engine, value.Addr()) + } + return nil +} diff --git a/libgo/go/gob/encoder.go b/libgo/go/gob/encoder.go new file mode 100644 index 000000000..8869b2629 --- /dev/null +++ b/libgo/go/gob/encoder.go @@ -0,0 +1,207 @@ +// 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 + state *encoderState // so we can encode integers, strings directly + countState *encoderState // stage for writing counts + buf []byte // for collecting the output. + 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 = w + enc.sent = make(map[reflect.Type]typeId) + enc.state = newEncoderState(enc, new(bytes.Buffer)) + enc.countState = newEncoderState(enc, new(bytes.Buffer)) + return enc +} + +func (enc *Encoder) badType(rt reflect.Type) { + enc.setError(os.ErrorString("gob: can't encode type " + rt.String())) +} + +func (enc *Encoder) setError(err os.Error) { + if enc.err == nil { // remember the first. + enc.err = err + } + enc.state.b.Reset() +} + +// Send the data item preceded by a unsigned count of its length. +func (enc *Encoder) send() { + // Encode the length. + enc.countState.encodeUint(uint64(enc.state.b.Len())) + // Build the buffer. + countLen := enc.countState.b.Len() + total := countLen + enc.state.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. + enc.state.b.Read(enc.buf[countLen:total]) + // Write the data. + _, err := enc.w.Write(enc.buf[0:total]) + if err != nil { + enc.setError(err) + } +} + +func (enc *Encoder) sendType(origt reflect.Type) (sent bool) { + // Drill down to the base type. + rt, _ := indirect(origt) + + switch rt := rt.(type) { + default: + // Basic types and interfaces do not need to be described. + return + case *reflect.SliceType: + // 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.ArrayType: + // arrays must be sent so we know their lengths and element types. + break + case *reflect.MapType: + // maps must be sent so we know their lengths and key/value types. + break + case *reflect.StructType: + // structs must be sent so we know their fields. + break + case *reflect.ChanType, *reflect.FuncType: + // Probably a bad field in a struct. + enc.badType(rt) + return + } + + // Have we already sent this type? This time we ask about the base type. + if _, alreadySent := enc.sent[rt]; alreadySent { + return + } + + // Need to send it. + typeLock.Lock() + info, err := getTypeInfo(rt) + typeLock.Unlock() + if err != nil { + enc.setError(err) + return + } + // Send the pair (-id, type) + // Id: + enc.state.encodeInt(-int64(info.id)) + // Type: + enc.encode(enc.state.b, reflect.NewValue(info.wire)) + enc.send() + if enc.err != nil { + return + } + + // Remember we've sent this type. + enc.sent[rt] = info.id + // Remember we've sent the top-level, possibly indirect type too. + enc.sent[origt] = info.id + // Now send the inner types + switch st := rt.(type) { + case *reflect.StructType: + for i := 0; i < st.NumField(); i++ { + enc.sendType(st.Field(i).Type) + } + case reflect.ArrayOrSliceType: + enc.sendType(st.Elem()) + } + return true +} + +// 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.NewValue(e)) +} + +// sendTypeId 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. Regardless, it sends the id. +func (enc *Encoder) sendTypeDescriptor(rt reflect.Type) { + // Make sure the type is known to the other side. + // First, have we already sent this type? + if _, alreadySent := enc.sent[rt]; !alreadySent { + // No, so send it. + sent := enc.sendType(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(rt) + typeLock.Unlock() + if err != nil { + enc.setError(err) + return + } + enc.sent[rt] = info.id + } + } + + // Identify the type of this top-level value. + enc.state.encodeInt(int64(enc.sent[rt])) +} + +// 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() + + enc.err = nil + rt, _ := indirect(value.Type()) + + // Sanity check only: encoder should never come in with data present. + if enc.state.b.Len() > 0 || enc.countState.b.Len() > 0 { + enc.err = os.ErrorString("encoder: buffer not empty") + return enc.err + } + + enc.sendTypeDescriptor(rt) + if enc.err != nil { + return enc.err + } + + // Encode the object. + err := enc.encode(enc.state.b, value) + if err != nil { + enc.setError(err) + } else { + enc.send() + } + + return enc.err +} diff --git a/libgo/go/gob/encoder_test.go b/libgo/go/gob/encoder_test.go new file mode 100644 index 000000000..c2309352a --- /dev/null +++ b/libgo/go/gob/encoder_test.go @@ -0,0 +1,385 @@ +// 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" + "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.Error("expected error", err, "got", 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 := (*Type0)(nil) + 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") + } +} + +// 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.NewValue(test.out).(*reflect.PtrValue).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) + } +} diff --git a/libgo/go/gob/error.go b/libgo/go/gob/error.go new file mode 100644 index 000000000..b053761fb --- /dev/null +++ b/libgo/go/gob/error.go @@ -0,0 +1,41 @@ +// 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. +func errorf(format string, args ...interface{}) { + error(fmt.Errorf(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/libgo/go/gob/type.go b/libgo/go/gob/type.go new file mode 100644 index 000000000..22502a6e6 --- /dev/null +++ b/libgo/go/gob/type.go @@ -0,0 +1,539 @@ +// 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" +) + +// Reflection types are themselves interface values holding structs +// describing the type. Each type has a different struct so that struct can +// be the kind. For example, if typ is the reflect type for an int8, typ is +// a pointer to a reflect.Int8Type struct; if typ is the reflect type for a +// function, typ is a pointer to a reflect.FuncType struct; we use the type +// of that pointer as the kind. + +// 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 "<nil>" + } + return t.gobType().string() +} + +// Name returns the name of the type associated with the typeId. +func (t typeId) name() string { + if t.gobType() == nil { + return "<nil>" + } + return t.gobType().name() +} + +// 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. + tBool = bootstrapType("bool", false, 1) + tInt = bootstrapType("int", int(0), 2) + tUint = bootstrapType("uint", uint(0), 3) + tFloat = bootstrapType("float", 0.0, 4) + tBytes = bootstrapType("bytes", make([]byte, 0), 5) + tString = bootstrapType("string", "", 6) + tComplex = bootstrapType("complex", 0+0i, 7) + tInterface = bootstrapType("interface", interface{}(nil), 8) + // Reserve some Ids for compatible expansion + tReserved7 = bootstrapType("_reserved1", struct{ r7 int }{}, 9) + tReserved6 = bootstrapType("_reserved1", struct{ r6 int }{}, 10) + tReserved5 = bootstrapType("_reserved1", struct{ r5 int }{}, 11) + tReserved4 = bootstrapType("_reserved1", struct{ r4 int }{}, 12) + tReserved3 = bootstrapType("_reserved1", struct{ r3 int }{}, 13) + tReserved2 = bootstrapType("_reserved1", struct{ r2 int }{}, 14) + tReserved1 = bootstrapType("_reserved1", struct{ r1 int }{}, 15) +) + +// Predefined because it's needed by the Decoder +var tWireType = mustGetTypeInfo(reflect.Typeof(wireType{})).id + +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() +} + +// Array type +type arrayType struct { + CommonType + Elem typeId + Len int +} + +func newArrayType(name string, elem gobType, length int) *arrayType { + a := &arrayType{CommonType{Name: name}, elem.id(), length} + setTypeId(a) + return a +} + +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)) } + +// Map type +type mapType struct { + CommonType + Key typeId + Elem typeId +} + +func newMapType(name string, key, elem gobType) *mapType { + m := &mapType{CommonType{Name: name}, key.id(), elem.id()} + setTypeId(m) + return m +} + +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, elem gobType) *sliceType { + s := &sliceType{CommonType{Name: name}, elem.id()} + setTypeId(s) + return s +} + +func (s *sliceType) safeString(seen map[typeId]bool) string { + if seen[s.Id] { + return s.Name + } + seen[s.Id] = true + return fmt.Sprintf("[]%s", s.Elem.gobType().safeString(seen)) +} + +func (s *sliceType) string() string { return s.safeString(make(map[typeId]bool)) } + +// Struct type +type fieldType struct { + Name string + Id typeId +} + +type structType struct { + CommonType + Field []*fieldType +} + +func (s *structType) safeString(seen map[typeId]bool) string { + if s == nil { + return "<nil>" + } + if _, ok := seen[s.Id]; ok { + return s.Name + } + seen[s.Id] = true + str := s.Name + " = struct { " + for _, f := range s.Field { + str += fmt.Sprintf("%s %s; ", f.Name, f.Id.gobType().safeString(seen)) + } + str += "}" + return str +} + +func (s *structType) string() string { return s.safeString(make(map[typeId]bool)) } + +func newStructType(name string) *structType { + s := &structType{CommonType{Name: name}, nil} + setTypeId(s) + return s +} + +// Step through the indirections on a type to discover the base type. +// Return the base type and the number of indirections. +func indirect(t reflect.Type) (rt reflect.Type, count int) { + rt = t + for { + pt, ok := rt.(*reflect.PtrType) + if !ok { + break + } + rt = pt.Elem() + count++ + } + return +} + +func newTypeObject(name string, rt reflect.Type) (gobType, os.Error) { + switch t := rt.(type) { + // All basic types are easy: they are predefined. + case *reflect.BoolType: + return tBool.gobType(), nil + + case *reflect.IntType: + return tInt.gobType(), nil + + case *reflect.UintType: + return tUint.gobType(), nil + + case *reflect.FloatType: + return tFloat.gobType(), nil + + case *reflect.ComplexType: + return tComplex.gobType(), nil + + case *reflect.StringType: + return tString.gobType(), nil + + case *reflect.InterfaceType: + return tInterface.gobType(), nil + + case *reflect.ArrayType: + gt, err := getType("", t.Elem()) + if err != nil { + return nil, err + } + return newArrayType(name, gt, t.Len()), nil + + case *reflect.MapType: + kt, err := getType("", t.Key()) + if err != nil { + return nil, err + } + vt, err := getType("", t.Elem()) + if err != nil { + return nil, err + } + return newMapType(name, kt, vt), nil + + case *reflect.SliceType: + // []byte == []uint8 is a special case + if t.Elem().Kind() == reflect.Uint8 { + return tBytes.gobType(), nil + } + gt, err := getType(t.Elem().Name(), t.Elem()) + if err != nil { + return nil, err + } + return newSliceType(name, gt), nil + + case *reflect.StructType: + // Install the struct type itself before the fields so recursive + // structures can be constructed safely. + strType := newStructType(name) + types[rt] = strType + idToType[strType.id()] = strType + field := make([]*fieldType, t.NumField()) + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + typ, _ := indirect(f.Type) + tname := typ.Name() + if tname == "" { + t, _ := indirect(f.Type) + tname = t.String() + } + gt, err := getType(tname, f.Type) + if err != nil { + return nil, err + } + field[i] = &fieldType{f.Name, gt.id()} + } + strType.Field = field + return strType, nil + + default: + return nil, os.ErrorString("gob NewTypeObject can't handle type: " + rt.String()) + } + return nil, nil +} + +// getType returns the Gob type describing the given reflect.Type. +// typeLock must be held. +func getType(name string, rt reflect.Type) (gobType, os.Error) { + rt, _ = indirect(rt) + typ, present := types[rt] + if present { + return typ, nil + } + typ, err := newTypeObject(name, 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(want), int(got)) + panic("bootstrap type wrong id: " + got.name() + " " + got.string() + " not " + want.string()) + } +} + +// used for building the basic types; called only from init() +func bootstrapType(name string, e interface{}, expect typeId) typeId { + rt := reflect.Typeof(e) + _, 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) + 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 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 +} + +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 + } + return unknown +} + +type typeInfo struct { + id typeId + encoder *encEngine + wire *wireType +} + +var typeInfoMap = make(map[reflect.Type]*typeInfo) // protected by typeLock + +// The reflection type must have all its indirections processed out. +// typeLock must be held. +func getTypeInfo(rt reflect.Type) (*typeInfo, os.Error) { + if rt.Kind() == reflect.Ptr { + panic("pointer type in getTypeInfo: " + rt.String()) + } + info, ok := typeInfoMap[rt] + if !ok { + info = new(typeInfo) + name := rt.Name() + gt, err := getType(name, rt) + if err != nil { + return nil, err + } + info.id = gt.id() + t := info.id.gobType() + switch typ := rt.(type) { + case *reflect.ArrayType: + info.wire = &wireType{ArrayT: t.(*arrayType)} + case *reflect.MapType: + info.wire = &wireType{MapT: t.(*mapType)} + case *reflect.SliceType: + // []byte == []uint8 is a special case handled separately + if typ.Elem().Kind() != reflect.Uint8 { + info.wire = &wireType{SliceT: t.(*sliceType)} + } + case *reflect.StructType: + 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(rt) + if err != nil { + panic("getTypeInfo: " + err.String()) + } + return t +} + +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") + } + rt, _ := indirect(reflect.Typeof(value)) + // Check for incompatible duplicates. + if t, ok := nameToConcreteType[name]; ok && t != rt { + panic("gob: registering duplicate types for " + name) + } + if n, ok := concreteTypeToName[rt]; ok && n != name { + panic("gob: registering duplicate names for " + rt.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[rt] = 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, ok := rt.(*reflect.PtrType); ok { + 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(0.0) + Register(complex64(0i)) + Register(complex128(0i)) + Register(false) + Register("") + Register([]byte(nil)) +} diff --git a/libgo/go/gob/type_test.go b/libgo/go/gob/type_test.go new file mode 100644 index 000000000..5aecde103 --- /dev/null +++ b/libgo/go/gob/type_test.go @@ -0,0 +1,153 @@ +// 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 := getType(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) + } +} |