pub const Operation = union(enum)
pub const Operation = union(enum) {
file_read_streaming: FileReadStreaming,
file_write_streaming: FileWriteStreaming,
/// On Windows this is NtDeviceIoControlFile. On POSIX this is ioctl. On
/// other systems this tag is unreachable.
device_io_control: DeviceIoControl,
net_receive: NetReceive,
net_read: NetRead,
pub const Tag = @typeInfo(Operation).@"union".tag_type.?;
/// May return 0 reads which is different than `error.EndOfStream`.
pub const FileReadStreaming = struct {
file: File,
data: []const []u8,
pub const Error = UnendingError || error{EndOfStream};
pub const UnendingError = error{
InputOutput,
SystemResources,
/// Trying to read a directory file descriptor as if it were a file.
IsDir,
ConnectionResetByPeer,
/// File was not opened with read capability.
NotOpenForReading,
SocketUnconnected,
/// Non-blocking has been enabled, and reading from the file descriptor
/// would block.
WouldBlock,
/// In WASI, this error occurs when the file descriptor does
/// not hold the required rights to read from it.
AccessDenied,
/// Unable to read file due to lock. Depending on the `Io` implementation,
/// reading from a locked file may return this error, or may ignore the
/// lock.
LockViolation,
} || Io.UnexpectedError;
pub const Result = Error!usize;
};
pub const FileWriteStreaming = struct {
file: File,
header: []const u8 = &.{},
data: []const []const u8,
splat: usize = 1,
pub const Error = error{
DiskQuota,
FileTooBig,
InputOutput,
NoSpaceLeft,
DeviceBusy,
/// File descriptor does not hold the required rights to write to it.
AccessDenied,
PermissionDenied,
/// File is an unconnected socket, or closed its read end.
BrokenPipe,
/// Insufficient kernel memory to read from in_fd.
SystemResources,
NotOpenForWriting,
/// The process cannot access the file because another process has locked
/// a portion of the file. Windows-only.
LockViolation,
/// Non-blocking has been enabled and this operation would block.
WouldBlock,
/// 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,
FileBusy,
} || Io.UnexpectedError;
pub const Result = Error!usize;
};
pub const DeviceIoControl = switch (builtin.os.tag) {
.wasi => noreturn,
.windows => struct {
file: File,
code: std.os.windows.CTL_CODE,
in: []const u8 = &.{},
out: []u8 = &.{},
pub const Result = std.os.windows.IO_STATUS_BLOCK;
},
else => struct {
file: File,
/// Device-dependent operation code.
code: u32,
arg: ?*anyopaque,
/// Device and operation dependent result. Negative values are
/// negative errno.
pub const Result = i32;
},
};
pub const NetReceive = struct {
socket_handle: net.Socket.Handle,
message_buffer: []net.IncomingMessage,
data_buffer: []u8,
flags: net.ReceiveFlags,
pub const Error = error{
/// Insufficient memory or other resource internal to the operating system.
SystemResources,
/// Per-process limit on the number of open file descriptors has been reached.
ProcessFdQuotaExceeded,
/// System-wide limit on the total number of open files has been reached.
SystemFdQuotaExceeded,
/// Local end has been shut down on a connection-oriented socket, or
/// the socket was never connected.
SocketUnconnected,
/// The socket type requires that message be sent atomically, and the
/// size of the message to be sent made this impossible. The message
/// was not transmitted, or was partially transmitted.
MessageOversize,
/// Network connection was unexpectedly closed by sender.
ConnectionResetByPeer,
/// The local network interface used to reach the destination is offline.
NetworkDown,
/// A connectionless packet was previously sent successfully,
/// however, it was not received because no service is operating at
/// the destination port of the transport on the remote system.
/// This caused an ICMP port unreachable packet to be returned to
/// the OS where it was queued up to be reported at the next call
/// to send or receive on the bound socket.
PortUnreachable,
} || Io.UnexpectedError;
pub const Result = struct { ?net.Socket.ReceiveError, usize };
};
pub const NetRead = struct {
socket_handle: net.Socket.Handle,
data: [][]u8,
pub const Error = error{
SystemResources,
ConnectionResetByPeer,
SocketUnconnected,
/// The file descriptor does not hold the required rights to read
/// from it.
AccessDenied,
NetworkDown,
} || Io.UnexpectedError;
pub const Result = Error!usize;
};
pub const Result = Result: {
const operation_info = @typeInfo(Operation).@"union";
const operation_count = operation_info.field_names.len;
var field_names: [operation_count][]const u8 = undefined;
var field_types: [operation_count]type = undefined;
for (operation_info.field_names, operation_info.field_types, &field_names, &field_types) |f_name, f_type, *field_name, *field_type| {
field_name.* = f_name;
field_type.* = if (f_type == noreturn) noreturn else f_type.Result;
}
break :Result @Union(.auto, Tag, &field_names, &field_types, &@splat(.{}));
};
pub const Storage = union {
unused: List.DoubleNode,
submission: Submission,
pending: Pending,
completion: Completion,
pub const Submission = struct {
node: List.SingleNode,
operation: Operation,
};
pub const Pending = struct {
node: List.DoubleNode,
tag: Tag,
userdata: Userdata align(@max(@alignOf(usize), 4)),
pub const Userdata = [7]usize;
};
pub const Completion = struct {
node: List.SingleNode,
result: Result,
};
};
pub const OptionalIndex = enum(u32) {
none = std.math.maxInt(u32),
_,
pub fn fromIndex(i: usize) OptionalIndex {
const oi: OptionalIndex = @fromBackingInt(@intCast(i));
assert(oi != .none);
return oi;
}
pub fn toIndex(oi: OptionalIndex) u32 {
assert(oi != .none);
return @backingInt(oi);
}
};
pub const List = struct {
head: OptionalIndex,
tail: OptionalIndex,
pub const empty: List = .{ .head = .none, .tail = .none };
pub const SingleNode = struct { next: OptionalIndex };
pub const DoubleNode = struct { prev: OptionalIndex, next: OptionalIndex };
};
}