| ... | @@ -70,13 +70,11 @@ pub fn DecompressStream( | ... | @@ -70,13 +70,11 @@ pub fn DecompressStream( |
| 70 | self.state = .NewFrame; | 70 | self.state = .NewFrame; |
| 71 | }, | 71 | }, |
| 72 | .zstandard => |header| { | 72 | .zstandard => |header| { |
| 73 | const frame_context = context: { | 73 | const frame_context = try decompress.FrameContext.init( |
| 74 | break :context try decompress.FrameContext.init( | 74 | header, |
| 75 | header, | 75 | options.window_size_max, |
| 76 | options.window_size_max, | 76 | options.verify_checksum, |
| 77 | options.verify_checksum, | 77 | ); |
| 78 | ); | | |
| 79 | }; | | |
| 80 | | 78 | |
| 81 | const literal_fse_buffer = try self.allocator.alloc( | 79 | const literal_fse_buffer = try self.allocator.alloc( |
| 82 | types.compressed_block.Table.Fse, | 80 | types.compressed_block.Table.Fse, |
| ... | @@ -219,7 +217,9 @@ pub fn DecompressStream( | ... | @@ -219,7 +217,9 @@ pub fn DecompressStream( |
| 219 | } | 217 | } |
| 220 | | 218 | |
| 221 | const size = @min(self.buffer.len(), buffer.len); | 219 | const size = @min(self.buffer.len(), buffer.len); |
| 222 | self.buffer.readFirstAssumeLength(buffer, size); | 220 | if (size > 0) { |
| | 221 | self.buffer.readFirstAssumeLength(buffer, size); |
| | 222 | } |
| 223 | if (self.state == .LastBlock and self.buffer.len() == 0) { | 223 | if (self.state == .LastBlock and self.buffer.len() == 0) { |
| 224 | self.state = .NewFrame; | 224 | self.state = .NewFrame; |
| 225 | self.allocator.free(self.literal_fse_buffer); | 225 | self.allocator.free(self.literal_fse_buffer); |
| ... | @@ -282,3 +282,48 @@ test "zstandard decompression" { | ... | @@ -282,3 +282,48 @@ test "zstandard decompression" { |
| 282 | try testReader(compressed3, uncompressed); | 282 | try testReader(compressed3, uncompressed); |
| 283 | try testReader(compressed19, uncompressed); | 283 | try testReader(compressed19, uncompressed); |
| 284 | } | 284 | } |
| | 285 | |
| | 286 | fn expectEqualDecoded(expected: []const u8, input: []const u8) !void { |
| | 287 | const allocator = std.testing.allocator; |
| | 288 | |
| | 289 | { |
| | 290 | const result = try decompress.decodeAlloc(allocator, input, false, 1 << 23); |
| | 291 | defer allocator.free(result); |
| | 292 | try std.testing.expectEqualStrings(expected, result); |
| | 293 | } |
| | 294 | |
| | 295 | { |
| | 296 | var buffer = try allocator.alloc(u8, 2 * expected.len); |
| | 297 | defer allocator.free(buffer); |
| | 298 | |
| | 299 | const size = try decompress.decode(buffer, input, false); |
| | 300 | try std.testing.expectEqualStrings(expected, buffer[0..size]); |
| | 301 | } |
| | 302 | |
| | 303 | { |
| | 304 | var in_stream = std.io.fixedBufferStream(input); |
| | 305 | var stream = decompressStream(allocator, in_stream.reader()); |
| | 306 | defer stream.deinit(); |
| | 307 | |
| | 308 | const result = try stream.reader().readAllAlloc(allocator, std.math.maxInt(usize)); |
| | 309 | defer allocator.free(result); |
| | 310 | |
| | 311 | try std.testing.expectEqualStrings(expected, result); |
| | 312 | } |
| | 313 | } |
| | 314 | |
| | 315 | test "zero sized block" { |
| | 316 | const input_raw = |
| | 317 | "\x28\xb5\x2f\xfd" ++ // zstandard frame magic number |
| | 318 | "\x20\x00" ++ // frame header: only single_segment_flag set, frame_content_size zero |
| | 319 | "\x01\x00\x00"; // block header with: last_block set, block_type raw, block_size zero |
| | 320 | |
| | 321 | const input_rle = |
| | 322 | "\x28\xb5\x2f\xfd" ++ // zstandard frame magic number |
| | 323 | "\x20\x00" ++ // frame header: only single_segment_flag set, frame_content_size zero |
| | 324 | "\x03\x00\x00" ++ // block header with: last_block set, block_type rle, block_size zero |
| | 325 | "\xaa"; // block_content |
| | 326 | |
| | 327 | try expectEqualDecoded("", input_raw); |
| | 328 | try expectEqualDecoded("", input_rle); |
| | 329 | } |