class Async::HTTP::Protocol::HTTP2::Stream::Buffer

def close(error)

def close(error)
	if @body
		@body.close(error)
		@body = nil
	end
	
	@task&.stop
end

def end_stream

def end_stream
	@stream.send_data(nil, ::Protocol::HTTP2::END_STREAM)
end

def initialize(stream, body, task: Task.current)

def initialize(stream, body, task: Task.current)
	@stream = stream
	
	@body = body
	@remainder = nil
	
	@window_updated = Async::Condition.new
	
	@task = task.async(&self.method(:passthrough))
end

def passthrough(task)

def passthrough(task)
	while chunk = self.read
		maximum_size = @stream.available_frame_size
		
		while maximum_size <= 0
			@window_updated.wait
			
			maximum_size = @stream.available_frame_size
		end
		
		self.send_data(chunk, maximum_size)
	end
	
	self.end_stream
rescue Async::Stop
	# Ignore.
ensure
	@body&.close($!)
	@body = nil
end

def push(chunk)

def push(chunk)
	@remainder = chunk
end

def read

def read
	if @remainder
		remainder = @remainder
		@remainder = nil
		
		return remainder
	else
		@body&.read
	end
end

def send_data(chunk, maximum_size)

Parameters:
  • stream (Stream) -- the stream to use for sending data frames.
  • maximum_size (Integer) -- send up to this many bytes of data.
def send_data(chunk, maximum_size)
	if chunk.bytesize <= maximum_size
		@stream.send_data(chunk, maximum_size: maximum_size)
	else
		@stream.send_data(chunk.byteslice(0, maximum_size), maximum_size: maximum_size)
		
		# The window was not big enough to send all the data, so we save it for next time:
		self.push(
			chunk.byteslice(maximum_size, chunk.bytesize - maximum_size)
		)
	end
end

def window_updated(size)

def window_updated(size)
	@window_updated.signal
end