def readpartial(length = nil, outbuf = nil)
      fail IOError, "closed stream" if closed?

      data = outbuf.clear.force_encoding(@encoding) if outbuf

      return data.to_s if length == 0

      if cache && !cache.eof?
        data = cache.read(length, outbuf)
        data.force_encoding(@encoding)
      end

      if @buffer.nil? && (data.nil? || data.empty?)
        fail EOFError, "end of file reached" if chunks_depleted?
        @buffer = retrieve_chunk
      end

      remaining_length = data && length ? length - data.bytesize : length

      unless @buffer.nil? || remaining_length == 0
        if remaining_length && remaining_length < @buffer.bytesize
          buffered_data = @buffer.byteslice(0, remaining_length)
          @buffer       = @buffer.byteslice(remaining_length..-1)
        else
          buffered_data = @buffer
          @buffer       = nil
        end

        if data
          data << buffered_data
        else
          data = buffered_data
        end

        cache.write(buffered_data) if cache

        buffered_data.clear unless buffered_data.equal?(data)
      end

      @position += data.bytesize

      data.force_encoding(Encoding::BINARY) if length
      data
    end
def readpartial(length = nil, outbuf = nil)
      fail IOError, "closed stream" if closed?

      data = outbuf.clear.force_encoding(@encoding) if outbuf

      return data.to_s if length == 0

      if cache && !cache.eof?
        data = cache.read(length, outbuf)
        data.force_encoding(@encoding)
      end

      if @buffer.nil? && (data.nil? || data.empty?)
        fail EOFError, "end of file reached" if chunks_depleted?
        @buffer = retrieve_chunk
      end

      remaining_length = data && length ? length - data.bytesize : length

      unless @buffer.nil? || remaining_length == 0
        if remaining_length && remaining_length < @buffer.bytesize
          buffered_data = @buffer.byteslice(0, remaining_length)
          @buffer       = @buffer.byteslice(remaining_length..-1)
        else
          buffered_data = @buffer
          @buffer       = nil
        end

        if data
          data << buffered_data
        else
          data = buffered_data
        end

        cache.write(buffered_data) if cache

        buffered_data.clear unless buffered_data.equal?(data)
      end

      @position += data.bytesize

      data.force_encoding(Encoding::BINARY) if length
      data
    end
Implements IO#readpartial semantics. If there is any content readily
 available reads from it, otherwise fetches and reads from the next chunk.
 It writes to and reads from the cache when needed.

 Without arguments it either returns all content that's readily available,
 or the next chunk. This is useful when you don't care about the size of
 chunks and you want to minimize string allocations.

 With `length` argument returns maximum of that amount of bytes.

 With `outbuf` argument each call will return that same string object,
 where the value is replaced with retrieved content.

 Raises EOFError if end of file is reached. Raises IOError if closed.