Skip to content

Commit 6eac56c

Browse files
committed
std.compress.flate.Decompress: allow users to swap out Writer
1 parent 2024abd commit 6eac56c

File tree

1 file changed

+26
-7
lines changed

1 file changed

+26
-7
lines changed

lib/std/compress/flate/Decompress.zig

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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

81-
fn rebase(r: *Reader, capacity: usize) Reader.RebaseError!void {
81+
fn rebaseFallible(r: *Reader, capacity: usize) Reader.RebaseError!void {
82+
const d: *Decompress = @alignCast(@fieldParentPtr("reader", r));
83+
rebase(d, capacity);
84+
}
85+
86+
fn 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

116124
fn 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+
130+
fn 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

189203
pub 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+
209+
fn 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

210-
fn readInner(d: *Decompress, w: *Writer, limit: std.Io.Limit) (Error || Reader.StreamError)!usize {
229+
fn 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) {

0 commit comments

Comments
 (0)