| ... | @@ -480,6 +480,90 @@ pub fn decodeZStandardFrame(dest: []u8, src: []const u8, verify_checksum: bool) | ... | @@ -480,6 +480,90 @@ pub fn decodeZStandardFrame(dest: []u8, src: []const u8, verify_checksum: bool) |
| 480 | return ReadWriteCount{ .read_count = consumed_count, .write_count = written_count }; | 480 | return ReadWriteCount{ .read_count = consumed_count, .write_count = written_count }; |
| 481 | } | 481 | } |
| 482 | | 482 | |
| | 483 | pub fn decodeZStandardFrameAlloc(allocator: std.mem.Allocator, src: []const u8, verify_checksum: bool) ![]u8 { |
| | 484 | var result = std.ArrayList(u8).init(allocator); |
| | 485 | assert(readInt(u32, src[0..4]) == frame.ZStandard.magic_number); |
| | 486 | var consumed_count: usize = 4; |
| | 487 | |
| | 488 | const frame_header = try decodeZStandardHeader(src[consumed_count..], &consumed_count); |
| | 489 | |
| | 490 | if (frame_header.descriptor.dictionary_id_flag != 0) return error.DictionaryIdFlagUnsupported; |
| | 491 | |
| | 492 | const window_size = frameWindowSize(frame_header) orelse return error.WindowSizeUnknown; |
| | 493 | log.debug("window size = {d}", .{window_size}); |
| | 494 | |
| | 495 | const should_compute_checksum = frame_header.descriptor.content_checksum_flag and verify_checksum; |
| | 496 | var hash = if (should_compute_checksum) std.hash.XxHash64.init(0) else null; |
| | 497 | |
| | 498 | const block_size_maximum = @min(1 << 17, window_size); |
| | 499 | log.debug("block size maximum = {d}", .{block_size_maximum}); |
| | 500 | |
| | 501 | var window_data = try allocator.alloc(u8, window_size); |
| | 502 | defer allocator.free(window_data); |
| | 503 | var ring_buffer = RingBuffer{ |
| | 504 | .data = window_data, |
| | 505 | .write_index = 0, |
| | 506 | .read_index = 0, |
| | 507 | }; |
| | 508 | |
| | 509 | // These tables take 7680 bytes |
| | 510 | var literal_fse_data: [literal_table_size_max]Table.Fse = undefined; |
| | 511 | var match_fse_data: [match_table_size_max]Table.Fse = undefined; |
| | 512 | var offset_fse_data: [offset_table_size_max]Table.Fse = undefined; |
| | 513 | |
| | 514 | var block_header = decodeBlockHeader(src[consumed_count..][0..3]); |
| | 515 | consumed_count += 3; |
| | 516 | var decode_state = DecodeState{ |
| | 517 | .repeat_offsets = .{ |
| | 518 | types.compressed_block.start_repeated_offset_1, |
| | 519 | types.compressed_block.start_repeated_offset_2, |
| | 520 | types.compressed_block.start_repeated_offset_3, |
| | 521 | }, |
| | 522 | |
| | 523 | .offset = undefined, |
| | 524 | .match = undefined, |
| | 525 | .literal = undefined, |
| | 526 | |
| | 527 | .literal_fse_buffer = &literal_fse_data, |
| | 528 | .match_fse_buffer = &match_fse_data, |
| | 529 | .offset_fse_buffer = &offset_fse_data, |
| | 530 | |
| | 531 | .fse_tables_undefined = true, |
| | 532 | |
| | 533 | .literal_written_count = 0, |
| | 534 | .literal_stream_reader = undefined, |
| | 535 | .literal_stream_bytes = undefined, |
| | 536 | .literal_stream_index = undefined, |
| | 537 | .huffman_tree = null, |
| | 538 | }; |
| | 539 | var written_count: usize = 0; |
| | 540 | while (true) : ({ |
| | 541 | block_header = decodeBlockHeader(src[consumed_count..][0..3]); |
| | 542 | consumed_count += 3; |
| | 543 | }) { |
| | 544 | if (block_header.block_size > block_size_maximum) return error.CompressedBlockSizeOverMaximum; |
| | 545 | const written_size = try decodeBlockRingBuffer( |
| | 546 | &ring_buffer, |
| | 547 | src[consumed_count..], |
| | 548 | block_header, |
| | 549 | &decode_state, |
| | 550 | &consumed_count, |
| | 551 | block_size_maximum, |
| | 552 | ); |
| | 553 | if (written_size > block_size_maximum) return error.DecompressedBlockSizeOverMaximum; |
| | 554 | const written_slice = ring_buffer.sliceLast(written_size); |
| | 555 | try result.appendSlice(written_slice.first); |
| | 556 | try result.appendSlice(written_slice.second); |
| | 557 | if (hash) |*hash_state| { |
| | 558 | hash_state.update(written_slice.first); |
| | 559 | hash_state.update(written_slice.second); |
| | 560 | } |
| | 561 | written_count += written_size; |
| | 562 | if (block_header.last_block) break; |
| | 563 | } |
| | 564 | return result.toOwnedSlice(); |
| | 565 | } |
| | 566 | |
| 483 | pub fn decodeFrameBlocks(dest: []u8, src: []const u8, consumed_count: *usize, hash: ?*std.hash.XxHash64) !usize { | 567 | pub fn decodeFrameBlocks(dest: []u8, src: []const u8, consumed_count: *usize, hash: ?*std.hash.XxHash64) !usize { |
| 484 | // These tables take 7680 bytes | 568 | // These tables take 7680 bytes |
| 485 | var literal_fse_data: [literal_table_size_max]Table.Fse = undefined; | 569 | var literal_fse_data: [literal_table_size_max]Table.Fse = undefined; |