mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 22:04:21 +00:00
std.fs.File.Writer: implement positional writing
This commit is contained in:
parent
7e2a26c0c4
commit
fd7feed04b
1 changed files with 91 additions and 42 deletions
|
|
@ -1240,6 +1240,8 @@ pub const Reader = struct {
|
||||||
file: File,
|
file: File,
|
||||||
err: ?ReadError = null,
|
err: ?ReadError = null,
|
||||||
mode: Reader.Mode = .positional,
|
mode: Reader.Mode = .positional,
|
||||||
|
/// Tracks the true seek position in the file. To obtain the logical
|
||||||
|
/// position, subtract the buffer size from this value.
|
||||||
pos: u64 = 0,
|
pos: u64 = 0,
|
||||||
size: ?u64 = null,
|
size: ?u64 = null,
|
||||||
size_err: ?GetEndPosError = null,
|
size_err: ?GetEndPosError = null,
|
||||||
|
|
@ -1407,10 +1409,14 @@ pub const Reader = struct {
|
||||||
const n = posix.preadv(r.file.handle, dest, r.pos) catch |err| switch (err) {
|
const n = posix.preadv(r.file.handle, dest, r.pos) catch |err| switch (err) {
|
||||||
error.Unseekable => {
|
error.Unseekable => {
|
||||||
r.mode = r.mode.toStreaming();
|
r.mode = r.mode.toStreaming();
|
||||||
if (r.pos != 0) r.seekBy(@intCast(r.pos)) catch {
|
const pos = r.pos;
|
||||||
r.mode = .failure;
|
if (pos != 0) {
|
||||||
return error.ReadFailed;
|
r.pos = 0;
|
||||||
};
|
r.seekBy(@intCast(pos)) catch {
|
||||||
|
r.mode = .failure;
|
||||||
|
return error.ReadFailed;
|
||||||
|
};
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
},
|
},
|
||||||
else => |e| {
|
else => |e| {
|
||||||
|
|
@ -1535,10 +1541,14 @@ pub const Reader = struct {
|
||||||
const n = r.file.pread(dest, r.pos) catch |err| switch (err) {
|
const n = r.file.pread(dest, r.pos) catch |err| switch (err) {
|
||||||
error.Unseekable => {
|
error.Unseekable => {
|
||||||
r.mode = r.mode.toStreaming();
|
r.mode = r.mode.toStreaming();
|
||||||
if (r.pos != 0) r.seekBy(@intCast(r.pos)) catch {
|
const pos = r.pos;
|
||||||
r.mode = .failure;
|
if (pos != 0) {
|
||||||
return error.ReadFailed;
|
r.pos = 0;
|
||||||
};
|
r.seekBy(@intCast(pos)) catch {
|
||||||
|
r.mode = .failure;
|
||||||
|
return error.ReadFailed;
|
||||||
|
};
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
},
|
},
|
||||||
else => |e| {
|
else => |e| {
|
||||||
|
|
@ -1586,6 +1596,8 @@ pub const Writer = struct {
|
||||||
file: File,
|
file: File,
|
||||||
err: ?WriteError = null,
|
err: ?WriteError = null,
|
||||||
mode: Writer.Mode = .positional,
|
mode: Writer.Mode = .positional,
|
||||||
|
/// Tracks the true seek position in the file. To obtain the logical
|
||||||
|
/// position, add the buffer size to this value.
|
||||||
pos: u64 = 0,
|
pos: u64 = 0,
|
||||||
sendfile_err: ?SendfileError = null,
|
sendfile_err: ?SendfileError = null,
|
||||||
copy_file_range_err: ?CopyFileRangeError = null,
|
copy_file_range_err: ?CopyFileRangeError = null,
|
||||||
|
|
@ -1652,32 +1664,36 @@ pub const Writer = struct {
|
||||||
const w: *Writer = @fieldParentPtr("interface", io_w);
|
const w: *Writer = @fieldParentPtr("interface", io_w);
|
||||||
const handle = w.file.handle;
|
const handle = w.file.handle;
|
||||||
const buffered = io_w.buffered();
|
const buffered = io_w.buffered();
|
||||||
if (is_windows) {
|
if (is_windows) switch (w.mode) {
|
||||||
var i: usize = 0;
|
.positional, .positional_reading => @panic("TODO"),
|
||||||
while (i < buffered.len) {
|
.streaming, .streaming_reading => {
|
||||||
const n = windows.WriteFile(handle, buffered[i..], null) catch |err| {
|
var i: usize = 0;
|
||||||
w.err = err;
|
while (i < buffered.len) {
|
||||||
w.pos += i;
|
const n = windows.WriteFile(handle, buffered[i..], null) catch |err| {
|
||||||
_ = io_w.consume(i);
|
w.err = err;
|
||||||
return error.WriteFailed;
|
w.pos += i;
|
||||||
};
|
_ = io_w.consume(i);
|
||||||
i += n;
|
return error.WriteFailed;
|
||||||
if (data.len > 0 and buffered.len - i < n) {
|
};
|
||||||
|
i += n;
|
||||||
|
if (data.len > 0 and buffered.len - i < n) {
|
||||||
|
w.pos += i;
|
||||||
|
return io_w.consume(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i != 0 or data.len == 0 or (data.len == 1 and splat == 0)) {
|
||||||
w.pos += i;
|
w.pos += i;
|
||||||
return io_w.consume(i);
|
return io_w.consume(i);
|
||||||
}
|
}
|
||||||
}
|
const n = windows.WriteFile(handle, data[0], null) catch |err| {
|
||||||
if (i != 0 or data.len == 0 or (data.len == 1 and splat == 0)) {
|
w.err = err;
|
||||||
w.pos += i;
|
return 0;
|
||||||
return io_w.consume(i);
|
};
|
||||||
}
|
w.pos += n;
|
||||||
const n = windows.WriteFile(handle, data[0], null) catch |err| {
|
return n;
|
||||||
w.err = err;
|
},
|
||||||
return 0;
|
.failure => return error.WriteFailed,
|
||||||
};
|
};
|
||||||
w.pos += n;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
var iovecs: [max_buffers_len]std.posix.iovec_const = undefined;
|
var iovecs: [max_buffers_len]std.posix.iovec_const = undefined;
|
||||||
var len: usize = 0;
|
var len: usize = 0;
|
||||||
if (buffered.len > 0) {
|
if (buffered.len > 0) {
|
||||||
|
|
@ -1733,12 +1749,39 @@ pub const Writer = struct {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
const n = std.posix.writev(handle, iovecs[0..len]) catch |err| {
|
switch (w.mode) {
|
||||||
w.err = err;
|
.positional, .positional_reading => {
|
||||||
return error.WriteFailed;
|
const n = std.posix.pwritev(handle, iovecs[0..len], w.pos) catch |err| switch (err) {
|
||||||
};
|
error.Unseekable => {
|
||||||
w.pos += n;
|
w.mode = w.mode.toStreaming();
|
||||||
return io_w.consume(n);
|
const pos = w.pos;
|
||||||
|
if (pos != 0) {
|
||||||
|
w.pos = 0;
|
||||||
|
w.seekTo(@intCast(pos)) catch {
|
||||||
|
w.mode = .failure;
|
||||||
|
return error.WriteFailed;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
|
else => |e| {
|
||||||
|
w.err = e;
|
||||||
|
return error.WriteFailed;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
w.pos += n;
|
||||||
|
return io_w.consume(n);
|
||||||
|
},
|
||||||
|
.streaming, .streaming_reading => {
|
||||||
|
const n = std.posix.writev(handle, iovecs[0..len]) catch |err| {
|
||||||
|
w.err = err;
|
||||||
|
return error.WriteFailed;
|
||||||
|
};
|
||||||
|
w.pos += n;
|
||||||
|
return io_w.consume(n);
|
||||||
|
},
|
||||||
|
.failure => return error.WriteFailed,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sendFile(
|
pub fn sendFile(
|
||||||
|
|
@ -1781,10 +1824,14 @@ pub const Writer = struct {
|
||||||
const n = std.os.linux.wrapped.sendfile(out_fd, in_fd, off_ptr, count) catch |err| switch (err) {
|
const n = std.os.linux.wrapped.sendfile(out_fd, in_fd, off_ptr, count) catch |err| switch (err) {
|
||||||
error.Unseekable => {
|
error.Unseekable => {
|
||||||
file_reader.mode = file_reader.mode.toStreaming();
|
file_reader.mode = file_reader.mode.toStreaming();
|
||||||
if (file_reader.pos != 0) file_reader.seekBy(@intCast(file_reader.pos)) catch {
|
const pos = file_reader.pos;
|
||||||
file_reader.mode = .failure;
|
if (pos != 0) {
|
||||||
return error.ReadFailed;
|
file_reader.pos = 0;
|
||||||
};
|
file_reader.seekBy(@intCast(pos)) catch {
|
||||||
|
file_reader.mode = .failure;
|
||||||
|
return error.ReadFailed;
|
||||||
|
};
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
},
|
},
|
||||||
else => |e| {
|
else => |e| {
|
||||||
|
|
@ -1877,17 +1924,19 @@ pub const Writer = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn seekTo(w: *Writer, offset: u64) SeekError!void {
|
pub fn seekTo(w: *Writer, offset: u64) SeekError!void {
|
||||||
if (w.seek_err) |err| return err;
|
|
||||||
switch (w.mode) {
|
switch (w.mode) {
|
||||||
.positional, .positional_reading => {
|
.positional, .positional_reading => {
|
||||||
w.pos = offset;
|
w.pos = offset;
|
||||||
},
|
},
|
||||||
.streaming, .streaming_reading => {
|
.streaming, .streaming_reading => {
|
||||||
|
if (w.seek_err) |err| return err;
|
||||||
posix.lseek_SET(w.file.handle, offset) catch |err| {
|
posix.lseek_SET(w.file.handle, offset) catch |err| {
|
||||||
w.seek_err = err;
|
w.seek_err = err;
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
|
w.pos = offset;
|
||||||
},
|
},
|
||||||
|
.failure => return w.seek_err.?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue