authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-29 23:28:41-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-31 22:10:11-07:00
logafe9f3a9ec10e1d92fa02ef91168301daac47c67
tree8ea7e7b64a3e09639049bf83591dffd2c54637ba
parent81af4f3efc2e40db757426b9c870157d10ebec5a

std.compress.flate.Decompress: implement readVec and discard


1 files changed, 28 insertions(+), 8 deletions(-)

lib/std/compress/flate/Decompress.zig+28-8
......@@ -56,11 +56,11 @@ pub const Error = Container.Error || error{
5656pub fn init(input: *Reader, container: Container, buffer: []u8) Decompress {
5757 return .{
5858 .reader = .{
59 // TODO populate discard so that when an amount is discarded that
60 // includes an entire frame, skip decoding that frame.
6159 .vtable = &.{
6260 .stream = stream,
6361 .rebase = rebase,
62 .discard = discard,
63 .readVec = Reader.indirectReadVec,
6464 },
6565 .buffer = buffer,
6666 .seek = 0,
......@@ -81,12 +81,32 @@ pub fn init(input: *Reader, container: Container, buffer: []u8) Decompress {
8181fn rebase(r: *Reader, capacity: usize) Reader.RebaseError!void {
8282 assert(capacity <= r.buffer.len - flate.history_len);
8383 assert(r.end + capacity > r.buffer.len);
84 const buffered = r.buffer[0..r.end];
85 const discard = buffered.len - flate.history_len;
86 const keep = buffered[discard..];
84 const discard_n = r.end - flate.history_len;
85 const keep = r.buffer[discard_n..r.end];
8786 @memmove(r.buffer[0..keep.len], keep);
8887 r.end = keep.len;
89 r.seek -= discard;
88 r.seek -= discard_n;
89}
90
91/// This could be improved so that when an amount is discarded that includes an
92/// entire frame, skip decoding that frame.
93fn discard(r: *Reader, limit: std.Io.Limit) Reader.Error!usize {
94 r.rebase(flate.history_len) catch unreachable;
95 var writer: Writer = .{
96 .vtable = &.{
97 .drain = std.Io.Writer.Discarding.drain,
98 .sendFile = std.Io.Writer.Discarding.sendFile,
99 },
100 .buffer = r.buffer,
101 .end = r.end,
102 };
103 const n = r.stream(&writer, limit) catch |err| switch (err) {
104 error.WriteFailed => unreachable,
105 error.ReadFailed => return error.ReadFailed,
106 error.EndOfStream => return error.EndOfStream,
107 };
108 assert(n <= @intFromEnum(limit));
109 return n;
90110}
91111
92112fn decodeLength(self: *Decompress, code: u8) !u16 {
......@@ -268,8 +288,8 @@ fn readInner(d: *Decompress, w: *Writer, limit: std.Io.Limit) (Error || Reader.S
268288 },
269289 .stored_block => |remaining_len| {
270290 const out = try w.writableSliceGreedyPreserve(flate.history_len, 1);
271 const limited_out = limit.min(.limited(remaining_len)).slice(out);
272 const n = try d.input.readVec(&.{limited_out});
291 var limited_out: [1][]u8 = .{limit.min(.limited(remaining_len)).slice(out)};
292 const n = try d.input.readVec(&limited_out);
273293 if (remaining_len - n == 0) {
274294 d.state = if (d.final_block) .protocol_footer else .block_header;
275295 } else {