diff --git a/src/TranscodingStreams.jl b/src/TranscodingStreams.jl index e1d96946..a2780d98 100644 --- a/src/TranscodingStreams.jl +++ b/src/TranscodingStreams.jl @@ -7,6 +7,9 @@ export const ByteData = Union{Vector{UInt8},Base.CodeUnits{UInt8}} +# in-place variant of transcode when output buffer size is known +function transcode! end + include("memory.jl") include("buffer.jl") include("error.jl") diff --git a/src/transcode.jl b/src/transcode.jl index 6043853d..ed03b51a 100644 --- a/src/transcode.jl +++ b/src/transcode.jl @@ -129,3 +129,43 @@ function initial_output_size(codec::Codec, input::Memory) 8, # just in case where both minoutsize and expectedsize are foolish ) end +# Mutates the provided output buffer. Useful for cases when output size is known. +function transcode!(codec::Codec, data::ByteData,output::Buffer) + input = Buffer(data) + error = Error() + code = startproc(codec, :write, error) + if code === :error + @goto error + end + @label process + Δin, Δout, code = process(codec, buffermem(input), marginmem(output), error) + @debug( + "called process()", + code = code, + input_size = buffersize(input), + output_size = marginsize(output), + input_delta = Δin, + output_delta = Δout, + ) + consumed!(input, Δin) + supplied!(output, Δout) + if code === :error + @goto error + elseif code === :end + if buffersize(input) > 0 + if startproc(codec, :write, error) === :error + @goto error + end + @goto process + end + resize!(output.data, output.marginpos - 1) + return output.data + else + @goto process + end + @label error + if !haserror(error) + set_default_error!(error) + end + throw(error[]) +end \ No newline at end of file