Skip to content

Commit

Permalink
make it possible to parse a varint at the end of a reader
Browse files Browse the repository at this point in the history
An io.Reader can read into the buffer and return the io.EOF in the same
call. In fact, that's how the quic.Stream is implemented.
In that case, we shouldn't return an error from quicvarint.Read,
otherwise the caller won't be able to parse a varint sent just before a
stream was closed.
  • Loading branch information
marten-seemann committed May 22, 2022
1 parent 8185d1b commit d7622a2
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 1 deletion.
5 changes: 4 additions & 1 deletion quicvarint/io.go
Expand Up @@ -31,7 +31,10 @@ func NewReader(r io.Reader) Reader {

func (r *byteReader) ReadByte() (byte, error) {
var b [1]byte
_, err := r.Reader.Read(b[:])
n, err := r.Reader.Read(b[:])
if n == 1 && err == io.EOF {
err = nil
}
return b[0], err
}

Expand Down
43 changes: 43 additions & 0 deletions quicvarint/io_test.go
Expand Up @@ -22,6 +22,21 @@ func (r *nopWriter) Write(_ []byte) (int, error) {
return 0, io.ErrShortBuffer
}

// eofReader is a reader that returns data and the io.EOF at the same time in the last Read call
type eofReader struct {
Data []byte
pos int
}

func (r *eofReader) Read(b []byte) (int, error) {
n := copy(b, r.Data[r.pos:])
r.pos += n
if r.pos >= len(r.Data) {
return n, io.EOF
}
return n, nil
}

var _ io.Writer = &nopWriter{}

var _ = Describe("Varint I/O", func() {
Expand All @@ -46,6 +61,34 @@ var _ = Describe("Varint I/O", func() {
Expect(err).To(Equal(io.ErrUnexpectedEOF))
Expect(val).To(Equal(byte(0)))
})

Context("EOF handling", func() {
It("eofReader works correctly", func() {
r := &eofReader{Data: []byte("foobar")}
b := make([]byte, 3)
n, err := r.Read(b)
Expect(n).To(Equal(3))
Expect(err).ToNot(HaveOccurred())
Expect(string(b)).To(Equal("foo"))
n, err = r.Read(b)
Expect(n).To(Equal(3))
Expect(err).To(MatchError(io.EOF))
Expect(string(b)).To(Equal("bar"))
n, err = r.Read(b)
Expect(err).To(MatchError(io.EOF))
Expect(n).To(BeZero())
})

It("correctly handles io.EOF", func() {
buf := &bytes.Buffer{}
Write(buf, 1337)

r := NewReader(&eofReader{Data: buf.Bytes()})
n, err := Read(r)
Expect(err).ToNot(HaveOccurred())
Expect(n).To(BeEquivalentTo(1337))
})
})
})

Context("Writer", func() {
Expand Down

0 comments on commit d7622a2

Please sign in to comment.