| ... | ... | @@ -58,7 +58,7 @@ pub fn init(input: *Reader, container: Container, buffer: []u8) Decompress { |
| 58 | 58 | .reader = .{ |
| 59 | 59 | .vtable = &.{ |
| 60 | 60 | .stream = stream, |
| 61 | | .rebase = rebase, |
| 61 | .rebase = rebaseFallible, |
| 62 | 62 | .discard = discard, |
| 63 | 63 | .readVec = readVec, |
| 64 | 64 | }, |
| ... | ... | @@ -78,12 +78,19 @@ pub fn init(input: *Reader, container: Container, buffer: []u8) Decompress { |
| 78 | 78 | }; |
| 79 | 79 | } |
| 80 | 80 | |
| 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; |
| 82 | 88 | assert(capacity <= r.buffer.len - flate.history_len); |
| 83 | 89 | assert(r.end + capacity > r.buffer.len); |
| 84 | 90 | const discard_n = r.end - flate.history_len; |
| 85 | 91 | const keep = r.buffer[discard_n..r.end]; |
| 86 | 92 | @memmove(r.buffer[0..keep.len], keep); |
| 93 | assert(keep.len != 0); |
| 87 | 94 | r.end = keep.len; |
| 88 | 95 | r.seek -= discard_n; |
| 89 | 96 | } |
| ... | ... | @@ -101,6 +108,7 @@ fn discard(r: *Reader, limit: std.Io.Limit) Reader.Error!usize { |
| 101 | 108 | .end = r.end, |
| 102 | 109 | }; |
| 103 | 110 | defer { |
| 111 | assert(writer.end != 0); |
| 104 | 112 | r.end = writer.end; |
| 105 | 113 | r.seek = r.end; |
| 106 | 114 | } |
| ... | ... | @@ -115,14 +123,20 @@ fn discard(r: *Reader, limit: std.Io.Limit) Reader.Error!usize { |
| 115 | 123 | |
| 116 | 124 | fn readVec(r: *Reader, data: [][]u8) Reader.Error!usize { |
| 117 | 125 | _ = 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); |
| 120 | 133 | var writer: Writer = .{ |
| 121 | 134 | .buffer = r.buffer, |
| 122 | 135 | .end = r.end, |
| 123 | 136 | .vtable = &.{ .drain = Writer.fixedDrain }, |
| 124 | 137 | }; |
| 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) { |
| 126 | 140 | error.WriteFailed => unreachable, |
| 127 | 141 | else => |e| return e, |
| 128 | 142 | }; |
| ... | ... | @@ -188,7 +202,12 @@ fn decodeSymbol(self: *Decompress, decoder: anytype) !Symbol { |
| 188 | 202 | |
| 189 | 203 | pub fn stream(r: *Reader, w: *Writer, limit: std.Io.Limit) Reader.StreamError!usize { |
| 190 | 204 | 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) { |
| 192 | 211 | error.EndOfStream => { |
| 193 | 212 | if (d.state == .end) { |
| 194 | 213 | return error.EndOfStream; |
| ... | ... | @@ -207,7 +226,7 @@ pub fn stream(r: *Reader, w: *Writer, limit: std.Io.Limit) Reader.StreamError!us |
| 207 | 226 | }; |
| 208 | 227 | } |
| 209 | 228 | |
| 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 { |
| 211 | 230 | var remaining = @intFromEnum(limit); |
| 212 | 231 | const in = d.input; |
| 213 | 232 | sw: switch (d.state) { |