std.compress.zstd.Decompress: implement discard and readVec

This commit is contained in:
Andrew Kelley 2025-07-30 00:28:11 -07:00
parent 84e4343b0c
commit 4c04835a08
2 changed files with 32 additions and 22 deletions

View file

@ -438,23 +438,6 @@ pub fn defaultReadVec(r: *Reader, data: []const []u8) Error!usize {
return 0;
}
/// Always writes to `Reader.buffer` and returns 0.
pub fn indirectReadVec(r: *Reader, data: []const []u8) Error!usize {
_ = data;
assert(r.seek == r.end);
var writer: Writer = .{
.buffer = r.buffer,
.end = r.end,
.vtable = &.{ .drain = Writer.fixedDrain },
};
const limit: Limit = .limited(writer.buffer.len - writer.end);
r.end += r.vtable.stream(r, &writer, limit) catch |err| switch (err) {
error.WriteFailed => unreachable,
else => |e| return e,
};
return 0;
}
pub fn buffered(r: *Reader) []u8 {
return r.buffer[r.seek..r.end];
}

View file

@ -89,7 +89,7 @@ pub fn init(input: *Reader, buffer: []u8, options: Options) Decompress {
.stream = stream,
.rebase = rebase,
.discard = discard,
.readVec = Reader.indirectReadVec,
.readVec = readVec,
},
.buffer = buffer,
.seek = 0,
@ -109,10 +109,20 @@ fn rebase(r: *Reader, capacity: usize) Reader.RebaseError!void {
r.seek -= discard_n;
}
fn discard(r: *Reader, limit: Limit) Reader.Error!usize {
r.rebase(zstd.block_size_max) catch unreachable;
var d: Writer.Discarding = .init(r.buffer);
const n = r.stream(&d.writer, limit) catch |err| switch (err) {
/// This could be improved so that when an amount is discarded that includes an
/// entire frame, skip decoding that frame.
fn discard(r: *Reader, limit: std.Io.Limit) Reader.Error!usize {
const d: *Decompress = @alignCast(@fieldParentPtr("reader", r));
r.rebase(d.window_len) catch unreachable;
var writer: Writer = .{
.vtable = &.{
.drain = std.Io.Writer.Discarding.drain,
.sendFile = std.Io.Writer.Discarding.sendFile,
},
.buffer = r.buffer,
.end = r.end,
};
const n = r.stream(&writer, limit) catch |err| switch (err) {
error.WriteFailed => unreachable,
error.ReadFailed => return error.ReadFailed,
error.EndOfStream => return error.EndOfStream,
@ -121,6 +131,23 @@ fn discard(r: *Reader, limit: Limit) Reader.Error!usize {
return n;
}
fn readVec(r: *Reader, data: []const []u8) Reader.Error!usize {
_ = data;
const d: *Decompress = @alignCast(@fieldParentPtr("reader", r));
assert(r.seek == r.end);
r.rebase(d.window_len) catch unreachable;
var writer: Writer = .{
.buffer = r.buffer,
.end = r.end,
.vtable = &.{ .drain = Writer.fixedDrain },
};
r.end += r.vtable.stream(r, &writer, .limited(writer.buffer.len - writer.end)) catch |err| switch (err) {
error.WriteFailed => unreachable,
else => |e| return e,
};
return 0;
}
fn stream(r: *Reader, w: *Writer, limit: Limit) Reader.StreamError!usize {
const d: *Decompress = @alignCast(@fieldParentPtr("reader", r));
const in = d.input;