| author | |
| committer | |
| log | 89f9c5cb373c81af5cb052cd9e68e44a123d0b04 |
| tree | 1c4d428ad6138ff50d62c0d054acb5b23e31926d |
| parent | 7e2755646f5c9cab9973708a79c8aaa369d148e7 |
2 files changed, 137 insertions(+), 67 deletions(-)
lib/std/compress/zstandard/decode/block.zig+60-36| ... | @@ -23,7 +23,6 @@ pub const Error = error{ | ... | @@ -23,7 +23,6 @@ pub const Error = error{ |
| 23 | ReservedBlock, | 23 | ReservedBlock, |
| 24 | MalformedRleBlock, | 24 | MalformedRleBlock, |
| 25 | MalformedCompressedBlock, | 25 | MalformedCompressedBlock, |
| 26 | EndOfStream, | ||
| 27 | }; | 26 | }; |
| 28 | 27 | ||
| 29 | pub const DecodeState = struct { | 28 | pub const DecodeState = struct { |
| ... | @@ -92,11 +91,17 @@ pub const DecodeState = struct { | ... | @@ -92,11 +91,17 @@ pub const DecodeState = struct { |
| 92 | /// stream and Huffman tree from `literals` and reads the FSE tables from | 91 | /// stream and Huffman tree from `literals` and reads the FSE tables from |
| 93 | /// `source`. | 92 | /// `source`. |
| 94 | /// | 93 | /// |
| 95 | /// Errors: | 94 | /// Errors returned: |
| 96 | /// - returns `error.BitStreamHasNoStartBit` if the (reversed) literal bitstream's | 95 | /// - `error.BitStreamHasNoStartBit` if the (reversed) literal bitstream's |
| 97 | /// first byte does not have any bits set. | 96 | /// first byte does not have any bits set |
| 98 | /// - returns `error.TreelessLiteralsFirst` `literals` is a treeless literals section | 97 | /// - `error.TreelessLiteralsFirst` `literals` is a treeless literals |
| 99 | /// and the decode state does not have a Huffman tree from a previous block. | 98 | /// section and the decode state does not have a Huffman tree from a |
| 99 | /// previous block | ||
| 100 | /// - `error.RepeatModeFirst` on the first call if one of the sequence FSE | ||
| 101 | /// tables is set to repeat mode | ||
| 102 | /// - `error.MalformedAccuracyLog` if an FSE table has an invalid accuracy | ||
| 103 | /// - `error.MalformedFseTable` if there are errors decoding an FSE table | ||
| 104 | /// - `error.EndOfStream` if `source` ends before all FSE tables are read | ||
| 100 | pub fn prepare( | 105 | pub fn prepare( |
| 101 | self: *DecodeState, | 106 | self: *DecodeState, |
| 102 | source: anytype, | 107 | source: anytype, |
| ... | @@ -132,8 +137,10 @@ pub const DecodeState = struct { | ... | @@ -132,8 +137,10 @@ pub const DecodeState = struct { |
| 132 | } | 137 | } |
| 133 | } | 138 | } |
| 134 | 139 | ||
| 135 | /// Read initial FSE states for sequence decoding. Returns `error.EndOfStream` | 140 | /// Read initial FSE states for sequence decoding. |
| 136 | /// if `bit_reader` does not contain enough bits. | 141 | /// |
| 142 | /// Errors returned: | ||
| 143 | /// - `error.EndOfStream` if `bit_reader` does not contain enough bits. | ||
| 137 | pub fn readInitialFseState(self: *DecodeState, bit_reader: *readers.ReverseBitReader) error{EndOfStream}!void { | 144 | pub fn readInitialFseState(self: *DecodeState, bit_reader: *readers.ReverseBitReader) error{EndOfStream}!void { |
| 138 | self.literal.state = try bit_reader.readBitsNoEof(u9, self.literal.accuracy_log); | 145 | self.literal.state = try bit_reader.readBitsNoEof(u9, self.literal.accuracy_log); |
| 139 | self.offset.state = try bit_reader.readBitsNoEof(u8, self.offset.accuracy_log); | 146 | self.offset.state = try bit_reader.readBitsNoEof(u8, self.offset.accuracy_log); |
| ... | @@ -308,13 +315,19 @@ pub const DecodeState = struct { | ... | @@ -308,13 +315,19 @@ pub const DecodeState = struct { |
| 308 | } || DecodeLiteralsError; | 315 | } || DecodeLiteralsError; |
| 309 | 316 | ||
| 310 | /// Decode one sequence from `bit_reader` into `dest`, written starting at | 317 | /// Decode one sequence from `bit_reader` into `dest`, written starting at |
| 311 | /// `write_pos` and update FSE states if `last_sequence` is `false`. Returns | 318 | /// `write_pos` and update FSE states if `last_sequence` is `false`. |
| 312 | /// `error.MalformedSequence` error if the decompressed sequence would be longer | 319 | /// `prepare()` must be called for the block before attempting to decode |
| 313 | /// than `sequence_size_limit` or the sequence's offset is too large; returns | 320 | /// sequences. |
| 314 | /// `error.EndOfStream` if `bit_reader` does not contain enough bits; returns | 321 | /// |
| 315 | /// `error.UnexpectedEndOfLiteralStream` if the decoder state's literal streams | 322 | /// Errors returned: |
| 316 | /// do not contain enough literals for the sequence (this may mean the literal | 323 | /// - `error.MalformedSequence` if the decompressed sequence would be |
| 317 | /// stream or the sequence is malformed). | 324 | /// longer than `sequence_size_limit` or the sequence's offset is too |
| 325 | /// large | ||
| 326 | /// - `error.UnexpectedEndOfLiteralStream` if the decoder state's literal | ||
| 327 | /// streams do not contain enough literals for the sequence (this may | ||
| 328 | /// mean the literal stream or the sequence is malformed). | ||
| 329 | /// - `error.OffsetCodeTooLarge` if an invalid offset code is found | ||
| 330 | /// - `error.EndOfStream` if `bit_reader` does not contain enough bits | ||
| 318 | pub fn decodeSequenceSlice( | 331 | pub fn decodeSequenceSlice( |
| 319 | self: *DecodeState, | 332 | self: *DecodeState, |
| 320 | dest: []u8, | 333 | dest: []u8, |
| ... | @@ -336,7 +349,8 @@ pub const DecodeState = struct { | ... | @@ -336,7 +349,8 @@ pub const DecodeState = struct { |
| 336 | return sequence_length; | 349 | return sequence_length; |
| 337 | } | 350 | } |
| 338 | 351 | ||
| 339 | /// Decode one sequence from `bit_reader` into `dest`; see `decodeSequenceSlice`. | 352 | /// Decode one sequence from `bit_reader` into `dest`; see |
| 353 | /// `decodeSequenceSlice`. | ||
| 340 | pub fn decodeSequenceRingBuffer( | 354 | pub fn decodeSequenceRingBuffer( |
| 341 | self: *DecodeState, | 355 | self: *DecodeState, |
| 342 | dest: *RingBuffer, | 356 | dest: *RingBuffer, |
| ... | @@ -364,7 +378,7 @@ pub const DecodeState = struct { | ... | @@ -364,7 +378,7 @@ pub const DecodeState = struct { |
| 364 | try self.initLiteralStream(self.literal_streams.four[self.literal_stream_index]); | 378 | try self.initLiteralStream(self.literal_streams.four[self.literal_stream_index]); |
| 365 | } | 379 | } |
| 366 | 380 | ||
| 367 | pub fn initLiteralStream(self: *DecodeState, bytes: []const u8) error{BitStreamHasNoStartBit}!void { | 381 | fn initLiteralStream(self: *DecodeState, bytes: []const u8) error{BitStreamHasNoStartBit}!void { |
| 368 | try self.literal_stream_reader.init(bytes); | 382 | try self.literal_stream_reader.init(bytes); |
| 369 | } | 383 | } |
| 370 | 384 | ||
| ... | @@ -393,12 +407,14 @@ pub const DecodeState = struct { | ... | @@ -393,12 +407,14 @@ pub const DecodeState = struct { |
| 393 | PrefixNotFound, | 407 | PrefixNotFound, |
| 394 | } || LiteralBitsError; | 408 | } || LiteralBitsError; |
| 395 | 409 | ||
| 396 | /// Decode `len` bytes of literals into `dest`. `literals` should be the | 410 | /// Decode `len` bytes of literals into `dest`. |
| 397 | /// `LiteralsSection` that was passed to `prepare()`. Returns | 411 | /// |
| 398 | /// `error.MalformedLiteralsLength` if the number of literal bytes decoded by | 412 | /// Errors returned: |
| 399 | /// `self` plus `len` is greater than the regenerated size of `literals`. | 413 | /// - `error.MalformedLiteralsLength` if the number of literal bytes |
| 400 | /// Returns `error.UnexpectedEndOfLiteralStream` and `error.PrefixNotFound` if | 414 | /// decoded by `self` plus `len` is greater than the regenerated size of |
| 401 | /// there are problems decoding Huffman compressed literals. | 415 | /// `literals` |
| 416 | /// - `error.UnexpectedEndOfLiteralStream` and `error.PrefixNotFound` if | ||
| 417 | /// there are problems decoding Huffman compressed literals | ||
| 402 | pub fn decodeLiteralsSlice( | 418 | pub fn decodeLiteralsSlice( |
| 403 | self: *DecodeState, | 419 | self: *DecodeState, |
| 404 | dest: []u8, | 420 | dest: []u8, |
| ... | @@ -561,7 +577,6 @@ pub const DecodeState = struct { | ... | @@ -561,7 +577,6 @@ pub const DecodeState = struct { |
| 561 | /// - `error.MalformedRleBlock` if the block is an RLE block and `src.len < 1` | 577 | /// - `error.MalformedRleBlock` if the block is an RLE block and `src.len < 1` |
| 562 | /// - `error.MalformedCompressedBlock` if there are errors decoding a | 578 | /// - `error.MalformedCompressedBlock` if there are errors decoding a |
| 563 | /// compressed block | 579 | /// compressed block |
| 564 | /// - `error.EndOfStream` if the sequence bit stream ends unexpectedly | ||
| 565 | pub fn decodeBlock( | 580 | pub fn decodeBlock( |
| 566 | dest: []u8, | 581 | dest: []u8, |
| 567 | src: []const u8, | 582 | src: []const u8, |
| ... | @@ -738,7 +753,8 @@ pub fn decodeBlockRingBuffer( | ... | @@ -738,7 +753,8 @@ pub fn decodeBlockRingBuffer( |
| 738 | /// `error.SequenceBufferTooSmall` are returned (the maximum block size is an | 753 | /// `error.SequenceBufferTooSmall` are returned (the maximum block size is an |
| 739 | /// upper bound for the size of both buffers). See `decodeBlock` | 754 | /// upper bound for the size of both buffers). See `decodeBlock` |
| 740 | /// and `decodeBlockRingBuffer` for function that can decode a block without | 755 | /// and `decodeBlockRingBuffer` for function that can decode a block without |
| 741 | /// these extra copies. | 756 | /// these extra copies. `error.EndOfStream` is returned if `source` does not |
| 757 | /// contain enough bytes. | ||
| 742 | pub fn decodeBlockReader( | 758 | pub fn decodeBlockReader( |
| 743 | dest: *RingBuffer, | 759 | dest: *RingBuffer, |
| 744 | source: anytype, | 760 | source: anytype, |
| ... | @@ -820,6 +836,10 @@ pub fn decodeBlockHeader(src: *const [3]u8) frame.ZStandard.Block.Header { | ... | @@ -820,6 +836,10 @@ pub fn decodeBlockHeader(src: *const [3]u8) frame.ZStandard.Block.Header { |
| 820 | }; | 836 | }; |
| 821 | } | 837 | } |
| 822 | 838 | ||
| 839 | /// Decode the header of a block. | ||
| 840 | /// | ||
| 841 | /// Errors returned: | ||
| 842 | /// - `error.EndOfStream` if `src.len < 3` | ||
| 823 | pub fn decodeBlockHeaderSlice(src: []const u8) error{EndOfStream}!frame.ZStandard.Block.Header { | 843 | pub fn decodeBlockHeaderSlice(src: []const u8) error{EndOfStream}!frame.ZStandard.Block.Header { |
| 824 | if (src.len < 3) return error.EndOfStream; | 844 | if (src.len < 3) return error.EndOfStream; |
| 825 | return decodeBlockHeader(src[0..3]); | 845 | return decodeBlockHeader(src[0..3]); |
| ... | @@ -828,9 +848,14 @@ pub fn decodeBlockHeaderSlice(src: []const u8) error{EndOfStream}!frame.ZStandar | ... | @@ -828,9 +848,14 @@ pub fn decodeBlockHeaderSlice(src: []const u8) error{EndOfStream}!frame.ZStandar |
| 828 | /// Decode a `LiteralsSection` from `src`, incrementing `consumed_count` by the | 848 | /// Decode a `LiteralsSection` from `src`, incrementing `consumed_count` by the |
| 829 | /// number of bytes the section uses. | 849 | /// number of bytes the section uses. |
| 830 | /// | 850 | /// |
| 831 | /// Errors: | 851 | /// Errors returned: |
| 832 | /// - returns `error.MalformedLiteralsHeader` if the header is invalid | 852 | /// - `error.MalformedLiteralsHeader` if the header is invalid |
| 833 | /// - returns `error.MalformedLiteralsSection` if there are errors decoding | 853 | /// - `error.MalformedLiteralsSection` if there are decoding errors |
| 854 | /// - `error.MalformedAccuracyLog` if compressed literals have invalid | ||
| 855 | /// accuracy | ||
| 856 | /// - `error.MalformedFseTable` if compressed literals have invalid FSE table | ||
| 857 | /// - `error.MalformedHuffmanTree` if there are errors decoding a Huffamn tree | ||
| 858 | /// - `error.EndOfStream` if there are not enough bytes in `src` | ||
| 834 | pub fn decodeLiteralsSectionSlice( | 859 | pub fn decodeLiteralsSectionSlice( |
| 835 | src: []const u8, | 860 | src: []const u8, |
| 836 | consumed_count: *usize, | 861 | consumed_count: *usize, |
| ... | @@ -886,11 +911,7 @@ pub fn decodeLiteralsSectionSlice( | ... | @@ -886,11 +911,7 @@ pub fn decodeLiteralsSectionSlice( |
| 886 | } | 911 | } |
| 887 | 912 | ||
| 888 | /// Decode a `LiteralsSection` from `src`, incrementing `consumed_count` by the | 913 | /// Decode a `LiteralsSection` from `src`, incrementing `consumed_count` by the |
| 889 | /// number of bytes the section uses. | 914 | /// number of bytes the section uses. See `decodeLiterasSectionSlice()`. |
| 890 | /// | ||
| 891 | /// Errors: | ||
| 892 | /// - returns `error.MalformedLiteralsHeader` if the header is invalid | ||
| 893 | /// - returns `error.MalformedLiteralsSection` if there are errors decoding | ||
| 894 | pub fn decodeLiteralsSection( | 915 | pub fn decodeLiteralsSection( |
| 895 | source: anytype, | 916 | source: anytype, |
| 896 | buffer: []u8, | 917 | buffer: []u8, |
| ... | @@ -961,6 +982,9 @@ fn decodeStreams(size_format: u2, stream_data: []const u8) !LiteralsSection.Stre | ... | @@ -961,6 +982,9 @@ fn decodeStreams(size_format: u2, stream_data: []const u8) !LiteralsSection.Stre |
| 961 | } | 982 | } |
| 962 | 983 | ||
| 963 | /// Decode a literals section header. | 984 | /// Decode a literals section header. |
| 985 | /// | ||
| 986 | /// Errors returned: | ||
| 987 | /// - `error.EndOfStream` if there are not enough bytes in `source` | ||
| 964 | pub fn decodeLiteralsHeader(source: anytype) !LiteralsSection.Header { | 988 | pub fn decodeLiteralsHeader(source: anytype) !LiteralsSection.Header { |
| 965 | const byte0 = try source.readByte(); | 989 | const byte0 = try source.readByte(); |
| 966 | const block_type = @intToEnum(LiteralsSection.BlockType, byte0 & 0b11); | 990 | const block_type = @intToEnum(LiteralsSection.BlockType, byte0 & 0b11); |
| ... | @@ -1011,9 +1035,9 @@ pub fn decodeLiteralsHeader(source: anytype) !LiteralsSection.Header { | ... | @@ -1011,9 +1035,9 @@ pub fn decodeLiteralsHeader(source: anytype) !LiteralsSection.Header { |
| 1011 | 1035 | ||
| 1012 | /// Decode a sequences section header. | 1036 | /// Decode a sequences section header. |
| 1013 | /// | 1037 | /// |
| 1014 | /// Errors: | 1038 | /// Errors returned: |
| 1015 | /// - returns `error.ReservedBitSet` is the reserved bit is set | 1039 | /// - `error.ReservedBitSet` if the reserved bit is set |
| 1016 | /// - returns `error.MalformedSequencesHeader` if the header is invalid | 1040 | /// - `error.EndOfStream` if there are not enough bytes in `source` |
| 1017 | pub fn decodeSequencesHeader( | 1041 | pub fn decodeSequencesHeader( |
| 1018 | source: anytype, | 1042 | source: anytype, |
| 1019 | ) !SequencesSection.Header { | 1043 | ) !SequencesSection.Header { |
lib/std/compress/zstandard/decompress.zig+77-31| ... | @@ -25,11 +25,12 @@ pub fn isSkippableMagic(magic: u32) bool { | ... | @@ -25,11 +25,12 @@ pub fn isSkippableMagic(magic: u32) bool { |
| 25 | 25 | ||
| 26 | /// Returns the kind of frame at the beginning of `src`. | 26 | /// Returns the kind of frame at the beginning of `src`. |
| 27 | /// | 27 | /// |
| 28 | /// Errors: | 28 | /// Errors returned: |
| 29 | /// - returns `error.BadMagic` if `source` begins with bytes not equal to the | 29 | /// - `error.BadMagic` if `source` begins with bytes not equal to the |
| 30 | /// Zstandard frame magic number, or outside the range of magic numbers for | 30 | /// Zstandard frame magic number, or outside the range of magic numbers for |
| 31 | /// skippable frames. | 31 | /// skippable frames. |
| 32 | pub fn decodeFrameType(source: anytype) !frame.Kind { | 32 | /// - `error.EndOfStream` if `source` contains fewer than 4 bytes |
| 33 | pub fn decodeFrameType(source: anytype) error{ BadMagic, EndOfStream }!frame.Kind { | ||
| 33 | const magic = try source.readIntLittle(u32); | 34 | const magic = try source.readIntLittle(u32); |
| 34 | return if (magic == frame.ZStandard.magic_number) | 35 | return if (magic == frame.ZStandard.magic_number) |
| 35 | .zstandard | 36 | .zstandard |
| ... | @@ -45,12 +46,23 @@ const ReadWriteCount = struct { | ... | @@ -45,12 +46,23 @@ const ReadWriteCount = struct { |
| 45 | }; | 46 | }; |
| 46 | 47 | ||
| 47 | /// Decodes the frame at the start of `src` into `dest`. Returns the number of | 48 | /// Decodes the frame at the start of `src` into `dest`. Returns the number of |
| 48 | /// bytes read from `src` and written to `dest`. | 49 | /// bytes read from `src` and written to `dest`. This function can only decode |
| 50 | /// frames that declare the decompressed content size. | ||
| 49 | /// | 51 | /// |
| 50 | /// Errors: | 52 | /// Errors returned: |
| 51 | /// - returns `error.UnknownContentSizeUnsupported` | 53 | /// - `error.UnknownContentSizeUnsupported` if the frame does not declare the |
| 52 | /// - returns `error.ContentTooLarge` | 54 | /// uncompressed content size |
| 53 | /// - returns `error.BadMagic` | 55 | /// - `error.ContentTooLarge` if `dest` is smaller than the uncompressed data |
| 56 | /// - `error.BadMagic` if the first 4 bytes of `src` is not a valid magic | ||
| 57 | /// number for a Zstandard or Skippable frame | ||
| 58 | /// - `error.DictionaryIdFlagUnsupported` if the frame uses a dictionary | ||
| 59 | /// - `error.ChecksumFailure` if `verify_checksum` is true and the frame | ||
| 60 | /// contains a checksum that does not match the checksum of the decompressed | ||
| 61 | /// data | ||
| 62 | /// - `error.ReservedBitSet` if the reserved bit of the frame header is set | ||
| 63 | /// - `error.UnusedBitSet` if the unused bit of the frame header is set | ||
| 64 | /// - `error.EndOfStream` if `src` does not contain a complete frame | ||
| 65 | /// - an error in `block.Error` if there are errors decoding a block | ||
| 54 | pub fn decodeFrame( | 66 | pub fn decodeFrame( |
| 55 | dest: []u8, | 67 | dest: []u8, |
| 56 | src: []const u8, | 68 | src: []const u8, |
| ... | @@ -66,6 +78,7 @@ pub fn decodeFrame( | ... | @@ -66,6 +78,7 @@ pub fn decodeFrame( |
| 66 | }; | 78 | }; |
| 67 | } | 79 | } |
| 68 | 80 | ||
| 81 | /// Returns the frame checksum corresponding to the data fed into `hasher` | ||
| 69 | pub fn computeChecksum(hasher: *std.hash.XxHash64) u32 { | 82 | pub fn computeChecksum(hasher: *std.hash.XxHash64) u32 { |
| 70 | const hash = hasher.final(); | 83 | const hash = hasher.final(); |
| 71 | return @intCast(u32, hash & 0xFFFFFFFF); | 84 | return @intCast(u32, hash & 0xFFFFFFFF); |
| ... | @@ -74,20 +87,31 @@ pub fn computeChecksum(hasher: *std.hash.XxHash64) u32 { | ... | @@ -74,20 +87,31 @@ pub fn computeChecksum(hasher: *std.hash.XxHash64) u32 { |
| 74 | const FrameError = error{ | 87 | const FrameError = error{ |
| 75 | DictionaryIdFlagUnsupported, | 88 | DictionaryIdFlagUnsupported, |
| 76 | ChecksumFailure, | 89 | ChecksumFailure, |
| 90 | EndOfStream, | ||
| 77 | } || InvalidBit || block.Error; | 91 | } || InvalidBit || block.Error; |
| 78 | 92 | ||
| 79 | /// Decode a Zstandard frame from `src` into `dest`, returning the number of | 93 | /// Decode a Zstandard frame from `src` into `dest`, returning the number of |
| 80 | /// bytes read from `src` and written to `dest`; if the frame does not declare | 94 | /// bytes read from `src` and written to `dest`. The first four bytes of `src` |
| 81 | /// its decompressed content size `error.UnknownContentSizeUnsupported` is | 95 | /// must be the magic number for a Zstandard frame. |
| 82 | /// returned. Returns `error.DictionaryIdFlagUnsupported` if the frame uses a | 96 | /// |
| 83 | /// dictionary, and `error.ChecksumFailure` if `verify_checksum` is `true` and | 97 | /// Error returned: |
| 84 | /// the frame contains a checksum that does not match the checksum computed from | 98 | /// - `error.UnknownContentSizeUnsupported` if the frame does not declare the |
| 85 | /// the decompressed frame. | 99 | /// uncompressed content size |
| 100 | /// - `error.ContentTooLarge` if `dest` is smaller than the uncompressed data | ||
| 101 | /// number for a Zstandard or Skippable frame | ||
| 102 | /// - `error.DictionaryIdFlagUnsupported` if the frame uses a dictionary | ||
| 103 | /// - `error.ChecksumFailure` if `verify_checksum` is true and the frame | ||
| 104 | /// contains a checksum that does not match the checksum of the decompressed | ||
| 105 | /// data | ||
| 106 | /// - `error.ReservedBitSet` if the reserved bit of the frame header is set | ||
| 107 | /// - `error.UnusedBitSet` if the unused bit of the frame header is set | ||
| 108 | /// - `error.EndOfStream` if `src` does not contain a complete frame | ||
| 109 | /// - an error in `block.Error` if there are errors decoding a block | ||
| 86 | pub fn decodeZStandardFrame( | 110 | pub fn decodeZStandardFrame( |
| 87 | dest: []u8, | 111 | dest: []u8, |
| 88 | src: []const u8, | 112 | src: []const u8, |
| 89 | verify_checksum: bool, | 113 | verify_checksum: bool, |
| 90 | ) (error{ UnknownContentSizeUnsupported, ContentTooLarge, EndOfStream } || FrameError)!ReadWriteCount { | 114 | ) (error{ UnknownContentSizeUnsupported, ContentTooLarge } || FrameError)!ReadWriteCount { |
| 91 | assert(readInt(u32, src[0..4]) == frame.ZStandard.magic_number); | 115 | assert(readInt(u32, src[0..4]) == frame.ZStandard.magic_number); |
| 92 | var consumed_count: usize = 4; | 116 | var consumed_count: usize = 4; |
| 93 | 117 | ||
| ... | @@ -127,7 +151,18 @@ pub const FrameContext = struct { | ... | @@ -127,7 +151,18 @@ pub const FrameContext = struct { |
| 127 | has_checksum: bool, | 151 | has_checksum: bool, |
| 128 | block_size_max: usize, | 152 | block_size_max: usize, |
| 129 | 153 | ||
| 130 | pub fn init(frame_header: frame.ZStandard.Header, window_size_max: usize, verify_checksum: bool) !FrameContext { | 154 | const Error = error{ DictionaryIdFlagUnsupported, WindowSizeUnknown, WindowTooLarge }; |
| 155 | /// Validates `frame_header` and returns the associated `FrameContext`. | ||
| 156 | /// | ||
| 157 | /// Errors returned: | ||
| 158 | /// - `error.DictionaryIdFlagUnsupported` if the frame uses a dictionary | ||
| 159 | /// - `error.WindowSizeUnknown` if the frame does not have a valid window size | ||
| 160 | /// - `error.WindowTooLarge` if the window size is larger than | ||
| 161 | pub fn init( | ||
| 162 | frame_header: frame.ZStandard.Header, | ||
| 163 | window_size_max: usize, | ||
| 164 | verify_checksum: bool, | ||
| 165 | ) Error!FrameContext { | ||
| 131 | if (frame_header.descriptor.dictionary_id_flag != 0) return error.DictionaryIdFlagUnsupported; | 166 | if (frame_header.descriptor.dictionary_id_flag != 0) return error.DictionaryIdFlagUnsupported; |
| 132 | 167 | ||
| 133 | const window_size_raw = frameWindowSize(frame_header) orelse return error.WindowSizeUnknown; | 168 | const window_size_raw = frameWindowSize(frame_header) orelse return error.WindowSizeUnknown; |
| ... | @@ -147,19 +182,29 @@ pub const FrameContext = struct { | ... | @@ -147,19 +182,29 @@ pub const FrameContext = struct { |
| 147 | }; | 182 | }; |
| 148 | 183 | ||
| 149 | /// Decode a Zstandard from from `src` and return the decompressed bytes; see | 184 | /// Decode a Zstandard from from `src` and return the decompressed bytes; see |
| 150 | /// `decodeZStandardFrame()`. Returns `error.WindowSizeUnknown` if the frame | 185 | /// `decodeZStandardFrame()`. `allocator` is used to allocate both the returned |
| 151 | /// does not declare its content size or a window descriptor (this indicates a | 186 | /// slice and internal buffers used during decoding. The first four bytes of |
| 152 | /// malformed frame). | 187 | /// `src` must be the magic number for a Zstandard frame. |
| 153 | /// | 188 | /// |
| 154 | /// Errors: | 189 | /// Errors returned: |
| 155 | /// - returns `error.WindowTooLarge` | 190 | /// - `error.WindowSizeUnknown` if the frame does not have a valid window size |
| 156 | /// - returns `error.WindowSizeUnknown` | 191 | /// - `error.WindowTooLarge` if the window size is larger than |
| 192 | /// `window_size_max` | ||
| 193 | /// - `error.DictionaryIdFlagUnsupported` if the frame uses a dictionary | ||
| 194 | /// - `error.ChecksumFailure` if `verify_checksum` is true and the frame | ||
| 195 | /// contains a checksum that does not match the checksum of the decompressed | ||
| 196 | /// data | ||
| 197 | /// - `error.ReservedBitSet` if the reserved bit of the frame header is set | ||
| 198 | /// - `error.UnusedBitSet` if the unused bit of the frame header is set | ||
| 199 | /// - `error.EndOfStream` if `src` does not contain a complete frame | ||
| 200 | /// - `error.OutOfMemory` if `allocator` cannot allocate enough memory | ||
| 201 | /// - an error in `block.Error` if there are errors decoding a block | ||
| 157 | pub fn decodeZStandardFrameAlloc( | 202 | pub fn decodeZStandardFrameAlloc( |
| 158 | allocator: std.mem.Allocator, | 203 | allocator: std.mem.Allocator, |
| 159 | src: []const u8, | 204 | src: []const u8, |
| 160 | verify_checksum: bool, | 205 | verify_checksum: bool, |
| 161 | window_size_max: usize, | 206 | window_size_max: usize, |
| 162 | ) (error{ WindowSizeUnknown, WindowTooLarge, OutOfMemory, EndOfStream } || FrameError)![]u8 { | 207 | ) (error{OutOfMemory} || FrameContext.Error || FrameError)![]u8 { |
| 163 | var result = std.ArrayList(u8).init(allocator); | 208 | var result = std.ArrayList(u8).init(allocator); |
| 164 | assert(readInt(u32, src[0..4]) == frame.ZStandard.magic_number); | 209 | assert(readInt(u32, src[0..4]) == frame.ZStandard.magic_number); |
| 165 | var consumed_count: usize = 4; | 210 | var consumed_count: usize = 4; |
| ... | @@ -222,7 +267,7 @@ fn decodeFrameBlocks( | ... | @@ -222,7 +267,7 @@ fn decodeFrameBlocks( |
| 222 | src: []const u8, | 267 | src: []const u8, |
| 223 | consumed_count: *usize, | 268 | consumed_count: *usize, |
| 224 | hash: ?*std.hash.XxHash64, | 269 | hash: ?*std.hash.XxHash64, |
| 225 | ) block.Error!usize { | 270 | ) (error{EndOfStream} || block.Error)!usize { |
| 226 | // These tables take 7680 bytes | 271 | // These tables take 7680 bytes |
| 227 | var literal_fse_data: [types.compressed_block.table_size_max.literal]Table.Fse = undefined; | 272 | var literal_fse_data: [types.compressed_block.table_size_max.literal]Table.Fse = undefined; |
| 228 | var match_fse_data: [types.compressed_block.table_size_max.match]Table.Fse = undefined; | 273 | var match_fse_data: [types.compressed_block.table_size_max.match]Table.Fse = undefined; |
| ... | @@ -252,7 +297,8 @@ fn decodeFrameBlocks( | ... | @@ -252,7 +297,8 @@ fn decodeFrameBlocks( |
| 252 | return written_count; | 297 | return written_count; |
| 253 | } | 298 | } |
| 254 | 299 | ||
| 255 | /// Decode the header of a skippable frame. | 300 | /// Decode the header of a skippable frame. The first four bytes of `src` must |
| 301 | /// be a valid magic number for a Skippable frame. | ||
| 256 | pub fn decodeSkippableHeader(src: *const [8]u8) frame.Skippable.Header { | 302 | pub fn decodeSkippableHeader(src: *const [8]u8) frame.Skippable.Header { |
| 257 | const magic = readInt(u32, src[0..4]); | 303 | const magic = readInt(u32, src[0..4]); |
| 258 | assert(isSkippableMagic(magic)); | 304 | assert(isSkippableMagic(magic)); |
| ... | @@ -263,8 +309,8 @@ pub fn decodeSkippableHeader(src: *const [8]u8) frame.Skippable.Header { | ... | @@ -263,8 +309,8 @@ pub fn decodeSkippableHeader(src: *const [8]u8) frame.Skippable.Header { |
| 263 | }; | 309 | }; |
| 264 | } | 310 | } |
| 265 | 311 | ||
| 266 | /// Returns the window size required to decompress a frame, or `null` if it cannot be | 312 | /// Returns the window size required to decompress a frame, or `null` if it |
| 267 | /// determined, which indicates a malformed frame header. | 313 | /// cannot be determined (which indicates a malformed frame header). |
| 268 | pub fn frameWindowSize(header: frame.ZStandard.Header) ?u64 { | 314 | pub fn frameWindowSize(header: frame.ZStandard.Header) ?u64 { |
| 269 | if (header.window_descriptor) |descriptor| { | 315 | if (header.window_descriptor) |descriptor| { |
| 270 | const exponent = (descriptor & 0b11111000) >> 3; | 316 | const exponent = (descriptor & 0b11111000) >> 3; |
| ... | @@ -279,10 +325,10 @@ pub fn frameWindowSize(header: frame.ZStandard.Header) ?u64 { | ... | @@ -279,10 +325,10 @@ pub fn frameWindowSize(header: frame.ZStandard.Header) ?u64 { |
| 279 | const InvalidBit = error{ UnusedBitSet, ReservedBitSet }; | 325 | const InvalidBit = error{ UnusedBitSet, ReservedBitSet }; |
| 280 | /// Decode the header of a Zstandard frame. | 326 | /// Decode the header of a Zstandard frame. |
| 281 | /// | 327 | /// |
| 282 | /// Errors: | 328 | /// Errors returned: |
| 283 | /// - returns `error.UnusedBitSet` if the unused bits of the header are set | 329 | /// - `error.UnusedBitSet` if the unused bits of the header are set |
| 284 | /// - returns `error.ReservedBitSet` if the reserved bits of the header are | 330 | /// - `error.ReservedBitSet` if the reserved bits of the header are set |
| 285 | /// set | 331 | /// - `error.EndOfStream` if `source` does not contain a complete header |
| 286 | pub fn decodeZStandardHeader(source: anytype) (error{EndOfStream} || InvalidBit)!frame.ZStandard.Header { | 332 | pub fn decodeZStandardHeader(source: anytype) (error{EndOfStream} || InvalidBit)!frame.ZStandard.Header { |
| 287 | const descriptor = @bitCast(frame.ZStandard.Header.Descriptor, try source.readByte()); | 333 | const descriptor = @bitCast(frame.ZStandard.Header.Descriptor, try source.readByte()); |
| 288 | 334 |