Function decodeBlockRingBuffer [src]
Decode a single block from src into dest; see decodeBlock(). Returns
the size of the decompressed block, which can be used with dest.sliceLast()
to get the decompressed bytes. error.BlockSizeOverMaximum is returned if
the block's compressed or decompressed size is larger than block_size_max.
Prototype
pub fn decodeBlockRingBuffer( dest: *RingBuffer, src: []const u8, block_header: frame.Zstandard.Block.Header, decode_state: *DecodeState, consumed_count: *usize, block_size_max: usize, ) Error!usize
Parameters
dest: *RingBuffer
src: []const u8
block_header: frame.Zstandard.Block.Header
decode_state: *DecodeState
consumed_count: *usize
block_size_max: usize
Possible Errors
Source
pub fn decodeBlockRingBuffer(
dest: *RingBuffer,
src: []const u8,
block_header: frame.Zstandard.Block.Header,
decode_state: *DecodeState,
consumed_count: *usize,
block_size_max: usize,
) Error!usize {
const block_size = block_header.block_size;
if (block_size_max < block_size) return error.BlockSizeOverMaximum;
switch (block_header.block_type) {
.raw => {
if (src.len < block_size) return error.MalformedBlockSize;
// dest may have length zero if block_size == 0, causing division by zero in
// writeSliceAssumeCapacity()
if (block_size > 0) {
const data = src[0..block_size];
dest.writeSliceAssumeCapacity(data);
consumed_count.* += block_size;
decode_state.written_count += block_size;
}
return block_size;
},
.rle => {
if (src.len < 1) return error.MalformedRleBlock;
for (0..block_size) |_| {
dest.writeAssumeCapacity(src[0]);
}
consumed_count.* += 1;
decode_state.written_count += block_size;
return block_size;
},
.compressed => {
if (src.len < block_size) return error.MalformedBlockSize;
var bytes_read: usize = 0;
const literals = decodeLiteralsSectionSlice(src[0..block_size], &bytes_read) catch
return error.MalformedCompressedBlock;
var fbs = std.io.fixedBufferStream(src[bytes_read..block_size]);
const fbs_reader = fbs.reader();
const sequences_header = decodeSequencesHeader(fbs_reader) catch
return error.MalformedCompressedBlock;
decode_state.prepare(fbs_reader, literals, sequences_header) catch
return error.MalformedCompressedBlock;
bytes_read += fbs.pos;
var bytes_written: usize = 0;
{
const bit_stream_bytes = src[bytes_read..block_size];
var bit_stream: readers.ReverseBitReader = undefined;
bit_stream.init(bit_stream_bytes) catch return error.MalformedCompressedBlock;
if (sequences_header.sequence_count > 0) {
decode_state.readInitialFseState(&bit_stream) catch
return error.MalformedCompressedBlock;
var sequence_size_limit = block_size_max;
for (0..sequences_header.sequence_count) |i| {
const decompressed_size = decode_state.decodeSequenceRingBuffer(
dest,
&bit_stream,
sequence_size_limit,
i == sequences_header.sequence_count - 1,
) catch return error.MalformedCompressedBlock;
bytes_written += decompressed_size;
sequence_size_limit -= decompressed_size;
}
}
if (!bit_stream.isEmpty()) {
return error.MalformedCompressedBlock;
}
}
if (decode_state.literal_written_count < literals.header.regenerated_size) {
const len = literals.header.regenerated_size - decode_state.literal_written_count;
decode_state.decodeLiteralsRingBuffer(dest, len) catch
return error.MalformedCompressedBlock;
bytes_written += len;
}
switch (decode_state.literal_header.block_type) {
.treeless, .compressed => {
if (!decode_state.isLiteralStreamEmpty()) return error.MalformedCompressedBlock;
},
.raw, .rle => {},
}
consumed_count.* += block_size;
if (bytes_written > block_size_max) return error.BlockSizeOverMaximum;
return bytes_written;
},
.reserved => return error.ReservedBlock,
}
}