Skip to content

Commit a79c78f

Browse files
authored
Unread extra data when stopping (#209)
1 parent 8fdabed commit a79c78f

File tree

3 files changed

+24
-17
lines changed

3 files changed

+24
-17
lines changed

docs/src/examples.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ eof(stream) #> true
157157
In the case where you need to reuse the wrapped stream, the code above must be
158158
slightly modified because the transcoding stream may read more bytes than
159159
necessary from the wrapped stream. Wrapping the stream with `NoopStream` solves
160-
the problem because adjacent transcoding streams share the same buffer.
160+
the problem because any extra data read after the end of the chunk will be
161+
stored back in the internal buffer of the wrapped transcoding stream.
161162
```julia
162163
using CodecZlib
163164
using TranscodingStreams

ext/TestExt.jl

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -81,24 +81,26 @@ function TranscodingStreams.test_chunked_read(Encoder, Decoder)
8181
alpha = b"色即是空"
8282
encoder = Encoder()
8383
initialize(encoder)
84-
for _ in 1:500
85-
chunks = [rand(alpha, rand(0:100)) for _ in 1:rand(1:100)]
86-
data = mapfoldl(x->transcode(encoder, x), vcat, chunks, init=UInt8[])
87-
buffer = NoopStream(IOBuffer(data))
88-
ok = true
89-
for chunk in chunks
90-
stream = TranscodingStream(Decoder(), buffer, stop_on_end=true)
91-
ok &= read(stream) == chunk
92-
ok &= position(stream) == length(chunk)
93-
ok &= eof(stream)
94-
ok &= isreadable(stream)
84+
for sharedbuf in false:true
85+
for _ in 1:500
86+
chunks = [rand(alpha, rand(0:100)) for _ in 1:rand(1:100)]
87+
data = mapfoldl(x->transcode(encoder, x), vcat, chunks, init=UInt8[])
88+
buffer = NoopStream(IOBuffer(data))
89+
ok = true
90+
for chunk in chunks
91+
stream = TranscodingStream(Decoder(), buffer; stop_on_end=true, sharedbuf)
92+
ok &= read(stream) == chunk
93+
ok &= position(stream) == length(chunk)
94+
ok &= eof(stream)
95+
ok &= isreadable(stream)
96+
close(stream)
97+
end
98+
# read without stop_on_end should read the full data.
99+
stream = TranscodingStream(Decoder(), IOBuffer(data))
100+
ok &= read(stream) == reduce(vcat, chunks)
95101
close(stream)
102+
Test.@test ok
96103
end
97-
# read without stop_on_end should read the full data.
98-
stream = TranscodingStream(Decoder(), IOBuffer(data))
99-
ok &= read(stream) == reduce(vcat, chunks)
100-
close(stream)
101-
Test.@test ok
102104
end
103105
finalize(encoder)
104106
end

src/stream.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,10 @@ function callprocess(stream::TranscodingStream, inbuf::Buffer, outbuf::Buffer)
700700
makemargin!(outbuf, max(16, marginsize(outbuf) * 2))
701701
elseif state.code == :end && state.stop_on_end
702702
if stream.state.mode == :read
703+
if stream.stream isa TranscodingStream && !has_sharedbuf(stream) && !iszero(buffersize(inbuf))
704+
# unread data to match behavior if inbuf was shared.
705+
GC.@preserve inbuf unsafe_unread(stream.stream, bufferptr(inbuf), buffersize(inbuf))
706+
end
703707
changemode!(stream, :stop)
704708
end
705709
end

0 commit comments

Comments
 (0)