anyerror means the error set is known only at runtime.
In WASI, this error occurs when the file descriptor does not hold the required rights to read from it.
reading a timerfd with CANCEL_ON_SET will lead to this error when the clock goes through a discontinuous change
Unable to read file due to lock.
This error occurs in Linux if the process to be read from no longer exists.
The Operating System returned an undocumented error code.
This error is in theory not possible, but it would be better to handle this error than to invoke undefined behavior.
When this error code is observed, it usually means the Zig Standard Library needs a small patch to add the error code to the error set for the respective function.
This error occurs when no global event loop is configured, and reading from the file descriptor would block.
pub const ReadError = error{
InputOutput,
SystemResources,
IsDir,
OperationAborted,
BrokenPipe,
ConnectionResetByPeer,
ConnectionTimedOut,
NotOpenForReading,
SocketNotConnected,
/// This error occurs when no global event loop is configured,
/// and reading from the file descriptor would block.
WouldBlock,
/// reading a timerfd with CANCEL_ON_SET will lead to this error
/// when the clock goes through a discontinuous change
Canceled,
/// In WASI, this error occurs when the file descriptor does
/// not hold the required rights to read from it.
AccessDenied,
/// This error occurs in Linux if the process to be read from
/// no longer exists.
ProcessNotFound,
/// Unable to read file due to lock.
LockViolation,
} || UnexpectedErroranyerror means the error set is known only at runtime.
File descriptor does not hold the required rights to write to it.
Connection reset by peer.
The process cannot access the file because another process has locked a portion of the file. Windows-only.
This error occurs when a device gets disconnected before or mid-flush while it's being written to - errno(6): No such device or address.
This error occurs in Linux if the process being written to no longer exists.
The Operating System returned an undocumented error code.
This error is in theory not possible, but it would be better to handle this error than to invoke undefined behavior.
When this error code is observed, it usually means the Zig Standard Library needs a small patch to add the error code to the error set for the respective function.
This error occurs when no global event loop is configured, and reading from the file descriptor would block.
pub const WriteError = error{
DiskQuota,
FileTooBig,
InputOutput,
NoSpaceLeft,
DeviceBusy,
InvalidArgument,
/// File descriptor does not hold the required rights to write to it.
AccessDenied,
BrokenPipe,
SystemResources,
OperationAborted,
NotOpenForWriting,
/// The process cannot access the file because another process has locked
/// a portion of the file. Windows-only.
LockViolation,
/// This error occurs when no global event loop is configured,
/// and reading from the file descriptor would block.
WouldBlock,
/// Connection reset by peer.
ConnectionResetByPeer,
/// This error occurs in Linux if the process being written to
/// no longer exists.
ProcessNotFound,
/// This error occurs when a device gets disconnected before or mid-flush
/// while it's being written to - errno(6): No such device or address.
NoDevice,
} || UnexpectedErrorpub fn readv(s: Stream, iovecs: []const posix.iovec) ReadError!usize {
if (native_os == .windows) {
// TODO improve this to use ReadFileScatter
if (iovecs.len == 0) return @as(usize, 0);
const first = iovecs[0];
return windows.ReadFile(s.handle, first.base[0..first.len], null);
}
return posix.readv(s.handle, iovecs);
}Returns the number of bytes read. If the number read is smaller than
buffer.len, it means the stream reached the end. Reaching the end of
a stream is not an error condition.
s: Streambuffer: []u8pub fn readAll(s: Stream, buffer: []u8) ReadError!usize {
return readAtLeast(s, buffer, buffer.len);
}Returns the number of bytes read, calling the underlying read function
the minimal number of times until the buffer has at least len bytes
filled. If the number read is less than len it means the stream
reached the end. Reaching the end of the stream is not an error
condition.
pub fn write(self: Stream, buffer: []const u8) WriteError!usizeTODO in evented I/O mode, this implementation incorrectly uses the event loop's file system thread instead of non-blocking. It needs to be reworked to properly use non-blocking I/O.
self: Streambuffer: []const u8pub fn writeAll(self: Stream, bytes: []const u8) WriteError!voidself: Streambytes: []const u8pub fn writeAll(self: Stream, bytes: []const u8) WriteError!void {
var index: usize = 0;
while (index < bytes.len) {
index += try self.write(bytes[index..]);
}
}pub fn writev(self: Stream, iovecs: []const posix.iovec_const) WriteError!usizeSee https://github.com/ziglang/zig/issues/7699
See equivalent function: std.fs.File.writev.
self: Streamiovecs: []const posix.iovec_constpub fn writev(self: Stream, iovecs: []const posix.iovec_const) WriteError!usize {
return posix.writev(self.handle, iovecs);
}pub fn writevAll(self: Stream, iovecs: []posix.iovec_const) WriteError!voidThe iovecs parameter is mutable because this function needs to mutate the fields in
order to handle partial writes from the underlying OS layer.
See https://github.com/ziglang/zig/issues/7699
See equivalent function: std.fs.File.writevAll.
self: Streamiovecs: []posix.iovec_constpub fn writevAll(self: Stream, iovecs: []posix.iovec_const) WriteError!void {
if (iovecs.len == 0) return;
var i: usize = 0;
while (true) {
var amt = try self.writev(iovecs[i..]);
while (amt >= iovecs[i].len) {
amt -= iovecs[i].len;
i += 1;
if (i >= iovecs.len) return;
}
iovecs[i].base += amt;
iovecs[i].len -= amt;
}
}pub const Stream = struct {
/// Underlying platform-defined type which may or may not be
/// interchangeable with a file system file descriptor.
handle: posix.socket_t,
pub fn close(s: Stream) void {
switch (native_os) {
.windows => windows.closesocket(s.handle) catch unreachable,
else => posix.close(s.handle),
}
}
pub const ReadError = posix.ReadError;
pub const WriteError = posix.WriteError;
pub const Reader = io.Reader(Stream, ReadError, read);
pub const Writer = io.Writer(Stream, WriteError, write);
pub fn reader(self: Stream) Reader {
return .{ .context = self };
}
pub fn writer(self: Stream) Writer {
return .{ .context = self };
}
pub fn read(self: Stream, buffer: []u8) ReadError!usize {
if (native_os == .windows) {
return windows.ReadFile(self.handle, buffer, null);
}
return posix.read(self.handle, buffer);
}
pub fn readv(s: Stream, iovecs: []const posix.iovec) ReadError!usize {
if (native_os == .windows) {
// TODO improve this to use ReadFileScatter
if (iovecs.len == 0) return @as(usize, 0);
const first = iovecs[0];
return windows.ReadFile(s.handle, first.base[0..first.len], null);
}
return posix.readv(s.handle, iovecs);
}
/// Returns the number of bytes read. If the number read is smaller than
/// `buffer.len`, it means the stream reached the end. Reaching the end of
/// a stream is not an error condition.
pub fn readAll(s: Stream, buffer: []u8) ReadError!usize {
return readAtLeast(s, buffer, buffer.len);
}
/// Returns the number of bytes read, calling the underlying read function
/// the minimal number of times until the buffer has at least `len` bytes
/// filled. If the number read is less than `len` it means the stream
/// reached the end. Reaching the end of the stream is not an error
/// condition.
pub fn readAtLeast(s: Stream, buffer: []u8, len: usize) ReadError!usize {
assert(len <= buffer.len);
var index: usize = 0;
while (index < len) {
const amt = try s.read(buffer[index..]);
if (amt == 0) break;
index += amt;
}
return index;
}
/// TODO in evented I/O mode, this implementation incorrectly uses the event loop's
/// file system thread instead of non-blocking. It needs to be reworked to properly
/// use non-blocking I/O.
pub fn write(self: Stream, buffer: []const u8) WriteError!usize {
if (native_os == .windows) {
return windows.WriteFile(self.handle, buffer, null);
}
return posix.write(self.handle, buffer);
}
pub fn writeAll(self: Stream, bytes: []const u8) WriteError!void {
var index: usize = 0;
while (index < bytes.len) {
index += try self.write(bytes[index..]);
}
}
/// See https://github.com/ziglang/zig/issues/7699
/// See equivalent function: `std.fs.File.writev`.
pub fn writev(self: Stream, iovecs: []const posix.iovec_const) WriteError!usize {
return posix.writev(self.handle, iovecs);
}
/// The `iovecs` parameter is mutable because this function needs to mutate the fields in
/// order to handle partial writes from the underlying OS layer.
/// See https://github.com/ziglang/zig/issues/7699
/// See equivalent function: `std.fs.File.writevAll`.
pub fn writevAll(self: Stream, iovecs: []posix.iovec_const) WriteError!void {
if (iovecs.len == 0) return;
var i: usize = 0;
while (true) {
var amt = try self.writev(iovecs[i..]);
while (amt >= iovecs[i].len) {
amt -= iovecs[i].len;
i += 1;
if (i >= iovecs.len) return;
}
iovecs[i].base += amt;
iovecs[i].len -= amt;
}
}
}