aboutsummaryrefslogtreecommitdiff
path: root/lib/std/fs/File.zig
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std/fs/File.zig')
-rw-r--r--lib/std/fs/File.zig209
1 files changed, 105 insertions, 104 deletions
diff --git a/lib/std/fs/File.zig b/lib/std/fs/File.zig
index 99dda27885..169f3f5222 100644
--- a/lib/std/fs/File.zig
+++ b/lib/std/fs/File.zig
@@ -60,7 +60,7 @@ pub const OpenError = error{
/// WASI-only; file paths must be valid UTF-8.
InvalidUtf8,
/// Windows-only; file paths provided by the user must be valid WTF-8.
- /// https://simonsapin.github.io/wtf-8/
+ /// https://wtf-8.codeberg.page/
InvalidWtf8,
/// On Windows, file paths cannot contain these characters:
/// '/', '*', '?', '"', '<', '>', '|'
@@ -1189,7 +1189,7 @@ pub const Reader = struct {
pub fn seekBy(r: *Reader, offset: i64) Reader.SeekError!void {
switch (r.mode) {
.positional, .positional_reading => {
- setPosAdjustingBuffer(r, @intCast(@as(i64, @intCast(r.pos)) + offset));
+ setLogicalPos(r, @intCast(@as(i64, @intCast(logicalPos(r))) + offset));
},
.streaming, .streaming_reading => {
if (posix.SEEK == void) {
@@ -1198,7 +1198,7 @@ pub const Reader = struct {
}
const seek_err = r.seek_err orelse e: {
if (posix.lseek_CUR(r.file.handle, offset)) |_| {
- setPosAdjustingBuffer(r, @intCast(@as(i64, @intCast(r.pos)) + offset));
+ setLogicalPos(r, @intCast(@as(i64, @intCast(logicalPos(r))) + offset));
return;
} else |err| {
r.seek_err = err;
@@ -1222,16 +1222,17 @@ pub const Reader = struct {
pub fn seekTo(r: *Reader, offset: u64) Reader.SeekError!void {
switch (r.mode) {
.positional, .positional_reading => {
- setPosAdjustingBuffer(r, offset);
+ setLogicalPos(r, offset);
},
.streaming, .streaming_reading => {
- if (offset >= r.pos) return Reader.seekBy(r, @intCast(offset - r.pos));
+ const logical_pos = logicalPos(r);
+ if (offset >= logical_pos) return Reader.seekBy(r, @intCast(offset - logical_pos));
if (r.seek_err) |err| return err;
posix.lseek_SET(r.file.handle, offset) catch |err| {
r.seek_err = err;
return err;
};
- setPosAdjustingBuffer(r, offset);
+ setLogicalPos(r, offset);
},
.failure => return r.seek_err.?,
}
@@ -1241,7 +1242,7 @@ pub const Reader = struct {
return r.pos - r.interface.bufferedLen();
}
- fn setPosAdjustingBuffer(r: *Reader, offset: u64) void {
+ fn setLogicalPos(r: *Reader, offset: u64) void {
const logical_pos = logicalPos(r);
if (offset < logical_pos or offset >= r.pos) {
r.interface.seek = 0;
@@ -1269,13 +1270,15 @@ pub const Reader = struct {
},
.positional_reading => {
const dest = limit.slice(try w.writableSliceGreedy(1));
- const n = try readPositional(r, dest);
+ var data: [1][]u8 = .{dest};
+ const n = try readVecPositional(r, &data);
w.advance(n);
return n;
},
.streaming_reading => {
const dest = limit.slice(try w.writableSliceGreedy(1));
- const n = try readStreaming(r, dest);
+ var data: [1][]u8 = .{dest};
+ const n = try readVecStreaming(r, &data);
w.advance(n);
return n;
},
@@ -1286,92 +1289,98 @@ pub const Reader = struct {
fn readVec(io_reader: *std.Io.Reader, data: [][]u8) std.Io.Reader.Error!usize {
const r: *Reader = @alignCast(@fieldParentPtr("interface", io_reader));
switch (r.mode) {
- .positional, .positional_reading => {
- if (is_windows) {
- // Unfortunately, `ReadFileScatter` cannot be used since it
- // requires page alignment.
- if (io_reader.seek == io_reader.end) {
- io_reader.seek = 0;
- io_reader.end = 0;
- }
- const first = data[0];
- if (first.len >= io_reader.buffer.len - io_reader.end) {
- return readPositional(r, first);
- } else {
- io_reader.end += try readPositional(r, io_reader.buffer[io_reader.end..]);
- return 0;
- }
- }
- var iovecs_buffer: [max_buffers_len]posix.iovec = undefined;
- const dest_n, const data_size = try io_reader.writableVectorPosix(&iovecs_buffer, data);
- const dest = iovecs_buffer[0..dest_n];
- assert(dest[0].len > 0);
- const n = posix.preadv(r.file.handle, dest, r.pos) catch |err| switch (err) {
- error.Unseekable => {
- r.mode = r.mode.toStreaming();
- const pos = r.pos;
- if (pos != 0) {
- r.pos = 0;
- r.seekBy(@intCast(pos)) catch {
- r.mode = .failure;
- return error.ReadFailed;
- };
- }
- return 0;
- },
- else => |e| {
- r.err = e;
+ .positional, .positional_reading => return readVecPositional(r, data),
+ .streaming, .streaming_reading => return readVecStreaming(r, data),
+ .failure => return error.ReadFailed,
+ }
+ }
+
+ fn readVecPositional(r: *Reader, data: [][]u8) std.Io.Reader.Error!usize {
+ const io_reader = &r.interface;
+ if (is_windows) {
+ // Unfortunately, `ReadFileScatter` cannot be used since it
+ // requires page alignment.
+ if (io_reader.seek == io_reader.end) {
+ io_reader.seek = 0;
+ io_reader.end = 0;
+ }
+ const first = data[0];
+ if (first.len >= io_reader.buffer.len - io_reader.end) {
+ return readPositional(r, first);
+ } else {
+ io_reader.end += try readPositional(r, io_reader.buffer[io_reader.end..]);
+ return 0;
+ }
+ }
+ var iovecs_buffer: [max_buffers_len]posix.iovec = undefined;
+ const dest_n, const data_size = try io_reader.writableVectorPosix(&iovecs_buffer, data);
+ const dest = iovecs_buffer[0..dest_n];
+ assert(dest[0].len > 0);
+ const n = posix.preadv(r.file.handle, dest, r.pos) catch |err| switch (err) {
+ error.Unseekable => {
+ r.mode = r.mode.toStreaming();
+ const pos = r.pos;
+ if (pos != 0) {
+ r.pos = 0;
+ r.seekBy(@intCast(pos)) catch {
+ r.mode = .failure;
return error.ReadFailed;
- },
- };
- if (n == 0) {
- r.size = r.pos;
- return error.EndOfStream;
- }
- r.pos += n;
- if (n > data_size) {
- io_reader.end += n - data_size;
- return data_size;
+ };
}
- return n;
+ return 0;
},
- .streaming, .streaming_reading => {
- if (is_windows) {
- // Unfortunately, `ReadFileScatter` cannot be used since it
- // requires page alignment.
- if (io_reader.seek == io_reader.end) {
- io_reader.seek = 0;
- io_reader.end = 0;
- }
- const first = data[0];
- if (first.len >= io_reader.buffer.len - io_reader.end) {
- return readStreaming(r, first);
- } else {
- io_reader.end += try readStreaming(r, io_reader.buffer[io_reader.end..]);
- return 0;
- }
- }
- var iovecs_buffer: [max_buffers_len]posix.iovec = undefined;
- const dest_n, const data_size = try io_reader.writableVectorPosix(&iovecs_buffer, data);
- const dest = iovecs_buffer[0..dest_n];
- assert(dest[0].len > 0);
- const n = posix.readv(r.file.handle, dest) catch |err| {
- r.err = err;
- return error.ReadFailed;
- };
- if (n == 0) {
- r.size = r.pos;
- return error.EndOfStream;
- }
- r.pos += n;
- if (n > data_size) {
- io_reader.end += n - data_size;
- return data_size;
- }
- return n;
+ else => |e| {
+ r.err = e;
+ return error.ReadFailed;
},
- .failure => return error.ReadFailed,
+ };
+ if (n == 0) {
+ r.size = r.pos;
+ return error.EndOfStream;
+ }
+ r.pos += n;
+ if (n > data_size) {
+ io_reader.end += n - data_size;
+ return data_size;
}
+ return n;
+ }
+
+ fn readVecStreaming(r: *Reader, data: [][]u8) std.Io.Reader.Error!usize {
+ const io_reader = &r.interface;
+ if (is_windows) {
+ // Unfortunately, `ReadFileScatter` cannot be used since it
+ // requires page alignment.
+ if (io_reader.seek == io_reader.end) {
+ io_reader.seek = 0;
+ io_reader.end = 0;
+ }
+ const first = data[0];
+ if (first.len >= io_reader.buffer.len - io_reader.end) {
+ return readStreaming(r, first);
+ } else {
+ io_reader.end += try readStreaming(r, io_reader.buffer[io_reader.end..]);
+ return 0;
+ }
+ }
+ var iovecs_buffer: [max_buffers_len]posix.iovec = undefined;
+ const dest_n, const data_size = try io_reader.writableVectorPosix(&iovecs_buffer, data);
+ const dest = iovecs_buffer[0..dest_n];
+ assert(dest[0].len > 0);
+ const n = posix.readv(r.file.handle, dest) catch |err| {
+ r.err = err;
+ return error.ReadFailed;
+ };
+ if (n == 0) {
+ r.size = r.pos;
+ return error.EndOfStream;
+ }
+ r.pos += n;
+ if (n > data_size) {
+ io_reader.end += n - data_size;
+ return data_size;
+ }
+ return n;
}
fn discard(io_reader: *std.Io.Reader, limit: std.Io.Limit) std.Io.Reader.Error!usize {
@@ -1440,7 +1449,7 @@ pub const Reader = struct {
}
}
- pub fn readPositional(r: *Reader, dest: []u8) std.Io.Reader.Error!usize {
+ fn readPositional(r: *Reader, dest: []u8) std.Io.Reader.Error!usize {
const n = r.file.pread(dest, r.pos) catch |err| switch (err) {
error.Unseekable => {
r.mode = r.mode.toStreaming();
@@ -1467,7 +1476,7 @@ pub const Reader = struct {
return n;
}
- pub fn readStreaming(r: *Reader, dest: []u8) std.Io.Reader.Error!usize {
+ fn readStreaming(r: *Reader, dest: []u8) std.Io.Reader.Error!usize {
const n = r.file.read(dest) catch |err| {
r.err = err;
return error.ReadFailed;
@@ -1480,14 +1489,6 @@ pub const Reader = struct {
return n;
}
- pub fn read(r: *Reader, dest: []u8) std.Io.Reader.Error!usize {
- switch (r.mode) {
- .positional, .positional_reading => return readPositional(r, dest),
- .streaming, .streaming_reading => return readStreaming(r, dest),
- .failure => return error.ReadFailed,
- }
- }
-
pub fn atEnd(r: *Reader) bool {
// Even if stat fails, size is set when end is encountered.
const size = r.size orelse return false;
@@ -1732,7 +1733,7 @@ pub const Writer = struct {
) std.Io.Writer.FileError!usize {
const reader_buffered = file_reader.interface.buffered();
if (reader_buffered.len >= @intFromEnum(limit))
- return sendFileBuffered(io_w, file_reader, reader_buffered);
+ return sendFileBuffered(io_w, file_reader, limit.slice(reader_buffered));
const writer_buffered = io_w.buffered();
const file_limit = @intFromEnum(limit) - reader_buffered.len;
const w: *Writer = @alignCast(@fieldParentPtr("interface", io_w));
@@ -1804,7 +1805,7 @@ pub const Writer = struct {
return error.EndOfStream;
}
const consumed = io_w.consume(@intCast(sbytes));
- file_reader.seekTo(file_reader.pos + consumed) catch return error.ReadFailed;
+ file_reader.seekBy(@intCast(consumed)) catch return error.ReadFailed;
return consumed;
}
@@ -1865,7 +1866,7 @@ pub const Writer = struct {
return error.EndOfStream;
}
const consumed = io_w.consume(@bitCast(len));
- file_reader.seekTo(file_reader.pos + consumed) catch return error.ReadFailed;
+ file_reader.seekBy(@intCast(consumed)) catch return error.ReadFailed;
return consumed;
}
@@ -1998,7 +1999,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.seekBy(@intCast(n)) catch return error.ReadFailed;
return n;
}