Skip to content

Commit d127ceb

Browse files
authored
add transcode(::Type{Codec}, data) method (#23)
1 parent ad37a57 commit d127ceb

File tree

7 files changed

+111
-41
lines changed

7 files changed

+111
-41
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ close(stream)
5151

5252
# Array API.
5353
array = Vector{UInt8}(text)
54-
array = transcode(GzipCompression(), array)
55-
array = transcode(GzipDecompression(), array)
54+
array = transcode(GzipCompression, array)
55+
array = transcode(GzipDecompression, array)
5656
@assert text == String(array)
5757
```
5858

docs/src/examples.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,33 @@ in one shot. `transcode` takes a codec object as its first argument and a data
140140
vector as its second argument:
141141
```julia
142142
using CodecZlib
143-
decompressed = transcode(ZlibDecompression(), b"x\x9cKL*JLNLI\x04R\x00\x19\xf2\x04U")
143+
decompressed = transcode(ZlibDecompression, b"x\x9cKL*JLNLI\x04R\x00\x19\xf2\x04U")
144144
String(decompressed)
145145
```
146146

147+
Transcode lots of strings
148+
-------------------------
149+
150+
`transcode(<codec type>, data)` method is convenient but suboptimal when
151+
transcoding a number of objects. This is because the method reallocates a new
152+
codec object for every call. Instead, you can use `transcode(<codec object>,
153+
data)` method that reuses the allocated object as follows:
154+
```julia
155+
using CodecZstd
156+
strings = ["foo", "bar", "baz"]
157+
codec = ZstdCompression()
158+
try
159+
for s in strings
160+
data = transcode(codec, s)
161+
# do something...
162+
end
163+
catch
164+
rethrow()
165+
finally
166+
CodecZstd.TranscodingStreams.finalize(codec)
167+
end
168+
```
169+
147170
Unread data
148171
-----------
149172

src/TranscodingStreams.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ include("stream.jl")
1616
include("io.jl")
1717
include("identity.jl")
1818
include("noop.jl")
19+
include("transcode.jl")
1920
include("testtools.jl")
2021

2122
end # module

src/stream.jl

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -333,44 +333,6 @@ function Base.write(stream::TranscodingStream, ::EndToken)
333333
end
334334

335335

336-
# Transcode
337-
# ---------
338-
339-
"""
340-
transcode(codec::Codec, data::Vector{UInt8})::Vector{UInt8}
341-
342-
Transcode `data` by applying `codec`.
343-
344-
Examples
345-
--------
346-
347-
```julia
348-
julia> using CodecZlib
349-
350-
julia> data = Vector{UInt8}("abracadabra");
351-
352-
julia> compressed = transcode(ZlibCompression(), data);
353-
354-
julia> decompressed = transcode(ZlibDecompression(), compressed);
355-
356-
julia> String(decompressed)
357-
"abracadabra"
358-
359-
```
360-
"""
361-
function Base.transcode(codec::Codec, data::Vector{UInt8})
362-
# Add `minoutsize` because `transcode` will be called at least two times.
363-
buffer2 = Buffer(
364-
expectedsize(codec, Memory(data)) + minoutsize(codec, Memory(C_NULL, 0)))
365-
mark!(buffer2)
366-
stream = TranscodingStream(codec, DevNull, State(Buffer(data), buffer2))
367-
write(stream, TOKEN_END)
368-
transcoded = takemarked!(buffer2)
369-
changemode!(stream, :idle)
370-
return transcoded
371-
end
372-
373-
374336
# Utils
375337
# -----
376338

src/testtools.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,11 @@ function test_roundtrip_transcode(encode, decode)
3030
decoder = decode()
3131
for n in vcat(0:30, sort!(rand(500:100_000, 30))), alpha in (0x00:0xff, 0x00:0x0f)
3232
data = rand(alpha, n)
33+
Base.Test.@test hash(transcode(decode, transcode(encode, data))) == hash(data)
3334
Base.Test.@test hash(transcode(decoder, transcode(encoder, data))) == hash(data)
3435
end
36+
finalize(encoder)
37+
finalize(decoder)
3538
end
3639

3740
function test_roundtrip_lines(encoder, decoder)

src/transcode.jl

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Transcode
2+
# =========
3+
4+
"""
5+
transcode(::Type{C}, data::Vector{UInt8})::Vector{UInt8} where C<:Codec
6+
7+
Transcode `data` by applying a codec `C()`.
8+
9+
Note that this method does allocation and deallocation of `C()` in every call,
10+
which is handy but less efficient when transcoding a number of objects.
11+
`transcode(codec, data)` is a recommended method in terms of performance.
12+
13+
Examples
14+
--------
15+
16+
```julia
17+
julia> using CodecZlib
18+
19+
julia> data = b"abracadabra";
20+
21+
julia> compressed = transcode(ZlibCompression, data);
22+
23+
julia> decompressed = transcode(ZlibDecompression, compressed);
24+
25+
julia> String(decompressed)
26+
"abracadabra"
27+
28+
```
29+
"""
30+
function Base.transcode(::Type{C}, data::Vector{UInt8}) where C<:Codec
31+
codec = C()
32+
try
33+
return transcode(codec, data)
34+
finally
35+
finalize(codec)
36+
end
37+
end
38+
39+
"""
40+
transcode(codec::Codec, data::Vector{UInt8})::Vector{UInt8}
41+
42+
Transcode `data` by applying `codec`.
43+
44+
Note that this method does not deallocation of `codec`, which is efficient but
45+
the caller will need to deallocate `codec`.
46+
47+
Examples
48+
--------
49+
50+
```julia
51+
julia> using CodecZlib
52+
53+
julia> data = b"abracadabra";
54+
55+
julia> compressed = transcode(ZlibCompression(), data);
56+
57+
julia> decompressed = transcode(ZlibDecompression(), compressed);
58+
59+
julia> String(decompressed)
60+
"abracadabra"
61+
62+
```
63+
"""
64+
function Base.transcode(codec::Codec, data::Vector{UInt8})
65+
# Add `minoutsize` because `transcode` will be called at least two times.
66+
buffer2 = Buffer(
67+
expectedsize(codec, Memory(data)) + minoutsize(codec, Memory(C_NULL, 0)))
68+
mark!(buffer2)
69+
stream = TranscodingStream(codec, DevNull, State(Buffer(data), buffer2))
70+
write(stream, TOKEN_END)
71+
transcoded = takemarked!(buffer2)
72+
changemode!(stream, :idle)
73+
return transcoded
74+
end

test/runtests.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,13 @@ end
169169
@test readavailable(stream) == b"oobar"
170170
close(stream)
171171

172+
data = b""
173+
@test transcode(Noop, data) == data
174+
@test transcode(Noop, data) !== data
175+
data = b"foo"
176+
@test transcode(Noop, data) == data
177+
@test transcode(Noop, data) !== data
178+
172179
data = b""
173180
@test transcode(Noop(), data) == data
174181
@test transcode(Noop(), data) !== data

0 commit comments

Comments
 (0)