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