@@ -84,27 +84,34 @@ // 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, 0, size) + 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 len(buffer) > 0 { - count = copy(output, buffer) + if to-from > 0 { + count = copy(output, buffer[from:to]) // Advance the data in the buffer - buffer = buffer[:copy(buffer, buffer[count:])] + from += count - // Return count and error if we have read the whole buffer - if len(buffer) == 0 { + // 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 @@ -114,18 +121,18 @@ if len(output) >= size { return reader.Read(output[:(len(output)/size)*size]) } // Perform a read into the buffer - count, err = reader.Read(buffer[:size]) + count, err = reader.Read(buffer) // Size the buffer down to the read data size // and restart if we have successfully read some bytes - buffer = buffer[:count] - if len(buffer) > 0 { + from, to = 0, count + if to-from > 0 { goto start } // Returning on err/misbehaving noop reader return 0, err }) }