File.Writer.sendFile: properly update reader pos

seekBy affects the reader's physical position, not its logical
position.
This commit is contained in:
Kendall Condon 2025-08-18 18:37:14 -04:00
parent d94e061ade
commit 7687b916fd
2 changed files with 48 additions and 7 deletions

View file

@ -1803,9 +1803,15 @@ pub const Writer = struct {
file_reader.size = file_reader.pos;
return error.EndOfStream;
}
const consumed = io_w.consume(@intCast(sbytes));
file_reader.seekTo(file_reader.pos + consumed) catch return error.ReadFailed;
return consumed;
const n = io_w.consume(@intCast(sbytes));
if (n <= file_reader.interface.bufferedLen()) {
file_reader.interface.toss(n);
} else {
const direct_n = n - file_reader.interface.bufferedLen();
file_reader.interface.tossBuffered();
file_reader.seekBy(@intCast(direct_n)) catch return error.ReadFailed;
}
return n;
}
if (native_os.isDarwin() and w.mode == .streaming) sf: {
@ -1864,9 +1870,15 @@ pub const Writer = struct {
file_reader.size = file_reader.pos;
return error.EndOfStream;
}
const consumed = io_w.consume(@bitCast(len));
file_reader.seekTo(file_reader.pos + consumed) catch return error.ReadFailed;
return consumed;
const n = io_w.consume(@bitCast(len));
if (n <= file_reader.interface.bufferedLen()) {
file_reader.interface.toss(n);
} else {
const direct_n = n - file_reader.interface.bufferedLen();
file_reader.interface.tossBuffered();
file_reader.seekBy(@intCast(direct_n)) catch return error.ReadFailed;
}
return n;
}
if (native_os == .linux and w.mode == .streaming) sf: {
@ -1998,7 +2010,7 @@ pub const Writer = struct {
reader_buffered: []const u8,
) std.Io.Writer.FileError!usize {
const n = try drain(io_w, &.{reader_buffered}, 1);
file_reader.seekTo(file_reader.pos + n) catch return error.ReadFailed;
file_reader.interface.toss(n);
return n;
}

View file

@ -2180,3 +2180,32 @@ test "seekTo flushes buffered data" {
try file_reader.interface.readSliceAll(&buf);
try std.testing.expectEqualStrings(contents, &buf);
}
test "File.Writer sendfile with buffered contents" {
var tmp_dir = testing.tmpDir(.{});
defer tmp_dir.cleanup();
try tmp_dir.dir.writeFile(.{ .sub_path = "a", .data = "bcd" });
const in = try tmp_dir.dir.openFile("a", .{});
defer in.close();
const out = try tmp_dir.dir.createFile("b", .{});
defer out.close();
var in_buf: [2]u8 = undefined;
var in_r = in.reader(&in_buf);
_ = try in_r.getSize(); // Catch seeks past end by populating size
try in_r.interface.fill(2);
var out_buf: [1]u8 = undefined;
var out_w = out.writerStreaming(&out_buf);
try out_w.interface.writeByte('a');
try testing.expectEqual(3, try out_w.interface.sendFileAll(&in_r, .unlimited));
try out_w.interface.flush();
var check = try tmp_dir.dir.openFile("b", .{});
defer check.close();
var check_buf: [4]u8 = undefined;
var check_r = check.reader(&check_buf);
try testing.expectEqualStrings("abcd", try check_r.interface.take(4));
try testing.expectError(error.EndOfStream, check_r.interface.takeByte());
}