@@ -28,57 +28,23 @@ // // It can buffer data as the predictor mandates 8-byte blocks with a header. // A call with no data will force a flush. func Compressor(writer io.Writer) io.Writer { var ctx context - ctx.input = make([]byte, 0, 8) - - // Forward declaration as it is required for recursion - var write iou.WriterFunc - - write = func(data []byte) (int, error) { - var ( - blockSize int = 8 - bufferLength int = len(ctx.input) - datalength int = len(data) - ) - - // Force a flush if we are called with no data to write - if datalength == 0 { - // Nothing to flush if the buffer is empty though - if len(ctx.input) == 0 { - return 0, nil - } - // We can't have more than 7 bytes in the buffer so this is safe - data, datalength = ctx.input, len(ctx.input) - blockSize, bufferLength = datalength, 0 - } - - // Check if there are pending bytes in the buffer - if datalength < blockSize || bufferLength > 0 { - - // If the current buffer + new data can fit into a block - if (datalength + bufferLength) <= blockSize { - ctx.input = append(ctx.input, data...) - - // Flush the block if the buffer fills it - if len(ctx.input) == blockSize { - return write(nil) - } - // ... otherwise just return - return datalength, nil - } - - // The current buffer + new data overflow the block size - // Complete the block, flush it ... - ctx.input = append(ctx.input, data[:blockSize-bufferLength]...) - if c, err := write(nil); err != nil { - return c, err - } - // ... and stage the rest of the data in the buffer - ctx.input = append(ctx.input, data[blockSize-bufferLength:]...) - return datalength, nil + + return iou.SizedWriter(iou.WriterFunc(func(data []byte) (int, error) { + var ( + blockSize int = 8 + datalength int = len(data) + ) + + if datalength == 0 { + return 0, nil + } + + if datalength < blockSize { + blockSize = datalength } var buf []byte = make([]byte, 1, blockSize+1) for block := 0; block < datalength/blockSize; block++ { for i := 0; i < blockSize; i++ { @@ -100,21 +66,12 @@ // Reset the flags and buffer for the next iteration buf, buf[0] = buf[:1], 0 } - if remaining := datalength % blockSize; remaining > 0 { - ctx.input = ctx.input[:remaining] - copy(ctx.input, data[datalength-remaining:]) - } else { - ctx.input = ctx.input[:0] - } - return datalength, nil - } - - return write + }), 8) } // Returns an io.Reader implementation that wraps the provided io.Reader // and decompresses data according to the predictor algorithm func Decompressor(reader io.Reader) io.Reader {