authorgravatar for 4678790+dweiller@users.noreply.github.comDominic <4678790+dweiller@users.noreply.github.com> 2023-02-09 17:52:21+11:00
committergravatar for 4678790+dweiller@users.noreply.github.comDominic <4678790+dweiller@users.noreply.github.com> 2023-02-20 09:09:06+11:00
log6d48b055af0cbe17e72426f808fa8408fce3eed6
treecf01976fd842c128b6b7ce15976df1f0aac89d71
parent3975a9d7ca2013a4ac667b637fb273a9432c53aa

std.compress.zstandard: add decodeFrameHeader

Also do some other minor API cleanup

1 files changed, 60 insertions(+), 17 deletions(-)

lib/std/compress/zstandard/decompress.zig+60-17
......@@ -49,6 +49,25 @@ pub fn frameType(magic: u32) error{BadMagic}!frame.Kind {
4949 error.BadMagic;
5050}
5151
52pub const FrameHeader = union(enum) {
53 zstandard: types.frame.Zstandard.Header,
54 skippable: types.frame.Skippable.Header,
55};
56
57pub fn decodeFrameHeader(source: anytype) error{ BadMagic, EndOfStream, ReservedBitSet }!FrameHeader {
58 const magic = try source.readIntLittle(u32);
59 const frame_type = try frameType(magic);
60 switch (frame_type) {
61 .zstandard => return FrameHeader{ .zstandard = try decodeZstandardHeader(source) },
62 .skippable => return FrameHeader{
63 .skippable = .{
64 .magic_number = magic,
65 .frame_size = try source.readIntLittle(u32),
66 },
67 },
68 }
69}
70
5271const ReadWriteCount = struct {
5372 read_count: usize,
5473 write_count: usize,
......@@ -129,15 +148,6 @@ pub fn decodeFrame(
129148 }
130149}
131150
132pub const DecodeResult = struct {
133 bytes: []u8,
134 read_count: usize,
135};
136pub const DecodedFrame = union(enum) {
137 zstandard: DecodeResult,
138 skippable: frame.Skippable.Header,
139};
140
141151/// Decodes the frame at the start of `src` into `dest`. Returns the number of
142152/// bytes read from `src`.
143153///
......@@ -186,7 +196,6 @@ pub fn computeChecksum(hasher: *std.hash.XxHash64) u32 {
186196}
187197
188198const FrameError = error{
189 DictionaryIdFlagUnsupported,
190199 ChecksumFailure,
191200 BadContentSize,
192201 EndOfStream,
......@@ -220,6 +229,7 @@ pub fn decodeZstandardFrame(
220229 ContentTooLarge,
221230 ContentSizeTooLarge,
222231 WindowSizeUnknown,
232 DictionaryIdFlagUnsupported,
223233} || FrameError)!ReadWriteCount {
224234 assert(readInt(u32, src[0..4]) == frame.Zstandard.magic_number);
225235 var consumed_count: usize = 4;
......@@ -234,11 +244,27 @@ pub fn decodeZstandardFrame(
234244 inline else => |e| return e,
235245 };
236246 };
247 const counts = try decodeZStandardFrameBlocks(
248 dest,
249 src[consumed_count..],
250 &frame_context,
251 );
252 return ReadWriteCount{
253 .read_count = counts.read_count + consumed_count,
254 .write_count = counts.write_count,
255 };
256}
237257
258pub fn decodeZStandardFrameBlocks(
259 dest: []u8,
260 src: []const u8,
261 frame_context: *FrameContext,
262) (error{ ContentTooLarge, UnknownContentSizeUnsupported } || FrameError)!ReadWriteCount {
238263 const content_size = frame_context.content_size orelse return error.UnknownContentSizeUnsupported;
239264 if (dest.len < content_size) return error.ContentTooLarge;
240265
241 const written_count = decodeFrameBlocks(
266 var consumed_count: usize = 0;
267 const written_count = decodeFrameBlocksInner(
242268 dest[0..content_size],
243269 src[consumed_count..],
244270 &consumed_count,
......@@ -279,7 +305,7 @@ pub const FrameContext = struct {
279305 /// Errors returned:
280306 /// - `error.DictionaryIdFlagUnsupported` if the frame uses a dictionary
281307 /// - `error.WindowSizeUnknown` if the frame does not have a valid window size
282 /// - `error.WindowTooLarge` if the window size is larger than
308 /// - `error.WindowTooLarge` if the window size is larger than `window_size_max`
283309 pub fn init(
284310 frame_header: frame.Zstandard.Header,
285311 window_size_max: usize,
......@@ -336,7 +362,6 @@ pub fn decodeZstandardFrameArrayList(
336362 window_size_max: usize,
337363) (error{OutOfMemory} || FrameContext.Error || FrameError)!usize {
338364 assert(readInt(u32, src[0..4]) == frame.Zstandard.magic_number);
339 const initial_len = dest.items.len;
340365 var consumed_count: usize = 4;
341366
342367 var frame_context = context: {
......@@ -347,6 +372,23 @@ pub fn decodeZstandardFrameArrayList(
347372 break :context try FrameContext.init(frame_header, window_size_max, verify_checksum);
348373 };
349374
375 consumed_count += try decodeZstandardFrameBlocksArrayList(
376 allocator,
377 dest,
378 src[consumed_count..],
379 &frame_context,
380 );
381 return consumed_count;
382}
383
384pub fn decodeZstandardFrameBlocksArrayList(
385 allocator: Allocator,
386 dest: *std.ArrayList(u8),
387 src: []const u8,
388 frame_context: *FrameContext,
389) (error{OutOfMemory} || FrameError)!usize {
390 const initial_len = dest.items.len;
391
350392 var ring_buffer = try RingBuffer.init(allocator, frame_context.window_size);
351393 defer ring_buffer.deinit(allocator);
352394
......@@ -355,8 +397,8 @@ pub fn decodeZstandardFrameArrayList(
355397 var match_fse_data: [types.compressed_block.table_size_max.match]Table.Fse = undefined;
356398 var offset_fse_data: [types.compressed_block.table_size_max.offset]Table.Fse = undefined;
357399
358 var block_header = try block.decodeBlockHeaderSlice(src[consumed_count..]);
359 consumed_count += 3;
400 var block_header = try block.decodeBlockHeaderSlice(src);
401 var consumed_count: usize = 3;
360402 var decode_state = block.DecodeState.init(&literal_fse_data, &match_fse_data, &offset_fse_data);
361403 while (true) : ({
362404 block_header = try block.decodeBlockHeaderSlice(src[consumed_count..]);
......@@ -399,8 +441,9 @@ pub fn decodeZstandardFrameArrayList(
399441 return consumed_count;
400442}
401443
402/// Convenience wrapper for decoding all blocks in a frame; see `decodeBlock()`.
403fn decodeFrameBlocks(
444/// Convenience wrapper for decoding all blocks in a frame; see
445/// `decodeZStandardFrameBlocks()`.
446fn decodeFrameBlocksInner(
404447 dest: []u8,
405448 src: []const u8,
406449 consumed_count: *usize,