class Protocol::HTTP::Body::Streamable::Body

A streaming body that can be read from and written to.

def call(stream)

@parameter stream [Stream] The stream to read and write to.

Invoke the block with the given stream. The block can read and write to the stream, and must close the stream when finishing.
def call(stream)
	if @block.nil?
		raise ConsumedError, "Streaming block has already been consumed!"
	end
	
	block = @block
	
	@input = @output = @block = nil
	
	# Ownership of the stream is passed into the block, in other words, the block is responsible for closing the stream.
	block.call(stream)
rescue => error
	# If, for some reason, the block raises an error, we assume it may not have closed the stream, so we close it here:
	stream.close
	raise
end

def close_input(error = nil)

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

Close the input. The streaming body will eventually read all the input.
def close_input(error = nil)
	if input = @input
		@input = nil
		input.close(error)
	end
end

def close_output(error = nil)

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

Close the output, the streaming body will be unable to write any more output.
def close_output(error = nil)
	@output&.close(error)
end

def initialize(block, input = nil)

@parameter input [Readable] The input stream, if known.
@parameter block [Proc] The block that generates the body.

Initialize the body with the given block and input.
def initialize(block, input = nil)
	@block = block
	@input = input
	@output = nil
end

def read

Invokes the block in a fiber which yields chunks when they are available.
def read
	# We are reading chunk by chunk, allocate an output stream and execute the block to generate the chunks:
	if @output.nil?
		if @block.nil?
			raise ConsumedError, "Streaming body has already been consumed!"
		end
		
		@output = Output.schedule(@input, @block)
		@block = nil
	end
	
	@output.read
end

def stream?

@returns [Boolean] Whether the body can be streamed, which is true.
def stream?
	true
end