From f755edc210a8fcf3d167a5d4583f4460b3853eeb Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Wed, 21 Aug 2024 11:47:45 +1200 Subject: [PATCH 1/3] Support output buffer in `read_partial`/`readpartial`. --- lib/protocol/http/body/stream.rb | 22 ++++++++++++++++------ test/protocol/http/body/stream.rb | 10 ++++++++++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/lib/protocol/http/body/stream.rb b/lib/protocol/http/body/stream.rb index 52afdf3..4a74183 100644 --- a/lib/protocol/http/body/stream.rb +++ b/lib/protocol/http/body/stream.rb @@ -89,12 +89,22 @@ 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 - @buffer = nil + if buffer + buffer.replace(@buffer) + else + buffer = @buffer + @buffer = nil + end else - buffer = read_next + chunk = read_next + + if buffer and chunk + buffer.replace(chunk) + else + buffer = chunk + end end if buffer and length @@ -111,8 +121,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. diff --git a/test/protocol/http/body/stream.rb b/test/protocol/http/body/stream.rb index c094679..3f4010f 100644 --- a/test/protocol/http/body/stream.rb +++ b/test/protocol/http/body/stream.rb @@ -224,4 +224,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 From f9ed1befc560c32bf182e393c6303bc50fcd4ac3 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Wed, 21 Aug 2024 12:34:18 +1200 Subject: [PATCH 2/3] More tests. --- lib/protocol/http/body/stream.rb | 15 +++++++++------ test/protocol/http/body/stream.rb | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/lib/protocol/http/body/stream.rb b/lib/protocol/http/body/stream.rb index 4a74183..f1209ea 100644 --- a/lib/protocol/http/body/stream.rb +++ b/lib/protocol/http/body/stream.rb @@ -95,15 +95,18 @@ def read_partial(length = nil, buffer = nil) buffer.replace(@buffer) else buffer = @buffer - @buffer = nil end + @buffer = nil else - chunk = read_next - - if buffer and chunk - buffer.replace(chunk) + if chunk = read_next + if buffer + buffer.replace(chunk) + else + buffer = chunk + end else - buffer = chunk + buffer&.clear + buffer = nil end end diff --git a/test/protocol/http/body/stream.rb b/test/protocol/http/body/stream.rb index 3f4010f..60956f5 100644 --- a/test/protocol/http/body/stream.rb +++ b/test/protocol/http/body/stream.rb @@ -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 From 79a1b20743e3bbe5c4b48a0f16b8b07408e2eda6 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Wed, 21 Aug 2024 12:37:48 +1200 Subject: [PATCH 3/3] More tests. --- test/protocol/http/body/stream.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/protocol/http/body/stream.rb b/test/protocol/http/body/stream.rb index 60956f5..3b117ee 100644 --- a/test/protocol/http/body/stream.rb +++ b/test/protocol/http/body/stream.rb @@ -147,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