Skip to content

Commit 6b13d1f

Browse files
authored
Fix position of underlying stream when sharing buffers (#222)
1 parent b5b03e6 commit 6b13d1f

File tree

5 files changed

+59
-29
lines changed

5 files changed

+59
-29
lines changed

fuzz/fuzz.jl

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,41 @@ read_methods = Data.SampledFrom([
9191
end
9292
])
9393

94+
# Return true if the stats of a stream are self consistent
95+
# This function assumes stream was never seeked.
96+
function is_stats_consistent(stream)
97+
if stream isa TranscodingStream
98+
s = TranscodingStreams.stats(stream)
99+
inner_pos = position(stream.stream)
100+
pos = position(stream)
101+
# event!("stats(stream)", s)
102+
# event!("position(stream.stream)", inner_pos)
103+
# event!("position(stream)", pos)
104+
if isreadable(stream)
105+
s.out == pos || return false
106+
s.in == inner_pos || return false
107+
else
108+
iswritable(stream) || return false
109+
s.in == pos || return false
110+
s.out == inner_pos || return false
111+
end
112+
s.transcoded_in s.in || return false
113+
s.transcoded_out s.out || return false
114+
end
115+
true
116+
end
94117

95118
@check function read_byte_data(
96119
kws=read_codecs_kws,
97120
data=datas,
98121
)
99122
stream = wrap_stream(kws, IOBuffer(data))
100-
for i in eachindex(data)
123+
for i in 1:length(data)
124+
position(stream) == i-1 || return false
125+
is_stats_consistent(stream) || return false
101126
read(stream, UInt8) == data[i] || return false
102127
end
128+
is_stats_consistent(stream) || return false
103129
eof(stream)
104130
end
105131
@check function read_data(
@@ -108,6 +134,7 @@ end
108134
)
109135
stream = wrap_stream(kws, IOBuffer(data))
110136
read(stream) == data || return false
137+
is_stats_consistent(stream) || return false
111138
eof(stream)
112139
end
113140
@check function read_data_methods(
@@ -122,13 +149,15 @@ end
122149
append!(x, d)
123150
length(x) == position(stream) || return false
124151
end
152+
is_stats_consistent(stream) || return false
125153
x == data[eachindex(x)]
126154
end
127155

128156
# flush all nested streams and return final data
129157
function take_all(stream)
130158
if stream isa Base.GenericIOBuffer
131-
take!(stream)
159+
seekstart(stream)
160+
read(stream)
132161
else
133162
write(stream, TranscodingStreams.TOKEN_END)
134163
flush(stream)
@@ -144,7 +173,9 @@ const write_codecs_kws = map(reverse, read_codecs_kws)
144173
)
145174
stream = wrap_stream(kws, IOBuffer())
146175
write(stream, data) == length(data) || return false
147-
take_all(stream) == data
176+
take_all(stream) == data || return false
177+
is_stats_consistent(stream) || return false
178+
true
148179
end
149180
@check function write_byte_data(
150181
kws=write_codecs_kws,
@@ -153,24 +184,10 @@ end
153184
stream = wrap_stream(kws, IOBuffer())
154185
for i in 1:length(data)
155186
position(stream) == i-1 || return false
156-
if stream isa TranscodingStream
157-
s = TranscodingStreams.stats(stream)
158-
s.in == i-1 || return false
159-
# TODO fix position(stream.stream)
160-
# s.out == position(stream.stream) || return false
161-
# s.transcoded_in == s.out || return false
162-
# s.transcoded_out == s.out || return false
163-
end
187+
is_stats_consistent(stream) || return false
164188
write(stream, data[i]) == 1 || return false
165189
end
166190
take_all(stream) == data || return false
167-
if stream isa TranscodingStream
168-
s = TranscodingStreams.stats(stream)
169-
s.in == length(data) || return false
170-
# TODO fix position(stream.stream)
171-
# s.out == position(stream.stream) || return false
172-
# s.transcoded_in == s.out || return false
173-
# s.transcoded_out == s.out || return false
174-
end
191+
is_stats_consistent(stream) || return false
175192
true
176193
end

src/noop.jl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,12 @@ function stats(stream::NoopStream)
155155
if mode === :idle
156156
in = out = 0
157157
elseif mode === :read
158-
in = buffer.transcoded
159-
out = in - buffersize(buffer)
158+
out = buffer.transcoded - buffersize(buffer)
159+
if has_sharedbuf(stream)
160+
in = out
161+
else
162+
in = buffer.transcoded
163+
end
160164
elseif mode === :write
161165
out = stream.state.bytes_written_out
162166
in = out

src/stream.jl

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -605,10 +605,15 @@ function stats(stream::TranscodingStream)
605605
if mode === :idle
606606
transcoded_in = transcoded_out = in = out = 0
607607
elseif mode === :read || mode === :stop
608-
transcoded_in = buffer2.transcoded
609608
transcoded_out = buffer1.transcoded
610-
in = transcoded_in + buffersize(buffer2)
611609
out = transcoded_out - buffersize(buffer1)
610+
if has_sharedbuf(stream)
611+
transcoded_in = stats(stream.stream).out
612+
in = transcoded_in
613+
else
614+
transcoded_in = buffer2.transcoded
615+
in = transcoded_in + buffersize(buffer2)
616+
end
612617
elseif mode === :write
613618
transcoded_in = buffer1.transcoded
614619
out = state.bytes_written_out
@@ -709,8 +714,12 @@ function callprocess(stream::TranscodingStream, inbuf::Buffer, outbuf::Buffer)
709714
input_delta = Δin,
710715
output_delta = Δout,
711716
)
712-
consumed!(inbuf, Δin, transcode = true)
713-
supplied!(outbuf, Δout, transcode = true)
717+
consumed!(inbuf, Δin;
718+
transcode = !has_sharedbuf(stream) || stream.state.mode === :write,
719+
) # inbuf is buffer1 if mode is :write
720+
supplied!(outbuf, Δout;
721+
transcode = !has_sharedbuf(stream) || stream.state.mode !== :write,
722+
) # outbuf is buffer1 if mode is not :write
714723
if has_sharedbuf(stream)
715724
if stream.state.mode === :write
716725
# this must be updated before throwing any error if outbuf is shared.

test/codecdoubleframe.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,8 @@ DoubleFrameDecoderStream(stream::IO; kwargs...) = TranscodingStream(DoubleFrameD
324324
@test stat.out == 0
325325
read(stream)
326326
stat = TranscodingStreams.stats(stream)
327-
@test_broken stat.in == 16
328-
@test_broken stat.transcoded_in == 16
327+
@test stat.in == 16
328+
@test stat.transcoded_in == 16
329329
@test stat.transcoded_out == 6
330330
@test stat.out == 6
331331
close(stream)
@@ -373,7 +373,7 @@ DoubleFrameDecoderStream(stream::IO; kwargs...) = TranscodingStream(DoubleFrameD
373373
@test stat.transcoded_in == 16
374374
@test stat.transcoded_out == 6
375375
@test stat.out == 6
376-
@test_broken position(stream.stream) == 6
376+
@test position(stream.stream) == 6
377377
close(stream)
378378
end
379379
end

test/codecnoop.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ using FillArrays: Zeros
193193
@test stat.out === Int64(0)
194194
eof(stream)
195195
stat = TranscodingStreams.stats(stream)
196-
@test_broken stat.in === Int64(0)
196+
@test stat.in === Int64(0)
197197
@test stat.out === Int64(0)
198198
read(stream)
199199
stat = TranscodingStreams.stats(stream)

0 commit comments

Comments
 (0)