rc is a tiny, dependency-free Go package that keeps track of how many bytes
have been read from a stream. It is handy when implementing
io.ReaderFrom — or any method that must
report a byte count — without having to thread a running total through every
read call yourself.
A ReadCounter wraps an io.Reader and transparently counts every byte read
through it. Because it also implements
io.ByteReader, it can be passed straight to
helpers such as binary.Read or binary.ReadUvarint. As a bonus, it records
the call site where it was created, so the errors it produces are annotated with
the originating function, file and line.
go get github.com/KarpelesLab/rcWrap your reader with rc.New, read through the returned *ReadCounter, and
return the accumulated count when you are done:
func (obj *myObject) ReadFrom(r io.Reader) (int64, error) {
rc := rc.New(r)
// ReadCounter implements io.Reader and io.ByteReader, so it works
// anywhere a reader is expected.
if err := binary.Read(rc, binary.BigEndian, &obj.Value); err != nil {
// Error64 returns the bytes read so far plus an annotated error.
return rc.Error64(err)
}
// ... more reading ...
// Ret64 returns the total byte count with a nil error.
return rc.Ret64()
}When an error is returned via Error64, it is wrapped with the call site
captured by New, for example:
in main.(*myObject).ReadFrom at main.go:42: unexpected EOF
The wrapped error keeps the original error reachable through errors.Is and
errors.As.
| Method | Purpose |
|---|---|
New(r io.Reader) *ReadCounter |
Wrap r and start counting from zero. A plain io.Reader is adapted so ReadByte works; a *ReadCounter may be nested. |
Read(p []byte) (int, error) |
Read into p, adding the number of bytes read to the counter. |
ReadByte() (byte, error) |
Read a single byte, incrementing the counter on success. |
ReadFull(buf []byte) error |
Read exactly len(buf) bytes via io.ReadFull, counting them. |
Ret64() (int64, error) |
Return the count and a nil error, shaped for io.ReaderFrom. |
Ret() (int, error) |
Return the count and a nil error, shaped for io.Reader. |
Error64(err error) (int64, error) |
Return the count and err annotated with the call site, shaped for io.ReaderFrom. |
Error(err error) (int, error) |
Same as Error64, shaped for io.Reader. |
- A
ReadCounteris not safe for concurrent use. - The zero value is not usable — always create one with
New. Newpanics if it is given anilreader.
Released under the MIT License. See LICENSE for details.