Skip to content

Commit edde03a

Browse files
committed
add some docs on transcoding protocol
1 parent ebabeb4 commit edde03a

File tree

3 files changed

+60
-3
lines changed

3 files changed

+60
-3
lines changed

docs/make.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ using Documenter
22
using TranscodingStreams
33

44
makedocs(
5-
# Documenter.jl doesn't support including HTML elements.
65
format=:html,
76
sitename="TranscodingStreams.jl",
87
modules=[TranscodingStreams],

src/codec.jl

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,62 @@
44
"""
55
An abstract codec type.
66
7-
Any codec supporting transcoding interfaces must be a subtype of this type.
7+
Any codec supporting the transcoding protocol must be a subtype of this type.
8+
9+
10+
Transcoding protocol
11+
--------------------
12+
13+
Transcoding proceeds by calling some functions in a specific way. We call this
14+
"transcoding protocol" and any codec must implement it as described below.
15+
16+
There are four functions for a codec to implement:
17+
- initialize: initialize the codec
18+
- finalize: finalize the codec
19+
- startproc: start processing with the codec
20+
- process: process data with the codec.
21+
22+
These are defined in the `TranscodingStreams` and a new codec type must extend
23+
these methods if necessary. Implementing a `process` method is mandatory but
24+
other three are optional. `initialize`, `finalize`, and `startproc` have a
25+
default implementation that does nothing.
26+
27+
Your codec type is denoted by `C` and its object by `codec`.
28+
29+
The `initialize(codec::C)::Void` method takes `codec` and returns
30+
`nothing`. This is called once and only once before starting any data
31+
processing. Therefore, you may initialize `codec` (e.g. allocating memory
32+
needed to process data) with this method. If initialization fails for some
33+
reason, it may throw an exception and no other methods will be called.
34+
35+
The `finalize(codec::C)::Void` method takes `codec` and returns `nothing`. This
36+
is called when and only when the transcoding stream goes to the close state
37+
(i.e. when `Base.close` is called). Therefore, you may finalize `codec` (e.g.
38+
freeing memory) with this method. If finalization fails for some reason, it may
39+
throw an exception. Even when an exception is thrown while finalizing a stream,
40+
the stream will become the close state for safety.
41+
42+
The `startproc(codec::C, state::Symbol)::Symbol` method takes `codec` and
43+
`state`, and returns a status code. This is called just before the stream starts
44+
reading or writing data. `state` is either `:read` or `:write` and then the
45+
stream starts reading or writing, respectively. The return code must be `:ok` if
46+
`codec` is ready to read or write data. Otherwise, it should be `:fail` and then
47+
the stream throws an exception.
48+
49+
The `process(codec::C, input::Memory, output::Memory)::Tuple{Int,Int,Symbol}`
50+
method takes `codec`, `input` and `output`, and returns a consumed data size, a
51+
produced data size and a status code. This is called repeatedly while processing
52+
data. The input (`input`) and output (`output`) data are a `Memory` object,
53+
which is a pointer to a contiguous memory region with size. You must read input
54+
data from `input`, transcode the bytes, and then write the output data to
55+
`output`. Finally you need to return the size of read data, the size of written
56+
data, and `:ok` status code so that the caller can know how many bytes are
57+
consumed and produced in the method. When transcoding reaches the end of a data
58+
stream, it is notified to this method by empty input. In that case, the method
59+
need to write the buffered data (if any) to `output`. If there is no data to
60+
write, the status code must be set to `:end`. The `process` method will be
61+
called repeatedly until it returns `:end` status code.
62+
863
"""
964
abstract type Codec end
1065

src/stream.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,8 +453,11 @@ function changestate!(stream::TranscodingStream, newstate::Symbol)
453453
stream.state.state = newstate
454454
return
455455
elseif newstate == :close
456-
finalize(stream.codec)
456+
# Set the new state before calling `finalize` because it may throw
457+
# an exception. This is undesirable but would be better than keeping
458+
# it in the open state.
457459
stream.state.state = newstate
460+
finalize(stream.codec)
458461
return
459462
end
460463
elseif state == :read

0 commit comments

Comments
 (0)