authorgravatar for 4678790+dweiller@users.noreply.github.comDominic <4678790+dweiller@users.noreply.github.com> 2023-02-04 13:49:06+11:00
committergravatar for 4678790+dweiller@users.noreply.github.comDominic <4678790+dweiller@users.noreply.github.com> 2023-02-20 09:09:06+11:00
log06ab5a2cd21ecd972477f067bb1d595a9ebef483
treee996ea257c116b501b80f94a401a190dc59d81a8
parenta625df463648b7f6ff2d15de8be5e168c8bc7363

std.compress.zstandard: add multi-frame decoding functions


1 files changed, 55 insertions(+), 3 deletions(-)

lib/std/compress/zstandard/decompress.zig+55-3
...@@ -54,6 +54,40 @@ const ReadWriteCount = struct {...@@ -54,6 +54,40 @@ const ReadWriteCount = struct {
54 write_count: usize,54 write_count: usize,
55};55};
5656
57/// Decodes frames from `src` into `dest`; see `decodeFrame()`.
58pub fn decode(dest: []u8, src: []const u8, verify_checksum: bool) !usize {
59 var write_count: usize = 0;
60 var read_count: usize = 0;
61 while (read_count < src.len) {
62 const counts = try decodeFrame(dest, src[read_count..], verify_checksum);
63 read_count += counts.read_count;
64 write_count += counts.write_count;
65 }
66 return write_count;
67}
68
69pub fn decodeAlloc(
70 allocator: Allocator,
71 src: []const u8,
72 verify_checksum: bool,
73 window_size_max: usize,
74) ![]u8 {
75 var result = std.ArrayList(u8).init(allocator);
76 errdefer result.deinit();
77
78 var read_count: usize = 0;
79 while (read_count < src.len) {
80 read_count += try decodeZstandardFrameArrayList(
81 allocator,
82 &result,
83 src[read_count..],
84 verify_checksum,
85 window_size_max,
86 );
87 }
88 return result.toOwnedSlice();
89}
90
57/// Decodes the frame at the start of `src` into `dest`. Returns the number of91/// Decodes the frame at the start of `src` into `dest`. Returns the number of
58/// bytes read from `src` and written to `dest`. This function can only decode92/// bytes read from `src` and written to `dest`. This function can only decode
59/// frames that declare the decompressed content size.93/// frames that declare the decompressed content size.
...@@ -268,6 +302,24 @@ pub fn decodeZstandardFrameAlloc(...@@ -268,6 +302,24 @@ pub fn decodeZstandardFrameAlloc(
268) (error{OutOfMemory} || FrameContext.Error || FrameError)!DecodeResult {302) (error{OutOfMemory} || FrameContext.Error || FrameError)!DecodeResult {
269 var result = std.ArrayList(u8).init(allocator);303 var result = std.ArrayList(u8).init(allocator);
270 errdefer result.deinit();304 errdefer result.deinit();
305 const read_count = try decodeZstandardFrameArrayList(
306 allocator,
307 &result,
308 src,
309 verify_checksum,
310 window_size_max,
311 );
312 return DecodeResult{ .bytes = try result.toOwnedSlice(), .read_count = read_count };
313}
314
315/// Decode a ZStandard frame into `dest`; see `decodeZStandardFrameAlloc()`.
316pub fn decodeZstandardFrameArrayList(
317 allocator: Allocator,
318 dest: *std.ArrayList(u8),
319 src: []const u8,
320 verify_checksum: bool,
321 window_size_max: usize,
322) (error{OutOfMemory} || FrameContext.Error || FrameError)!usize {
271 assert(readInt(u32, src[0..4]) == frame.Zstandard.magic_number);323 assert(readInt(u32, src[0..4]) == frame.Zstandard.magic_number);
272 var consumed_count: usize = 4;324 var consumed_count: usize = 4;
273325
...@@ -305,8 +357,8 @@ pub fn decodeZstandardFrameAlloc(...@@ -305,8 +357,8 @@ pub fn decodeZstandardFrameAlloc(
305 );357 );
306 if (written_size > 0) {358 if (written_size > 0) {
307 const written_slice = ring_buffer.sliceLast(written_size);359 const written_slice = ring_buffer.sliceLast(written_size);
308 try result.appendSlice(written_slice.first);360 try dest.appendSlice(written_slice.first);
309 try result.appendSlice(written_slice.second);361 try dest.appendSlice(written_slice.second);
310 if (frame_context.hasher_opt) |*hasher| {362 if (frame_context.hasher_opt) |*hasher| {
311 hasher.update(written_slice.first);363 hasher.update(written_slice.first);
312 hasher.update(written_slice.second);364 hasher.update(written_slice.second);
...@@ -323,7 +375,7 @@ pub fn decodeZstandardFrameAlloc(...@@ -323,7 +375,7 @@ pub fn decodeZstandardFrameAlloc(
323 if (checksum != computeChecksum(hasher)) return error.ChecksumFailure;375 if (checksum != computeChecksum(hasher)) return error.ChecksumFailure;
324 }376 }
325 }377 }
326 return DecodeResult{ .bytes = try result.toOwnedSlice(), .read_count = consumed_count };378 return consumed_count;
327}379}
328380
329/// Convenience wrapper for decoding all blocks in a frame; see `decodeBlock()`.381/// Convenience wrapper for decoding all blocks in a frame; see `decodeBlock()`.