From afe9f3a9ec10e1d92fa02ef91168301daac47c67 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 29 Jul 2025 23:28:41 -0700 Subject: [PATCH] std.compress.flate.Decompress: implement readVec and discard --- lib/std/compress/flate/Decompress.zig | 36 +++++++++++++++++++++------ 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/lib/std/compress/flate/Decompress.zig b/lib/std/compress/flate/Decompress.zig index ffbaf156f6..cd3a07fac6 100644 --- a/lib/std/compress/flate/Decompress.zig +++ b/lib/std/compress/flate/Decompress.zig @@ -56,11 +56,11 @@ pub const Error = Container.Error || error{ pub fn init(input: *Reader, container: Container, buffer: []u8) Decompress { return .{ .reader = .{ - // TODO populate discard so that when an amount is discarded that - // includes an entire frame, skip decoding that frame. .vtable = &.{ .stream = stream, .rebase = rebase, + .discard = discard, + .readVec = Reader.indirectReadVec, }, .buffer = buffer, .seek = 0, @@ -81,12 +81,32 @@ pub fn init(input: *Reader, container: Container, buffer: []u8) Decompress { fn rebase(r: *Reader, capacity: usize) Reader.RebaseError!void { assert(capacity <= r.buffer.len - flate.history_len); assert(r.end + capacity > r.buffer.len); - const buffered = r.buffer[0..r.end]; - const discard = buffered.len - flate.history_len; - const keep = buffered[discard..]; + const discard_n = r.end - flate.history_len; + const keep = r.buffer[discard_n..r.end]; @memmove(r.buffer[0..keep.len], keep); r.end = keep.len; - r.seek -= discard; + r.seek -= discard_n; +} + +/// This could be improved so that when an amount is discarded that includes an +/// entire frame, skip decoding that frame. +fn discard(r: *Reader, limit: std.Io.Limit) Reader.Error!usize { + r.rebase(flate.history_len) catch unreachable; + var writer: Writer = .{ + .vtable = &.{ + .drain = std.Io.Writer.Discarding.drain, + .sendFile = std.Io.Writer.Discarding.sendFile, + }, + .buffer = r.buffer, + .end = r.end, + }; + const n = r.stream(&writer, limit) catch |err| switch (err) { + error.WriteFailed => unreachable, + error.ReadFailed => return error.ReadFailed, + error.EndOfStream => return error.EndOfStream, + }; + assert(n <= @intFromEnum(limit)); + return n; } fn decodeLength(self: *Decompress, code: u8) !u16 { @@ -268,8 +288,8 @@ fn readInner(d: *Decompress, w: *Writer, limit: std.Io.Limit) (Error || Reader.S }, .stored_block => |remaining_len| { const out = try w.writableSliceGreedyPreserve(flate.history_len, 1); - const limited_out = limit.min(.limited(remaining_len)).slice(out); - const n = try d.input.readVec(&.{limited_out}); + var limited_out: [1][]u8 = .{limit.min(.limited(remaining_len)).slice(out)}; + const n = try d.input.readVec(&limited_out); if (remaining_len - n == 0) { d.state = if (d.final_block) .protocol_footer else .block_header; } else {