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 }