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{...@@ -56,11 +56,11 @@ pub const Error = Container.Error || error{
56pub fn init(input: *Reader, container: Container, buffer: []u8) Decompress {56pub fn init(input: *Reader, container: Container, buffer: []u8) Decompress {
57 return .{57 return .{
58 .reader = .{58 .reader = .{
59 // TODO populate discard so that when an amount is discarded that
60 // includes an entire frame, skip decoding that frame.
61 .vtable = &.{59 .vtable = &.{
62 .stream = stream,60 .stream = stream,
63 .rebase = rebase,61 .rebase = rebase,
62 .discard = discard,
63 .readVec = Reader.indirectReadVec,
64 },64 },
65 .buffer = buffer,65 .buffer = buffer,
66 .seek = 0,66 .seek = 0,
...@@ -81,12 +81,32 @@ pub fn init(input: *Reader, container: Container, buffer: []u8) Decompress {...@@ -81,12 +81,32 @@ pub fn init(input: *Reader, container: Container, buffer: []u8) Decompress {
81fn rebase(r: *Reader, capacity: usize) Reader.RebaseError!void {81fn rebase(r: *Reader, capacity: usize) Reader.RebaseError!void {
82 assert(capacity <= r.buffer.len - flate.history_len);82 assert(capacity <= r.buffer.len - flate.history_len);
83 assert(r.end + capacity > r.buffer.len);83 assert(r.end + capacity > r.buffer.len);
84 const buffered = r.buffer[0..r.end];84 const discard_n = r.end - flate.history_len;
85 const discard = buffered.len - flate.history_len;85 const keep = r.buffer[discard_n..r.end];
86 const keep = buffered[discard..];
87 @memmove(r.buffer[0..keep.len], keep);86 @memmove(r.buffer[0..keep.len], keep);
88 r.end = keep.len;87 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;
90}110}
91111
92fn decodeLength(self: *Decompress, code: u8) !u16 {112fn decodeLength(self: *Decompress, code: u8) !u16 {
...@@ -268,8 +288,8 @@ fn readInner(d: *Decompress, w: *Writer, limit: std.Io.Limit) (Error || Reader.S...@@ -268,8 +288,8 @@ fn readInner(d: *Decompress, w: *Writer, limit: std.Io.Limit) (Error || Reader.S
268 },288 },
269 .stored_block => |remaining_len| {289 .stored_block => |remaining_len| {
270 const out = try w.writableSliceGreedyPreserve(flate.history_len, 1);290 const out = try w.writableSliceGreedyPreserve(flate.history_len, 1);
271 const limited_out = limit.min(.limited(remaining_len)).slice(out);291 var limited_out: [1][]u8 = .{limit.min(.limited(remaining_len)).slice(out)};
272 const n = try d.input.readVec(&.{limited_out});292 const n = try d.input.readVec(&limited_out);
273 if (remaining_len - n == 0) {293 if (remaining_len - n == 0) {
274 d.state = if (d.final_block) .protocol_footer else .block_header;294 d.state = if (d.final_block) .protocol_footer else .block_header;
275 } else {295 } else {