]> Cypherpunks repositories - gostls13.git/commitdiff
gob: when possible, allow sequential decoders on the same input stream.
authorRob Pike <r@golang.org>
Wed, 5 Oct 2011 16:47:09 +0000 (09:47 -0700)
committerRob Pike <r@golang.org>
Wed, 5 Oct 2011 16:47:09 +0000 (09:47 -0700)
This can work only if there is no type info required to initialize the decoder,
but it's easy and gains a few percent in the basic benchmarks by avoiding
bufio when it's a bytes.Buffer - a testing-only scenario, I admit.
Add a comment about what Decode expects from the input.

R=rsc
CC=golang-dev
https://golang.org/cl/5165048

src/pkg/gob/decoder.go
src/pkg/gob/encoder_test.go

index c2a1e0c3a8736c66b2dcbf3362ee35254bb98490..5efcea8bc16f6a1965323597d15ea4a502067343 100644 (file)
@@ -29,9 +29,15 @@ type Decoder struct {
 }
 
 // NewDecoder returns a new decoder that reads from the io.Reader.
+// If r does not also implement io.ByteReader, it will be wrapped in a
+// bufio.Reader.
 func NewDecoder(r io.Reader) *Decoder {
        dec := new(Decoder)
-       dec.r = bufio.NewReader(r)
+       // We use the ability to read bytes as a plausible surrogate for buffering.
+       if _, ok := r.(io.ByteReader); !ok {
+               r = bufio.NewReader(r)
+       }
+       dec.r = r
        dec.wireType = make(map[typeId]*wireType)
        dec.decoderCache = make(map[reflect.Type]map[typeId]**decEngine)
        dec.ignorerCache = make(map[typeId]**decEngine)
index 4263666393b1123d7e5570e2161fbb628fc68172..a774438d38854c054f7fef46e6397e079f93b8a7 100644 (file)
@@ -638,3 +638,28 @@ func TestBadCount(t *testing.T) {
                t.Error("expected bad count error; got", err)
        }
 }
+
+// Verify that sequential Decoders built on a single input will
+// succeed if the input implements ReadByte and there is no
+// type information in the stream.
+func TestSequentialDecoder(t *testing.T) {
+       b := new(bytes.Buffer)
+       enc := NewEncoder(b)
+       const count = 10
+       for i := 0; i < count; i++ {
+               s := fmt.Sprintf("%d", i)
+               if err := enc.Encode(s); err != nil {
+                       t.Error("encoder fail:", err)
+               }
+       }
+       for i := 0; i < count; i++ {
+               dec := NewDecoder(b)
+               var s string
+               if err := dec.Decode(&s); err != nil {
+                       t.Fatal("decoder fail:", err)
+               }
+               if s != fmt.Sprintf("%d", i) {
+                       t.Fatalf("decode expected %d got %s", i, s)
+               }
+       }
+}