mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
std.compress.flate.Decompress: allow users to swap out Writer
This commit is contained in:
parent
2024abda6a
commit
6eac56caf7
@ -58,7 +58,7 @@ pub fn init(input: *Reader, container: Container, buffer: []u8) Decompress {
|
|||||||
.reader = .{
|
.reader = .{
|
||||||
.vtable = &.{
|
.vtable = &.{
|
||||||
.stream = stream,
|
.stream = stream,
|
||||||
.rebase = rebase,
|
.rebase = rebaseFallible,
|
||||||
.discard = discard,
|
.discard = discard,
|
||||||
.readVec = readVec,
|
.readVec = readVec,
|
||||||
},
|
},
|
||||||
@ -78,12 +78,19 @@ pub fn init(input: *Reader, container: Container, buffer: []u8) Decompress {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rebase(r: *Reader, capacity: usize) Reader.RebaseError!void {
|
fn rebaseFallible(r: *Reader, capacity: usize) Reader.RebaseError!void {
|
||||||
|
const d: *Decompress = @alignCast(@fieldParentPtr("reader", r));
|
||||||
|
rebase(d, capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rebase(d: *Decompress, capacity: usize) void {
|
||||||
|
const r = &d.reader;
|
||||||
assert(capacity <= r.buffer.len - flate.history_len);
|
assert(capacity <= r.buffer.len - flate.history_len);
|
||||||
assert(r.end + capacity > r.buffer.len);
|
assert(r.end + capacity > r.buffer.len);
|
||||||
const discard_n = r.end - flate.history_len;
|
const discard_n = r.end - flate.history_len;
|
||||||
const keep = r.buffer[discard_n..r.end];
|
const keep = r.buffer[discard_n..r.end];
|
||||||
@memmove(r.buffer[0..keep.len], keep);
|
@memmove(r.buffer[0..keep.len], keep);
|
||||||
|
assert(keep.len != 0);
|
||||||
r.end = keep.len;
|
r.end = keep.len;
|
||||||
r.seek -= discard_n;
|
r.seek -= discard_n;
|
||||||
}
|
}
|
||||||
@ -101,6 +108,7 @@ fn discard(r: *Reader, limit: std.Io.Limit) Reader.Error!usize {
|
|||||||
.end = r.end,
|
.end = r.end,
|
||||||
};
|
};
|
||||||
defer {
|
defer {
|
||||||
|
assert(writer.end != 0);
|
||||||
r.end = writer.end;
|
r.end = writer.end;
|
||||||
r.seek = r.end;
|
r.seek = r.end;
|
||||||
}
|
}
|
||||||
@ -115,14 +123,20 @@ fn discard(r: *Reader, limit: std.Io.Limit) Reader.Error!usize {
|
|||||||
|
|
||||||
fn readVec(r: *Reader, data: [][]u8) Reader.Error!usize {
|
fn readVec(r: *Reader, data: [][]u8) Reader.Error!usize {
|
||||||
_ = data;
|
_ = data;
|
||||||
assert(r.seek == r.end);
|
const d: *Decompress = @alignCast(@fieldParentPtr("reader", r));
|
||||||
r.rebase(flate.history_len) catch unreachable;
|
return streamIndirect(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn streamIndirect(d: *Decompress) Reader.Error!usize {
|
||||||
|
const r = &d.reader;
|
||||||
|
if (r.end + flate.history_len > r.buffer.len) rebase(d, flate.history_len);
|
||||||
var writer: Writer = .{
|
var writer: Writer = .{
|
||||||
.buffer = r.buffer,
|
.buffer = r.buffer,
|
||||||
.end = r.end,
|
.end = r.end,
|
||||||
.vtable = &.{ .drain = Writer.fixedDrain },
|
.vtable = &.{ .drain = Writer.fixedDrain },
|
||||||
};
|
};
|
||||||
r.end += r.vtable.stream(r, &writer, .limited(writer.buffer.len - writer.end)) catch |err| switch (err) {
|
defer r.end = writer.end;
|
||||||
|
_ = streamFallible(d, &writer, .limited(writer.buffer.len - writer.end)) catch |err| switch (err) {
|
||||||
error.WriteFailed => unreachable,
|
error.WriteFailed => unreachable,
|
||||||
else => |e| return e,
|
else => |e| return e,
|
||||||
};
|
};
|
||||||
@ -188,7 +202,12 @@ fn decodeSymbol(self: *Decompress, decoder: anytype) !Symbol {
|
|||||||
|
|
||||||
pub fn stream(r: *Reader, w: *Writer, limit: std.Io.Limit) Reader.StreamError!usize {
|
pub fn stream(r: *Reader, w: *Writer, limit: std.Io.Limit) Reader.StreamError!usize {
|
||||||
const d: *Decompress = @alignCast(@fieldParentPtr("reader", r));
|
const d: *Decompress = @alignCast(@fieldParentPtr("reader", r));
|
||||||
return readInner(d, w, limit) catch |err| switch (err) {
|
if (w.end >= r.end) return streamFallible(d, w, limit);
|
||||||
|
return streamIndirect(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn streamFallible(d: *Decompress, w: *Writer, limit: std.Io.Limit) Reader.StreamError!usize {
|
||||||
|
return streamInner(d, w, limit) catch |err| switch (err) {
|
||||||
error.EndOfStream => {
|
error.EndOfStream => {
|
||||||
if (d.state == .end) {
|
if (d.state == .end) {
|
||||||
return error.EndOfStream;
|
return error.EndOfStream;
|
||||||
@ -207,7 +226,7 @@ pub fn stream(r: *Reader, w: *Writer, limit: std.Io.Limit) Reader.StreamError!us
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readInner(d: *Decompress, w: *Writer, limit: std.Io.Limit) (Error || Reader.StreamError)!usize {
|
fn streamInner(d: *Decompress, w: *Writer, limit: std.Io.Limit) (Error || Reader.StreamError)!usize {
|
||||||
var remaining = @intFromEnum(limit);
|
var remaining = @intFromEnum(limit);
|
||||||
const in = d.input;
|
const in = d.input;
|
||||||
sw: switch (d.state) {
|
sw: switch (d.state) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user