| ... | ... | @@ -8,10 +8,14 @@ pub const compressed_block = types.compressed_block; |
| 8 | 8 | |
| 9 | 9 | pub const decompress = @import("zstandard/decompress.zig"); |
| 10 | 10 | |
| 11 | pub const DecompressStreamOptions = struct { |
| 12 | verify_checksum: bool = true, |
| 13 | window_size_max: usize = 1 << 23, // 8MiB default maximum window size, |
| 14 | }; |
| 15 | |
| 11 | 16 | pub fn DecompressStream( |
| 12 | 17 | comptime ReaderType: type, |
| 13 | | comptime verify_checksum: bool, |
| 14 | | comptime window_size_max: usize, |
| 18 | comptime options: DecompressStreamOptions, |
| 15 | 19 | ) type { |
| 16 | 20 | return struct { |
| 17 | 21 | const Self = @This(); |
| ... | ... | @@ -27,7 +31,7 @@ pub fn DecompressStream( |
| 27 | 31 | offset_fse_buffer: []types.compressed_block.Table.Fse, |
| 28 | 32 | literals_buffer: []u8, |
| 29 | 33 | sequence_buffer: []u8, |
| 30 | | checksum: if (verify_checksum) ?u32 else void, |
| 34 | checksum: if (options.verify_checksum) ?u32 else void, |
| 31 | 35 | current_frame_decompressed_size: usize, |
| 32 | 36 | |
| 33 | 37 | pub const Error = ReaderType.Error || error{ |
| ... | ... | @@ -69,8 +73,8 @@ pub fn DecompressStream( |
| 69 | 73 | const frame_context = context: { |
| 70 | 74 | break :context try decompress.FrameContext.init( |
| 71 | 75 | header, |
| 72 | | window_size_max, |
| 73 | | verify_checksum, |
| 76 | options.window_size_max, |
| 77 | options.verify_checksum, |
| 74 | 78 | ); |
| 75 | 79 | }; |
| 76 | 80 | |
| ... | ... | @@ -99,10 +103,10 @@ pub fn DecompressStream( |
| 99 | 103 | ); |
| 100 | 104 | const buffer = try RingBuffer.init(self.allocator, frame_context.window_size); |
| 101 | 105 | |
| 102 | | const literals_data = try self.allocator.alloc(u8, window_size_max); |
| 106 | const literals_data = try self.allocator.alloc(u8, options.window_size_max); |
| 103 | 107 | errdefer self.allocator.free(literals_data); |
| 104 | 108 | |
| 105 | | const sequence_data = try self.allocator.alloc(u8, window_size_max); |
| 109 | const sequence_data = try self.allocator.alloc(u8, options.window_size_max); |
| 106 | 110 | errdefer self.allocator.free(sequence_data); |
| 107 | 111 | |
| 108 | 112 | self.literal_fse_buffer = literal_fse_buffer; |
| ... | ... | @@ -116,7 +120,7 @@ pub fn DecompressStream( |
| 116 | 120 | self.decode_state = decode_state; |
| 117 | 121 | self.frame_context = frame_context; |
| 118 | 122 | |
| 119 | | self.checksum = if (verify_checksum) null else {}; |
| 123 | self.checksum = if (options.verify_checksum) null else {}; |
| 120 | 124 | self.current_frame_decompressed_size = 0; |
| 121 | 125 | |
| 122 | 126 | self.state = .InFrame; |
| ... | ... | @@ -199,7 +203,7 @@ pub fn DecompressStream( |
| 199 | 203 | if (self.frame_context.has_checksum) { |
| 200 | 204 | const checksum = source_reader.readIntLittle(u32) catch |
| 201 | 205 | return error.MalformedFrame; |
| 202 | | if (comptime verify_checksum) { |
| 206 | if (comptime options.verify_checksum) { |
| 203 | 207 | if (self.frame_context.hasher_opt) |*hasher| { |
| 204 | 208 | if (checksum != decompress.computeChecksum(hasher)) |
| 205 | 209 | return error.ChecksumFailure; |
| ... | ... | @@ -232,17 +236,24 @@ pub fn DecompressStream( |
| 232 | 236 | }; |
| 233 | 237 | } |
| 234 | 238 | |
| 239 | pub fn decompressStreamOptions( |
| 240 | allocator: Allocator, |
| 241 | reader: anytype, |
| 242 | comptime options: DecompressStreamOptions, |
| 243 | ) DecompressStream(@TypeOf(reader, options)) { |
| 244 | return DecompressStream(@TypeOf(reader), options).init(allocator, reader); |
| 245 | } |
| 246 | |
| 235 | 247 | pub fn decompressStream( |
| 236 | 248 | allocator: Allocator, |
| 237 | 249 | reader: anytype, |
| 238 | | comptime window_size_max: usize, |
| 239 | | ) DecompressStream(@TypeOf(reader), true, window_size_max) { |
| 240 | | return DecompressStream(@TypeOf(reader), true, 8 * (1 << 20)).init(allocator, reader); |
| 250 | ) DecompressStream(@TypeOf(reader), .{}) { |
| 251 | return DecompressStream(@TypeOf(reader), .{}).init(allocator, reader); |
| 241 | 252 | } |
| 242 | 253 | |
| 243 | 254 | fn testDecompress(data: []const u8) ![]u8 { |
| 244 | 255 | var in_stream = std.io.fixedBufferStream(data); |
| 245 | | var zstd_stream = decompressStream(std.testing.allocator, in_stream.reader(), 1 << 23); |
| 256 | var zstd_stream = decompressStream(std.testing.allocator, in_stream.reader()); |
| 246 | 257 | defer zstd_stream.deinit(); |
| 247 | 258 | const result = zstd_stream.reader().readAllAlloc(std.testing.allocator, std.math.maxInt(usize)); |
| 248 | 259 | return result; |