authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-31 17:31:54-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-31 22:10:11-07:00
log6eac56caf715bdc2dbd63b628ca48c0e32d5a70c
tree2fdf465c77963be579faef35461b9366fcddf8f6
parent2024abda6ae7c02c7fc1667d221e98da23ebcd2a

std.compress.flate.Decompress: allow users to swap out Writer


1 files changed, 26 insertions(+), 7 deletions(-)

lib/std/compress/flate/Decompress.zig+26-7
......@@ -58,7 +58,7 @@ pub fn init(input: *Reader, container: Container, buffer: []u8) Decompress {
5858 .reader = .{
5959 .vtable = &.{
6060 .stream = stream,
61 .rebase = rebase,
61 .rebase = rebaseFallible,
6262 .discard = discard,
6363 .readVec = readVec,
6464 },
......@@ -78,12 +78,19 @@ pub fn init(input: *Reader, container: Container, buffer: []u8) Decompress {
7878 };
7979}
8080
81fn rebase(r: *Reader, capacity: usize) Reader.RebaseError!void {
81fn rebaseFallible(r: *Reader, capacity: usize) Reader.RebaseError!void {
82 const d: *Decompress = @alignCast(@fieldParentPtr("reader", r));
83 rebase(d, capacity);
84}
85
86fn rebase(d: *Decompress, capacity: usize) void {
87 const r = &d.reader;
8288 assert(capacity <= r.buffer.len - flate.history_len);
8389 assert(r.end + capacity > r.buffer.len);
8490 const discard_n = r.end - flate.history_len;
8591 const keep = r.buffer[discard_n..r.end];
8692 @memmove(r.buffer[0..keep.len], keep);
93 assert(keep.len != 0);
8794 r.end = keep.len;
8895 r.seek -= discard_n;
8996}
......@@ -101,6 +108,7 @@ fn discard(r: *Reader, limit: std.Io.Limit) Reader.Error!usize {
101108 .end = r.end,
102109 };
103110 defer {
111 assert(writer.end != 0);
104112 r.end = writer.end;
105113 r.seek = r.end;
106114 }
......@@ -115,14 +123,20 @@ fn discard(r: *Reader, limit: std.Io.Limit) Reader.Error!usize {
115123
116124fn readVec(r: *Reader, data: [][]u8) Reader.Error!usize {
117125 _ = data;
118 assert(r.seek == r.end);
119 r.rebase(flate.history_len) catch unreachable;
126 const d: *Decompress = @alignCast(@fieldParentPtr("reader", r));
127 return streamIndirect(d);
128}
129
130fn streamIndirect(d: *Decompress) Reader.Error!usize {
131 const r = &d.reader;
132 if (r.end + flate.history_len > r.buffer.len) rebase(d, flate.history_len);
120133 var writer: Writer = .{
121134 .buffer = r.buffer,
122135 .end = r.end,
123136 .vtable = &.{ .drain = Writer.fixedDrain },
124137 };
125 r.end += r.vtable.stream(r, &writer, .limited(writer.buffer.len - writer.end)) catch |err| switch (err) {
138 defer r.end = writer.end;
139 _ = streamFallible(d, &writer, .limited(writer.buffer.len - writer.end)) catch |err| switch (err) {
126140 error.WriteFailed => unreachable,
127141 else => |e| return e,
128142 };
......@@ -188,7 +202,12 @@ fn decodeSymbol(self: *Decompress, decoder: anytype) !Symbol {
188202
189203pub fn stream(r: *Reader, w: *Writer, limit: std.Io.Limit) Reader.StreamError!usize {
190204 const d: *Decompress = @alignCast(@fieldParentPtr("reader", r));
191 return readInner(d, w, limit) catch |err| switch (err) {
205 if (w.end >= r.end) return streamFallible(d, w, limit);
206 return streamIndirect(d);
207}
208
209fn streamFallible(d: *Decompress, w: *Writer, limit: std.Io.Limit) Reader.StreamError!usize {
210 return streamInner(d, w, limit) catch |err| switch (err) {
192211 error.EndOfStream => {
193212 if (d.state == .end) {
194213 return error.EndOfStream;
......@@ -207,7 +226,7 @@ pub fn stream(r: *Reader, w: *Writer, limit: std.Io.Limit) Reader.StreamError!us
207226 };
208227}
209228
210fn readInner(d: *Decompress, w: *Writer, limit: std.Io.Limit) (Error || Reader.StreamError)!usize {
229fn streamInner(d: *Decompress, w: *Writer, limit: std.Io.Limit) (Error || Reader.StreamError)!usize {
211230 var remaining = @intFromEnum(limit);
212231 const in = d.input;
213232 sw: switch (d.state) {