Commit ee5af3c74c
Changed files (5)
lib
std
compress
zstandard
lib/std/compress/zstandard/decode/block.zig
@@ -413,7 +413,7 @@ pub const DecodeState = struct {
const DecodeLiteralsError = error{
MalformedLiteralsLength,
- PrefixNotFound,
+ NotFound,
} || LiteralBitsError;
/// Decode `len` bytes of literals into `dest`.
@@ -422,8 +422,8 @@ pub const DecodeState = struct {
/// - `error.MalformedLiteralsLength` if the number of literal bytes
/// decoded by `self` plus `len` is greater than the regenerated size of
/// `literals`
- /// - `error.UnexpectedEndOfLiteralStream` and `error.PrefixNotFound` if
- /// there are problems decoding Huffman compressed literals
+ /// - `error.UnexpectedEndOfLiteralStream` and `error.NotFound` if there
+ /// are problems decoding Huffman compressed literals
pub fn decodeLiteralsSlice(
self: *DecodeState,
dest: []u8,
lib/std/compress/zstandard/decompress.zig
@@ -6,6 +6,8 @@ const types = @import("types.zig");
const frame = types.frame;
const LiteralsSection = types.compressed_block.LiteralsSection;
const SequencesSection = types.compressed_block.SequencesSection;
+const SkippableHeader = types.frame.Skippable.Header;
+const ZstandardHeader = types.frame.Zstandard.Header;
const Table = types.compressed_block.Table;
pub const block = @import("decode/block.zig");
@@ -16,15 +18,13 @@ const readers = @import("readers.zig");
const readInt = std.mem.readIntLittle;
const readIntSlice = std.mem.readIntSliceLittle;
-fn readVarInt(comptime T: type, bytes: []const u8) T {
- return std.mem.readVarInt(T, bytes, .Little);
-}
+/// Returns `true` is `magic` is a valid magic number for a skippable frame
pub fn isSkippableMagic(magic: u32) bool {
return frame.Skippable.magic_number_min <= magic and magic <= frame.Skippable.magic_number_max;
}
-/// Returns the kind of frame at the beginning of `src`.
+/// Returns the kind of frame at the beginning of `source`.
///
/// Errors returned:
/// - `error.BadMagic` if `source` begins with bytes not equal to the
@@ -50,11 +50,22 @@ pub fn frameType(magic: u32) error{BadMagic}!frame.Kind {
}
pub const FrameHeader = union(enum) {
- zstandard: types.frame.Zstandard.Header,
- skippable: types.frame.Skippable.Header,
+ zstandard: ZstandardHeader,
+ skippable: SkippableHeader,
};
-pub fn decodeFrameHeader(source: anytype) error{ BadMagic, EndOfStream, ReservedBitSet }!FrameHeader {
+pub const HeaderError = error{ BadMagic, EndOfStream, ReservedBitSet };
+
+/// Returns the header of the frame at the beginning of `source`.
+///
+/// Errors returned:
+/// - `error.BadMagic` if `source` begins with bytes not equal to the
+/// Zstandard frame magic number, or outside the range of magic numbers for
+/// skippable frames.
+/// - `error.EndOfStream` if `source` contains fewer than 4 bytes
+/// - `error.ReservedBitSet` if the frame is a Zstandard frame and any of the
+/// reserved bits are set
+pub fn decodeFrameHeader(source: anytype) HeaderError!FrameHeader {
const magic = try source.readIntLittle(u32);
const frame_type = try frameType(magic);
switch (frame_type) {
@@ -68,41 +79,74 @@ pub fn decodeFrameHeader(source: anytype) error{ BadMagic, EndOfStream, Reserved
}
}
-const ReadWriteCount = struct {
+pub const ReadWriteCount = struct {
read_count: usize,
write_count: usize,
};
-/// Decodes frames from `src` into `dest`; see `decodeFrame()`.
-pub fn decode(dest: []u8, src: []const u8, verify_checksum: bool) !usize {
+/// Decodes frames from `src` into `dest`; returns the length of the result.
+/// The stream should not have extra trailing bytes - either all bytes in `src`
+/// will be decoded, or an error will be returned. An error will be returned if
+/// a Zstandard frame in `src` does not declare its content size.
+///
+/// Errors returned:
+/// - `error.DictionaryIdFlagUnsupported` if a `src` contains a frame that
+/// uses a dictionary
+/// - `error.MalformedFrame` if a frame in `src` is invalid
+/// - `error.UnknownContentSizeUnsupported` if a frame in `src` does not
+/// declare its content size
+pub fn decode(dest: []u8, src: []const u8, verify_checksum: bool) error{
+ MalformedFrame,
+ UnknownContentSizeUnsupported,
+ DictionaryIdFlagUnsupported,
+}!usize {
var write_count: usize = 0;
var read_count: usize = 0;
while (read_count < src.len) {
- const counts = try decodeFrame(dest, src[read_count..], verify_checksum);
+ const counts = decodeFrame(dest, src[read_count..], verify_checksum) catch |err| {
+ switch (err) {
+ error.UnknownContentSizeUnsupported => return error.UnknownContentSizeUnsupported,
+ error.DictionaryIdFlagUnsupported => return error.DictionaryIdFlagUnsupported,
+ else => return error.MalformedFrame,
+ }
+ };
read_count += counts.read_count;
write_count += counts.write_count;
}
return write_count;
}
+/// Decodes a stream of frames from `src`; returns the decoded bytes. The stream
+/// should not have extra trailing bytes - either all bytes in `src` will be
+/// decoded, or an error will be returned.
+///
+/// Errors returned:
+/// - `error.DictionaryIdFlagUnsupported` if a `src` contains a frame that
+/// uses a dictionary
+/// - `error.MalformedFrame` if a frame in `src` is invalid
+/// - `error.OutOfMemory` if `allocator` cannot allocate enough memory
pub fn decodeAlloc(
allocator: Allocator,
src: []const u8,
verify_checksum: bool,
window_size_max: usize,
-) ![]u8 {
+) error{ DictionaryIdFlagUnsupported, MalformedFrame, OutOfMemory }![]u8 {
var result = std.ArrayList(u8).init(allocator);
errdefer result.deinit();
var read_count: usize = 0;
while (read_count < src.len) {
- read_count += try decodeFrameArrayList(
+ read_count += decodeFrameArrayList(
allocator,
&result,
src[read_count..],
verify_checksum,
window_size_max,
- );
+ ) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ error.DictionaryIdFlagUnsupported => return error.DictionaryIdFlagUnsupported,
+ else => return error.MalformedFrame,
+ };
}
return result.toOwnedSlice();
}
@@ -112,18 +156,24 @@ pub fn decodeAlloc(
/// frames that declare the decompressed content size.
///
/// Errors returned:
+/// - `error.BadMagic` if the first 4 bytes of `src` is not a valid magic
+/// number for a Zstandard or skippable frame
/// - `error.UnknownContentSizeUnsupported` if the frame does not declare the
/// uncompressed content size
+/// - `error.WindowSizeUnknown` if the frame does not have a valid window size
/// - `error.ContentTooLarge` if `dest` is smaller than the uncompressed data
/// size declared by the frame header
-/// - `error.BadMagic` if the first 4 bytes of `src` is not a valid magic
-/// number for a Zstandard or Skippable frame
+/// - `error.ContentSizeTooLarge` if the frame header indicates a content size
+/// that is larger than `std.math.maxInt(usize)`
/// - `error.DictionaryIdFlagUnsupported` if the frame uses a dictionary
/// - `error.ChecksumFailure` if `verify_checksum` is true and the frame
/// contains a checksum that does not match the checksum of the decompressed
/// data
-/// - `error.ReservedBitSet` if the reserved bit of the frame header is set
+/// - `error.ReservedBitSet` if any of the reserved bits of the frame header
+/// are set
/// - `error.EndOfStream` if `src` does not contain a complete frame
+/// - `error.BadContentSize` if the content size declared by the frame does
+/// not equal the actual size of decompressed data
/// - an error in `block.Error` if there are errors decoding a block
/// - `error.SkippableSizeTooLarge` if the frame is skippable and reports a
/// size greater than `src.len`
@@ -131,7 +181,15 @@ pub fn decodeFrame(
dest: []u8,
src: []const u8,
verify_checksum: bool,
-) !ReadWriteCount {
+) (error{
+ BadMagic,
+ UnknownContentSizeUnsupported,
+ ContentTooLarge,
+ ContentSizeTooLarge,
+ WindowSizeUnknown,
+ DictionaryIdFlagUnsupported,
+ SkippableSizeTooLarge,
+} || FrameError)!ReadWriteCount {
var fbs = std.io.fixedBufferStream(src);
switch (try decodeFrameType(fbs.reader())) {
.zstandard => return decodeZstandardFrame(dest, src, verify_checksum),
@@ -153,16 +211,21 @@ pub fn decodeFrame(
///
/// Errors returned:
/// - `error.BadMagic` if the first 4 bytes of `src` is not a valid magic
-/// number for a Zstandard or Skippable frame
+/// number for a Zstandard or skippable frame
/// - `error.WindowSizeUnknown` if the frame does not have a valid window size
/// - `error.WindowTooLarge` if the window size is larger than
/// `window_size_max`
+/// - `error.ContentSizeTooLarge` if the frame header indicates a content size
+/// that is larger than `std.math.maxInt(usize)`
/// - `error.DictionaryIdFlagUnsupported` if the frame uses a dictionary
/// - `error.ChecksumFailure` if `verify_checksum` is true and the frame
/// contains a checksum that does not match the checksum of the decompressed
/// data
-/// - `error.ReservedBitSet` if the reserved bit of the frame header is set
+/// - `error.ReservedBitSet` if any of the reserved bits of the frame header
+/// are set
/// - `error.EndOfStream` if `src` does not contain a complete frame
+/// - `error.BadContentSize` if the content size declared by the frame does
+/// not equal the actual size of decompressed data
/// - `error.OutOfMemory` if `allocator` cannot allocate enough memory
/// - an error in `block.Error` if there are errors decoding a block
/// - `error.SkippableSizeTooLarge` if the frame is skippable and reports a
@@ -173,12 +236,18 @@ pub fn decodeFrameArrayList(
src: []const u8,
verify_checksum: bool,
window_size_max: usize,
-) !usize {
+) (error{ BadMagic, OutOfMemory, SkippableSizeTooLarge } || FrameContext.Error || FrameError)!usize {
var fbs = std.io.fixedBufferStream(src);
const reader = fbs.reader();
const magic = try reader.readIntLittle(u32);
switch (try frameType(magic)) {
- .zstandard => return decodeZstandardFrameArrayList(allocator, dest, src, verify_checksum, window_size_max),
+ .zstandard => return decodeZstandardFrameArrayList(
+ allocator,
+ dest,
+ src,
+ verify_checksum,
+ window_size_max,
+ ),
.skippable => {
const content_size = try fbs.reader().readIntLittle(u32);
if (content_size > std.math.maxInt(usize) - 8) return error.SkippableSizeTooLarge;
@@ -211,7 +280,10 @@ const FrameError = error{
/// uncompressed content size
/// - `error.ContentTooLarge` if `dest` is smaller than the uncompressed data
/// size declared by the frame header
+/// - `error.WindowSizeUnknown` if the frame does not have a valid window size
/// - `error.DictionaryIdFlagUnsupported` if the frame uses a dictionary
+/// - `error.ContentSizeTooLarge` if the frame header indicates a content size
+/// that is larger than `std.math.maxInt(usize)`
/// - `error.ChecksumFailure` if `verify_checksum` is true and the frame
/// contains a checksum that does not match the checksum of the decompressed
/// data
@@ -239,7 +311,11 @@ pub fn decodeZstandardFrame(
var source = fbs.reader();
const frame_header = try decodeZstandardHeader(source);
consumed_count += fbs.pos;
- break :context FrameContext.init(frame_header, std.math.maxInt(usize), verify_checksum) catch |err| switch (err) {
+ break :context FrameContext.init(
+ frame_header,
+ std.math.maxInt(usize),
+ verify_checksum,
+ ) catch |err| switch (err) {
error.WindowTooLarge => unreachable,
inline else => |e| return e,
};
@@ -260,7 +336,8 @@ pub fn decodeZStandardFrameBlocks(
src: []const u8,
frame_context: *FrameContext,
) (error{ ContentTooLarge, UnknownContentSizeUnsupported } || FrameError)!ReadWriteCount {
- const content_size = frame_context.content_size orelse return error.UnknownContentSizeUnsupported;
+ const content_size = frame_context.content_size orelse
+ return error.UnknownContentSizeUnsupported;
if (dest.len < content_size) return error.ContentTooLarge;
var consumed_count: usize = 0;
@@ -304,14 +381,19 @@ pub const FrameContext = struct {
///
/// Errors returned:
/// - `error.DictionaryIdFlagUnsupported` if the frame uses a dictionary
- /// - `error.WindowSizeUnknown` if the frame does not have a valid window size
- /// - `error.WindowTooLarge` if the window size is larger than `window_size_max`
+ /// - `error.WindowSizeUnknown` if the frame does not have a valid window
+ /// size
+ /// - `error.WindowTooLarge` if the window size is larger than
+ /// `window_size_max`
+ /// - `error.ContentSizeTooLarge` if the frame header indicates a content
+ /// size larger than `std.math.maxInt(usize)`
pub fn init(
- frame_header: frame.Zstandard.Header,
+ frame_header: ZstandardHeader,
window_size_max: usize,
verify_checksum: bool,
) Error!FrameContext {
- if (frame_header.descriptor.dictionary_id_flag != 0) return error.DictionaryIdFlagUnsupported;
+ if (frame_header.descriptor.dictionary_id_flag != 0)
+ return error.DictionaryIdFlagUnsupported;
const window_size_raw = frameWindowSize(frame_header) orelse return error.WindowSizeUnknown;
const window_size = if (window_size_raw > window_size_max)
@@ -319,7 +401,8 @@ pub const FrameContext = struct {
else
@intCast(usize, window_size_raw);
- const should_compute_checksum = frame_header.descriptor.content_checksum_flag and verify_checksum;
+ const should_compute_checksum =
+ frame_header.descriptor.content_checksum_flag and verify_checksum;
const content_size = if (frame_header.content_size) |size|
std.math.cast(usize, size) orelse return error.ContentSizeTooLarge
@@ -345,6 +428,8 @@ pub const FrameContext = struct {
/// - `error.WindowTooLarge` if the window size is larger than
/// `window_size_max`
/// - `error.DictionaryIdFlagUnsupported` if the frame uses a dictionary
+/// - `error.ContentSizeTooLarge` if the frame header indicates a content size
+/// that is larger than `std.math.maxInt(usize)`
/// - `error.ChecksumFailure` if `verify_checksum` is true and the frame
/// contains a checksum that does not match the checksum of the decompressed
/// data
@@ -441,8 +526,6 @@ pub fn decodeZstandardFrameBlocksArrayList(
return consumed_count;
}
-/// Convenience wrapper for decoding all blocks in a frame; see
-/// `decodeZStandardFrameBlocks()`.
fn decodeFrameBlocksInner(
dest: []u8,
src: []const u8,
@@ -459,7 +542,7 @@ fn decodeFrameBlocksInner(
var bytes_read: usize = 3;
defer consumed_count.* += bytes_read;
var decode_state = block.DecodeState.init(&literal_fse_data, &match_fse_data, &offset_fse_data);
- var written_count: usize = 0;
+ var count: usize = 0;
while (true) : ({
block_header = try block.decodeBlockHeaderSlice(src[bytes_read..]);
bytes_read += 3;
@@ -471,18 +554,18 @@ fn decodeFrameBlocksInner(
&decode_state,
&bytes_read,
block_size_max,
- written_count,
+ count,
);
- if (hash) |hash_state| hash_state.update(dest[written_count .. written_count + written_size]);
- written_count += written_size;
+ if (hash) |hash_state| hash_state.update(dest[count .. count + written_size]);
+ count += written_size;
if (block_header.last_block) break;
}
- return written_count;
+ return count;
}
/// Decode the header of a skippable frame. The first four bytes of `src` must
-/// be a valid magic number for a Skippable frame.
-pub fn decodeSkippableHeader(src: *const [8]u8) frame.Skippable.Header {
+/// be a valid magic number for a skippable frame.
+pub fn decodeSkippableHeader(src: *const [8]u8) SkippableHeader {
const magic = readInt(u32, src[0..4]);
assert(isSkippableMagic(magic));
const frame_size = readInt(u32, src[4..8]);
@@ -494,7 +577,7 @@ pub fn decodeSkippableHeader(src: *const [8]u8) frame.Skippable.Header {
/// Returns the window size required to decompress a frame, or `null` if it
/// cannot be determined (which indicates a malformed frame header).
-pub fn frameWindowSize(header: frame.Zstandard.Header) ?u64 {
+pub fn frameWindowSize(header: ZstandardHeader) ?u64 {
if (header.window_descriptor) |descriptor| {
const exponent = (descriptor & 0b11111000) >> 3;
const mantissa = descriptor & 0b00000111;
@@ -508,10 +591,10 @@ pub fn frameWindowSize(header: frame.Zstandard.Header) ?u64 {
/// Decode the header of a Zstandard frame.
///
/// Errors returned:
-/// - `error.ReservedBitSet` if the reserved bits of the header are set
+/// - `error.ReservedBitSet` if any of the reserved bits of the header are set
/// - `error.EndOfStream` if `source` does not contain a complete header
-pub fn decodeZstandardHeader(source: anytype) error{ EndOfStream, ReservedBitSet }!frame.Zstandard.Header {
- const descriptor = @bitCast(frame.Zstandard.Header.Descriptor, try source.readByte());
+pub fn decodeZstandardHeader(source: anytype) error{ EndOfStream, ReservedBitSet }!ZstandardHeader {
+ const descriptor = @bitCast(ZstandardHeader.Descriptor, try source.readByte());
if (descriptor.reserved) return error.ReservedBitSet;
@@ -534,7 +617,7 @@ pub fn decodeZstandardHeader(source: anytype) error{ EndOfStream, ReservedBitSet
if (field_size == 2) content_size.? += 256;
}
- const header = frame.Zstandard.Header{
+ const header = ZstandardHeader{
.descriptor = descriptor,
.window_descriptor = window_descriptor,
.dictionary_id = dictionary_id,
lib/std/compress/zstandard/RingBuffer.zig
@@ -13,6 +13,8 @@ data: []u8,
read_index: usize,
write_index: usize,
+pub const Error = error{Full};
+
/// Allocate a new `RingBuffer`
pub fn init(allocator: Allocator, capacity: usize) Allocator.Error!RingBuffer {
const bytes = try allocator.alloc(u8, capacity);
@@ -41,7 +43,7 @@ pub fn mask2(self: RingBuffer, index: usize) usize {
/// Write `byte` into the ring buffer. Returns `error.Full` if the ring
/// buffer is full.
-pub fn write(self: *RingBuffer, byte: u8) !void {
+pub fn write(self: *RingBuffer, byte: u8) Error!void {
if (self.isFull()) return error.Full;
self.writeAssumeCapacity(byte);
}
@@ -55,7 +57,7 @@ pub fn writeAssumeCapacity(self: *RingBuffer, byte: u8) void {
/// Write `bytes` into the ring bufffer. Returns `error.Full` if the ring
/// buffer does not have enough space, without writing any data.
-pub fn writeSlice(self: *RingBuffer, bytes: []const u8) !void {
+pub fn writeSlice(self: *RingBuffer, bytes: []const u8) Error!void {
if (self.len() + bytes.len > self.data.len) return error.Full;
self.writeSliceAssumeCapacity(bytes);
}
@@ -87,7 +89,8 @@ pub fn isFull(self: RingBuffer) bool {
/// Returns the length
pub fn len(self: RingBuffer) usize {
- const adjusted_write_index = self.write_index + @as(usize, @boolToInt(self.write_index < self.read_index)) * 2 * self.data.len;
+ const wrap_offset = 2 * self.data.len * @boolToInt(self.write_index < self.read_index);
+ const adjusted_write_index = self.write_index + wrap_offset;
return adjusted_write_index - self.read_index;
}
lib/std/compress/zstandard/types.zig
@@ -92,13 +92,13 @@ pub const compressed_block = struct {
index: usize,
};
- pub fn query(self: HuffmanTree, index: usize, prefix: u16) error{PrefixNotFound}!Result {
+ pub fn query(self: HuffmanTree, index: usize, prefix: u16) error{NotFound}!Result {
var node = self.nodes[index];
const weight = node.weight;
var i: usize = index;
while (node.weight == weight) {
if (node.prefix == prefix) return Result{ .symbol = node.symbol };
- if (i == 0) return error.PrefixNotFound;
+ if (i == 0) return error.NotFound;
i -= 1;
node = self.nodes[i];
}
@@ -164,12 +164,14 @@ pub const compressed_block = struct {
};
pub const match_length_code_table = [53]struct { u32, u5 }{
- .{ 3, 0 }, .{ 4, 0 }, .{ 5, 0 }, .{ 6, 0 }, .{ 7, 0 }, .{ 8, 0 }, .{ 9, 0 }, .{ 10, 0 },
- .{ 11, 0 }, .{ 12, 0 }, .{ 13, 0 }, .{ 14, 0 }, .{ 15, 0 }, .{ 16, 0 }, .{ 17, 0 }, .{ 18, 0 },
- .{ 19, 0 }, .{ 20, 0 }, .{ 21, 0 }, .{ 22, 0 }, .{ 23, 0 }, .{ 24, 0 }, .{ 25, 0 }, .{ 26, 0 },
- .{ 27, 0 }, .{ 28, 0 }, .{ 29, 0 }, .{ 30, 0 }, .{ 31, 0 }, .{ 32, 0 }, .{ 33, 0 }, .{ 34, 0 },
- .{ 35, 1 }, .{ 37, 1 }, .{ 39, 1 }, .{ 41, 1 }, .{ 43, 2 }, .{ 47, 2 }, .{ 51, 3 }, .{ 59, 3 },
- .{ 67, 4 }, .{ 83, 4 }, .{ 99, 5 }, .{ 131, 7 }, .{ 259, 8 }, .{ 515, 9 }, .{ 1027, 10 }, .{ 2051, 11 },
+ .{ 3, 0 }, .{ 4, 0 }, .{ 5, 0 }, .{ 6, 0 }, .{ 7, 0 }, .{ 8, 0 },
+ .{ 9, 0 }, .{ 10, 0 }, .{ 11, 0 }, .{ 12, 0 }, .{ 13, 0 }, .{ 14, 0 },
+ .{ 15, 0 }, .{ 16, 0 }, .{ 17, 0 }, .{ 18, 0 }, .{ 19, 0 }, .{ 20, 0 },
+ .{ 21, 0 }, .{ 22, 0 }, .{ 23, 0 }, .{ 24, 0 }, .{ 25, 0 }, .{ 26, 0 },
+ .{ 27, 0 }, .{ 28, 0 }, .{ 29, 0 }, .{ 30, 0 }, .{ 31, 0 }, .{ 32, 0 },
+ .{ 33, 0 }, .{ 34, 0 }, .{ 35, 1 }, .{ 37, 1 }, .{ 39, 1 }, .{ 41, 1 },
+ .{ 43, 2 }, .{ 47, 2 }, .{ 51, 3 }, .{ 59, 3 }, .{ 67, 4 }, .{ 83, 4 },
+ .{ 99, 5 }, .{ 131, 7 }, .{ 259, 8 }, .{ 515, 9 }, .{ 1027, 10 }, .{ 2051, 11 },
.{ 4099, 12 }, .{ 8195, 13 }, .{ 16387, 14 }, .{ 32771, 15 }, .{ 65539, 16 },
};
lib/std/compress/zstandard.zig
@@ -7,7 +7,11 @@ const RingBuffer = @import("zstandard/RingBuffer.zig");
pub const decompress = @import("zstandard/decompress.zig");
pub usingnamespace @import("zstandard/types.zig");
-pub fn ZstandardStream(comptime ReaderType: type, comptime verify_checksum: bool, comptime window_size_max: usize) type {
+pub fn ZstandardStream(
+ comptime ReaderType: type,
+ comptime verify_checksum: bool,
+ comptime window_size_max: usize,
+) type {
return struct {
const Self = @This();
@@ -24,11 +28,16 @@ pub fn ZstandardStream(comptime ReaderType: type, comptime verify_checksum: bool
sequence_buffer: []u8,
checksum: if (verify_checksum) ?u32 else void,
- pub const Error = ReaderType.Error || error{ ChecksumFailure, MalformedBlock, MalformedFrame, OutOfMemory };
+ pub const Error = ReaderType.Error || error{
+ ChecksumFailure,
+ MalformedBlock,
+ MalformedFrame,
+ OutOfMemory,
+ };
pub const Reader = std.io.Reader(*Self, Error, read);
- pub fn init(allocator: Allocator, source: ReaderType) !Self {
+ pub fn init(allocator: Allocator, source: ReaderType) Self {
return Self{
.allocator = allocator,
.source = std.io.countingReader(source),
@@ -146,7 +155,8 @@ pub fn ZstandardStream(comptime ReaderType: type, comptime verify_checksum: bool
const source_reader = self.source.reader();
while (self.buffer.isEmpty() and self.state != .LastBlock) {
- const header_bytes = source_reader.readBytesNoEof(3) catch return error.MalformedFrame;
+ const header_bytes = source_reader.readBytesNoEof(3) catch
+ return error.MalformedFrame;
const block_header = decompress.block.decodeBlockHeader(&header_bytes);
decompress.block.decodeBlockReader(
@@ -171,10 +181,12 @@ pub fn ZstandardStream(comptime ReaderType: type, comptime verify_checksum: bool
if (block_header.last_block) {
self.state = .LastBlock;
if (self.frame_context.has_checksum) {
- const checksum = source_reader.readIntLittle(u32) catch return error.MalformedFrame;
+ const checksum = source_reader.readIntLittle(u32) catch
+ return error.MalformedFrame;
if (comptime verify_checksum) {
if (self.frame_context.hasher_opt) |*hasher| {
- if (checksum != decompress.computeChecksum(hasher)) return error.ChecksumFailure;
+ if (checksum != decompress.computeChecksum(hasher))
+ return error.ChecksumFailure;
}
}
}
@@ -182,9 +194,9 @@ pub fn ZstandardStream(comptime ReaderType: type, comptime verify_checksum: bool
}
const decoded_data_len = self.buffer.len();
- var written_count: usize = 0;
- while (written_count < decoded_data_len and written_count < buffer.len) : (written_count += 1) {
- buffer[written_count] = self.buffer.read().?;
+ var count: usize = 0;
+ while (count < decoded_data_len and count < buffer.len) : (count += 1) {
+ buffer[count] = self.buffer.read().?;
}
if (self.state == .LastBlock and self.buffer.len() == 0) {
self.state = .NewFrame;
@@ -195,18 +207,22 @@ pub fn ZstandardStream(comptime ReaderType: type, comptime verify_checksum: bool
self.allocator.free(self.sequence_buffer);
self.buffer.deinit(self.allocator);
}
- return written_count;
+ return count;
}
};
}
-pub fn zstandardStream(allocator: Allocator, reader: anytype) !ZstandardStream(@TypeOf(reader), true, 8 * (1 << 20)) {
+pub fn zstandardStream(
+ allocator: Allocator,
+ reader: anytype,
+ comptime window_size_max: usize,
+) ZstandardStream(@TypeOf(reader), true, window_size_max) {
return ZstandardStream(@TypeOf(reader), true, 8 * (1 << 20)).init(allocator, reader);
}
fn testDecompress(data: []const u8) ![]u8 {
var in_stream = std.io.fixedBufferStream(data);
- var stream = try zstandardStream(std.testing.allocator, in_stream.reader());
+ var stream = zstandardStream(std.testing.allocator, in_stream.reader(), 1 << 23);
defer stream.deinit();
const result = stream.reader().readAllAlloc(std.testing.allocator, std.math.maxInt(usize));
return result;