@@ -1,9 +1,10 @@ // Package ioutil contains various constructs for io operations package ioutil import ( + //"fmt" "io" ) // An function alias type that implements io.Writer type WriterFunc func([]byte) (int, error) @@ -24,48 +25,50 @@ // Returns a reader that will delegate calls to Read(...) while ensuring // that the output buffer will never be smaller than the required size func MinReader(reader io.Reader, size int) io.Reader { var buffer []byte = make([]byte, 0, size) - return ReaderFunc(func(output []byte) (readCount int, e error) { + return ReaderFunc(func(output []byte) (int, error) { var ( - bufferLength int = len(buffer) - err error + readCount int + err error ) start: + //fmt.Println("Requesting read with length ", len(output), "buffer's length is ", len(buffer)) + // Reply with the buffered data if there is any - if bufferLength > 0 { + if len(buffer) > 0 { readCount = copy(output, buffer) - if readCount < bufferLength { - // Advance the data in the buffer - buffer = buffer[:copy(buffer, buffer[readCount:])] - } else { - // Clear the buffer - buffer = buffer[:0] - } - // Stage any error for returning - e, err = err, nil - return readCount, e + // Advance the data in the buffer + buffer = buffer[:copy(buffer, buffer[readCount:])] + + //fmt.Println("After buffer read - buffer lenght is", len(buffer)) + + if len(buffer) == 0 { + return readCount, err + } + + // Do not propagate an error until the buffer is exhausted + return readCount, 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]) + //fmt.Println("Delegating read for output length ", len(output), " and size ", size) + return reader.Read(output[:(len(output)/size)*size]) } - // Extend the buffer up to the desired size and perform a Read - buffer = buffer[:size] - readCount, err = reader.Read(buffer) + // Perform a read into the buffer + readCount, err = reader.Read(buffer[:size]) // Size the buffer down to the read data size and restart buffer = buffer[:readCount] - bufferLength = len(buffer) + + //fmt.Println("Read into buffer: ", len(buffer), "bytes") - if bufferLength > 0 { + if len(buffer) > 0 { goto start } - // Stage any error for returning - e, err = err, nil - return 0, e + return 0, err }) }