Commit b35c55e237
lib/std/fs/File.zig
@@ -1135,7 +1135,7 @@ pub const Reader = struct {
err: ?ReadError = null,
mode: Reader.Mode = .positional,
/// Tracks the true seek position in the file. To obtain the logical
- /// position, subtract the buffer size from this value.
+ /// position, use `logicalPos`.
pos: u64 = 0,
size: ?u64 = null,
size_err: ?GetEndPosError = null,
@@ -1274,14 +1274,20 @@ pub const Reader = struct {
}
}
+ pub fn logicalPos(r: *const Reader) u64 {
+ return r.pos - r.interface.bufferedLen();
+ }
+
fn setPosAdjustingBuffer(r: *Reader, offset: u64) void {
- if (offset < r.pos or offset >= r.pos + r.interface.bufferedLen()) {
+ const logical_pos = logicalPos(r);
+ if (offset < logical_pos or offset >= r.pos) {
r.interface.seek = 0;
r.interface.end = 0;
+ r.pos = offset;
} else {
- r.interface.seek += @intCast(offset - r.pos);
+ const logical_delta: usize = @intCast(offset - logical_pos);
+ r.interface.seek += logical_delta;
}
- r.pos = offset;
}
/// Number of slices to store on the stack, when trying to send as many byte
lib/std/fs/test.zig
@@ -2060,7 +2060,7 @@ test "invalid UTF-8/WTF-8 paths" {
}
test "read file non vectored" {
- var tmp_dir = std.testing.tmpDir(.{});
+ var tmp_dir = testing.tmpDir(.{});
defer tmp_dir.cleanup();
const contents = "hello, world!\n";
@@ -2085,6 +2085,47 @@ test "read file non vectored" {
else => |e| return e,
};
}
- try std.testing.expectEqualStrings(contents, w.buffered());
- try std.testing.expectEqual(contents.len, i);
+ try testing.expectEqualStrings(contents, w.buffered());
+ try testing.expectEqual(contents.len, i);
+}
+
+test "seek keeping partial buffer" {
+ var tmp_dir = testing.tmpDir(.{});
+ defer tmp_dir.cleanup();
+
+ const contents = "0123456789";
+
+ const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true });
+ defer file.close();
+ {
+ var file_writer: std.fs.File.Writer = .init(file, &.{});
+ try file_writer.interface.writeAll(contents);
+ try file_writer.interface.flush();
+ }
+
+ var read_buffer: [3]u8 = undefined;
+ var file_reader: std.fs.File.Reader = .init(file, &read_buffer);
+
+ try testing.expectEqual(0, file_reader.logicalPos());
+
+ var buf: [4]u8 = undefined;
+ try file_reader.interface.readSliceAll(&buf);
+
+ if (file_reader.interface.bufferedLen() != 3) {
+ // Pass the test if the OS doesn't give us vectored reads.
+ return;
+ }
+
+ try testing.expectEqual(4, file_reader.logicalPos());
+ try testing.expectEqual(7, file_reader.pos);
+ try file_reader.seekTo(6);
+ try testing.expectEqual(6, file_reader.logicalPos());
+ try testing.expectEqual(7, file_reader.pos);
+
+ try testing.expectEqualStrings("0123", &buf);
+
+ const n = try file_reader.interface.readSliceShort(&buf);
+ try testing.expectEqual(4, n);
+
+ try testing.expectEqualStrings("6789", &buf);
}