module IO::Stream::Readable

def consume_read_buffer(size = nil, buffer = nil)

@returns [String | Nil] The consumed data, or nil if no data available.
@parameter buffer [String | Nil] An optional buffer to fill with data instead of allocating a new string.
@parameter size [Integer | Nil] The amount of data to consume. If nil, consume entire buffer.
Consumes at most `size` bytes from the buffer.
def consume_read_buffer(size = nil, buffer = nil)
	# If we are at finished, and the read buffer is empty, we can't consume anything.
	if @finished && @read_buffer.empty?
		# Clear the buffer even when returning nil
		if buffer
			buffer.clear
			buffer.force_encoding(Encoding::BINARY)
		end
		return nil
	end
	
	result = nil
	
	if size.nil? or size >= @read_buffer.bytesize
		# Consume the entire read buffer:
		if buffer
			buffer.clear
			buffer << @read_buffer
			result = buffer
		else
			result = @read_buffer
		end
		@read_buffer = StringBuffer.new
	else
		# We know that we are not going to reuse the original buffer.
		# But byteslice will generate a hidden copy. So let's freeze it first:
		@read_buffer.freeze
		
		if buffer
			# Use replace instead of clear + << for better performance
			buffer.replace(@read_buffer.byteslice(0, size))
			result = buffer
		else
			result = @read_buffer.byteslice(0, size)
		end
		@read_buffer = @read_buffer.byteslice(size, @read_buffer.bytesize)
	end
	
	return result
end