Skip to content

Commit 1f65032

Browse files
authored
Merge pull request #212 from JuliaIO/td-non-seekable-iobuffers
Support for non-seekable IOBuffers
2 parents eb9519f + bd317b8 commit 1f65032

File tree

2 files changed

+56
-27
lines changed

2 files changed

+56
-27
lines changed

src/codec/encode.jl

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,36 +13,46 @@ maybe_ensure_room(::IO, n) = nothing
1313
# 3. come back to beginning and encode the length
1414
# 4. shift the encoded data in case we didn't use all 5 bytes allocated for length
1515
@inline function _with_size(f, io::IOBuffer, sink, x)
16-
MAX_LENGTH_VARINT_BYTES = 5 # max size of a UInt32 as vbyte
17-
initpos = position(io)
18-
truncate(io, initpos + MAX_LENGTH_VARINT_BYTES) # 1.
19-
seek(io, initpos + MAX_LENGTH_VARINT_BYTES)
20-
f(sink, x) # e.g. _encode(io, x) # 2.
21-
endpos = position(io)
22-
data_len = endpos - initpos - MAX_LENGTH_VARINT_BYTES
23-
seek(io, initpos) # 3.
24-
vbyte_encode(io, UInt32(data_len)) # --||--
25-
lenght_len = position(io) - initpos
26-
unsafe_copyto!(io.data, initpos + lenght_len + 1, io.data, initpos + MAX_LENGTH_VARINT_BYTES + 1, data_len) # 4.
27-
seek(io, initpos + lenght_len + data_len)
28-
truncate(io, initpos + lenght_len + data_len)
16+
if io.seekable
17+
MAX_LENGTH_VARINT_BYTES = 5 # max size of a UInt32 as vbyte
18+
initpos = position(io)
19+
truncate(io, initpos + MAX_LENGTH_VARINT_BYTES) # 1.
20+
seek(io, initpos + MAX_LENGTH_VARINT_BYTES)
21+
f(sink, x) # e.g. _encode(io, x) # 2.
22+
endpos = position(io)
23+
data_len = endpos - initpos - MAX_LENGTH_VARINT_BYTES
24+
seek(io, initpos) # 3.
25+
vbyte_encode(io, UInt32(data_len)) # --||--
26+
lenght_len = position(io) - initpos
27+
unsafe_copyto!(io.data, initpos + lenght_len + 1, io.data, initpos + MAX_LENGTH_VARINT_BYTES + 1, data_len) # 4.
28+
seek(io, initpos + lenght_len + data_len)
29+
truncate(io, initpos + lenght_len + data_len)
30+
else
31+
vbyte_encode(io, UInt32(_encoded_size(x)))
32+
f(sink, x)
33+
end
2934
return nothing
3035
end
3136

3237
@inline function _with_size(f, io::IOBuffer, sink, x, V)
33-
MAX_LENGTH_VARINT_BYTES = 5 # max size of a UInt32 as vbyte
34-
initpos = position(io)
35-
truncate(io, initpos + MAX_LENGTH_VARINT_BYTES) # 1.
36-
seek(io, initpos + MAX_LENGTH_VARINT_BYTES)
37-
f(sink, x, V) # e.g. _encode(io, x, Val{:zigzag}) # 2.
38-
endpos = position(io)
39-
data_len = endpos - initpos - MAX_LENGTH_VARINT_BYTES
40-
seek(io, initpos) # 3.
41-
vbyte_encode(io, UInt32(data_len)) # --||--
42-
lenght_len = position(io) - initpos
43-
unsafe_copyto!(io.data, initpos + lenght_len + 1, io.data, initpos + MAX_LENGTH_VARINT_BYTES + 1, data_len) # 4.
44-
seek(io, initpos + lenght_len + data_len)
45-
truncate(io, initpos + lenght_len + data_len)
38+
if io.seekable
39+
MAX_LENGTH_VARINT_BYTES = 5 # max size of a UInt32 as vbyte
40+
initpos = position(io)
41+
truncate(io, initpos + MAX_LENGTH_VARINT_BYTES) # 1.
42+
seek(io, initpos + MAX_LENGTH_VARINT_BYTES)
43+
f(sink, x, V) # e.g. _encode(io, x, Val{:zigzag}) # 2.
44+
endpos = position(io)
45+
data_len = endpos - initpos - MAX_LENGTH_VARINT_BYTES
46+
seek(io, initpos) # 3.
47+
vbyte_encode(io, UInt32(data_len)) # --||--
48+
lenght_len = position(io) - initpos
49+
unsafe_copyto!(io.data, initpos + lenght_len + 1, io.data, initpos + MAX_LENGTH_VARINT_BYTES + 1, data_len) # 4.
50+
seek(io, initpos + lenght_len + data_len)
51+
truncate(io, initpos + lenght_len + data_len)
52+
else
53+
vbyte_encode(io, UInt32(_encoded_size(x, V)))
54+
f(sink, x, V)
55+
end
4656
return nothing
4757
end
4858

test/test_encode.jl

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module TestEncode
22
using ProtoBuf: Codecs
33
import ProtoBuf as PB
4-
using .Codecs: encode, ProtoEncoder, WireType
4+
using .Codecs: _with_size, encode, ProtoEncoder, WireType
55
using Test
66
using EnumX: @enumx
77

@@ -319,6 +319,7 @@ module TestEncodedSize
319319
using Test
320320
using ProtoBuf: _encoded_size
321321
import ProtoBuf as PB
322+
using ProtoBuf: Codecs
322323

323324
using EnumX
324325
@enumx TestEnum DEFAULT=0 OTHER=1
@@ -338,6 +339,24 @@ function PB._encoded_size(x::NonEmptyMessage)
338339
return encoded_size
339340
end
340341

342+
@testset "_with_size" begin
343+
io = IOBuffer()
344+
Codecs._with_size(Codecs._encode, io, io, [1, 2, 3, 4, 5, 6])
345+
@test take!(io) == UInt8[6, 1, 2, 3, 4, 5, 6]
346+
347+
io = IOBuffer()
348+
Codecs._with_size(Codecs._encode, io, io, [1, 2, 3, 4, 5, 6], Val{:zigzag})
349+
@test take!(io) == UInt8[6, 2, 4, 6, 8, 10, 12]
350+
351+
io = PipeBuffer()
352+
Codecs._with_size(Codecs._encode, io, io, [1, 2, 3, 4, 5, 6])
353+
@test take!(io) == UInt8[6, 1, 2, 3, 4, 5, 6]
354+
355+
io = PipeBuffer()
356+
Codecs._with_size(Codecs._encode, io, io, [1, 2, 3, 4, 5, 6], Val{:zigzag})
357+
@test take!(io) == UInt8[6, 2, 4, 6, 8, 10, 12]
358+
end
359+
341360
@testset "_encoded_size" begin
342361
@test _encoded_size(nothing) == 0
343362
@test _encoded_size(UInt8[0xff]) == 1

0 commit comments

Comments
 (0)