Skip to content

Commit 3ece750

Browse files
baumgoldmkittiJoaoAparicio
authored
#132 allow users to optionally provide an output buffer when calling transcode (#136)
* allow users to optionally provide an output buffer when calling transcode * add tests and refactor docstring * nicer formating Co-authored-by: Mark Kittisopikul <[email protected]> * new copydata! method * reassociate docstring with correct method * Expand ByteData Co-authored-by: Mark Kittisopikul <[email protected]> * Expand ByteData Co-authored-by: Mark Kittisopikul <[email protected]> * Expand ByteData Co-authored-by: Mark Kittisopikul <[email protected]> * clarify formatting * formatting * Generic args Co-authored-by: Joao Aparicio <[email protected]> * Generic args Co-authored-by: Joao Aparicio <[email protected]> * small fixes * simplify * fix buffer * fix * formatting * fix buffer * Address PR comment #136 (comment) * Address PR comment #136 (comment) * Address PR review #136 (comment) #136 (comment) * dont use isnothing * add doc-string * replace keepbytes with marginpos * fix typeo --------- Co-authored-by: Mark Kittisopikul <[email protected]> Co-authored-by: Joao Aparicio <[email protected]>
1 parent de62b63 commit 3ece750

File tree

4 files changed

+85
-19
lines changed

4 files changed

+85
-19
lines changed

src/buffer.jl

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,18 @@ mutable struct Buffer
2626
# the total number of transcoded bytes
2727
transcoded::Int64
2828

29-
function Buffer(size::Integer)
30-
return new(Vector{UInt8}(undef, size), 0, 1, 1, 0)
29+
function Buffer(data::Vector{UInt8}, marginpos::Integer=length(data)+1)
30+
@assert 1 <= marginpos <= length(data)+1
31+
return new(data, 0, 1, marginpos, 0)
3132
end
33+
end
3234

33-
function Buffer(data::Vector{UInt8})
34-
return new(data, 0, 1, length(data)+1, 0)
35-
end
35+
function Buffer(size::Integer = 0)
36+
return Buffer(Vector{UInt8}(undef, size), 1)
3637
end
3738

38-
function Buffer(data::Base.CodeUnits{UInt8})
39-
return Buffer(Vector{UInt8}(data))
39+
function Buffer(data::Base.CodeUnits{UInt8}, args...)
40+
return Buffer(Vector{UInt8}(data), args...)
4041
end
4142

4243
function Base.length(buf::Buffer)
@@ -199,6 +200,11 @@ function copydata!(buf::Buffer, data::Ptr{UInt8}, nbytes::Integer)
199200
return buf
200201
end
201202

203+
# Copy data from `data` to `buf`.
204+
function copydata!(buf::Buffer, data::Buffer, nbytes::Integer = length(data))
205+
return copydata!(buf, bufferptr(data), nbytes)
206+
end
207+
202208
# Copy data from `buf` to `data`.
203209
function copydata!(data::Ptr{UInt8}, buf::Buffer, nbytes::Integer)
204210
# NOTE: It's caller's responsibility to ensure that the buffer has at least

src/noop.jl

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,9 @@ function Base.transcode(::Type{Noop}, data::ByteData)
120120
return transcode(Noop(), data)
121121
end
122122

123-
function Base.transcode(::Noop, data::ByteData)
124-
# Copy data because the caller may expect the return object is not the same
125-
# as from the input.
126-
return Vector{UInt8}(data)
123+
function Base.transcode(codec::Noop, input::Buffer, output::Buffer = Buffer())
124+
copydata!(output, input)
125+
return output.data
127126
end
128127

129128

src/transcode.jl

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
# =========
33

44
"""
5-
transcode(::Type{C}, data::Vector{UInt8})::Vector{UInt8} where C<:Codec
5+
transcode(
6+
::Type{C},
7+
data::Union{Vector{UInt8},Base.CodeUnits{UInt8}},
8+
)::Vector{UInt8} where {C<:Codec}
69
710
Transcode `data` by applying a codec `C()`.
811
@@ -27,21 +30,34 @@ julia> String(decompressed)
2730
2831
```
2932
"""
30-
function Base.transcode(::Type{C}, data::ByteData) where C<:Codec
33+
function Base.transcode(::Type{C}, args...) where {C<:Codec}
3134
codec = C()
3235
initialize(codec)
3336
try
34-
return transcode(codec, data)
37+
return transcode(codec, args...)
3538
finally
3639
finalize(codec)
3740
end
3841
end
3942

43+
_default_output_buffer(codec, input) = Buffer(
44+
initial_output_size(
45+
codec,
46+
buffermem(input)
47+
)
48+
)
49+
4050
"""
41-
transcode(codec::Codec, data::Vector{UInt8})::Vector{UInt8}
51+
transcode(
52+
codec::Codec,
53+
data::Union{Vector{UInt8},Base.CodeUnits{UInt8},Buffer},
54+
[output::Union{Vector{UInt8},Base.CodeUnits{UInt8},Buffer}],
55+
)::Vector{UInt8}
4256
4357
Transcode `data` by applying `codec`.
4458
59+
If `output` is unspecified, then this method will allocate it.
60+
4561
Note that this method does not initialize or finalize `codec`. This is
4662
efficient when you transcode a number of pieces of data, but you need to call
4763
[`TranscodingStreams.initialize`](@ref) and
@@ -59,7 +75,9 @@ julia> codec = ZlibCompressor();
5975
6076
julia> TranscodingStreams.initialize(codec)
6177
62-
julia> compressed = transcode(codec, data);
78+
julia> compressed = Vector{UInt8}()
79+
80+
julia> transcode(codec, data, compressed);
6381
6482
julia> TranscodingStreams.finalize(codec)
6583
@@ -76,9 +94,29 @@ julia> String(decompressed)
7694
7795
```
7896
"""
79-
function Base.transcode(codec::Codec, data::ByteData)
80-
input = Buffer(data)
81-
output = Buffer(initial_output_size(codec, buffermem(input)))
97+
function Base.transcode(
98+
codec::Codec,
99+
input::Buffer,
100+
output::Union{Buffer,Nothing} = nothing,
101+
)
102+
output = (output === nothing ? _default_output_buffer(codec, input) : initbuffer!(output))
103+
transcode!(output, codec, input)
104+
end
105+
106+
"""
107+
transcode!(output::Buffer, codec::Codec, input::Buffer)
108+
109+
Transcode `input` by applying `codec` and storing the results in `output`.
110+
Note that this method does not initialize or finalize `codec`. This is
111+
efficient when you transcode a number of pieces of data, but you need to call
112+
[`TranscodingStreams.initialize`](@ref) and
113+
[`TranscodingStreams.finalize`](@ref) explicitly.
114+
"""
115+
function transcode!(
116+
output::Buffer,
117+
codec::Codec,
118+
input::Buffer,
119+
)
82120
error = Error()
83121
code = startproc(codec, :write, error)
84122
if code === :error
@@ -121,6 +159,12 @@ function Base.transcode(codec::Codec, data::ByteData)
121159
throw(error[])
122160
end
123161

162+
Base.transcode(codec::Codec, data::Buffer, output::ByteData) =
163+
transcode(codec, data, Buffer(output))
164+
165+
Base.transcode(codec::Codec, data::ByteData, args...) =
166+
transcode(codec, Buffer(data), args...)
167+
124168
# Return the initial output buffer size.
125169
function initial_output_size(codec::Codec, input::Memory)
126170
return max(

test/codecnoop.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,26 @@
192192
data = b""
193193
@test transcode(Noop(), data) == data
194194
@test transcode(Noop(), data) !== data
195+
@test transcode(Noop(), data, Vector{UInt8}()) == data
196+
@test transcode(Noop(), data, TranscodingStreams.Buffer(Vector{UInt8}())) == data
197+
@test transcode(Noop(), data, Vector{UInt8}()) !== data
198+
@test transcode(Noop(), data, TranscodingStreams.Buffer(Vector{UInt8}())) !== data
199+
output = Vector{UInt8}()
200+
@test transcode(Noop(), data, output) === output
201+
output = TranscodingStreams.Buffer(Vector{UInt8}())
202+
@test transcode(Noop(), data, output) === output.data
203+
195204
data = b"foo"
196205
@test transcode(Noop(), data) == data
197206
@test transcode(Noop(), data) !== data
207+
@test transcode(Noop(), data, Vector{UInt8}()) == data
208+
@test transcode(Noop(), data, TranscodingStreams.Buffer(Vector{UInt8}())) == data
209+
@test transcode(Noop(), data, Vector{UInt8}()) !== data
210+
@test transcode(Noop(), data, TranscodingStreams.Buffer(Vector{UInt8}())) !== data
211+
output = Vector{UInt8}()
212+
@test transcode(Noop(), data, output) === output
213+
output = TranscodingStreams.Buffer(Vector{UInt8}())
214+
@test transcode(Noop(), data, output) === output.data
198215

199216
TranscodingStreams.test_roundtrip_transcode(Noop, Noop)
200217
TranscodingStreams.test_roundtrip_read(NoopStream, NoopStream)

0 commit comments

Comments
 (0)