class Protocol::HTTP::Body::Stream

The input stream is an IO-like object which contains the raw HTTP POST data. When applicable, its external encoding must be “ASCII-8BIT” and it must be opened in binary mode, for Ruby 1.9 compatibility. The input stream must respond to gets, each, read and rewind.

def <<(buffer)

Write data to the stream using {write}.
def <<(buffer)
	write(buffer)
end

def close(error = nil)

@parameter error [Exception | Nil] The error that caused this stream to be closed, if any.

Close the input and output bodies.
def close(error = nil)
	self.close_read(error)
	self.close_write(error)
	
	return nil
ensure
	@closed = true
end

def close_read(error = nil)

@parameter error [Exception | Nil] The error that was encountered, if any.

If, while processing the data that was read from this stream, an error is encountered, it should be passed to this method.

Close the input body.
def close_read(error = nil)
	if input = @input
		@input = nil
		@closed_read = true
		@buffer = nil
		
		input.close(error)
	end
end

def close_write(error = nil)

@parameter error [Exception | Nil] The error that was encountered, if any.

If, while generating the data that is written to this stream, an error is encountered, it should be passed to this method.

Close the output body.
def close_write(error = nil)
	if output = @output
		@output = nil
		
		output.close_write(error)
	end
end

def closed?

@returns [Boolean] Whether the stream has been closed.
def closed?
	@closed
end

def empty?

@returns [Boolean] Whether there are any output chunks remaining.
def empty?
	@output.empty?
end

def flush

This is currently a no-op.

Flush the output stream.
def flush
end

def initialize(input = nil, output = Buffered.new)

@parameter output [Writable] The output stream.
@parameter input [Readable] The input stream.

Initialize the stream with the given input and output.
def initialize(input = nil, output = Buffered.new)
	@input = input
	@output = output
	
	raise ArgumentError, "Non-writable output!" unless output.respond_to?(:write)
	
	# Will hold remaining data in `#read`.
	@buffer = nil
	
	@closed = false
	@closed_read = false
end

def puts(*arguments, separator: NEWLINE)

@parameter separator [String] The line separator, defaults to `\n`.
@parameter arguments [Array(String)] The lines to write.

The current implementation buffers the lines and writes them in a single operation.

Write lines to the stream.
def puts(*arguments, separator: NEWLINE)
	buffer = ::String.new
	
	arguments.each do |argument|
		buffer << argument << separator
	end
	
	write(buffer)
end

def read_next

@raises [IOError] If the input stream was explicitly closed.
@returns [String] The next chunk of data.

Read the next chunk of data from the input stream.
def read_next
	if @input
		return @input.read
	elsif @closed_read
		raise IOError, "Stream is not readable, input has been closed!"
	end
end

def write(buffer)

@returns [Integer] The number of bytes written.
@raises [IOError] If the stream is not writable.
@parameter buffer [String] The data to write.

Write data to the underlying stream.
def write(buffer)
	if @output
		@output.write(buffer)
		return buffer.bytesize
	else
		raise IOError, "Stream is not writable, output has been closed!"
	end
end

def write_nonblock(buffer, exception: nil)

@returns [Integer] The number of bytes written.
@parameter exception [Boolean] Whether to raise an exception if the write would block, currently ignored.
@parameter buffer [String] The data to write.

Provided for compatibility with IO-like objects.

Write data to the stream using {write}.
def write_nonblock(buffer, exception: nil)
	write(buffer)
end