authorgravatar for 4678790+dweiller@users.noreply.github.comDominic <4678790+dweiller@users.noreply.github.com> 2023-02-02 20:49:11+11:00
committergravatar for 4678790+dweiller@users.noreply.github.comDominic <4678790+dweiller@users.noreply.github.com> 2023-02-20 09:09:06+11:00
log89f9c5cb373c81af5cb052cd9e68e44a123d0b04
tree1c4d428ad6138ff50d62c0d054acb5b23e31926d
parent7e2755646f5c9cab9973708a79c8aaa369d148e7

std.compress.zstandard: improve doc comments


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};
2827
29pub const DecodeState = struct {28pub 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 from91 /// 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's95 /// - `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 section97 /// - `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 }
134139
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;
309316
310 /// Decode one sequence from `bit_reader` into `dest`, written starting at317 /// Decode one sequence from `bit_reader` into `dest`, written starting at
311 /// `write_pos` and update FSE states if `last_sequence` is `false`. Returns318 /// `write_pos` and update FSE states if `last_sequence` is `false`.
312 /// `error.MalformedSequence` error if the decompressed sequence would be longer319 /// `prepare()` must be called for the block before attempting to decode
313 /// than `sequence_size_limit` or the sequence's offset is too large; returns320 /// sequences.
314 /// `error.EndOfStream` if `bit_reader` does not contain enough bits; returns321 ///
315 /// `error.UnexpectedEndOfLiteralStream` if the decoder state's literal streams322 /// Errors returned:
316 /// do not contain enough literals for the sequence (this may mean the literal323 /// - `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 }
338351
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 }
366380
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 }
370384
...@@ -393,12 +407,14 @@ pub const DecodeState = struct {...@@ -393,12 +407,14 @@ pub const DecodeState = struct {
393 PrefixNotFound,407 PrefixNotFound,
394 } || LiteralBitsError;408 } || LiteralBitsError;
395409
396 /// Decode `len` bytes of literals into `dest`. `literals` should be the410 /// Decode `len` bytes of literals into `dest`.
397 /// `LiteralsSection` that was passed to `prepare()`. Returns411 ///
398 /// `error.MalformedLiteralsLength` if the number of literal bytes decoded by412 /// 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` if414 /// 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 a578/// - `error.MalformedCompressedBlock` if there are errors decoding a
563/// compressed block579/// compressed block
564/// - `error.EndOfStream` if the sequence bit stream ends unexpectedly
565pub fn decodeBlock(580pub 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 an753/// `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 without755/// 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.
742pub fn decodeBlockReader(758pub 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}
822838
839/// Decode the header of a block.
840///
841/// Errors returned:
842/// - `error.EndOfStream` if `src.len < 3`
823pub fn decodeBlockHeaderSlice(src: []const u8) error{EndOfStream}!frame.ZStandard.Block.Header {843pub 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 the848/// 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 invalid852/// - `error.MalformedLiteralsHeader` if the header is invalid
833/// - returns `error.MalformedLiteralsSection` if there are errors decoding853/// - `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`
834pub fn decodeLiteralsSectionSlice(859pub 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}
887912
888/// Decode a `LiteralsSection` from `src`, incrementing `consumed_count` by the913/// 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
894pub fn decodeLiteralsSection(915pub 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}
962983
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`
964pub fn decodeLiteralsHeader(source: anytype) !LiteralsSection.Header {988pub 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 {
10111035
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 set1039/// - `error.ReservedBitSet` if the reserved bit is set
1016/// - returns `error.MalformedSequencesHeader` if the header is invalid1040/// - `error.EndOfStream` if there are not enough bytes in `source`
1017pub fn decodeSequencesHeader(1041pub 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 {
2525
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 the29/// - `error.BadMagic` if `source` begins with bytes not equal to the
30/// Zstandard frame magic number, or outside the range of magic numbers for30/// Zstandard frame magic number, or outside the range of magic numbers for
31/// skippable frames.31/// skippable frames.
32pub fn decodeFrameType(source: anytype) !frame.Kind {32/// - `error.EndOfStream` if `source` contains fewer than 4 bytes
33pub 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 .zstandard36 .zstandard
...@@ -45,12 +46,23 @@ const ReadWriteCount = struct {...@@ -45,12 +46,23 @@ const ReadWriteCount = struct {
45};46};
4647
47/// Decodes the frame at the start of `src` into `dest`. Returns the number of48/// 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
54pub fn decodeFrame(66pub 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}
6880
81/// Returns the frame checksum corresponding to the data fed into `hasher`
69pub fn computeChecksum(hasher: *std.hash.XxHash64) u32 {82pub 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 {
74const FrameError = error{87const FrameError = error{
75 DictionaryIdFlagUnsupported,88 DictionaryIdFlagUnsupported,
76 ChecksumFailure,89 ChecksumFailure,
90 EndOfStream,
77} || InvalidBit || block.Error;91} || InvalidBit || block.Error;
7892
79/// Decode a Zstandard frame from `src` into `dest`, returning the number of93/// 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 declare94/// bytes read from `src` and written to `dest`. The first four bytes of `src`
81/// its decompressed content size `error.UnknownContentSizeUnsupported` is95/// must be the magic number for a Zstandard frame.
82/// returned. Returns `error.DictionaryIdFlagUnsupported` if the frame uses a96///
83/// dictionary, and `error.ChecksumFailure` if `verify_checksum` is `true` and97/// Error returned:
84/// the frame contains a checksum that does not match the checksum computed from98/// - `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
86pub fn decodeZStandardFrame(110pub 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;
93117
...@@ -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,
129153
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;
132167
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};
148183
149/// Decode a Zstandard from from `src` and return the decompressed bytes; see184/// Decode a Zstandard from from `src` and return the decompressed bytes; see
150/// `decodeZStandardFrame()`. Returns `error.WindowSizeUnknown` if the frame185/// `decodeZStandardFrame()`. `allocator` is used to allocate both the returned
151/// does not declare its content size or a window descriptor (this indicates a186/// 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
157pub fn decodeZStandardFrameAlloc(202pub 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 bytes271 // 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}
254299
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.
256pub fn decodeSkippableHeader(src: *const [8]u8) frame.Skippable.Header {302pub 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}
265311
266/// Returns the window size required to decompress a frame, or `null` if it cannot be312/// 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).
268pub fn frameWindowSize(header: frame.ZStandard.Header) ?u64 {314pub 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 {
279const InvalidBit = error{ UnusedBitSet, ReservedBitSet };325const 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 set329/// - `error.UnusedBitSet` if the unused bits of the header are set
284/// - returns `error.ReservedBitSet` if the reserved bits of the header are330/// - `error.ReservedBitSet` if the reserved bits of the header are set
285/// set331/// - `error.EndOfStream` if `source` does not contain a complete header
286pub fn decodeZStandardHeader(source: anytype) (error{EndOfStream} || InvalidBit)!frame.ZStandard.Header {332pub 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());
288334