| ... | @@ -73,7 +73,12 @@ const indirect_vtable: Reader.VTable = .{ | ... | @@ -73,7 +73,12 @@ const indirect_vtable: Reader.VTable = .{ |
| 73 | .readVec = readVec, | 73 | .readVec = readVec, |
| 74 | }; | 74 | }; |
| 75 | | 75 | |
| | 76 | /// `input` buffer is asserted to be at least 10 bytes, or EOF before then. |
| | 77 | /// |
| | 78 | /// If `buffer` is provided then asserted to have `flate.max_window_len` |
| | 79 | /// capacity, as well as `flate.history_len` unused capacity on every write. |
| 76 | pub fn init(input: *Reader, container: Container, buffer: []u8) Decompress { | 80 | pub fn init(input: *Reader, container: Container, buffer: []u8) Decompress { |
| | 81 | if (buffer.len != 0) assert(buffer.len >= flate.max_window_len); |
| 77 | return .{ | 82 | return .{ |
| 78 | .reader = .{ | 83 | .reader = .{ |
| 79 | .vtable = if (buffer.len == 0) &direct_vtable else &indirect_vtable, | 84 | .vtable = if (buffer.len == 0) &direct_vtable else &indirect_vtable, |
| ... | @@ -234,6 +239,8 @@ fn decodeSymbol(self: *Decompress, decoder: anytype) !Symbol { | ... | @@ -234,6 +239,8 @@ fn decodeSymbol(self: *Decompress, decoder: anytype) !Symbol { |
| 234 | } | 239 | } |
| 235 | | 240 | |
| 236 | fn streamDirect(r: *Reader, w: *Writer, limit: std.Io.Limit) Reader.StreamError!usize { | 241 | fn streamDirect(r: *Reader, w: *Writer, limit: std.Io.Limit) Reader.StreamError!usize { |
| | 242 | assert(w.buffer.len >= flate.max_window_len); |
| | 243 | assert(w.unusedCapacityLen() >= flate.history_len); |
| 237 | const d: *Decompress = @alignCast(@fieldParentPtr("reader", r)); | 244 | const d: *Decompress = @alignCast(@fieldParentPtr("reader", r)); |
| 238 | return streamFallible(d, w, limit); | 245 | return streamFallible(d, w, limit); |
| 239 | } | 246 | } |
| ... | @@ -1246,6 +1253,7 @@ test "zlib should not overshoot" { | ... | @@ -1246,6 +1253,7 @@ test "zlib should not overshoot" { |
| 1246 | fn testFailure(container: Container, in: []const u8, expected_err: anyerror) !void { | 1253 | fn testFailure(container: Container, in: []const u8, expected_err: anyerror) !void { |
| 1247 | var reader: Reader = .fixed(in); | 1254 | var reader: Reader = .fixed(in); |
| 1248 | var aw: Writer.Allocating = .init(testing.allocator); | 1255 | var aw: Writer.Allocating = .init(testing.allocator); |
| | 1256 | aw.minimum_unused_capacity = flate.history_len; |
| 1249 | try aw.ensureUnusedCapacity(flate.max_window_len); | 1257 | try aw.ensureUnusedCapacity(flate.max_window_len); |
| 1250 | defer aw.deinit(); | 1258 | defer aw.deinit(); |
| 1251 | | 1259 | |
| ... | @@ -1257,6 +1265,7 @@ fn testFailure(container: Container, in: []const u8, expected_err: anyerror) !vo | ... | @@ -1257,6 +1265,7 @@ fn testFailure(container: Container, in: []const u8, expected_err: anyerror) !vo |
| 1257 | fn testDecompress(container: Container, compressed: []const u8, expected_plain: []const u8) !void { | 1265 | fn testDecompress(container: Container, compressed: []const u8, expected_plain: []const u8) !void { |
| 1258 | var in: std.Io.Reader = .fixed(compressed); | 1266 | var in: std.Io.Reader = .fixed(compressed); |
| 1259 | var aw: std.Io.Writer.Allocating = .init(testing.allocator); | 1267 | var aw: std.Io.Writer.Allocating = .init(testing.allocator); |
| | 1268 | aw.minimum_unused_capacity = flate.history_len; |
| 1260 | try aw.ensureUnusedCapacity(flate.max_window_len); | 1269 | try aw.ensureUnusedCapacity(flate.max_window_len); |
| 1261 | defer aw.deinit(); | 1270 | defer aw.deinit(); |
| 1262 | | 1271 | |