clipper/backend/media/modulo_reader.go

44 lines
852 B
Go
Raw Permalink Normal View History

2021-12-17 16:52:59 +00:00
package media
import (
"bytes"
"io"
)
// ModuloReader reads from a reader in block sizes that are exactly modulo
// modSize, with any remainder buffered until the next read.
type ModuloReader struct {
io.ReadCloser
buf bytes.Buffer
modSize int
}
func NewModuloReader(r io.ReadCloser, modSize int) *ModuloReader {
return &ModuloReader{ReadCloser: r, modSize: modSize}
}
func (r *ModuloReader) Read(p []byte) (int, error) {
// err is always io.EOF or nil
nr1, _ := r.buf.Read(p)
nr2, err := r.ReadCloser.Read(p[nr1:])
nr := nr1 + nr2
rem := nr % r.modSize
// if there was an error, return immediately.
if err == io.EOF {
return nr, err
} else if err != nil {
return nr - rem, err
}
// write any remainder to the buffer
if rem != 0 {
// err is always nil
_, _ = r.buf.Write(p[nr-rem : nr])
}
return nr - rem, err
}