Skip to content

Commit 1d5637d

Browse files
committed
std.fs.File: fix streaming seekBy ignoring buffer
streaming seekBy completely ignored the buffer. the new logic checks if the seek offset is smaller than the buffer and adds the offset to r.interface.seek. otherwise the old logic is invoked.
1 parent 442e49f commit 1d5637d

File tree

2 files changed

+49
-13
lines changed

2 files changed

+49
-13
lines changed

lib/std/fs/File.zig

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,14 +1206,20 @@ pub const Reader = struct {
12061206
}
12071207
};
12081208
var remaining = std.math.cast(u64, offset) orelse return seek_err;
1209-
while (remaining > 0) {
1210-
remaining -= discard(&r.interface, .limited64(remaining)) catch |err| {
1211-
r.seek_err = err;
1212-
return err;
1213-
};
1209+
const bufferedLen = r.interface.bufferedLen();
1210+
if (remaining < bufferedLen) {
1211+
r.interface.seek += remaining;
1212+
} else {
1213+
remaining -= bufferedLen;
1214+
while (remaining > 0) {
1215+
remaining -= discard(&r.interface, .limited64(remaining)) catch |err| {
1216+
r.seek_err = err;
1217+
return err;
1218+
};
1219+
}
1220+
r.interface.seek = 0;
1221+
r.interface.end = 0;
12141222
}
1215-
r.interface.seek = 0;
1216-
r.interface.end = 0;
12171223
},
12181224
.failure => return r.seek_err.?,
12191225
}

lib/std/fs/test.zig

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2140,20 +2140,50 @@ test "seek keeping partial buffer" {
21402140
try testing.expectEqualStrings("6789", &buf);
21412141
}
21422142

2143-
test "seekBy streaming" {
2143+
test "seekBy streaming edge case" {
21442144
var tmp_dir = testing.tmpDir(.{});
21452145
defer tmp_dir.cleanup();
21462146

21472147
try tmp_dir.dir.writeFile(.{ .sub_path = "blah.txt", .data = "let's test seekBy" });
21482148
const f = try tmp_dir.dir.openFile("blah.txt", .{ .mode = .read_only });
21492149
defer f.close();
2150-
var reader = f.readerStreaming(&.{});
2151-
try reader.seekBy(2);
2150+
var read_buf: [10]u8 = undefined;
2151+
var reader = f.readerStreaming(&read_buf);
2152+
var buffer: [20]u8 = undefined;
2153+
const n1 = try reader.interface.readSliceShort(buffer[0..2]);
2154+
try testing.expectEqual(2, n1);
2155+
try testing.expectEqualStrings("le", buffer[0..2]);
2156+
// edge case seek: exactly up to buffer size
2157+
try reader.seekBy(10);
2158+
2159+
const n2 = try reader.interface.readSliceShort(&buffer);
2160+
try testing.expectEqual(5, n2);
2161+
try testing.expectEqualStrings("eekBy", buffer[0..5]);
2162+
}
2163+
2164+
test "seekBy streaming basic" {
2165+
var tmp_dir = testing.tmpDir(.{});
2166+
defer tmp_dir.cleanup();
21522167

2168+
try tmp_dir.dir.writeFile(.{ .sub_path = "blah.txt", .data = "let's test seekBy" });
2169+
const f = try tmp_dir.dir.openFile("blah.txt", .{ .mode = .read_only });
2170+
defer f.close();
2171+
var read_buf: [10]u8 = undefined;
2172+
var reader = f.readerStreaming(&read_buf);
21532173
var buffer: [20]u8 = undefined;
2154-
const n = try reader.interface.readSliceShort(&buffer);
2155-
try testing.expectEqual(15, n);
2156-
try testing.expectEqualStrings("t's test seekBy", buffer[0..15]);
2174+
const n1 = try reader.interface.readSliceShort(buffer[0..2]);
2175+
try testing.expectEqual(2, n1);
2176+
try testing.expectEqualStrings("le", buffer[0..2]);
2177+
// seek within bufferedLen
2178+
try reader.seekBy(2);
2179+
try reader.interface.readSliceAll(buffer[0..2]);
2180+
try testing.expectEqualStrings("s ", buffer[0..2]);
2181+
// seek past bufferedLen: causing discard
2182+
try reader.seekBy(10);
2183+
2184+
const n2 = try reader.interface.readSliceShort(&buffer);
2185+
try testing.expectEqual(1, n2);
2186+
try testing.expectEqualStrings("y", buffer[0..1]);
21572187
}
21582188

21592189
test "seekBy positional" {

0 commit comments

Comments
 (0)