diff options
Diffstat (limited to 'src/pkg/gob')
-rw-r--r-- | src/pkg/gob/Makefile | 4 | ||||
-rw-r--r-- | src/pkg/gob/codec_test.go | 772 | ||||
-rw-r--r-- | src/pkg/gob/debug.go | 310 | ||||
-rw-r--r-- | src/pkg/gob/decode.go | 488 | ||||
-rw-r--r-- | src/pkg/gob/decoder.go | 121 | ||||
-rw-r--r-- | src/pkg/gob/doc.go | 307 | ||||
-rw-r--r-- | src/pkg/gob/encode.go | 541 | ||||
-rw-r--r-- | src/pkg/gob/encoder.go | 81 | ||||
-rw-r--r-- | src/pkg/gob/encoder_test.go | 205 | ||||
-rw-r--r-- | src/pkg/gob/error.go | 41 | ||||
-rw-r--r-- | src/pkg/gob/type.go | 265 | ||||
-rw-r--r-- | src/pkg/gob/type_test.go | 12 |
12 files changed, 1954 insertions, 1193 deletions
diff --git a/src/pkg/gob/Makefile b/src/pkg/gob/Makefile index 1091adb01..68007c189 100644 --- a/src/pkg/gob/Makefile +++ b/src/pkg/gob/Makefile @@ -2,14 +2,16 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. -include ../../Make.$(GOARCH) +include ../../Make.inc TARG=gob GOFILES=\ decode.go\ decoder.go\ + doc.go\ encode.go\ encoder.go\ + error.go\ type.go\ include ../../Make.pkg diff --git a/src/pkg/gob/codec_test.go b/src/pkg/gob/codec_test.go index 2caaaa43f..d150dbe9a 100644 --- a/src/pkg/gob/codec_test.go +++ b/src/pkg/gob/codec_test.go @@ -21,50 +21,50 @@ type EncodeT struct { } var encodeT = []EncodeT{ - EncodeT{0x00, []byte{0x00}}, - EncodeT{0x0F, []byte{0x0F}}, - EncodeT{0xFF, []byte{0xFF, 0xFF}}, - EncodeT{0xFFFF, []byte{0xFE, 0xFF, 0xFF}}, - EncodeT{0xFFFFFF, []byte{0xFD, 0xFF, 0xFF, 0xFF}}, - EncodeT{0xFFFFFFFF, []byte{0xFC, 0xFF, 0xFF, 0xFF, 0xFF}}, - EncodeT{0xFFFFFFFFFF, []byte{0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}, - EncodeT{0xFFFFFFFFFFFF, []byte{0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}, - EncodeT{0xFFFFFFFFFFFFFF, []byte{0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}, - EncodeT{0xFFFFFFFFFFFFFFFF, []byte{0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}, - EncodeT{0x1111, []byte{0xFE, 0x11, 0x11}}, - EncodeT{0x1111111111111111, []byte{0xF8, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}}, - EncodeT{0x8888888888888888, []byte{0xF8, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88}}, - EncodeT{1 << 63, []byte{0xF8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {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 := new(encoderState) - encState.b = b + encState := newEncoderState(nil, b) for _, tt := range encodeT { b.Reset() - encodeUint(encState, tt.x) - if encState.err != nil { - t.Error("encodeUint:", tt.x, encState.err) - } + encState.encodeUint(tt.x) if !bytes.Equal(tt.b, b.Bytes()) { t.Errorf("encodeUint: %#x encode: expected % x got % x", tt.x, tt.b, b.Bytes()) } } - decState := newDecodeState(b) + decState := newDecodeState(nil, &b) for u := uint64(0); ; u = (u + 1) * 7 { b.Reset() - encodeUint(encState, u) - if encState.err != nil { - t.Error("encodeUint:", u, encState.err) - } - v := decodeUint(decState) - if decState.err != nil { - t.Error("DecodeUint:", u, decState.err) - } + encState.encodeUint(u) + v := decState.decodeUint() if u != v { - t.Errorf("Encode/Decode: sent %#x received %#x\n", u, v) + t.Errorf("Encode/Decode: sent %#x received %#x", u, v) } if u&(1<<63) != 0 { break @@ -73,21 +73,15 @@ func TestUintCodec(t *testing.T) { } func verifyInt(i int64, t *testing.T) { + defer testError(t) var b = new(bytes.Buffer) - encState := new(encoderState) - encState.b = b - encodeInt(encState, i) - if encState.err != nil { - t.Error("encodeInt:", i, encState.err) - } - decState := newDecodeState(b) + encState := newEncoderState(nil, b) + encState.encodeInt(i) + decState := newDecodeState(nil, &b) decState.buf = make([]byte, 8) - j := decodeInt(decState) - if decState.err != nil { - t.Error("DecodeInt:", i, decState.err) - } + j := decState.decodeInt() if i != j { - t.Errorf("Encode/Decode: sent %#x received %#x\n", uint64(i), uint64(j)) + t.Errorf("Encode/Decode: sent %#x received %#x", uint64(i), uint64(j)) } } @@ -119,8 +113,7 @@ var bytesResult = []byte{0x07, 0x05, 'h', 'e', 'l', 'l', 'o'} func newencoderState(b *bytes.Buffer) *encoderState { b.Reset() - state := new(encoderState) - state.b = b + state := newEncoderState(nil, b) state.fieldnum = -1 return state } @@ -323,10 +316,8 @@ func TestScalarEncInstructions(t *testing.T) { } func execDec(typ string, instr *decInstr, state *decodeState, t *testing.T, p unsafe.Pointer) { - v := int(decodeUint(state)) - if state.err != nil { - t.Fatalf("decoding %s field: %v", typ, state.err) - } + defer testError(t) + v := int(state.decodeUint()) if v+state.fieldnum != 6 { t.Fatalf("decoding field number %d, got %d", 6, v+state.fieldnum) } @@ -335,7 +326,8 @@ func execDec(typ string, instr *decInstr, state *decodeState, t *testing.T, p un } func newDecodeStateFromData(data []byte) *decodeState { - state := newDecodeState(bytes.NewBuffer(data)) + b := bytes.NewBuffer(data) + state := newDecodeState(nil, &b) state.fieldnum = -1 return state } @@ -607,35 +599,35 @@ func TestScalarDecInstructions(t *testing.T) { func TestEndToEnd(t *testing.T) { type T2 struct { - t string + T string } s1 := "string1" s2 := "string2" type T1 struct { - a, b, c int - m map[string]*float - n *[3]float - strs *[2]string - int64s *[]int64 - ri complex64 - s string - y []byte - t *T2 + A, B, C int + M map[string]*float + N *[3]float + 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]*float{"pi": &pi, "e": &e}, - n: &[3]float{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"}, + A: 17, + B: 18, + C: -5, + M: map[string]*float{"pi": &pi, "e": &e}, + N: &[3]float{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) @@ -654,13 +646,13 @@ func TestEndToEnd(t *testing.T) { func TestOverflow(t *testing.T) { type inputT struct { - maxi int64 - mini int64 - maxu uint64 - maxf float64 - minf float64 - maxc complex128 - minc complex128 + Maxi int64 + Mini int64 + Maxu uint64 + Maxf float64 + Minf float64 + Maxc complex128 + Minc complex128 } var it inputT var err os.Error @@ -671,152 +663,152 @@ func TestOverflow(t *testing.T) { // int8 b.Reset() it = inputT{ - maxi: math.MaxInt8 + 1, + Maxi: math.MaxInt8 + 1, } type outi8 struct { - maxi int8 - mini int8 + 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` { + 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, + Mini: math.MinInt8 - 1, } b.Reset() enc.Encode(it) err = dec.Decode(&o1) - if err == nil || err.String() != `value for "mini" out of range` { + 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, + Maxi: math.MaxInt16 + 1, } type outi16 struct { - maxi int16 - mini int16 + 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` { + 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, + Mini: math.MinInt16 - 1, } b.Reset() enc.Encode(it) err = dec.Decode(&o2) - if err == nil || err.String() != `value for "mini" out of range` { + 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, + Maxi: math.MaxInt32 + 1, } type outi32 struct { - maxi int32 - mini int32 + 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` { + 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, + Mini: math.MinInt32 - 1, } b.Reset() enc.Encode(it) err = dec.Decode(&o3) - if err == nil || err.String() != `value for "mini" out of range` { + 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, + Maxu: math.MaxUint8 + 1, } type outu8 struct { - maxu uint8 + Maxu uint8 } var o4 outu8 enc.Encode(it) err = dec.Decode(&o4) - if err == nil || err.String() != `value for "maxu" out of range` { + 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, + Maxu: math.MaxUint16 + 1, } type outu16 struct { - maxu uint16 + Maxu uint16 } var o5 outu16 enc.Encode(it) err = dec.Decode(&o5) - if err == nil || err.String() != `value for "maxu" out of range` { + 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, + Maxu: math.MaxUint32 + 1, } type outu32 struct { - maxu uint32 + Maxu uint32 } var o6 outu32 enc.Encode(it) err = dec.Decode(&o6) - if err == nil || err.String() != `value for "maxu" out of range` { + 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, + Maxf: math.MaxFloat32 * 2, } type outf32 struct { - maxf float32 - minf float32 + 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` { + 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: cmplx(math.MaxFloat32*2, math.MaxFloat32*2), + Maxc: cmplx(math.MaxFloat32*2, math.MaxFloat32*2), } type outc64 struct { - maxc complex64 - minc complex64 + 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` { + if err == nil || err.String() != `value for "Maxc" out of range` { t.Error("wrong overflow error for complex64:", err) } } @@ -824,92 +816,92 @@ func TestOverflow(t *testing.T) { func TestNesting(t *testing.T) { type RT struct { - a string - next *RT + A string + Next *RT } rt := new(RT) - rt.a = "level1" - rt.next = new(RT) - rt.next.a = "level2" + 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.Errorf("decoder error:", err) + t.Fatal("decoder error:", err) } - if drt.a != rt.a { + if drt.A != rt.A { t.Errorf("nesting: encode expected %v got %v", *rt, drt) } - if drt.next == nil { + 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) + 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 + A int + B int + C int + D int } type T1 struct { - a int - b *int - c **int - d ***int + A int + B *int + C **int + D ***int } type T2 struct { - a ***int - b **int - c *int - d int + 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 + 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 { + 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 + 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 { + 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) } @@ -919,8 +911,8 @@ func TestAutoIndirection(t *testing.T) { 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) + 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 @@ -928,40 +920,40 @@ func TestAutoIndirection(t *testing.T) { 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) + 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 + ***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) + 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 float + A int + B string + C float } type RT1 struct { - c float - b string - a int - notSet string + C float + B string + A int + NotSet string } func TestReorderedFields(t *testing.T) { var rt0 RT0 - rt0.a = 17 - rt0.b = "hello" - rt0.c = 3.14159 + rt0.A = 17 + rt0.B = "hello" + rt0.C = 3.14159 b := new(bytes.Buffer) NewEncoder(b).Encode(rt0) dec := NewDecoder(b) @@ -969,41 +961,41 @@ func TestReorderedFields(t *testing.T) { // Wire type is RT0, local type is RT1. err := dec.Decode(&rt1) if err != nil { - t.Error("decode error:", err) + t.Fatal("decode error:", err) } - if rt0.a != rt1.a || rt0.b != rt1.b || rt0.c != rt1.c { + 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]float - ignore_f bool - ignore_g string - ignore_h []byte - ignore_i *RT1 - ignore_m map[string]int - c float + A int64 + B string + Ignore_d []int + Ignore_e [3]float + Ignore_f bool + Ignore_g string + Ignore_h []byte + Ignore_i *RT1 + Ignore_m map[string]int + C float } 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} + 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) @@ -1014,56 +1006,58 @@ func TestIgnoredFields(t *testing.T) { if err != nil { t.Error("error: ", err) } - if int(it0.a) != rt1.a || it0.b != rt1.b || it0.c != rt1.c { - t.Errorf("rt1->rt0: expected %v; got %v", it0, rt1) + 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 { - inter interface{} - c float + ch chan int + c float } +var nilEncoder *Encoder + func TestInvalidField(t *testing.T) { var bad0 Bad0 - bad0.inter = 17 + bad0.ch = make(chan int) b := new(bytes.Buffer) - err := encode(b, reflect.NewValue(&bad0)) + err := nilEncoder.encode(b, reflect.NewValue(&bad0)) if err == nil { t.Error("expected error; got none") - } else if strings.Index(err.String(), "interface") < 0 { + } 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 + A ***[3]int + S ***[]int + M ****map[string]int } type Direct struct { - a [3]int - s []int - m map[string]int + 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} + 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) @@ -1072,34 +1066,328 @@ func TestIndirectSliceMapArray(t *testing.T) { 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.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.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) + 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} + 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.Error("error: ", err) + 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 float + +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 float + Sq []Squarer +} + +// The same struct without interfaces +type NoInterfaceItem struct { + I int + F float +} + +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") } - 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) + // 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)) } - 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) + 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) + } + } } - 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) + +} + +// A struct with all basic types, stored in interfaces. +type BasicInterfaceItem struct { + Int, Int8, Int16, Int32, Int64 interface{} + Uint, Uint8, Uint16, Uint32, Uint64 interface{} + Float, Float32, Float64 interface{} + Complex, 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), + float(1), float32(1), float64(1), + complex(0i), 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 float + 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 float + 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/src/pkg/gob/debug.go b/src/pkg/gob/debug.go index 02f2602ed..f3632a080 100644 --- a/src/pkg/gob/debug.go +++ b/src/pkg/gob/debug.go @@ -1,157 +1,236 @@ package gob // This file is not normally included in the gob package. Used only for debugging the package itself. +// Add debug.go to the files listed in the Makefile to add Debug to the gob package. import ( "bytes" "fmt" "io" - "log" "os" + "reflect" + "runtime" ) -// Debug prints a human-readable representation of the gob data read from r. -func Debug(r io.Reader) { NewDecoder(r).debug() } +var dump = false // If true, print the remaining bytes in the input buffer at each item. -// debug is like Decode but just prints what it finds. It should be safe even for corrupted data. -func (dec *Decoder) debug() { - dec.state.err = nil - for { - // Read a count. - var nbytes uint64 - nbytes, dec.state.err = decodeUintReader(dec.r, dec.countBuf[0:]) - if dec.state.err != nil { - break - } +// Init installs the debugging facility. If this file is not compiled in the +// package, the test in codec_test.go is a no-op. +func init() { + debugFunc = Debug +} - // Allocate the buffer. - if nbytes > uint64(len(dec.buf)) { - dec.buf = make([]byte, nbytes+1000) +// Debug prints a human-readable representation of the gob data read from r. +func Debug(r io.Reader) { + defer func() { + if e := recover(); e != nil { + if _, ok := e.(runtime.Error); ok { + panic(e) + } + fmt.Printf("error during debugging: %v\n", e) } - dec.state.b = bytes.NewBuffer(dec.buf[0:nbytes]) + }() + NewDecoder(r).debug() +} - // Read the data - _, dec.state.err = io.ReadFull(dec.r, dec.buf[0:nbytes]) - if dec.state.err != nil { - if dec.state.err == os.EOF { - dec.state.err = io.ErrUnexpectedEOF - } - break +// debugRecv is like recv but prints what it sees. +func (dec *Decoder) debugRecv() { + if dec.byteBuffer != nil && dec.byteBuffer.Len() != 0 { + fmt.Printf("error in recv: %d bytes left in input buffer\n", dec.byteBuffer.Len()) + return + } + // Read a count. + var nbytes uint64 + nbytes, dec.err = decodeUintReader(dec.r, dec.countBuf[0:]) + if dec.err != nil { + fmt.Printf("receiver error on count: %s\n", dec.err) + 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 { + fmt.Printf("receiver error on data: %s\n", dec.err) + if dec.err == os.EOF { + dec.err = io.ErrUnexpectedEOF } + return + } + if dump { + fmt.Printf("received %d bytes:\n\t% x\n", nbytes, dec.byteBuffer.Bytes()) + } +} + +// debug is like Decode but just prints what it finds. It should be safe even for corrupted data. +func (dec *Decoder) debug() { + // Make sure we're single-threaded through here. + dec.mutex.Lock() + defer dec.mutex.Unlock() + + dec.err = nil + dec.debugRecv() + if dec.err != nil { + return + } + dec.debugFromBuffer(0, false) +} + +// printFromBuffer prints the next value. The buffer contains data, but it may +// be a type descriptor and we may need to load more data to see the value; +// printType takes care of that. +func (dec *Decoder) debugFromBuffer(indent int, countPresent bool) { + for dec.state.b.Len() > 0 { // Receive a type id. - id := typeId(decodeInt(dec.state)) - if dec.state.err != nil { - break - } + 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. - fmt.Printf("new type id %d\n", -id) - dec.printType(-id) - if dec.state.err != nil { + dec.debugRecvType(-id) + if dec.err != nil { break } continue } - fmt.Printf("type id %d\n", id) // No, it's a value. - // Make sure the type has been defined already. - _, ok := dec.wireType[id] - if !ok { - dec.state.err = errBadType + // 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 } - fmt.Printf("\t%d bytes:\t% x\n", nbytes, dec.state.b.Bytes()) - dec.printData(0, id) + if countPresent { + dec.state.decodeUint() + } + dec.debugPrint(indent, id) break } - if dec.state.err != nil { - log.Stderr("debug:", dec.state.err) - } } -func (dec *Decoder) printType(id typeId) { +func (dec *Decoder) debugRecvType(id typeId) { // Have we already seen this type? That's an error if _, alreadySeen := dec.wireType[id]; alreadySeen { - dec.state.err = os.ErrorString("gob: duplicate type received") + dec.err = os.ErrorString("gob: duplicate type received") return } // Type: wire := new(wireType) - dec.state.err = dec.decode(tWireType, wire) - if dec.state.err == nil { + dec.err = dec.decode(tWireType, reflect.NewValue(wire)) + if dec.err == nil { printWireType(wire) } // Remember we've seen this type. dec.wireType[id] = wire + + // Load the next parcel. + dec.debugRecv() } func printWireType(wire *wireType) { + fmt.Printf("type definition {\n") switch { - case wire.array != nil: - printCommonType("array", &wire.array.commonType) - fmt.Printf("\tlen %d\n\telemid %d\n", wire.array.Len, wire.array.Elem) - case wire.slice != nil: - printCommonType("slice", &wire.slice.commonType) - fmt.Printf("\telemid %d\n", wire.slice.Elem) - case wire.strct != nil: - printCommonType("struct", &wire.strct.commonType) - for i, field := range wire.strct.field { - fmt.Printf("\tfield %d:\t%s\tid=%d\n", i, field.name, field.id) + case wire.ArrayT != nil: + printCommonType("array", &wire.ArrayT.CommonType) + fmt.Printf("\tlen %d\n\telemid %d\n", wire.ArrayT.Len, wire.ArrayT.Elem) + case wire.MapT != nil: + printCommonType("map", &wire.MapT.CommonType) + fmt.Printf("\tkeyid %d\n", wire.MapT.Key) + fmt.Printf("\telemid %d\n", wire.MapT.Elem) + case wire.SliceT != nil: + printCommonType("slice", &wire.SliceT.CommonType) + fmt.Printf("\telemid %d\n", wire.SliceT.Elem) + case wire.StructT != nil: + printCommonType("struct", &wire.StructT.CommonType) + for i, field := range wire.StructT.Field { + fmt.Printf("\tfield %d:\t%s\tid=%d\n", i, field.Name, field.Id) } } + fmt.Printf("}\n") } -func printCommonType(kind string, common *commonType) { - fmt.Printf("\t%s %s\n\tid: %d\n", kind, common.name, common._id) +func printCommonType(kind string, common *CommonType) { + fmt.Printf("\t%s %q\n\tid: %d\n", kind, common.Name, common.Id) } -func (dec *Decoder) printData(indent int, id typeId) { - if dec.state.err != nil { - return +func (dec *Decoder) debugPrint(indent int, id typeId) { + wire, ok := dec.wireType[id] + if ok && wire.StructT != nil { + dec.debugStruct(indent+1, id, wire) + } else { + dec.debugSingle(indent+1, id, wire) } +} + +func (dec *Decoder) debugSingle(indent int, id typeId, wire *wireType) { // is it a builtin type? _, ok := builtinIdToType[id] + if !ok && wire == nil { + errorf("type id %d not defined\n", id) + } + dec.state.decodeUint() + dec.printItem(indent, id) +} + +func (dec *Decoder) printItem(indent int, id typeId) { + if dump { + fmt.Printf("print item %d bytes: % x\n", dec.state.b.Len(), dec.state.b.Bytes()) + } + _, ok := builtinIdToType[id] if ok { dec.printBuiltin(indent, id) return } wire, ok := dec.wireType[id] if !ok { - fmt.Printf("type id %d not defined\n", id) - return + errorf("type id %d not defined\n", id) } switch { - case wire.array != nil: - dec.printArray(indent+1, wire) - case wire.slice != nil: - dec.printSlice(indent+1, wire) - case wire.strct != nil: - dec.printStruct(indent+1, wire) + case wire.ArrayT != nil: + dec.printArray(indent, wire) + case wire.MapT != nil: + dec.printMap(indent, wire) + case wire.SliceT != nil: + dec.printSlice(indent, wire) + case wire.StructT != nil: + dec.debugStruct(indent, id, wire) } } func (dec *Decoder) printArray(indent int, wire *wireType) { - elemId := wire.array.Elem - n := int(decodeUint(dec.state)) - for i := 0; i < n && dec.state.err == nil; i++ { - dec.printData(indent, elemId) + elemId := wire.ArrayT.Elem + n := int(dec.state.decodeUint()) + for i := 0; i < n && dec.err == nil; i++ { + dec.printItem(indent, elemId) } - if n != wire.array.Len { + if n != wire.ArrayT.Len { tab(indent) - fmt.Printf("(wrong length for array: %d should be %d)\n", n, wire.array.Len) + fmt.Printf("(wrong length for array: %d should be %d)\n", n, wire.ArrayT.Len) + } +} + +func (dec *Decoder) printMap(indent int, wire *wireType) { + keyId := wire.MapT.Key + elemId := wire.MapT.Elem + n := int(dec.state.decodeUint()) + for i := 0; i < n && dec.err == nil; i++ { + dec.printItem(indent, keyId) + dec.printItem(indent+1, elemId) } } func (dec *Decoder) printSlice(indent int, wire *wireType) { - elemId := wire.slice.Elem - n := int(decodeUint(dec.state)) - for i := 0; i < n && dec.state.err == nil; i++ { - dec.printData(indent, elemId) + elemId := wire.SliceT.Elem + n := int(dec.state.decodeUint()) + for i := 0; i < n && dec.err == nil; i++ { + dec.printItem(indent, elemId) } } @@ -159,58 +238,73 @@ func (dec *Decoder) printBuiltin(indent int, id typeId) { tab(indent) switch id { case tBool: - if decodeInt(dec.state) == 0 { - fmt.Printf("false") + if dec.state.decodeInt() == 0 { + fmt.Printf("false\n") } else { - fmt.Printf("true") + fmt.Printf("true\n") } case tInt: - fmt.Printf("%d", decodeInt(dec.state)) + fmt.Printf("%d\n", dec.state.decodeInt()) case tUint: - fmt.Printf("%d", decodeUint(dec.state)) + fmt.Printf("%d\n", dec.state.decodeUint()) case tFloat: - fmt.Printf("%g", floatFromBits(decodeUint(dec.state))) + fmt.Printf("%g\n", floatFromBits(dec.state.decodeUint())) case tBytes: - b := make([]byte, decodeUint(dec.state)) + b := make([]byte, dec.state.decodeUint()) dec.state.b.Read(b) - fmt.Printf("% x", b) + fmt.Printf("% x\n", b) case tString: - b := make([]byte, decodeUint(dec.state)) + b := make([]byte, dec.state.decodeUint()) + dec.state.b.Read(b) + fmt.Printf("%q\n", b) + case tInterface: + b := make([]byte, dec.state.decodeUint()) dec.state.b.Read(b) - fmt.Printf("%q", b) + if len(b) == 0 { + fmt.Printf("nil interface") + } else { + fmt.Printf("interface value; type %q\n", b) + dec.debugFromBuffer(indent, true) + } default: - fmt.Print("unknown") + fmt.Print("unknown\n") } - fmt.Print("\n") } -func (dec *Decoder) printStruct(indent int, wire *wireType) { - strct := wire.strct - state := newDecodeState(dec.state.b) +func (dec *Decoder) debugStruct(indent int, id typeId, wire *wireType) { + tab(indent) + fmt.Printf("%s struct {\n", id.name()) + strct := wire.StructT + state := newDecodeState(dec, dec.state.b) state.fieldnum = -1 - for state.err == nil { - delta := int(decodeUint(state)) + for dec.err == nil { + delta := int(state.decodeUint()) if delta < 0 { - dec.state.err = os.ErrorString("gob decode: corrupted data: negative delta") - return + errorf("gob decode: corrupted data: negative delta") } - if state.err != nil || delta == 0 { // struct terminator is zero delta fieldnum - return + if delta == 0 { // struct terminator is zero delta fieldnum + break } - fieldnum := state.fieldnum + delta - if fieldnum < 0 || fieldnum >= len(strct.field) { - dec.state.err = os.ErrorString("field number out of range") - return + fieldNum := state.fieldnum + delta + if fieldNum < 0 || fieldNum >= len(strct.Field) { + errorf("field number out of range") + break } tab(indent) - fmt.Printf("field %d:\n", fieldnum) - dec.printData(indent+1, strct.field[fieldnum].id) - state.fieldnum = fieldnum + fmt.Printf("%s(%d):\n", wire.StructT.Field[fieldNum].Name, fieldNum) + dec.printItem(indent+1, strct.Field[fieldNum].Id) + state.fieldnum = fieldNum } + tab(indent) + fmt.Printf(" } // end %s struct\n", id.name()) } func tab(indent int) { - for i := 0; i < indent; i++ { - fmt.Print("\t") + for i, w := 0, 0; i < indent; i += w { + w = 10 + if i+w > indent { + w = indent - i + } + fmt.Print("\t\t\t\t\t\t\t\t\t\t"[:w]) } } diff --git a/src/pkg/gob/decode.go b/src/pkg/gob/decode.go index a70799e9a..f88ca72da 100644 --- a/src/pkg/gob/decode.go +++ b/src/pkg/gob/decode.go @@ -13,7 +13,9 @@ import ( "math" "os" "reflect" + "unicode" "unsafe" + "utf8" ) var ( @@ -22,16 +24,20 @@ var ( errRange = os.ErrorString("gob: internal error: field numbers out of bounds") ) -// The global execution state of an instance of the decoder. +// The execution state of an instance of the decoder. A new state +// is created for nested objects. type decodeState struct { - b *bytes.Buffer - err os.Error + 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(b *bytes.Buffer) *decodeState { +func newDecodeState(dec *Decoder, b **bytes.Buffer) *decodeState { d := new(decodeState) + d.dec = dec d.b = b d.buf = make([]byte, uint64Size) return d @@ -74,24 +80,23 @@ func decodeUintReader(r io.Reader, buf []byte) (x uint64, err os.Error) { } // decodeUint reads an encoded unsigned integer from state.r. -// Sets state.err. If state.err is already non-nil, it does nothing. // Does not check for overflow. -func decodeUint(state *decodeState) (x uint64) { - if state.err != nil { - return +func (state *decodeState) decodeUint() (x uint64) { + b, err := state.b.ReadByte() + if err != nil { + error(err) } - var b uint8 - b, state.err = state.b.ReadByte() - if b <= 0x7f { // includes state.err != nil + if b <= 0x7f { return uint64(b) } nb := -int(int8(b)) if nb > uint64Size { - state.err = errBadUint - return + error(errBadUint) + } + n, err := state.b.Read(state.buf[0:nb]) + if err != nil { + error(err) } - var n int - n, state.err = state.b.Read(state.buf[0:nb]) // 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++ { @@ -102,13 +107,9 @@ func decodeUint(state *decodeState) (x uint64) { } // decodeInt reads an encoded signed integer from state.r. -// Sets state.err. If state.err is already non-nil, it does nothing. // Does not check for overflow. -func decodeInt(state *decodeState) int64 { - x := decodeUint(state) - if state.err != nil { - return 0 - } +func (state *decodeState) decodeInt() int64 { + x := state.decodeUint() if x&1 != 0 { return ^int64(x >> 1) } @@ -146,12 +147,12 @@ func decIndirect(p unsafe.Pointer, indir int) unsafe.Pointer { } func ignoreUint(i *decInstr, state *decodeState, p unsafe.Pointer) { - decodeUint(state) + state.decodeUint() } func ignoreTwoUints(i *decInstr, state *decodeState, p unsafe.Pointer) { - decodeUint(state) - decodeUint(state) + state.decodeUint() + state.decodeUint() } func decBool(i *decInstr, state *decodeState, p unsafe.Pointer) { @@ -161,7 +162,7 @@ func decBool(i *decInstr, state *decodeState, p unsafe.Pointer) { } p = *(*unsafe.Pointer)(p) } - *(*bool)(p) = decodeInt(state) != 0 + *(*bool)(p) = state.decodeInt() != 0 } func decInt8(i *decInstr, state *decodeState, p unsafe.Pointer) { @@ -171,9 +172,9 @@ func decInt8(i *decInstr, state *decodeState, p unsafe.Pointer) { } p = *(*unsafe.Pointer)(p) } - v := decodeInt(state) + v := state.decodeInt() if v < math.MinInt8 || math.MaxInt8 < v { - state.err = i.ovfl + error(i.ovfl) } else { *(*int8)(p) = int8(v) } @@ -186,9 +187,9 @@ func decUint8(i *decInstr, state *decodeState, p unsafe.Pointer) { } p = *(*unsafe.Pointer)(p) } - v := decodeUint(state) + v := state.decodeUint() if math.MaxUint8 < v { - state.err = i.ovfl + error(i.ovfl) } else { *(*uint8)(p) = uint8(v) } @@ -201,9 +202,9 @@ func decInt16(i *decInstr, state *decodeState, p unsafe.Pointer) { } p = *(*unsafe.Pointer)(p) } - v := decodeInt(state) + v := state.decodeInt() if v < math.MinInt16 || math.MaxInt16 < v { - state.err = i.ovfl + error(i.ovfl) } else { *(*int16)(p) = int16(v) } @@ -216,9 +217,9 @@ func decUint16(i *decInstr, state *decodeState, p unsafe.Pointer) { } p = *(*unsafe.Pointer)(p) } - v := decodeUint(state) + v := state.decodeUint() if math.MaxUint16 < v { - state.err = i.ovfl + error(i.ovfl) } else { *(*uint16)(p) = uint16(v) } @@ -231,9 +232,9 @@ func decInt32(i *decInstr, state *decodeState, p unsafe.Pointer) { } p = *(*unsafe.Pointer)(p) } - v := decodeInt(state) + v := state.decodeInt() if v < math.MinInt32 || math.MaxInt32 < v { - state.err = i.ovfl + error(i.ovfl) } else { *(*int32)(p) = int32(v) } @@ -246,9 +247,9 @@ func decUint32(i *decInstr, state *decodeState, p unsafe.Pointer) { } p = *(*unsafe.Pointer)(p) } - v := decodeUint(state) + v := state.decodeUint() if math.MaxUint32 < v { - state.err = i.ovfl + error(i.ovfl) } else { *(*uint32)(p) = uint32(v) } @@ -261,7 +262,7 @@ func decInt64(i *decInstr, state *decodeState, p unsafe.Pointer) { } p = *(*unsafe.Pointer)(p) } - *(*int64)(p) = int64(decodeInt(state)) + *(*int64)(p) = int64(state.decodeInt()) } func decUint64(i *decInstr, state *decodeState, p unsafe.Pointer) { @@ -271,7 +272,7 @@ func decUint64(i *decInstr, state *decodeState, p unsafe.Pointer) { } p = *(*unsafe.Pointer)(p) } - *(*uint64)(p) = uint64(decodeUint(state)) + *(*uint64)(p) = uint64(state.decodeUint()) } // Floating-point numbers are transmitted as uint64s holding the bits @@ -290,14 +291,14 @@ func floatFromBits(u uint64) float64 { } func storeFloat32(i *decInstr, state *decodeState, p unsafe.Pointer) { - v := floatFromBits(decodeUint(state)) + 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 { - state.err = i.ovfl + error(i.ovfl) } else { *(*float32)(p) = float32(v) } @@ -320,7 +321,7 @@ func decFloat64(i *decInstr, state *decodeState, p unsafe.Pointer) { } p = *(*unsafe.Pointer)(p) } - *(*float64)(p) = floatFromBits(uint64(decodeUint(state))) + *(*float64)(p) = floatFromBits(uint64(state.decodeUint())) } // Complex numbers are just a pair of floating-point numbers, real part first. @@ -342,8 +343,8 @@ func decComplex128(i *decInstr, state *decodeState, p unsafe.Pointer) { } p = *(*unsafe.Pointer)(p) } - real := floatFromBits(uint64(decodeUint(state))) - imag := floatFromBits(uint64(decodeUint(state))) + real := floatFromBits(uint64(state.decodeUint())) + imag := floatFromBits(uint64(state.decodeUint())) *(*complex128)(p) = cmplx(real, imag) } @@ -355,7 +356,7 @@ func decUint8Array(i *decInstr, state *decodeState, p unsafe.Pointer) { } p = *(*unsafe.Pointer)(p) } - b := make([]uint8, decodeUint(state)) + b := make([]uint8, state.decodeUint()) state.b.Read(b) *(*[]uint8)(p) = b } @@ -368,13 +369,13 @@ func decString(i *decInstr, state *decodeState, p unsafe.Pointer) { } p = *(*unsafe.Pointer)(p) } - b := make([]byte, decodeUint(state)) + 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, decodeUint(state)) + b := make([]byte, state.decodeUint()) state.b.Read(b) } @@ -404,15 +405,15 @@ func allocate(rtyp reflect.Type, p uintptr, indir int) uintptr { return *(*uintptr)(up) } -func decodeSingle(engine *decEngine, rtyp reflect.Type, b *bytes.Buffer, p uintptr, indir int) os.Error { +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(b) + state := newDecodeState(dec, b) state.fieldnum = singletonField basep := p - delta := int(decodeUint(state)) + delta := int(state.decodeUint()) if delta != 0 { - state.err = os.ErrorString("gob decode: corrupted data: non-zero delta for singleton") - return state.err + errorf("gob decode: corrupted data: non-zero delta for singleton") } instr := &engine.instr[singletonField] ptr := unsafe.Pointer(basep) // offset will be zero @@ -420,26 +421,26 @@ func decodeSingle(engine *decEngine, rtyp reflect.Type, b *bytes.Buffer, p uintp ptr = decIndirect(ptr, instr.indir) } instr.op(instr, state, ptr) - return state.err + return nil } -func decodeStruct(engine *decEngine, rtyp *reflect.StructType, b *bytes.Buffer, p uintptr, indir int) os.Error { +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(b) + state := newDecodeState(dec, b) state.fieldnum = -1 basep := p - for state.err == nil { - delta := int(decodeUint(state)) + for state.b.Len() > 0 { + delta := int(state.decodeUint()) if delta < 0 { - state.err = os.ErrorString("gob decode: corrupted data: negative delta") - break + errorf("gob decode: corrupted data: negative delta") } - if state.err != nil || delta == 0 { // struct terminator is zero delta fieldnum + if delta == 0 { // struct terminator is zero delta fieldnum break } fieldnum := state.fieldnum + delta if fieldnum >= len(engine.instr) { - state.err = errRange + error(errRange) break } instr := &engine.instr[fieldnum] @@ -450,36 +451,35 @@ func decodeStruct(engine *decEngine, rtyp *reflect.StructType, b *bytes.Buffer, instr.op(instr, state, p) state.fieldnum = fieldnum } - return state.err + return nil } -func ignoreStruct(engine *decEngine, b *bytes.Buffer) os.Error { - state := newDecodeState(b) +func (dec *Decoder) ignoreStruct(engine *decEngine, b **bytes.Buffer) (err os.Error) { + defer catchError(&err) + state := newDecodeState(dec, b) state.fieldnum = -1 - for state.err == nil { - delta := int(decodeUint(state)) + for state.b.Len() > 0 { + delta := int(state.decodeUint()) if delta < 0 { - state.err = os.ErrorString("gob ignore decode: corrupted data: negative delta") - break + errorf("gob ignore decode: corrupted data: negative delta") } - if state.err != nil || delta == 0 { // struct terminator is zero delta fieldnum + if delta == 0 { // struct terminator is zero delta fieldnum break } fieldnum := state.fieldnum + delta if fieldnum >= len(engine.instr) { - state.err = errRange - break + error(errRange) } instr := &engine.instr[fieldnum] instr.op(instr, state, unsafe.Pointer(nil)) state.fieldnum = fieldnum } - return state.err + return nil } -func decodeArrayHelper(state *decodeState, p uintptr, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl os.ErrorString) os.Error { +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 && state.err == nil; i++ { + for i := 0; i < length; i++ { up := unsafe.Pointer(p) if elemIndir > 1 { up = decIndirect(up, elemIndir) @@ -487,17 +487,16 @@ func decodeArrayHelper(state *decodeState, p uintptr, elemOp decOp, elemWid uint elemOp(instr, state, up) p += uintptr(elemWid) } - return state.err } -func decodeArray(atyp *reflect.ArrayType, state *decodeState, p uintptr, elemOp decOp, elemWid uintptr, length, indir, elemIndir int, ovfl os.ErrorString) os.Error { +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 := decodeUint(state); n != uint64(length) { - return os.ErrorString("gob: length mismatch in decodeArray") + if n := state.decodeUint(); n != uint64(length) { + errorf("gob: length mismatch in decodeArray") } - return decodeArrayHelper(state, p, elemOp, elemWid, length, elemIndir, ovfl) + 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 { @@ -510,7 +509,7 @@ func decodeIntoValue(state *decodeState, op decOp, indir int, v reflect.Value, o return v } -func decodeMap(mtyp *reflect.MapType, state *decodeState, p uintptr, keyOp, elemOp decOp, indir, keyIndir, elemIndir int, ovfl os.ErrorString) os.Error { +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 } @@ -523,50 +522,40 @@ func decodeMap(mtyp *reflect.MapType, state *decodeState, p uintptr, keyOp, elem // 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(decodeUint(state)) - for i := 0; i < n && state.err == nil; i++ { + n := int(state.decodeUint()) + for i := 0; i < n; i++ { key := decodeIntoValue(state, keyOp, keyIndir, reflect.MakeZero(mtyp.Key()), ovfl) - if state.err != nil { - break - } elem := decodeIntoValue(state, elemOp, elemIndir, reflect.MakeZero(mtyp.Elem()), ovfl) - if state.err != nil { - break - } v.SetElem(key, elem) } - return state.err } -func ignoreArrayHelper(state *decodeState, elemOp decOp, length int) os.Error { +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 && state.err == nil; i++ { + for i := 0; i < length; i++ { elemOp(instr, state, nil) } - return state.err } -func ignoreArray(state *decodeState, elemOp decOp, length int) os.Error { - if n := decodeUint(state); n != uint64(length) { - return os.ErrorString("gob: length mismatch in ignoreArray") +func (dec *Decoder) ignoreArray(state *decodeState, elemOp decOp, length int) { + if n := state.decodeUint(); n != uint64(length) { + errorf("gob: length mismatch in ignoreArray") } - return ignoreArrayHelper(state, elemOp, length) + dec.ignoreArrayHelper(state, elemOp, length) } -func ignoreMap(state *decodeState, keyOp, elemOp decOp) os.Error { - n := int(decodeUint(state)) +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 && state.err == nil; i++ { + for i := 0; i < n; i++ { keyOp(keyInstr, state, nil) elemOp(elemInstr, state, nil) } - return state.err } - -func decodeSlice(atyp *reflect.SliceType, state *decodeState, p uintptr, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl os.ErrorString) os.Error { - n := int(uintptr(decodeUint(state))) +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 { @@ -581,11 +570,77 @@ func decodeSlice(atyp *reflect.SliceType, state *decodeState, p uintptr, elemOp hdrp.Data = uintptr(unsafe.NewArray(atyp.Elem(), n)) hdrp.Len = n hdrp.Cap = n - return decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, n, elemIndir, ovfl) + dec.decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, n, elemIndir, ovfl) } -func ignoreSlice(state *decodeState, elemOp decOp) os.Error { - return ignoreArrayHelper(state, elemOp, int(decodeUint(state))) +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. @@ -608,17 +663,18 @@ var decOpMap = []decOp{ // 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, + 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, os.Error) { +func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string) (decOp, int) { typ, indir := indirect(rt) var op decOp k := typ.Kind() @@ -630,32 +686,23 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string) (decOp switch t := typ.(type) { case *reflect.ArrayType: name = "element of " + name - elemId := dec.wireType[wireId].arrayT.Elem - elemOp, elemIndir, err := dec.decOpFor(elemId, t.Elem(), name) - if err != nil { - return nil, 0, err - } + 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.err = decodeArray(t, state, uintptr(p), elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl) + 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, err := dec.decOpFor(keyId, t.Key(), name) - if err != nil { - return nil, 0, err - } - elemOp, elemIndir, err := dec.decOpFor(elemId, t.Elem(), name) - if err != nil { - return nil, 0, err - } + 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.err = decodeMap(t, state, uintptr(up), keyOp, elemOp, i.indir, keyIndir, elemIndir, ovfl) + state.dec.decodeMap(t, state, uintptr(up), keyOp, elemOp, i.indir, keyIndir, elemIndir, ovfl) } case *reflect.SliceType: @@ -668,111 +715,105 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string) (decOp if tt, ok := builtinIdToType[wireId]; ok { elemId = tt.(*sliceType).Elem } else { - elemId = dec.wireType[wireId].sliceT.Elem - } - elemOp, elemIndir, err := dec.decOpFor(elemId, t.Elem(), name) - if err != nil { - return nil, 0, err + 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.err = decodeSlice(t, state, uintptr(p), elemOp, t.Elem().Size(), i.indir, elemIndir, ovfl) + 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 { - return nil, 0, err + error(err) } op = func(i *decInstr, state *decodeState, p unsafe.Pointer) { // indirect through enginePtr to delay evaluation for recursive structs - state.err = decodeStruct(*enginePtr, t, state.b, uintptr(p), i.indir) + 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 { - return nil, 0, os.ErrorString("gob: decode can't handle type " + rt.String()) + errorf("gob: decode can't handle type %s", rt.String()) } - return op, indir, nil + return op, indir } // Return the decoding op for a field that has no destination. -func (dec *Decoder) decIgnoreOpFor(wireId typeId) (decOp, os.Error) { +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, err := dec.decIgnoreOpFor(elemId) - if err != nil { - return nil, err - } + case wire.ArrayT != nil: + elemId := wire.ArrayT.Elem + elemOp := dec.decIgnoreOpFor(elemId) op = func(i *decInstr, state *decodeState, p unsafe.Pointer) { - state.err = ignoreArray(state, elemOp, wire.arrayT.Len) + 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, err := dec.decIgnoreOpFor(keyId) - if err != nil { - return nil, err - } - elemOp, err := dec.decIgnoreOpFor(elemId) - if err != nil { - return nil, err - } + 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.err = ignoreMap(state, keyOp, elemOp) + state.dec.ignoreMap(state, keyOp, elemOp) } - case wire.sliceT != nil: - elemId := wire.sliceT.Elem - elemOp, err := dec.decIgnoreOpFor(elemId) - if err != nil { - return nil, err - } + case wire.SliceT != nil: + elemId := wire.SliceT.Elem + elemOp := dec.decIgnoreOpFor(elemId) op = func(i *decInstr, state *decodeState, p unsafe.Pointer) { - state.err = ignoreSlice(state, elemOp) + state.dec.ignoreSlice(state, elemOp) } - case wire.structT != nil: + 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 { - return nil, err + error(err) } op = func(i *decInstr, state *decodeState, p unsafe.Pointer) { // indirect through enginePtr to delay evaluation for recursive structs - state.err = ignoreStruct(*enginePtr, state.b) + state.dec.ignoreStruct(*enginePtr, state.b) } } } if op == nil { - return nil, os.ErrorString("ignore can't handle type " + wireId.string()) + errorf("ignore can't handle type %s", wireId.string()) } - return op, nil + 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 { - for { - if pt, ok := fr.(*reflect.PtrType); ok { - fr = pt.Elem() - continue - } - break - } + fr, _ = indirect(fr) switch t := fr.(type) { default: - // interface, map, chan, etc: cannot handle. + // map, chan, etc: cannot handle. return false case *reflect.BoolType: return fw == tBool @@ -786,20 +827,22 @@ func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId) bool { 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 { + if !ok || wire.ArrayT == nil { return false } - array := wire.arrayT + 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 { + if !ok || wire.MapT == nil { return false } - mapType := wire.mapT - return dec.compatibleType(t.Key(), mapType.Key) && dec.compatibleType(t.Elem(), mapType.Elem) + 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 { @@ -810,7 +853,7 @@ func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId) bool { if tt, ok := builtinIdToType[fw]; ok { sw = tt.(*sliceType) } else { - sw = dec.wireType[fw].sliceT + sw = dec.wireType[fw].SliceT } elem, _ := indirect(t.Elem()) return sw != nil && dec.compatibleType(elem, sw.Elem) @@ -820,61 +863,74 @@ func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId) bool { 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) - } - op, indir, err := dec.decOpFor(remoteId, rt, name) - if err != nil { - return nil, err + 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 + // 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) + wireStruct, _ = t.(*structType) } else { - wireStruct = dec.wireType[remoteId].structT + 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)) + 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] + 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) - ovfl := overflow(wireField.name) + localField, present := srt.FieldByName(wireField.Name) // TODO(r): anonymous names - if !present { - op, err := dec.decIgnoreOpFor(wireField.id) - if err != nil { - return nil, err - } + 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) { - return nil, os.ErrorString("gob: wrong type (" + - localField.Type.String() + ") for received field " + - wireStruct.name + "." + wireField.name) - } - op, indir, err := dec.decOpFor(wireField.id, localField.Type, localField.Name) - if err != nil { - return nil, err + 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++ } @@ -899,7 +955,7 @@ func (dec *Decoder) getDecEnginePtr(remoteId typeId, rt reflect.Type) (enginePtr return } -// When ignoring data, in effect we compile it into this type +// When ignoring struct data, in effect we compile it into this type type emptyStruct struct{} var emptyStructType = reflect.Typeof(emptyStruct{}) @@ -927,13 +983,13 @@ func (dec *Decoder) decode(wireId typeId, val reflect.Value) os.Error { } engine := *enginePtr if st, ok := rt.(*reflect.StructType); ok { - if engine.numInstr == 0 && st.NumField() > 0 && len(dec.wireType[wireId].structT.field) > 0 { + 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 decodeStruct(engine, st, dec.state.b, uintptr(val.Addr()), indir) + return dec.decodeStruct(engine, st, dec.state.b, uintptr(val.Addr()), indir) } - return decodeSingle(engine, rt, dec.state.b, uintptr(val.Addr()), indir) + return dec.decodeSingle(engine, rt, dec.state.b, uintptr(val.Addr()), indir) } func init() { diff --git a/src/pkg/gob/decoder.go b/src/pkg/gob/decoder.go index cf16433eb..664001a4b 100644 --- a/src/pkg/gob/decoder.go +++ b/src/pkg/gob/decoder.go @@ -24,6 +24,8 @@ type Decoder struct { 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. @@ -31,25 +33,32 @@ func NewDecoder(r io.Reader) *Decoder { dec := new(Decoder) dec.r = r dec.wireType = make(map[typeId]*wireType) - dec.state = newDecodeState(nil) // buffer set in Decode(); rest is unimportant + 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.state.err = os.ErrorString("gob: duplicate type received") + dec.err = os.ErrorString("gob: duplicate type received") return } // Type: wire := new(wireType) - dec.state.err = dec.decode(tWireType, reflect.NewValue(wire)) + 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 @@ -61,69 +70,95 @@ func (dec *Decoder) Decode(e interface{}) os.Error { // 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.state.err = os.ErrorString("gob: attempt to decode into a non-pointer") - return dec.state.err + dec.err = os.ErrorString("gob: attempt to decode into a non-pointer") + return dec.err } return dec.DecodeValue(value) } -// 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.state.err = nil - for { - // Read a count. - var nbytes uint64 - nbytes, dec.state.err = decodeUintReader(dec.r, dec.countBuf[0:]) - if dec.state.err != nil { - break - } - // Allocate the buffer. - if nbytes > uint64(len(dec.buf)) { - dec.buf = make([]byte, nbytes+1000) - } - dec.state.b = bytes.NewBuffer(dec.buf[0:nbytes]) +// 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.state.err = io.ReadFull(dec.r, dec.buf[0:nbytes]) - if dec.state.err != nil { - if dec.state.err == os.EOF { - dec.state.err = io.ErrUnexpectedEOF - } - break + // 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(decodeInt(dec.state)) - if dec.state.err != nil { - break - } + 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.state.err != nil { + if dec.err != nil { break } continue } - // No, it's a value. // 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.state.err = errBadType + dec.err = errBadType break } - dec.state.err = dec.decode(id, value) + // 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 } - return dec.state.err } + +// 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/src/pkg/gob/doc.go b/src/pkg/gob/doc.go new file mode 100644 index 000000000..31253f16d --- /dev/null +++ b/src/pkg/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/src/pkg/gob/encode.go b/src/pkg/gob/encode.go index 00548868b..3431eafa7 100644 --- a/src/pkg/gob/encode.go +++ b/src/pkg/gob/encode.go @@ -2,270 +2,8 @@ // 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). - - Interfaces, 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 0E). 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). - - 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 { - s structType; - } - type fieldType struct { - name string; // the name of the field. - id int; // the type id of the field, which must be already defined - } - type commonType { - name string; // the name of the struct type - id int; // the id of the type, repeated for so it's inside the type - } - type structType struct { - commonType; - field []fieldType; // the fields of the struct. - } - - 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 - wireType 7 - structType 8 - commonType 9 - fieldType 10 - - In summary, a gob stream looks like - - ((-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 {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 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 zero; this is done at the beginning - // of every struct, including nested structs. - 03 // Add 3 to field number; now 3 (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 1); start of embedded commonType. - 01 // add one to field number (now 1, the name of the type) - 05 // string is (unsigned) 5 bytes long - 50 6f 69 6e 74 // wireType.structType.commonType.name = "Point" - 01 // add one to field number (now 2, the id of the type) - ff 82 // wireType.structType.commonType._id = 65 - 00 // end of embedded wiretype.structType.commonType struct - 01 // add one to field number (now 2, 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 1: field[0].name - 01 // 1 byte - 78 // structType.field[0].name = "x" - 01 // Add 1 to get field number 2: 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 0. - 01 // Add 1 to get field number 1: field[1].name - 01 // 1 byte - 79 // structType.field[1].name = "y" - 01 // Add 1 to get field number 2: 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 zero: - - 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 1 - 2c // encoding of signed "22" (0x22 = 44 = 22<<1); Point.x = 22 - 01 // add one to field number, yielding field 2 - 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 - -*/ - import ( "bytes" "io" @@ -282,26 +20,29 @@ const uint64Size = unsafe.Sizeof(uint64(0)) // 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 - err os.Error // error encountered during encoding. 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. Sets state.err. -// If state.err is already non-nil, it does nothing. -func encodeUint(state *encoderState, x uint64) { - if state.err != nil { - return - } +// encodeUint writes an encoded unsigned integer to state.b. +func (state *encoderState) encodeUint(x uint64) { if x <= 0x7F { - state.err = state.b.WriteByte(uint8(x)) + err := state.b.WriteByte(uint8(x)) + if err != nil { + error(err) + } return } var n, m int @@ -312,20 +53,23 @@ func encodeUint(state *encoderState, x uint64) { m-- } state.buf[m] = uint8(-(n - 1)) - n, state.err = state.b.Write(state.buf[m : uint64Size+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. -// Sets state.err. If state.err is already non-nil, it does nothing. -func encodeInt(state *encoderState, i int64) { +// 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) } - encodeUint(state, uint64(x)) + state.encodeUint(uint64(x)) } type encOp func(i *encInstr, state *encoderState, p unsafe.Pointer) @@ -342,7 +86,7 @@ type encInstr struct { // If the instruction pointer is nil, do nothing func (state *encoderState) update(instr *encInstr) { if instr != nil { - encodeUint(state, uint64(instr.field-state.fieldnum)) + state.encodeUint(uint64(instr.field - state.fieldnum)) state.fieldnum = instr.field } } @@ -368,9 +112,9 @@ func encBool(i *encInstr, state *encoderState, p unsafe.Pointer) { if b || state.sendZero { state.update(i) if b { - encodeUint(state, 1) + state.encodeUint(1) } else { - encodeUint(state, 0) + state.encodeUint(0) } } } @@ -379,7 +123,7 @@ func encInt(i *encInstr, state *encoderState, p unsafe.Pointer) { v := int64(*(*int)(p)) if v != 0 || state.sendZero { state.update(i) - encodeInt(state, v) + state.encodeInt(v) } } @@ -387,7 +131,7 @@ func encUint(i *encInstr, state *encoderState, p unsafe.Pointer) { v := uint64(*(*uint)(p)) if v != 0 || state.sendZero { state.update(i) - encodeUint(state, v) + state.encodeUint(v) } } @@ -395,7 +139,7 @@ func encInt8(i *encInstr, state *encoderState, p unsafe.Pointer) { v := int64(*(*int8)(p)) if v != 0 || state.sendZero { state.update(i) - encodeInt(state, v) + state.encodeInt(v) } } @@ -403,7 +147,7 @@ func encUint8(i *encInstr, state *encoderState, p unsafe.Pointer) { v := uint64(*(*uint8)(p)) if v != 0 || state.sendZero { state.update(i) - encodeUint(state, v) + state.encodeUint(v) } } @@ -411,7 +155,7 @@ func encInt16(i *encInstr, state *encoderState, p unsafe.Pointer) { v := int64(*(*int16)(p)) if v != 0 || state.sendZero { state.update(i) - encodeInt(state, v) + state.encodeInt(v) } } @@ -419,7 +163,7 @@ func encUint16(i *encInstr, state *encoderState, p unsafe.Pointer) { v := uint64(*(*uint16)(p)) if v != 0 || state.sendZero { state.update(i) - encodeUint(state, v) + state.encodeUint(v) } } @@ -427,7 +171,7 @@ func encInt32(i *encInstr, state *encoderState, p unsafe.Pointer) { v := int64(*(*int32)(p)) if v != 0 || state.sendZero { state.update(i) - encodeInt(state, v) + state.encodeInt(v) } } @@ -435,7 +179,7 @@ func encUint32(i *encInstr, state *encoderState, p unsafe.Pointer) { v := uint64(*(*uint32)(p)) if v != 0 || state.sendZero { state.update(i) - encodeUint(state, v) + state.encodeUint(v) } } @@ -443,7 +187,7 @@ func encInt64(i *encInstr, state *encoderState, p unsafe.Pointer) { v := *(*int64)(p) if v != 0 || state.sendZero { state.update(i) - encodeInt(state, v) + state.encodeInt(v) } } @@ -451,7 +195,7 @@ func encUint64(i *encInstr, state *encoderState, p unsafe.Pointer) { v := *(*uint64)(p) if v != 0 || state.sendZero { state.update(i) - encodeUint(state, v) + state.encodeUint(v) } } @@ -459,7 +203,7 @@ func encUintptr(i *encInstr, state *encoderState, p unsafe.Pointer) { v := uint64(*(*uintptr)(p)) if v != 0 || state.sendZero { state.update(i) - encodeUint(state, v) + state.encodeUint(v) } } @@ -484,7 +228,7 @@ func encFloat(i *encInstr, state *encoderState, p unsafe.Pointer) { if f != 0 || state.sendZero { v := floatBits(float64(f)) state.update(i) - encodeUint(state, v) + state.encodeUint(v) } } @@ -493,7 +237,7 @@ func encFloat32(i *encInstr, state *encoderState, p unsafe.Pointer) { if f != 0 || state.sendZero { v := floatBits(float64(f)) state.update(i) - encodeUint(state, v) + state.encodeUint(v) } } @@ -502,7 +246,7 @@ func encFloat64(i *encInstr, state *encoderState, p unsafe.Pointer) { if f != 0 || state.sendZero { state.update(i) v := floatBits(f) - encodeUint(state, v) + state.encodeUint(v) } } @@ -513,8 +257,8 @@ func encComplex(i *encInstr, state *encoderState, p unsafe.Pointer) { rpart := floatBits(float64(real(c))) ipart := floatBits(float64(imag(c))) state.update(i) - encodeUint(state, rpart) - encodeUint(state, ipart) + state.encodeUint(rpart) + state.encodeUint(ipart) } } @@ -524,8 +268,8 @@ func encComplex64(i *encInstr, state *encoderState, p unsafe.Pointer) { rpart := floatBits(float64(real(c))) ipart := floatBits(float64(imag(c))) state.update(i) - encodeUint(state, rpart) - encodeUint(state, ipart) + state.encodeUint(rpart) + state.encodeUint(ipart) } } @@ -535,17 +279,20 @@ func encComplex128(i *encInstr, state *encoderState, p unsafe.Pointer) { rpart := floatBits(real(c)) ipart := floatBits(imag(c)) state.update(i) - encodeUint(state, rpart) - encodeUint(state, ipart) + 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) - encodeUint(state, uint64(len(b))) + state.encodeUint(uint64(len(b))) state.b.Write(b) } } @@ -555,14 +302,14 @@ func encString(i *encInstr, state *encoderState, p unsafe.Pointer) { s := *(*string)(p) if len(s) > 0 || state.sendZero { state.update(i) - encodeUint(state, uint64(len(s))) + 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) { - encodeUint(state, 0) + state.encodeUint(0) } // Execution engine @@ -575,9 +322,8 @@ type encEngine struct { const singletonField = 0 -func encodeSingle(engine *encEngine, b *bytes.Buffer, basep uintptr) os.Error { - state := new(encoderState) - state.b = b +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. @@ -586,16 +332,14 @@ func encodeSingle(engine *encEngine, b *bytes.Buffer, basep uintptr) os.Error { p := unsafe.Pointer(basep) // offset will be zero if instr.indir > 0 { if p = encIndirect(p, instr.indir); p == nil { - return nil + return } } instr.op(instr, state, p) - return state.err } -func encodeStruct(engine *encEngine, b *bytes.Buffer, basep uintptr) os.Error { - state := new(encoderState) - state.b = b +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] @@ -606,33 +350,26 @@ func encodeStruct(engine *encEngine, b *bytes.Buffer, basep uintptr) os.Error { } } instr.op(instr, state, p) - if state.err != nil { - break - } } - return state.err } -func encodeArray(b *bytes.Buffer, p uintptr, op encOp, elemWid uintptr, elemIndir int, length int) os.Error { - state := new(encoderState) - state.b = b +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 - encodeUint(state, uint64(length)) - for i := 0; i < length && state.err == nil; i++ { + 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 { - state.err = os.ErrorString("gob: encodeArray: nil element") - break + errorf("gob: encodeArray: nil element") } elemp = uintptr(up) } op(nil, state, unsafe.Pointer(elemp)) p += uintptr(elemWid) } - return state.err } func encodeReflectValue(state *encoderState, v reflect.Value, op encOp, indir int) { @@ -640,27 +377,60 @@ func encodeReflectValue(state *encoderState, v reflect.Value, op encOp, indir in v = reflect.Indirect(v) } if v == nil { - state.err = os.ErrorString("gob: encodeReflectValue: nil element") - return + errorf("gob: encodeReflectValue: nil element") } op(nil, state, unsafe.Pointer(v.Addr())) } -func encodeMap(b *bytes.Buffer, mv *reflect.MapValue, keyOp, elemOp encOp, keyIndir, elemIndir int) os.Error { - state := new(encoderState) - state.b = b +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() - encodeUint(state, uint64(len(keys))) + state.encodeUint(uint64(len(keys))) for _, key := range keys { - if state.err != nil { - break - } encodeReflectValue(state, key, keyOp, keyIndir) encodeReflectValue(state, mv.Elem(key), elemOp, elemIndir) } - return state.err +} + +// 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{ @@ -687,7 +457,7 @@ var encOpMap = []encOp{ // Return the encoding op for the base type under rt and // the indirection count to reach it. -func encOpFor(rt reflect.Type) (encOp, int, os.Error) { +func (enc *Encoder) encOpFor(rt reflect.Type) (encOp, int) { typ, indir := indirect(rt) var op encOp k := typ.Kind() @@ -703,128 +473,123 @@ func encOpFor(rt reflect.Type) (encOp, int, os.Error) { break } // Slices have a header; we decode it to find the underlying array. - elemOp, indir, err := encOpFor(t.Elem()) - if err != nil { - return nil, 0, err - } + elemOp, indir := enc.encOpFor(t.Elem()) op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { slice := (*reflect.SliceHeader)(p) - if slice.Len == 0 { + if !state.sendZero && slice.Len == 0 { return } state.update(i) - state.err = encodeArray(state.b, slice.Data, elemOp, t.Elem().Size(), indir, int(slice.Len)) + 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, err := encOpFor(t.Elem()) - if err != nil { - return nil, 0, err - } + elemOp, indir := enc.encOpFor(t.Elem()) op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { - slice := (*reflect.SliceHeader)(p) - if slice.Len == 0 { - return - } state.update(i) - state.err = encodeArray(state.b, uintptr(p), elemOp, t.Elem().Size(), indir, t.Len()) + state.enc.encodeArray(state.b, uintptr(p), elemOp, t.Elem().Size(), indir, t.Len()) } case *reflect.MapType: - keyOp, keyIndir, err := encOpFor(t.Key()) - if err != nil { - return nil, 0, err - } - elemOp, elemIndir, err := encOpFor(t.Elem()) - if err != nil { - return nil, 0, err - } + 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 mv.Len() == 0 { + if !state.sendZero && mv.Len() == 0 { return } state.update(i) - state.err = encodeMap(state.b, mv, keyOp, elemOp, keyIndir, elemIndir) + 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. - _, err := getEncEngine(typ) - if err != nil { - return nil, 0, err - } + 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.err = encodeStruct(info.encoder, state.b, uintptr(p)) + 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 { - return op, indir, os.ErrorString("gob enc: can't happen: encode type " + rt.String()) + errorf("gob enc: can't happen: encode type %s", rt.String()) } - return op, indir, nil + return op, indir } // The local Type was compiled from the actual value, so we know it's compatible. -func compileEnc(rt reflect.Type) (*encEngine, os.Error) { +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, err := encOpFor(f.Type) - if err != nil { - return nil, err + 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, err := encOpFor(rt) - if err != nil { - return nil, err - } + op, indir := enc.encOpFor(rt) engine.instr[0] = encInstr{op, singletonField, indir, 0} // offset is zero } - return engine, nil + 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 getEncEngine(rt reflect.Type) (*encEngine, os.Error) { - info, err := getTypeInfo(rt) - if err != nil { - return nil, err +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, err = compileEnc(rt) + info.encoder = enc.compileEnc(rt) } - return info.encoder, err + 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 encode(b *bytes.Buffer, value reflect.Value) os.Error { +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) } - typeLock.Lock() - engine, err := getEncEngine(rt) - typeLock.Unlock() - if err != nil { - return err - } + engine := enc.lockAndGetEncEngine(rt) if value.Type().Kind() == reflect.Struct { - return encodeStruct(engine, b, value.Addr()) + enc.encodeStruct(b, engine, value.Addr()) + } else { + enc.encodeSingle(b, engine, value.Addr()) } - return encodeSingle(engine, b, value.Addr()) + return nil } diff --git a/src/pkg/gob/encoder.go b/src/pkg/gob/encoder.go index aba8d0e5c..8869b2629 100644 --- a/src/pkg/gob/encoder.go +++ b/src/pkg/gob/encoder.go @@ -21,6 +21,7 @@ type Encoder struct { 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. @@ -28,10 +29,8 @@ func NewEncoder(w io.Writer) *Encoder { enc := new(Encoder) enc.w = w enc.sent = make(map[reflect.Type]typeId) - enc.state = new(encoderState) - enc.state.b = new(bytes.Buffer) // the rest isn't important; all we need is buffer and writer - enc.countState = new(encoderState) - enc.countState.b = new(bytes.Buffer) // the rest isn't important; all we need is buffer and writer + enc.state = newEncoderState(enc, new(bytes.Buffer)) + enc.countState = newEncoderState(enc, new(bytes.Buffer)) return enc } @@ -40,8 +39,8 @@ func (enc *Encoder) badType(rt reflect.Type) { } func (enc *Encoder) setError(err os.Error) { - if enc.state.err == nil { // remember the first. - enc.state.err = err + if enc.err == nil { // remember the first. + enc.err = err } enc.state.b.Reset() } @@ -49,7 +48,7 @@ func (enc *Encoder) setError(err os.Error) { // Send the data item preceded by a unsigned count of its length. func (enc *Encoder) send() { // Encode the length. - encodeUint(enc.countState, uint64(enc.state.b.Len())) + enc.countState.encodeUint(uint64(enc.state.b.Len())) // Build the buffer. countLen := enc.countState.b.Len() total := countLen + enc.state.b.Len() @@ -74,7 +73,7 @@ func (enc *Encoder) sendType(origt reflect.Type) (sent bool) { switch rt := rt.(type) { default: - // Basic types do not need to be described. + // 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. @@ -92,7 +91,7 @@ func (enc *Encoder) sendType(origt reflect.Type) (sent bool) { case *reflect.StructType: // structs must be sent so we know their fields. break - case *reflect.ChanType, *reflect.FuncType, *reflect.InterfaceType: + case *reflect.ChanType, *reflect.FuncType: // Probably a bad field in a struct. enc.badType(rt) return @@ -113,11 +112,11 @@ func (enc *Encoder) sendType(origt reflect.Type) (sent bool) { } // Send the pair (-id, type) // Id: - encodeInt(enc.state, -int64(info.id)) + enc.state.encodeInt(-int64(info.id)) // Type: - encode(enc.state.b, reflect.NewValue(info.wire)) + enc.encode(enc.state.b, reflect.NewValue(info.wire)) enc.send() - if enc.state.err != nil { + if enc.err != nil { return } @@ -134,7 +133,7 @@ func (enc *Encoder) sendType(origt reflect.Type) (sent bool) { case reflect.ArrayOrSliceType: enc.sendType(st.Elem()) } - return + return true } // Encode transmits the data item represented by the empty interface value, @@ -143,30 +142,17 @@ func (enc *Encoder) Encode(e interface{}) os.Error { return enc.EncodeValue(reflect.NewValue(e)) } -// 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.state.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.state.err = os.ErrorString("encoder: buffer not empty") - return enc.state.err - } - +// 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.state.err != nil { - return enc.state.err + 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 @@ -177,22 +163,45 @@ func (enc *Encoder) EncodeValue(value reflect.Value) os.Error { typeLock.Unlock() if err != nil { enc.setError(err) - return err + return } enc.sent[rt] = info.id } } // Identify the type of this top-level value. - encodeInt(enc.state, int64(enc.sent[rt])) + 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 := encode(enc.state.b, value) + err := enc.encode(enc.state.b, value) if err != nil { enc.setError(err) } else { enc.send() } - return enc.state.err + return enc.err } diff --git a/src/pkg/gob/encoder_test.go b/src/pkg/gob/encoder_test.go index b578cd0f8..db0b7db66 100644 --- a/src/pkg/gob/encoder_test.go +++ b/src/pkg/gob/encoder_test.go @@ -14,48 +14,48 @@ import ( ) type ET2 struct { - x string + X string } type ET1 struct { - a int - et2 *ET2 - next *ET1 + 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 + A int + Et2 *ET2 + DifferentNext *ET1 } // Like ET1 but with a different type for a field type ET4 struct { - a int - et2 float - next int + A int + Et2 float + Next int } func TestEncoderDecoder(t *testing.T) { b := new(bytes.Buffer) enc := NewEncoder(b) et1 := new(ET1) - et1.a = 7 - et1.et2 = new(ET2) - enc.Encode(et1) - if enc.state.err != nil { - t.Error("encoder fail:", enc.state.err) + 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) - dec.Decode(newEt1) - if dec.state.err != nil { - t.Fatal("error decoding ET1:", dec.state.err) + 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\n", *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") @@ -63,25 +63,25 @@ func TestEncoderDecoder(t *testing.T) { enc.Encode(et1) newEt1 = new(ET1) - dec.Decode(newEt1) - if dec.state.err != nil { - t.Fatal("round 2: error decoding ET1:", dec.state.err) + 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\n", *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. - enc.Encode(et1) - if enc.state.err != nil { - t.Error("round 3: encoder fail:", enc.state.err) + err = enc.Encode(et1) + if err != nil { + t.Error("round 3: encoder fail:", err) } newEt2 := new(ET2) - dec.Decode(newEt2) - if dec.state.err == nil { + err = dec.Decode(newEt2) + if err == nil { t.Fatal("round 3: expected `bad type' error decoding ET2") } } @@ -92,19 +92,19 @@ 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) - enc.Encode(et1) - if enc.state.err != nil { - t.Error("encoder fail:", enc.state.err) + et1.A = 7 + et1.Et2 = new(ET2) + err := enc.Encode(et1) + if err != nil { + t.Error("encoder fail:", err) } dec := NewDecoder(b) - dec.Decode(e) - if shouldFail && (dec.state.err == nil) { + err = dec.Decode(e) + if shouldFail && err == nil { t.Error("expected error for", msg) } - if !shouldFail && (dec.state.err != nil) { - t.Error("unexpected error for", msg, dec.state.err) + if !shouldFail && err != nil { + t.Error("unexpected error for", msg, err) } } @@ -118,9 +118,9 @@ func TestWrongTypeDecoder(t *testing.T) { func corruptDataCheck(s string, err os.Error, t *testing.T) { b := bytes.NewBufferString(s) dec := NewDecoder(b) - dec.Decode(new(ET2)) - if dec.state.err != err { - t.Error("expected error", err, "got", dec.state.err) + err1 := dec.Decode(new(ET2)) + if err1 != err { + t.Error("expected error", err, "got", err1) } } @@ -135,7 +135,6 @@ func TestBadData(t *testing.T) { var unsupportedValues = []interface{}{ make(chan int), func(a int) bool { return true }, - new(interface{}), } func TestUnsupported(t *testing.T) { @@ -152,14 +151,14 @@ func TestUnsupported(t *testing.T) { func encAndDec(in, out interface{}) os.Error { b := new(bytes.Buffer) enc := NewEncoder(b) - enc.Encode(in) - if enc.state.err != nil { - return enc.state.err + err := enc.Encode(in) + if err != nil { + return err } dec := NewDecoder(b) - dec.Decode(out) - if dec.state.err != nil { - return dec.state.err + err = dec.Decode(out) + if err != nil { + return err } return nil } @@ -167,7 +166,7 @@ func encAndDec(in, out interface{}) os.Error { func TestTypeToPtrType(t *testing.T) { // Encode a T, decode a *T type Type0 struct { - a int + A int } t0 := Type0{7} t0p := (*Type0)(nil) @@ -179,7 +178,7 @@ func TestTypeToPtrType(t *testing.T) { func TestPtrTypeToType(t *testing.T) { // Encode a *T, decode a T type Type1 struct { - a uint + A uint } t1p := &Type1{17} var t1 Type1 @@ -190,26 +189,26 @@ func TestPtrTypeToType(t *testing.T) { func TestTypeToPtrPtrPtrPtrType(t *testing.T) { type Type2 struct { - a ****float + A ****float } t2 := Type2{} - t2.a = new(***float) - *t2.a = new(**float) - **t2.a = new(*float) - ***t2.a = new(float) - ****t2.a = 27.4 + t2.A = new(***float) + *t2.A = new(**float) + **t2.A = new(*float) + ***t2.A = new(float) + ****t2.A = 27.4 t2pppp := new(***Type2) if err := encAndDec(t2, t2pppp); err != nil { - t.Error(err) + t.Fatal(err) } - if ****(****t2pppp).a != ****t2.a { - t.Errorf("wrong value after decode: %g not %g", ****(****t2pppp).a, ****t2.a) + 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 + A []string } t3p := &Type3{[]string{"hello", "world"}} var t3 Type3 @@ -232,11 +231,11 @@ func TestValueError(t *testing.T) { func TestArray(t *testing.T) { type Type5 struct { - a [3]string - b [3]byte + A [3]string + B [3]byte } type Type6 struct { - a [2]string // can't hold t5.a + A [2]string // can't hold t5.a } t5 := Type5{[3]string{"hello", ",", "world"}, [3]byte{1, 2, 3}} var t5p Type5 @@ -252,10 +251,10 @@ func TestArray(t *testing.T) { // 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 []float + B []bool + I []int + S []string + F []float } t7 := Type7{ []bool{false, false, true}, @@ -274,6 +273,7 @@ var testFloat32 float32 var testString string var testSlice []string var testMap map[string]int +var testArray [7]int type SingleTest struct { in interface{} @@ -282,14 +282,16 @@ type SingleTest struct { } var singleTests = []SingleTest{ - SingleTest{17, &testInt, ""}, - SingleTest{float32(17.5), &testFloat32, ""}, - SingleTest{"bike shed", &testString, ""}, - SingleTest{[]string{"bike", "shed", "paint", "color"}, &testSlice, ""}, - SingleTest{map[string]int{"seven": 7, "twelve": 12}, &testMap, ""}, + {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 - SingleTest{172, &testFloat32, "wrong type"}, + {172, &testFloat32, "wrong type"}, } func TestSingletons(t *testing.T) { @@ -320,7 +322,64 @@ func TestSingletons(t *testing.T) { // 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 int: expected %v got %v", 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/src/pkg/gob/error.go b/src/pkg/gob/error.go new file mode 100644 index 000000000..b053761fb --- /dev/null +++ b/src/pkg/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/src/pkg/gob/type.go b/src/pkg/gob/type.go index 0b01b74dc..c00af87bf 100644 --- a/src/pkg/gob/type.go +++ b/src/pkg/gob/type.go @@ -29,7 +29,7 @@ const firstUserId = 64 // lowest id number granted to user type gobType interface { id() typeId setId(id typeId) - Name() string + name() string string() string // not public; only for debugging safeString(seen map[typeId]bool) string } @@ -52,42 +52,60 @@ func (t typeId) gobType() gobType { } // string returns the string representation of the type associated with the typeId. -func (t typeId) string() string { return t.gobType().string() } +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 { return t.gobType().Name() } +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 +type CommonType struct { + Name string + Id typeId } -func (t *commonType) id() typeId { return t._id } +func (t *CommonType) id() typeId { return t.Id } -func (t *commonType) setId(id typeId) { t._id = id } +func (t *CommonType) setId(id typeId) { t.Id = id } -func (t *commonType) string() string { return t.name } +func (t *CommonType) string() string { return t.Name } -func (t *commonType) safeString(seen map[typeId]bool) string { - return t.name +func (t *CommonType) safeString(seen map[typeId]bool) string { + return t.Name } -func (t *commonType) Name() 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", float64(0), 4) - tBytes = bootstrapType("bytes", make([]byte, 0), 5) - tString = bootstrapType("string", "", 6) - // Types added to the language later, not needed during initialization. - tComplex typeId + tBool = bootstrapType("bool", false, 1) + tInt = bootstrapType("int", int(0), 2) + tUint = bootstrapType("uint", uint(0), 3) + tFloat = bootstrapType("float", float64(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 @@ -95,15 +113,13 @@ var tWireType = mustGetTypeInfo(reflect.Typeof(wireType{})).id func init() { // Some magic numbers to make sure there are no surprises. - checkId(7, tWireType) - checkId(9, mustGetTypeInfo(reflect.Typeof(commonType{})).id) - checkId(11, mustGetTypeInfo(reflect.Typeof(structType{})).id) - checkId(12, mustGetTypeInfo(reflect.Typeof(fieldType{})).id) - - // Complex was added after gob was written, so appears after the - // fundamental types are built. - tComplex = bootstrapType("complex", 0+0i, 15) - decIgnoreOpMap[tComplex] = ignoreTwoUints + 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 { @@ -116,26 +132,27 @@ func init() { panic(fmt.Sprintln("nextId too large:", nextId)) } nextId = firstUserId + registerBasics() } // Array type type arrayType struct { - commonType + CommonType Elem typeId Len int } func newArrayType(name string, elem gobType, length int) *arrayType { - a := &arrayType{commonType{name: name}, elem.id(), length} + 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 + if seen[a.Id] { + return a.Name } - seen[a._id] = true + seen[a.Id] = true return fmt.Sprintf("[%d]%s", a.Len, a.Elem.gobType().safeString(seen)) } @@ -143,22 +160,22 @@ func (a *arrayType) string() string { return a.safeString(make(map[typeId]bool)) // Map type type mapType struct { - commonType + CommonType Key typeId Elem typeId } func newMapType(name string, key, elem gobType) *mapType { - m := &mapType{commonType{name: name}, key.id(), elem.id()} + 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 + if seen[m.Id] { + return m.Name } - seen[m._id] = true + seen[m.Id] = true key := m.Key.gobType().safeString(seen) elem := m.Elem.gobType().safeString(seen) return fmt.Sprintf("map[%s]%s", key, elem) @@ -168,21 +185,21 @@ func (m *mapType) string() string { return m.safeString(make(map[typeId]bool)) } // Slice type type sliceType struct { - commonType + CommonType Elem typeId } func newSliceType(name string, elem gobType) *sliceType { - s := &sliceType{commonType{name: name}, elem.id()} + 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 + if seen[s.Id] { + return s.Name } - seen[s._id] = true + seen[s.Id] = true return fmt.Sprintf("[]%s", s.Elem.gobType().safeString(seen)) } @@ -190,26 +207,26 @@ func (s *sliceType) string() string { return s.safeString(make(map[typeId]bool)) // Struct type type fieldType struct { - name string - id typeId + Name string + Id typeId } type structType struct { - commonType - field []*fieldType + 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 + 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)) + 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 @@ -218,13 +235,13 @@ func (s *structType) safeString(seen map[typeId]bool) string { func (s *structType) string() string { return s.safeString(make(map[typeId]bool)) } func newStructType(name string) *structType { - s := &structType{commonType{name: name}, nil} + s := &structType{CommonType{Name: name}, nil} setTypeId(s) return s } // Step through the indirections on a type to discover the base type. -// Return the number of indirections. +// Return the base type and the number of indirections. func indirect(t reflect.Type) (rt reflect.Type, count int) { rt = t for { @@ -259,6 +276,9 @@ func newTypeObject(name string, rt reflect.Type) (gobType, os.Error) { 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 { @@ -300,7 +320,8 @@ func newTypeObject(name string, rt reflect.Type) (gobType, os.Error) { typ, _ := indirect(f.Type) tname := typ.Name() if tname == "" { - tname = f.Type.String() + t, _ := indirect(f.Type) + tname = t.String() } gt, err := getType(tname, f.Type) if err != nil { @@ -308,7 +329,7 @@ func newTypeObject(name string, rt reflect.Type) (gobType, os.Error) { } field[i] = &fieldType{f.Name, gt.id()} } - strType.field = field + strType.Field = field return strType, nil default: @@ -320,14 +341,7 @@ func newTypeObject(name string, rt reflect.Type) (gobType, os.Error) { // getType returns the Gob type describing the given reflect.Type. // typeLock must be held. func getType(name string, rt reflect.Type) (gobType, os.Error) { - // Flatten the data structure by collapsing out pointers - for { - pt, ok := rt.(*reflect.PtrType) - if !ok { - break - } - rt = pt.Elem() - } + rt, _ = indirect(rt) typ, present := types[rt] if present { return typ, nil @@ -341,7 +355,8 @@ func getType(name string, rt reflect.Type) (gobType, os.Error) { func checkId(want, got typeId) { if want != got { - panic("bootstrap type wrong id: " + got.Name() + " " + got.string() + " not " + want.string()) + 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()) } } @@ -352,7 +367,7 @@ func bootstrapType(name string, e interface{}, expect typeId) typeId { if present { panic("bootstrap type already present: " + name + ", " + rt.String()) } - typ := &commonType{name: name} + typ := &CommonType{Name: name} types[rt] = typ setTypeId(typ) checkId(expect, nextId) @@ -371,17 +386,28 @@ func bootstrapType(name string, e interface{}, expect typeId) typeId { // 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 + ArrayT *arrayType + SliceT *sliceType + StructT *structType + MapT *mapType } -func (w *wireType) name() string { - if w.structT != nil { - return w.structT.name +func (w *wireType) string() string { + const unknown = "unknown type" + if w == nil { + return unknown } - 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 { @@ -410,16 +436,16 @@ func getTypeInfo(rt reflect.Type) (*typeInfo, os.Error) { t := info.id.gobType() switch typ := rt.(type) { case *reflect.ArrayType: - info.wire = &wireType{arrayT: t.(*arrayType)} + info.wire = &wireType{ArrayT: t.(*arrayType)} case *reflect.MapType: - info.wire = &wireType{mapT: t.(*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)} + info.wire = &wireType{SliceT: t.(*sliceType)} } case *reflect.StructType: - info.wire = &wireType{structT: t.(*structType)} + info.wire = &wireType{StructT: t.(*structType)} } typeInfoMap[rt] = info } @@ -434,3 +460,82 @@ func mustGetTypeInfo(rt reflect.Type) *typeInfo { } 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(float(0)) + Register(float32(0)) + Register(float64(0)) + Register(complex(0i)) + Register(complex64(0i)) + Register(complex128(0i)) + Register(false) + Register("") + Register([]byte(nil)) +} diff --git a/src/pkg/gob/type_test.go b/src/pkg/gob/type_test.go index 6acfa7135..106e4f10b 100644 --- a/src/pkg/gob/type_test.go +++ b/src/pkg/gob/type_test.go @@ -15,12 +15,12 @@ type typeT struct { } var basicTypes = []typeT{ - typeT{tBool, "bool"}, - typeT{tInt, "int"}, - typeT{tUint, "uint"}, - typeT{tFloat, "float"}, - typeT{tBytes, "bytes"}, - typeT{tString, "string"}, + {tBool, "bool"}, + {tInt, "int"}, + {tUint, "uint"}, + {tFloat, "float"}, + {tBytes, "bytes"}, + {tString, "string"}, } func getTypeUnlocked(name string, rt reflect.Type) gobType { |