fix std.io.Writer.VectorWrapper mechanism

previous implementation erroneously attempted to detect whether vector
API was used via the buffer pointer. This implementation has an explicit
flag.
This commit is contained in:
Andrew Kelley 2025-07-06 18:20:11 -07:00
parent 9903587a63
commit a7387f0047
2 changed files with 14 additions and 4 deletions

View File

@ -328,17 +328,24 @@ pub fn readVecLimit(r: *Reader, data: []const []u8, limit: Limit) Error!usize {
};
var n = r.vtable.stream(r, &wrapper.writer, .limited(remaining)) catch |err| switch (err) {
error.WriteFailed => {
assert(!wrapper.used);
if (wrapper.writer.buffer.ptr == first.ptr) {
remaining -= wrapper.writer.end;
} else {
assert(wrapper.writer.end <= r.buffer.len);
r.end = wrapper.writer.end;
}
break;
},
else => |e| return e,
};
if (wrapper.writer.buffer.ptr != first.ptr) {
r.end = n;
if (!wrapper.used) {
if (wrapper.writer.buffer.ptr == first.ptr) {
remaining -= n;
} else {
assert(n <= r.buffer.len);
r.end = n;
}
break;
}
if (n < first.len) {
@ -355,6 +362,7 @@ pub fn readVecLimit(r: *Reader, data: []const []u8, limit: Limit) Error!usize {
remaining -= mid.len;
n -= mid.len;
}
assert(n <= r.buffer.len);
r.end = n;
break;
}
@ -596,12 +604,11 @@ pub fn readSliceShort(r: *Reader, buffer: []u8) ShortError!usize {
};
const n = r.vtable.stream(r, &wrapper.writer, .unlimited) catch |err| switch (err) {
error.WriteFailed => {
if (wrapper.writer.buffer.ptr != remaining.ptr) {
if (!wrapper.used) {
assert(r.seek == 0);
r.seek = remaining.len;
r.end = wrapper.writer.end;
@memcpy(remaining, r.buffer[0..remaining.len]);
return buffer.len;
}
return buffer.len;
},

View File

@ -390,12 +390,15 @@ pub const WritableVectorIterator = struct {
pub const VectorWrapper = struct {
writer: Writer,
it: WritableVectorIterator,
/// Tracks whether the "writable vector" API was used.
used: bool = false,
pub const vtable: VTable = .{ .drain = fixedDrain };
};
pub fn writableVectorIterator(w: *Writer) Error!WritableVectorIterator {
if (w.vtable == &VectorWrapper.vtable) {
const wrapper: *VectorWrapper = @fieldParentPtr("writer", w);
wrapper.used = true;
return wrapper.it;
}
return .{ .first = try writableSliceGreedy(w, 1) };