@@ -79,60 +79,67 @@ return write(input[count:]) } return write } + +type sizedReader struct { + reader io.Reader + buffer []byte + from, to, size int +} // Returns a reader that delegates calls to Read(...) while ensuring // that the output buffer is never smaller than the required size // and is downsized to a multiple of the required size if larger. func SizedReader(reader io.Reader, size int) io.Reader { - var ( - buffer []byte = make([]byte, size) - from, to int = 0, 0 - ) - - return ReaderFunc(func(output []byte) (int, error) { - var ( - count int - err error - ) - - start: - // Reply with the buffered data if there is any - if to-from > 0 { - count = copy(output, buffer[from:to]) - - // Advance the data in the buffer - from += count - - // Check whether we have reached the end of the buffer - if to-from == 0 { - // Reset the buffer - from, to = 0, 0 - - return count, err - } - - // Do not propagate an error until the buffer is exhausted - return count, nil - } - - // Delegate if the buffer is empty and the destination buffer is large enough - if len(output) >= size { - return reader.Read(output[:(len(output)/size)*size]) - } - - // Perform a read into the buffer - count, err = reader.Read(buffer) - - // Size the buffer down to the read data size - // and restart if we have successfully read some bytes - from, to = 0, count - if to-from > 0 { - goto start - } - - // Returning on err/misbehaving noop reader - return 0, err - }) + var sr sizedReader + sr.reader = reader + sr.buffer = make([]byte, size) + sr.size, sr.from, sr.to = size, 0, 0 + return &sr +} + +func (sr *sizedReader) Read(output []byte) (int, error) { + var ( + count int + err error + ) + +start: + // Reply with the buffered data if there is any + if sr.to-sr.from > 0 { + count = copy(output, sr.buffer[sr.from:sr.to]) + + // Advance the data in the buffer + sr.from += count + + // Check whether we have reached the end of the buffer + if sr.to-sr.from == 0 { + // Reset the buffer + sr.from, sr.to = 0, 0 + + return count, err + } + + // Do not propagate an error until the buffer is exhausted + return count, nil + } + + // Delegate if the buffer is empty and the destination buffer is large enough + if len(output) >= sr.size { + return sr.reader.Read(output[:(len(output)/sr.size)*sr.size]) + } + + // Perform a read into the buffer + count, err = sr.reader.Read(sr.buffer) + + // Size the buffer down to the read data size + // and restart if we have successfully read some bytes + sr.from, sr.to = 0, count + if sr.to-sr.from > 0 { + goto start + } + + // Returning on err/misbehaving noop reader + return 0, err }