Skip to content

Commit

Permalink
Support output buffer in read_partial/readpartial. (#61)
Browse files Browse the repository at this point in the history
  • Loading branch information
ioquatix authored Aug 21, 2024
1 parent a472da1 commit 9e33894
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 5 deletions.
23 changes: 18 additions & 5 deletions lib/protocol/http/body/stream.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,25 @@ def read(length = nil, buffer = nil)
# Will avoid reading from the underlying stream if there is buffered data available.
#
# @parameter length [Integer] The maximum number of bytes to read.
def read_partial(length = nil)
def read_partial(length = nil, buffer = nil)
if @buffer
buffer = @buffer
if buffer
buffer.replace(@buffer)
else
buffer = @buffer
end
@buffer = nil
else
buffer = read_next
if chunk = read_next
if buffer
buffer.replace(chunk)
else
buffer = chunk
end
else
buffer&.clear
buffer = nil
end
end

if buffer and length
Expand All @@ -111,8 +124,8 @@ def read_partial(length = nil)
end

# Similar to {read_partial} but raises an `EOFError` if the stream is at EOF.
def readpartial(length)
read_partial(length) or raise EOFError, "End of file reached!"
def readpartial(length, buffer = nil)
read_partial(length, buffer) or raise EOFError, "End of file reached!"
end

# Read data from the stream without blocking if possible.
Expand Down
38 changes: 38 additions & 0 deletions test/protocol/http/body/stream.rb
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,24 @@
expect(stream.read_partial(2)).to be == "d"
expect(stream.read_partial(2)).to be == nil
end

it "can read partial input with buffer" do
buffer = String.new
expect(stream.read_partial(2, buffer)).to be == "He"
expect(buffer).to be == "He"
expect(stream.read_partial(2, buffer)).to be == "ll"
expect(buffer).to be == "ll"
expect(stream.read_partial(2, buffer)).to be == "o"
expect(buffer).to be == "o"
expect(stream.read_partial(2, buffer)).to be == "Wo"
expect(buffer).to be == "Wo"
expect(stream.read_partial(2, buffer)).to be == "rl"
expect(buffer).to be == "rl"
expect(stream.read_partial(2, buffer)).to be == "d"
expect(buffer).to be == "d"
expect(stream.read_partial(2, buffer)).to be == nil
expect(buffer).to be == ""
end
end

with '#readpartial' do
Expand All @@ -129,6 +147,16 @@
expect(stream.readpartial(20)).to be == "World"
expect{stream.readpartial(20)}.to raise_exception(EOFError)
end

it "can read partial input with buffer" do
buffer = String.new
expect(stream.readpartial(20, buffer)).to be == "Hello"
expect(buffer).to be == "Hello"
expect(stream.readpartial(20, buffer)).to be == "World"
expect(buffer).to be == "World"
expect{stream.readpartial(20, buffer)}.to raise_exception(EOFError)
expect(buffer).to be == ""
end
end

with '#read_until' do
Expand Down Expand Up @@ -224,4 +252,14 @@
expect(stream).to be(:closed?)
end
end

with 'IO.copy_stream' do
let(:output) {StringIO.new}

it "can copy input to output" do
::IO.copy_stream(stream, output)

expect(output.string).to be == "HelloWorld"
end
end
end

0 comments on commit 9e33894

Please sign in to comment.