module Protocol::HTTP::Body::Stream::Reader

def read(length = nil, buffer = nil)

@returns [String] a buffer containing the data
@parameter buffer [String] the buffer which will receive the data
@parameterlength [Integer] the amount of data to read

If buffer is given, then the read data will be placed into buffer instead of a newly created String object.

If the length is not given, it will read all data until EOF, or return an empty string if the stream is already at EOF.

If given a non-negative length, it will read at most that many bytes from the stream. If the stream is at EOF, it will return nil.

Read data from the underlying stream.
def read(length = nil, buffer = nil)
	return "" if length == 0
	
	buffer ||= String.new.force_encoding(Encoding::BINARY)
	
	# Take any previously buffered data and replace it into the given buffer.
	if @buffer
		buffer.replace(@buffer)
		@buffer = nil
	else
		buffer.clear
	end
	
	if length
		while buffer.bytesize < length and chunk = read_next
			buffer << chunk
		end
		
		# This ensures the subsequent `slice!` works correctly.
		buffer.force_encoding(Encoding::BINARY)
		
		# This will be at least one copy:
		@buffer = buffer.byteslice(length, buffer.bytesize)
		
		# This should be zero-copy:
		buffer.slice!(length, buffer.bytesize)
		
		if buffer.empty?
			return nil
		else
			return buffer
		end
	else
		while chunk = read_next
			buffer << chunk
		end
		
		return buffer
	end
end