authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-25 13:15:23-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-25 14:15:33-07:00
log7f43f78b5bea8d6af8fa29451a427b43cb37291f
treeae6ce626e5372bcbd9c104efa51c5ea5b7f83991
parent13e08ea6f0fe6caa4ab0a0e6795f6864c96b9336

std.compress.zstd: keep frame state between blocks


1 files changed, 32 insertions(+), 42 deletions(-)

lib/std/compress/zstd/Decompress.zig+32-42
......@@ -23,6 +23,7 @@ const State = union(enum) {
2323 frame: Frame,
2424 checksum: ?u32,
2525 decompressed_size: usize,
26 decode: Frame.Zstandard.Decode,
2627 };
2728};
2829
......@@ -138,6 +139,7 @@ fn initFrame(d: *Decompress, window_size_max: usize, magic: Frame.Magic) !void {
138139 .frame = try Frame.init(header, window_size_max, d.verify_checksum),
139140 .checksum = null,
140141 .decompressed_size = 0,
142 .decode = .init,
141143 } };
142144 },
143145 .skippable => {
......@@ -168,16 +170,13 @@ fn readInFrame(d: *Decompress, w: *Writer, limit: Limit, state: *State.InFrame)
168170 bytes_written = block_size;
169171 },
170172 .compressed => {
171 var literal_fse_buffer: [zstd.table_size_max.literal]Table.Fse = undefined;
172 var match_fse_buffer: [zstd.table_size_max.match]Table.Fse = undefined;
173 var offset_fse_buffer: [zstd.table_size_max.offset]Table.Fse = undefined;
174173 var literals_buffer: [zstd.block_size_max]u8 = undefined;
175174 var sequence_buffer: [zstd.block_size_max]u8 = undefined;
176 var decode: Frame.Zstandard.Decode = .init(&literal_fse_buffer, &match_fse_buffer, &offset_fse_buffer, window_len);
177175 var remaining: Limit = .limited(block_size);
178176 const literals = try LiteralsSection.decode(in, &remaining, &literals_buffer);
179177 const sequences_header = try SequencesSection.Header.decode(in, &remaining);
180178
179 const decode = &state.decode;
181180 try decode.prepare(in, &remaining, literals, sequences_header);
182181
183182 {
......@@ -370,16 +369,15 @@ pub const Frame = struct {
370369 };
371370
372371 pub const Decode = struct {
373 window_len: u32,
374372 repeat_offsets: [3]u32,
375373
376374 offset: StateData(8),
377375 match: StateData(9),
378376 literal: StateData(9),
379377
380 offset_fse_buffer: []Table.Fse,
381 match_fse_buffer: []Table.Fse,
382 literal_fse_buffer: []Table.Fse,
378 literal_fse_buffer: [zstd.table_size_max.literal]Table.Fse,
379 match_fse_buffer: [zstd.table_size_max.match]Table.Fse,
380 offset_fse_buffer: [zstd.table_size_max.offset]Table.Fse,
383381
384382 fse_tables_undefined: bool,
385383
......@@ -401,38 +399,30 @@ pub const Frame = struct {
401399 };
402400 }
403401
404 pub fn init(
405 literal_fse_buffer: []Table.Fse,
406 match_fse_buffer: []Table.Fse,
407 offset_fse_buffer: []Table.Fse,
408 window_len: u32,
409 ) Decode {
410 return .{
411 .window_len = window_len,
412 .repeat_offsets = .{
413 zstd.start_repeated_offset_1,
414 zstd.start_repeated_offset_2,
415 zstd.start_repeated_offset_3,
416 },
402 const init: Decode = .{
403 .repeat_offsets = .{
404 zstd.start_repeated_offset_1,
405 zstd.start_repeated_offset_2,
406 zstd.start_repeated_offset_3,
407 },
417408
418 .offset = undefined,
419 .match = undefined,
420 .literal = undefined,
409 .offset = undefined,
410 .match = undefined,
411 .literal = undefined,
421412
422 .literal_fse_buffer = literal_fse_buffer,
423 .match_fse_buffer = match_fse_buffer,
424 .offset_fse_buffer = offset_fse_buffer,
413 .literal_fse_buffer = undefined,
414 .match_fse_buffer = undefined,
415 .offset_fse_buffer = undefined,
425416
426 .fse_tables_undefined = true,
417 .fse_tables_undefined = true,
427418
428 .literal_written_count = 0,
429 .literal_header = undefined,
430 .literal_streams = undefined,
431 .literal_stream_reader = undefined,
432 .literal_stream_index = undefined,
433 .huffman_tree = null,
434 };
435 }
419 .literal_written_count = 0,
420 .literal_header = undefined,
421 .literal_streams = undefined,
422 .literal_stream_reader = undefined,
423 .literal_stream_index = undefined,
424 .huffman_tree = null,
425 };
436426
437427 pub const PrepareError = error{
438428 /// the (reversed) literal bitstream's first byte does not have any bits set
......@@ -514,12 +504,12 @@ pub const Frame = struct {
514504 return self.repeat_offsets[0];
515505 }
516506
517 const DataType = enum { offset, match, literal };
507 const WhichFse = enum { offset, match, literal };
518508
519509 /// TODO: don't use `@field`
520510 fn updateState(
521511 self: *Decode,
522 comptime choice: DataType,
512 comptime choice: WhichFse,
523513 bit_reader: *ReverseBitReader,
524514 ) error{ MalformedFseBits, EndOfStream }!void {
525515 switch (@field(self, @tagName(choice)).table) {
......@@ -549,7 +539,7 @@ pub const Frame = struct {
549539 self: *Decode,
550540 in: *Reader,
551541 remaining: *Limit,
552 comptime choice: DataType,
542 comptime choice: WhichFse,
553543 mode: SequencesSection.Header.Mode,
554544 ) !void {
555545 const field_name = @tagName(choice);
......@@ -576,10 +566,10 @@ pub const Frame = struct {
576566 &bit_reader,
577567 @field(zstd.table_symbol_count_max, field_name),
578568 @field(zstd.table_accuracy_log_max, field_name),
579 @field(self, field_name ++ "_fse_buffer"),
569 &@field(self, field_name ++ "_fse_buffer"),
580570 );
581571 @field(self, field_name).table = .{
582 .fse = @field(self, field_name ++ "_fse_buffer")[0..table_size],
572 .fse = (&@field(self, field_name ++ "_fse_buffer"))[0..table_size],
583573 };
584574 @field(self, field_name).accuracy_log = std.math.log2_int_ceil(usize, table_size);
585575 in.toss(bit_reader.index);
......@@ -762,7 +752,7 @@ pub const Frame = struct {
762752 }
763753
764754 /// TODO: don't use `@field`
765 fn getCode(self: *Decode, comptime choice: DataType) u32 {
755 fn getCode(self: *Decode, comptime choice: WhichFse) u32 {
766756 return switch (@field(self, @tagName(choice)).table) {
767757 .rle => |value| value,
768758 .fse => |table| table[@field(self, @tagName(choice)).state].symbol,