authorgravatar for goon.pri.low@gmail.comKendall Condon <goon.pri.low@gmail.com> 2025-08-18 18:37:14-04:00
committergravatar for goon.pri.low@gmail.comKendall Condon <goon.pri.low@gmail.com> 2025-09-04 16:38:50-04:00
log7687b916fdb99605820bbbd515644707cc918703
tree5ab132795d38192fb2e863dbd89f7d5a1d134697
parentd94e061ade545f3fbdd4ab1a18f860b05050ebf6

File.Writer.sendFile: properly update reader pos

seekBy affects the reader's physical position, not its logical position.

2 files changed, 48 insertions(+), 7 deletions(-)

lib/std/fs/File.zig+19-7
...@@ -1803,9 +1803,15 @@ pub const Writer = struct {...@@ -1803,9 +1803,15 @@ pub const Writer = struct {
1803 file_reader.size = file_reader.pos;1803 file_reader.size = file_reader.pos;
1804 return error.EndOfStream;1804 return error.EndOfStream;
1805 }1805 }
1806 const consumed = io_w.consume(@intCast(sbytes));1806 const n = io_w.consume(@intCast(sbytes));
1807 file_reader.seekTo(file_reader.pos + consumed) catch return error.ReadFailed;1807 if (n <= file_reader.interface.bufferedLen()) {
1808 return consumed;1808 file_reader.interface.toss(n);
1809 } else {
1810 const direct_n = n - file_reader.interface.bufferedLen();
1811 file_reader.interface.tossBuffered();
1812 file_reader.seekBy(@intCast(direct_n)) catch return error.ReadFailed;
1813 }
1814 return n;
1809 }1815 }
18101816
1811 if (native_os.isDarwin() and w.mode == .streaming) sf: {1817 if (native_os.isDarwin() and w.mode == .streaming) sf: {
...@@ -1864,9 +1870,15 @@ pub const Writer = struct {...@@ -1864,9 +1870,15 @@ pub const Writer = struct {
1864 file_reader.size = file_reader.pos;1870 file_reader.size = file_reader.pos;
1865 return error.EndOfStream;1871 return error.EndOfStream;
1866 }1872 }
1867 const consumed = io_w.consume(@bitCast(len));1873 const n = io_w.consume(@bitCast(len));
1868 file_reader.seekTo(file_reader.pos + consumed) catch return error.ReadFailed;1874 if (n <= file_reader.interface.bufferedLen()) {
1869 return consumed;1875 file_reader.interface.toss(n);
1876 } else {
1877 const direct_n = n - file_reader.interface.bufferedLen();
1878 file_reader.interface.tossBuffered();
1879 file_reader.seekBy(@intCast(direct_n)) catch return error.ReadFailed;
1880 }
1881 return n;
1870 }1882 }
18711883
1872 if (native_os == .linux and w.mode == .streaming) sf: {1884 if (native_os == .linux and w.mode == .streaming) sf: {
...@@ -1998,7 +2010,7 @@ pub const Writer = struct {...@@ -1998,7 +2010,7 @@ pub const Writer = struct {
1998 reader_buffered: []const u8,2010 reader_buffered: []const u8,
1999 ) std.Io.Writer.FileError!usize {2011 ) std.Io.Writer.FileError!usize {
2000 const n = try drain(io_w, &.{reader_buffered}, 1);2012 const n = try drain(io_w, &.{reader_buffered}, 1);
2001 file_reader.seekTo(file_reader.pos + n) catch return error.ReadFailed;2013 file_reader.interface.toss(n);
2002 return n;2014 return n;
2003 }2015 }
20042016
lib/std/fs/test.zig+29
...@@ -2180,3 +2180,32 @@ test "seekTo flushes buffered data" {...@@ -2180,3 +2180,32 @@ test "seekTo flushes buffered data" {
2180 try file_reader.interface.readSliceAll(&buf);2180 try file_reader.interface.readSliceAll(&buf);
2181 try std.testing.expectEqualStrings(contents, &buf);2181 try std.testing.expectEqualStrings(contents, &buf);
2182}2182}
2183
2184test "File.Writer sendfile with buffered contents" {
2185 var tmp_dir = testing.tmpDir(.{});
2186 defer tmp_dir.cleanup();
2187
2188 try tmp_dir.dir.writeFile(.{ .sub_path = "a", .data = "bcd" });
2189 const in = try tmp_dir.dir.openFile("a", .{});
2190 defer in.close();
2191 const out = try tmp_dir.dir.createFile("b", .{});
2192 defer out.close();
2193
2194 var in_buf: [2]u8 = undefined;
2195 var in_r = in.reader(&in_buf);
2196 _ = try in_r.getSize(); // Catch seeks past end by populating size
2197 try in_r.interface.fill(2);
2198
2199 var out_buf: [1]u8 = undefined;
2200 var out_w = out.writerStreaming(&out_buf);
2201 try out_w.interface.writeByte('a');
2202 try testing.expectEqual(3, try out_w.interface.sendFileAll(&in_r, .unlimited));
2203 try out_w.interface.flush();
2204
2205 var check = try tmp_dir.dir.openFile("b", .{});
2206 defer check.close();
2207 var check_buf: [4]u8 = undefined;
2208 var check_r = check.reader(&check_buf);
2209 try testing.expectEqualStrings("abcd", try check_r.interface.take(4));
2210 try testing.expectError(error.EndOfStream, check_r.interface.takeByte());
2211}