Files
quic-go/quicvarint/io.go
Benjamin M. Schwartz c7cf12703d quicvarint: tolerate empty reads of the underlying io.Reader (#5275)
* Tolerate empty reads in `quicvarint.Read`

Currently, `quicvarint.Read` misinterprets an empty read (`n==0`)
as a single zero byte.  While empty reads are "discouraged" in
the `io.Reader` interface, they do sometimes happen, especially
when using `io.Pipe()`.

This change tolerates empty reads, adds a corresponding unit test,
and also includes some additional test coverage related to empty
capsules

* minor test refactor

---------

Co-authored-by: Marten Seemann <martenseemann@gmail.com>
2025-08-05 08:05:52 +02:00

74 lines
1.3 KiB
Go

package quicvarint
import (
"bytes"
"io"
)
// Reader implements both the io.ByteReader and io.Reader interfaces.
type Reader interface {
io.ByteReader
io.Reader
}
var _ Reader = &bytes.Reader{}
type byteReader struct {
io.Reader
}
var _ Reader = &byteReader{}
// NewReader returns a Reader for r.
// If r already implements both io.ByteReader and io.Reader, NewReader returns r.
// Otherwise, r is wrapped to add the missing interfaces.
func NewReader(r io.Reader) Reader {
if r, ok := r.(Reader); ok {
return r
}
return &byteReader{r}
}
func (r *byteReader) ReadByte() (byte, error) {
var b [1]byte
var n int
var err error
for n == 0 && err == nil {
n, err = r.Read(b[:])
}
if n == 1 && err == io.EOF {
err = nil
}
return b[0], err
}
// Writer implements both the io.ByteWriter and io.Writer interfaces.
type Writer interface {
io.ByteWriter
io.Writer
}
var _ Writer = &bytes.Buffer{}
type byteWriter struct {
io.Writer
}
var _ Writer = &byteWriter{}
// NewWriter returns a Writer for w.
// If r already implements both io.ByteWriter and io.Writer, NewWriter returns w.
// Otherwise, w is wrapped to add the missing interfaces.
func NewWriter(w io.Writer) Writer {
if w, ok := w.(Writer); ok {
return w
}
return &byteWriter{w}
}
func (w *byteWriter) WriteByte(c byte) error {
_, err := w.Write([]byte{c})
return err
}