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