Commit 7687b916fd
lib/std/fs/File.zig
@@ -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;
}
lib/std/fs/test.zig
@@ -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());
+}