| ... | ... | @@ -81,6 +81,8 @@ pub const DecodeState = struct { |
| 81 | 81 | |
| 82 | 82 | literal_stream_reader: ReverseBitReader, |
| 83 | 83 | literal_stream_index: usize, |
| 84 | literal_streams: LiteralsSection.Streams, |
| 85 | literal_header: LiteralsSection.Header, |
| 84 | 86 | huffman_tree: ?LiteralsSection.HuffmanTree, |
| 85 | 87 | |
| 86 | 88 | literal_written_count: usize, |
| ... | ... | @@ -105,6 +107,10 @@ pub const DecodeState = struct { |
| 105 | 107 | literals: LiteralsSection, |
| 106 | 108 | sequences_header: SequencesSection.Header, |
| 107 | 109 | ) (error{ BitStreamHasNoStartBit, TreelessLiteralsFirst } || FseTableError)!usize { |
| 110 | self.literal_written_count = 0; |
| 111 | self.literal_header = literals.header; |
| 112 | self.literal_streams = literals.streams; |
| 113 | |
| 108 | 114 | if (literals.huffman_tree) |tree| { |
| 109 | 115 | self.huffman_tree = tree; |
| 110 | 116 | } else if (literals.header.block_type == .treeless and self.huffman_tree == null) { |
| ... | ... | @@ -293,12 +299,11 @@ pub const DecodeState = struct { |
| 293 | 299 | self: *DecodeState, |
| 294 | 300 | dest: []u8, |
| 295 | 301 | write_pos: usize, |
| 296 | | literals: LiteralsSection, |
| 297 | 302 | sequence: Sequence, |
| 298 | 303 | ) (error{MalformedSequence} || DecodeLiteralsError)!void { |
| 299 | 304 | if (sequence.offset > write_pos + sequence.literal_length) return error.MalformedSequence; |
| 300 | 305 | |
| 301 | | try self.decodeLiteralsSlice(dest[write_pos..], literals, sequence.literal_length); |
| 306 | try self.decodeLiteralsSlice(dest[write_pos..], sequence.literal_length); |
| 302 | 307 | const copy_start = write_pos + sequence.literal_length - sequence.offset; |
| 303 | 308 | const copy_end = copy_start + sequence.match_length; |
| 304 | 309 | // NOTE: we ignore the usage message for std.mem.copy and copy with dest.ptr >= src.ptr |
| ... | ... | @@ -309,12 +314,11 @@ pub const DecodeState = struct { |
| 309 | 314 | fn executeSequenceRingBuffer( |
| 310 | 315 | self: *DecodeState, |
| 311 | 316 | dest: *RingBuffer, |
| 312 | | literals: LiteralsSection, |
| 313 | 317 | sequence: Sequence, |
| 314 | 318 | ) (error{MalformedSequence} || DecodeLiteralsError)!void { |
| 315 | 319 | if (sequence.offset > dest.data.len) return error.MalformedSequence; |
| 316 | 320 | |
| 317 | | try self.decodeLiteralsRingBuffer(dest, literals, sequence.literal_length); |
| 321 | try self.decodeLiteralsRingBuffer(dest, sequence.literal_length); |
| 318 | 322 | const copy_start = dest.write_index + dest.data.len - sequence.offset; |
| 319 | 323 | const copy_slice = dest.sliceAt(copy_start, sequence.match_length); |
| 320 | 324 | // TODO: would std.mem.copy and figuring out dest slice be better/faster? |
| ... | ... | @@ -328,6 +332,7 @@ pub const DecodeState = struct { |
| 328 | 332 | MalformedSequence, |
| 329 | 333 | MalformedFseBits, |
| 330 | 334 | } || DecodeLiteralsError; |
| 335 | |
| 331 | 336 | /// Decode one sequence from `bit_reader` into `dest`, written starting at |
| 332 | 337 | /// `write_pos` and update FSE states if `last_sequence` is `false`. Returns |
| 333 | 338 | /// `error.MalformedSequence` error if the decompressed sequence would be longer |
| ... | ... | @@ -340,7 +345,6 @@ pub const DecodeState = struct { |
| 340 | 345 | self: *DecodeState, |
| 341 | 346 | dest: []u8, |
| 342 | 347 | write_pos: usize, |
| 343 | | literals: LiteralsSection, |
| 344 | 348 | bit_reader: *ReverseBitReader, |
| 345 | 349 | sequence_size_limit: usize, |
| 346 | 350 | last_sequence: bool, |
| ... | ... | @@ -349,7 +353,7 @@ pub const DecodeState = struct { |
| 349 | 353 | const sequence_length = @as(usize, sequence.literal_length) + sequence.match_length; |
| 350 | 354 | if (sequence_length > sequence_size_limit) return error.MalformedSequence; |
| 351 | 355 | |
| 352 | | try self.executeSequenceSlice(dest, write_pos, literals, sequence); |
| 356 | try self.executeSequenceSlice(dest, write_pos, sequence); |
| 353 | 357 | if (!last_sequence) { |
| 354 | 358 | try self.updateState(.literal, bit_reader); |
| 355 | 359 | try self.updateState(.match, bit_reader); |
| ... | ... | @@ -362,7 +366,6 @@ pub const DecodeState = struct { |
| 362 | 366 | pub fn decodeSequenceRingBuffer( |
| 363 | 367 | self: *DecodeState, |
| 364 | 368 | dest: *RingBuffer, |
| 365 | | literals: LiteralsSection, |
| 366 | 369 | bit_reader: anytype, |
| 367 | 370 | sequence_size_limit: usize, |
| 368 | 371 | last_sequence: bool, |
| ... | ... | @@ -371,7 +374,7 @@ pub const DecodeState = struct { |
| 371 | 374 | const sequence_length = @as(usize, sequence.literal_length) + sequence.match_length; |
| 372 | 375 | if (sequence_length > sequence_size_limit) return error.MalformedSequence; |
| 373 | 376 | |
| 374 | | try self.executeSequenceRingBuffer(dest, literals, sequence); |
| 377 | try self.executeSequenceRingBuffer(dest, sequence); |
| 375 | 378 | if (!last_sequence) { |
| 376 | 379 | try self.updateState(.literal, bit_reader); |
| 377 | 380 | try self.updateState(.match, bit_reader); |
| ... | ... | @@ -382,13 +385,12 @@ pub const DecodeState = struct { |
| 382 | 385 | |
| 383 | 386 | fn nextLiteralMultiStream( |
| 384 | 387 | self: *DecodeState, |
| 385 | | literals: LiteralsSection, |
| 386 | 388 | ) error{BitStreamHasNoStartBit}!void { |
| 387 | 389 | self.literal_stream_index += 1; |
| 388 | | try self.initLiteralStream(literals.streams.four[self.literal_stream_index]); |
| 390 | try self.initLiteralStream(self.literal_streams.four[self.literal_stream_index]); |
| 389 | 391 | } |
| 390 | 392 | |
| 391 | | fn initLiteralStream(self: *DecodeState, bytes: []const u8) error{BitStreamHasNoStartBit}!void { |
| 393 | pub fn initLiteralStream(self: *DecodeState, bytes: []const u8) error{BitStreamHasNoStartBit}!void { |
| 392 | 394 | try self.literal_stream_reader.init(bytes); |
| 393 | 395 | } |
| 394 | 396 | |
| ... | ... | @@ -400,11 +402,10 @@ pub const DecodeState = struct { |
| 400 | 402 | self: *DecodeState, |
| 401 | 403 | comptime T: type, |
| 402 | 404 | bit_count_to_read: usize, |
| 403 | | literals: LiteralsSection, |
| 404 | 405 | ) LiteralBitsError!T { |
| 405 | 406 | return self.literal_stream_reader.readBitsNoEof(u16, bit_count_to_read) catch bits: { |
| 406 | | if (literals.streams == .four and self.literal_stream_index < 3) { |
| 407 | | try self.nextLiteralMultiStream(literals); |
| 407 | if (self.literal_streams == .four and self.literal_stream_index < 3) { |
| 408 | try self.nextLiteralMultiStream(); |
| 408 | 409 | break :bits self.literal_stream_reader.readBitsNoEof(u16, bit_count_to_read) catch |
| 409 | 410 | return error.UnexpectedEndOfLiteralStream; |
| 410 | 411 | } else { |
| ... | ... | @@ -427,23 +428,22 @@ pub const DecodeState = struct { |
| 427 | 428 | pub fn decodeLiteralsSlice( |
| 428 | 429 | self: *DecodeState, |
| 429 | 430 | dest: []u8, |
| 430 | | literals: LiteralsSection, |
| 431 | 431 | len: usize, |
| 432 | 432 | ) DecodeLiteralsError!void { |
| 433 | | if (self.literal_written_count + len > literals.header.regenerated_size) |
| 433 | if (self.literal_written_count + len > self.literal_header.regenerated_size) |
| 434 | 434 | return error.MalformedLiteralsLength; |
| 435 | 435 | |
| 436 | | switch (literals.header.block_type) { |
| 436 | switch (self.literal_header.block_type) { |
| 437 | 437 | .raw => { |
| 438 | 438 | const literals_end = self.literal_written_count + len; |
| 439 | | const literal_data = literals.streams.one[self.literal_written_count..literals_end]; |
| 439 | const literal_data = self.literal_streams.one[self.literal_written_count..literals_end]; |
| 440 | 440 | std.mem.copy(u8, dest, literal_data); |
| 441 | 441 | self.literal_written_count += len; |
| 442 | 442 | }, |
| 443 | 443 | .rle => { |
| 444 | 444 | var i: usize = 0; |
| 445 | 445 | while (i < len) : (i += 1) { |
| 446 | | dest[i] = literals.streams.one[0]; |
| 446 | dest[i] = self.literal_streams.one[0]; |
| 447 | 447 | } |
| 448 | 448 | self.literal_written_count += len; |
| 449 | 449 | }, |
| ... | ... | @@ -462,7 +462,7 @@ pub const DecodeState = struct { |
| 462 | 462 | while (i < len) : (i += 1) { |
| 463 | 463 | var prefix: u16 = 0; |
| 464 | 464 | while (true) { |
| 465 | | const new_bits = try self.readLiteralsBits(u16, bit_count_to_read, literals); |
| 465 | const new_bits = try self.readLiteralsBits(u16, bit_count_to_read); |
| 466 | 466 | prefix <<= bit_count_to_read; |
| 467 | 467 | prefix |= new_bits; |
| 468 | 468 | bits_read += bit_count_to_read; |
| ... | ... | @@ -496,23 +496,22 @@ pub const DecodeState = struct { |
| 496 | 496 | pub fn decodeLiteralsRingBuffer( |
| 497 | 497 | self: *DecodeState, |
| 498 | 498 | dest: *RingBuffer, |
| 499 | | literals: LiteralsSection, |
| 500 | 499 | len: usize, |
| 501 | 500 | ) DecodeLiteralsError!void { |
| 502 | | if (self.literal_written_count + len > literals.header.regenerated_size) |
| 501 | if (self.literal_written_count + len > self.literal_header.regenerated_size) |
| 503 | 502 | return error.MalformedLiteralsLength; |
| 504 | 503 | |
| 505 | | switch (literals.header.block_type) { |
| 504 | switch (self.literal_header.block_type) { |
| 506 | 505 | .raw => { |
| 507 | 506 | const literals_end = self.literal_written_count + len; |
| 508 | | const literal_data = literals.streams.one[self.literal_written_count..literals_end]; |
| 507 | const literal_data = self.literal_streams.one[self.literal_written_count..literals_end]; |
| 509 | 508 | dest.writeSliceAssumeCapacity(literal_data); |
| 510 | 509 | self.literal_written_count += len; |
| 511 | 510 | }, |
| 512 | 511 | .rle => { |
| 513 | 512 | var i: usize = 0; |
| 514 | 513 | while (i < len) : (i += 1) { |
| 515 | | dest.writeAssumeCapacity(literals.streams.one[0]); |
| 514 | dest.writeAssumeCapacity(self.literal_streams.one[0]); |
| 516 | 515 | } |
| 517 | 516 | self.literal_written_count += len; |
| 518 | 517 | }, |
| ... | ... | @@ -531,7 +530,7 @@ pub const DecodeState = struct { |
| 531 | 530 | while (i < len) : (i += 1) { |
| 532 | 531 | var prefix: u16 = 0; |
| 533 | 532 | while (true) { |
| 534 | | const new_bits = try self.readLiteralsBits(u16, bit_count_to_read, literals); |
| 533 | const new_bits = try self.readLiteralsBits(u16, bit_count_to_read); |
| 535 | 534 | prefix <<= bit_count_to_read; |
| 536 | 535 | prefix |= new_bits; |
| 537 | 536 | bits_read += bit_count_to_read; |
| ... | ... | @@ -569,10 +568,6 @@ pub const DecodeState = struct { |
| 569 | 568 | } |
| 570 | 569 | }; |
| 571 | 570 | |
| 572 | | const literal_table_size_max = 1 << types.compressed_block.table_accuracy_log_max.literal; |
| 573 | | const match_table_size_max = 1 << types.compressed_block.table_accuracy_log_max.match; |
| 574 | | const offset_table_size_max = 1 << types.compressed_block.table_accuracy_log_max.match; |
| 575 | | |
| 576 | 571 | pub fn computeChecksum(hasher: *std.hash.XxHash64) u32 { |
| 577 | 572 | const hash = hasher.final(); |
| 578 | 573 | return @intCast(u32, hash & 0xFFFFFFFF); |
| ... | ... | @@ -625,6 +620,31 @@ pub fn decodeZStandardFrame( |
| 625 | 620 | return ReadWriteCount{ .read_count = consumed_count, .write_count = written_count }; |
| 626 | 621 | } |
| 627 | 622 | |
| 623 | pub const FrameContext = struct { |
| 624 | hasher_opt: ?std.hash.XxHash64, |
| 625 | window_size: usize, |
| 626 | has_checksum: bool, |
| 627 | block_size_max: usize, |
| 628 | |
| 629 | pub fn init(frame_header: frame.ZStandard.Header, window_size_max: usize, verify_checksum: bool) !FrameContext { |
| 630 | if (frame_header.descriptor.dictionary_id_flag != 0) return error.DictionaryIdFlagUnsupported; |
| 631 | |
| 632 | const window_size_raw = frameWindowSize(frame_header) orelse return error.WindowSizeUnknown; |
| 633 | const window_size = if (window_size_raw > window_size_max) |
| 634 | return error.WindowTooLarge |
| 635 | else |
| 636 | @intCast(usize, window_size_raw); |
| 637 | |
| 638 | const should_compute_checksum = frame_header.descriptor.content_checksum_flag and verify_checksum; |
| 639 | return .{ |
| 640 | .hasher_opt = if (should_compute_checksum) std.hash.XxHash64.init(0) else null, |
| 641 | .window_size = window_size, |
| 642 | .has_checksum = frame_header.descriptor.content_checksum_flag, |
| 643 | .block_size_max = @min(1 << 17, window_size), |
| 644 | }; |
| 645 | } |
| 646 | }; |
| 647 | |
| 628 | 648 | /// Decode a Zstandard from from `src` and return the decompressed bytes; see |
| 629 | 649 | /// `decodeZStandardFrame()`. Returns `error.WindowSizeUnknown` if the frame |
| 630 | 650 | /// does not declare its content size or a window descriptor (this indicates a |
| ... | ... | @@ -639,33 +659,18 @@ pub fn decodeZStandardFrameAlloc( |
| 639 | 659 | assert(readInt(u32, src[0..4]) == frame.ZStandard.magic_number); |
| 640 | 660 | var consumed_count: usize = 4; |
| 641 | 661 | |
| 642 | | const frame_header = try decodeZStandardHeader(src[consumed_count..], &consumed_count); |
| 643 | | |
| 644 | | if (frame_header.descriptor.dictionary_id_flag != 0) return error.DictionaryIdFlagUnsupported; |
| 645 | | |
| 646 | | const window_size_raw = frameWindowSize(frame_header) orelse return error.WindowSizeUnknown; |
| 647 | | const window_size = if (window_size_raw > window_size_max) |
| 648 | | return error.WindowTooLarge |
| 649 | | else |
| 650 | | @intCast(usize, window_size_raw); |
| 651 | | |
| 652 | | const should_compute_checksum = frame_header.descriptor.content_checksum_flag and verify_checksum; |
| 653 | | var hasher_opt = if (should_compute_checksum) std.hash.XxHash64.init(0) else null; |
| 654 | | |
| 655 | | const block_size_maximum = @min(1 << 17, window_size); |
| 656 | | |
| 657 | | var window_data = try allocator.alloc(u8, window_size); |
| 658 | | defer allocator.free(window_data); |
| 659 | | var ring_buffer = RingBuffer{ |
| 660 | | .data = window_data, |
| 661 | | .write_index = 0, |
| 662 | | .read_index = 0, |
| 662 | var frame_context = context: { |
| 663 | const frame_header = try decodeZStandardHeader(src[consumed_count..], &consumed_count); |
| 664 | break :context try FrameContext.init(frame_header, window_size_max, verify_checksum); |
| 663 | 665 | }; |
| 664 | 666 | |
| 667 | var ring_buffer = try RingBuffer.init(allocator, frame_context.window_size); |
| 668 | defer ring_buffer.deinit(allocator); |
| 669 | |
| 665 | 670 | // These tables take 7680 bytes |
| 666 | | var literal_fse_data: [literal_table_size_max]Table.Fse = undefined; |
| 667 | | var match_fse_data: [match_table_size_max]Table.Fse = undefined; |
| 668 | | var offset_fse_data: [offset_table_size_max]Table.Fse = undefined; |
| 671 | var literal_fse_data: [types.compressed_block.table_size_max.literal]Table.Fse = undefined; |
| 672 | var match_fse_data: [types.compressed_block.table_size_max.match]Table.Fse = undefined; |
| 673 | var offset_fse_data: [types.compressed_block.table_size_max.offset]Table.Fse = undefined; |
| 669 | 674 | |
| 670 | 675 | var block_header = decodeBlockHeader(src[consumed_count..][0..3]); |
| 671 | 676 | consumed_count += 3; |
| ... | ... | @@ -687,6 +692,8 @@ pub fn decodeZStandardFrameAlloc( |
| 687 | 692 | .fse_tables_undefined = true, |
| 688 | 693 | |
| 689 | 694 | .literal_written_count = 0, |
| 695 | .literal_header = undefined, |
| 696 | .literal_streams = undefined, |
| 690 | 697 | .literal_stream_reader = undefined, |
| 691 | 698 | .literal_stream_index = undefined, |
| 692 | 699 | .huffman_tree = null, |
| ... | ... | @@ -695,30 +702,29 @@ pub fn decodeZStandardFrameAlloc( |
| 695 | 702 | block_header = decodeBlockHeader(src[consumed_count..][0..3]); |
| 696 | 703 | consumed_count += 3; |
| 697 | 704 | }) { |
| 698 | | if (block_header.block_size > block_size_maximum) return error.BlockSizeOverMaximum; |
| 705 | if (block_header.block_size > frame_context.block_size_max) return error.BlockSizeOverMaximum; |
| 699 | 706 | const written_size = try decodeBlockRingBuffer( |
| 700 | 707 | &ring_buffer, |
| 701 | 708 | src[consumed_count..], |
| 702 | 709 | block_header, |
| 703 | 710 | &decode_state, |
| 704 | 711 | &consumed_count, |
| 705 | | block_size_maximum, |
| 712 | frame_context.block_size_max, |
| 706 | 713 | ); |
| 707 | | if (written_size > block_size_maximum) return error.BlockSizeOverMaximum; |
| 708 | 714 | const written_slice = ring_buffer.sliceLast(written_size); |
| 709 | 715 | try result.appendSlice(written_slice.first); |
| 710 | 716 | try result.appendSlice(written_slice.second); |
| 711 | | if (hasher_opt) |*hasher| { |
| 717 | if (frame_context.hasher_opt) |*hasher| { |
| 712 | 718 | hasher.update(written_slice.first); |
| 713 | 719 | hasher.update(written_slice.second); |
| 714 | 720 | } |
| 715 | 721 | if (block_header.last_block) break; |
| 716 | 722 | } |
| 717 | 723 | |
| 718 | | if (frame_header.descriptor.content_checksum_flag) { |
| 724 | if (frame_context.has_checksum) { |
| 719 | 725 | const checksum = readIntSlice(u32, src[consumed_count .. consumed_count + 4]); |
| 720 | 726 | consumed_count += 4; |
| 721 | | if (hasher_opt) |*hasher| { |
| 727 | if (frame_context.hasher_opt) |*hasher| { |
| 722 | 728 | if (checksum != computeChecksum(hasher)) return error.ChecksumFailure; |
| 723 | 729 | } |
| 724 | 730 | } |
| ... | ... | @@ -741,9 +747,9 @@ pub fn decodeFrameBlocks( |
| 741 | 747 | hash: ?*std.hash.XxHash64, |
| 742 | 748 | ) DecodeBlockError!usize { |
| 743 | 749 | // These tables take 7680 bytes |
| 744 | | var literal_fse_data: [literal_table_size_max]Table.Fse = undefined; |
| 745 | | var match_fse_data: [match_table_size_max]Table.Fse = undefined; |
| 746 | | var offset_fse_data: [offset_table_size_max]Table.Fse = undefined; |
| 750 | var literal_fse_data: [types.compressed_block.table_size_max.literal]Table.Fse = undefined; |
| 751 | var match_fse_data: [types.compressed_block.table_size_max.match]Table.Fse = undefined; |
| 752 | var offset_fse_data: [types.compressed_block.table_size_max.offset]Table.Fse = undefined; |
| 747 | 753 | |
| 748 | 754 | var block_header = decodeBlockHeader(src[0..3]); |
| 749 | 755 | var bytes_read: usize = 3; |
| ... | ... | @@ -766,6 +772,8 @@ pub fn decodeFrameBlocks( |
| 766 | 772 | .fse_tables_undefined = true, |
| 767 | 773 | |
| 768 | 774 | .literal_written_count = 0, |
| 775 | .literal_header = undefined, |
| 776 | .literal_streams = undefined, |
| 769 | 777 | .literal_stream_reader = undefined, |
| 770 | 778 | .literal_stream_index = undefined, |
| 771 | 779 | .huffman_tree = null, |
| ... | ... | @@ -867,7 +875,8 @@ pub fn decodeBlock( |
| 867 | 875 | .compressed => { |
| 868 | 876 | if (src.len < block_size) return error.MalformedBlockSize; |
| 869 | 877 | var bytes_read: usize = 0; |
| 870 | | const literals = decodeLiteralsSection(src, &bytes_read) catch return error.MalformedCompressedBlock; |
| 878 | const literals = decodeLiteralsSection(src, &bytes_read) catch |
| 879 | return error.MalformedCompressedBlock; |
| 871 | 880 | const sequences_header = decodeSequencesHeader(src[bytes_read..], &bytes_read) catch |
| 872 | 881 | return error.MalformedCompressedBlock; |
| 873 | 882 | |
| ... | ... | @@ -889,7 +898,6 @@ pub fn decodeBlock( |
| 889 | 898 | const decompressed_size = decode_state.decodeSequenceSlice( |
| 890 | 899 | dest, |
| 891 | 900 | write_pos, |
| 892 | | literals, |
| 893 | 901 | &bit_stream, |
| 894 | 902 | sequence_size_limit, |
| 895 | 903 | i == sequences_header.sequence_count - 1, |
| ... | ... | @@ -903,12 +911,11 @@ pub fn decodeBlock( |
| 903 | 911 | |
| 904 | 912 | if (decode_state.literal_written_count < literals.header.regenerated_size) { |
| 905 | 913 | const len = literals.header.regenerated_size - decode_state.literal_written_count; |
| 906 | | decode_state.decodeLiteralsSlice(dest[written_count + bytes_written ..], literals, len) catch |
| 914 | decode_state.decodeLiteralsSlice(dest[written_count + bytes_written ..], len) catch |
| 907 | 915 | return error.MalformedCompressedBlock; |
| 908 | 916 | bytes_written += len; |
| 909 | 917 | } |
| 910 | 918 | |
| 911 | | decode_state.literal_written_count = 0; |
| 912 | 919 | assert(bytes_read == block_header.block_size); |
| 913 | 920 | consumed_count.* += bytes_read; |
| 914 | 921 | return bytes_written; |
| ... | ... | @@ -936,7 +943,8 @@ pub fn decodeBlockRingBuffer( |
| 936 | 943 | .compressed => { |
| 937 | 944 | if (src.len < block_size) return error.MalformedBlockSize; |
| 938 | 945 | var bytes_read: usize = 0; |
| 939 | | const literals = decodeLiteralsSection(src, &bytes_read) catch return error.MalformedCompressedBlock; |
| 946 | const literals = decodeLiteralsSection(src, &bytes_read) catch |
| 947 | return error.MalformedCompressedBlock; |
| 940 | 948 | const sequences_header = decodeSequencesHeader(src[bytes_read..], &bytes_read) catch |
| 941 | 949 | return error.MalformedCompressedBlock; |
| 942 | 950 | |
| ... | ... | @@ -956,7 +964,6 @@ pub fn decodeBlockRingBuffer( |
| 956 | 964 | while (i < sequences_header.sequence_count) : (i += 1) { |
| 957 | 965 | const decompressed_size = decode_state.decodeSequenceRingBuffer( |
| 958 | 966 | dest, |
| 959 | | literals, |
| 960 | 967 | &bit_stream, |
| 961 | 968 | sequence_size_limit, |
| 962 | 969 | i == sequences_header.sequence_count - 1, |
| ... | ... | @@ -970,14 +977,14 @@ pub fn decodeBlockRingBuffer( |
| 970 | 977 | |
| 971 | 978 | if (decode_state.literal_written_count < literals.header.regenerated_size) { |
| 972 | 979 | const len = literals.header.regenerated_size - decode_state.literal_written_count; |
| 973 | | decode_state.decodeLiteralsRingBuffer(dest, literals, len) catch |
| 980 | decode_state.decodeLiteralsRingBuffer(dest, len) catch |
| 974 | 981 | return error.MalformedCompressedBlock; |
| 975 | 982 | bytes_written += len; |
| 976 | 983 | } |
| 977 | 984 | |
| 978 | | decode_state.literal_written_count = 0; |
| 979 | 985 | assert(bytes_read == block_header.block_size); |
| 980 | 986 | consumed_count.* += bytes_read; |
| 987 | if (bytes_written > block_size_max) return error.BlockSizeOverMaximum; |
| 981 | 988 | return bytes_written; |
| 982 | 989 | }, |
| 983 | 990 | .reserved => return error.ReservedBlock, |