authorgravatar for reversedrooms@gmail.comxeondev <reversedrooms@gmail.com> 2026-04-16 15:11:25+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-04-16 22:13:29+02:00
log2b48f559f424d8bf790bf54f4bb83d631461a681
tree63afbec73718161bf16640d9a26427fbc0454789
parentbea4ea5ff89ca1e9c517b3c4b00934931d280c57

std.Io: move netRead to become an Operation


6 files changed, 77 insertions(+), 62 deletions(-)

lib/std/Io.zig+19-10
......@@ -243,8 +243,6 @@ pub const VTable = struct {
243243 netConnectUnix: *const fn (?*anyopaque, *const net.UnixAddress) net.UnixAddress.ConnectError!net.Socket.Handle,
244244 netSocketCreatePair: *const fn (?*anyopaque, net.Socket.CreatePairOptions) net.Socket.CreatePairError![2]net.Socket,
245245 netSend: *const fn (?*anyopaque, net.Socket.Handle, []net.OutgoingMessage, net.SendFlags) struct { ?net.Socket.SendError, usize },
246 /// Returns 0 on end of stream.
247 netRead: *const fn (?*anyopaque, src: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize,
248246 netWrite: *const fn (?*anyopaque, dest: net.Socket.Handle, header: []const u8, data: []const []const u8, splat: usize) net.Stream.Writer.Error!usize,
249247 netWriteFile: *const fn (?*anyopaque, net.Socket.Handle, header: []const u8, *Io.File.Reader, Io.Limit) net.Stream.Writer.WriteFileError!usize,
250248 netClose: *const fn (?*anyopaque, handle: []const net.Socket.Handle) void,
......@@ -261,6 +259,7 @@ pub const Operation = union(enum) {
261259 /// other systems this tag is unreachable.
262260 device_io_control: DeviceIoControl,
263261 net_receive: NetReceive,
262 net_read: NetRead,
264263
265264 pub const Tag = @typeInfo(Operation).@"union".tag_type.?;
266265
......@@ -386,6 +385,23 @@ pub const Operation = union(enum) {
386385 pub const Result = struct { ?net.Socket.ReceiveError, usize };
387386 };
388387
388 pub const NetRead = struct {
389 socket_handle: net.Socket.Handle,
390 data: [][]u8,
391
392 pub const Error = error{
393 SystemResources,
394 ConnectionResetByPeer,
395 SocketUnconnected,
396 /// The file descriptor does not hold the required rights to read
397 /// from it.
398 AccessDenied,
399 NetworkDown,
400 } || Io.UnexpectedError;
401
402 pub const Result = Error!usize;
403 };
404
389405 pub const Result = Result: {
390406 const operation_fields = @typeInfo(Operation).@"union".fields;
391407 var field_names: [operation_fields.len][]const u8 = undefined;
......@@ -2626,7 +2642,6 @@ pub const failing: std.Io = .{
26262642 .netConnectUnix = failingNetConnectUnix,
26272643 .netSocketCreatePair = failingNetSocketCreatePair,
26282644 .netSend = failingNetSend,
2629 .netRead = failingNetRead,
26302645 .netWrite = failingNetWrite,
26312646 .netWriteFile = failingNetWriteFile,
26322647 .netClose = unreachableNetClose,
......@@ -2774,6 +2789,7 @@ pub fn failingOperate(userdata: ?*anyopaque, operation: Operation) Cancelable!Op
27742789 .file_write_streaming => .{ .file_write_streaming = error.InputOutput },
27752790 .device_io_control => unreachable,
27762791 .net_receive => .{ .net_receive = .{ error.NetworkDown, 0 } },
2792 .net_read => .{ .net_read = error.NetworkDown },
27772793 };
27782794}
27792795
......@@ -3377,13 +3393,6 @@ pub fn failingNetSend(userdata: ?*anyopaque, handle: net.Socket.Handle, messages
33773393 return .{ error.NetworkDown, 0 };
33783394}
33793395
3380pub fn failingNetRead(userdata: ?*anyopaque, src: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize {
3381 _ = userdata;
3382 _ = src;
3383 _ = data;
3384 return error.NetworkDown;
3385}
3386
33873396pub fn failingNetWrite(userdata: ?*anyopaque, dest: net.Socket.Handle, header: []const u8, data: []const []const u8, splat: usize) net.Stream.Writer.Error!usize {
33883397 _ = userdata;
33893398 _ = dest;
lib/std/Io/Dispatch.zig+3-13
......@@ -459,7 +459,6 @@ pub fn io(ev: *Evented) Io {
459459 .netConnectUnix = netConnectUnixUnavailable,
460460 .netSocketCreatePair = netSocketCreatePairUnavailable,
461461 .netSend = netSendUnavailable,
462 .netRead = netReadUnavailable,
463462 .netWrite = netWriteUnavailable,
464463 .netWriteFile = netWriteFileUnavailable,
465464 .netClose = netClose,
......@@ -1713,6 +1712,7 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper
17131712 },
17141713 .device_io_control => |*o| return .{ .device_io_control = try deviceIoControl(o) },
17151714 .net_receive => @panic("TODO implement net_receive operation"),
1715 .net_read => @panic("TODO implement net_read operation"),
17161716 }
17171717}
17181718
......@@ -2134,6 +2134,7 @@ fn batchDrainSubmitted(
21342134 },
21352135 .device_io_control => {},
21362136 .net_receive => @panic("TODO implement batched net_receive"),
2137 .net_read => @panic("TODO implement batched net_read"),
21372138 };
21382139 if (concurrency) return error.ConcurrencyUnavailable;
21392140 break :result try operate(ev, storage.submission.operation);
......@@ -2193,6 +2194,7 @@ fn batchSourceEvent(context: ?*anyopaque) callconv(.c) void {
21932194 },
21942195 .device_io_control => unreachable,
21952196 .net_receive => @panic("TODO implement batched net_receive"),
2197 .net_read => @panic("TODO implement batched net_read"),
21962198 };
21972199
21982200 switch (pending.node.prev) {
......@@ -4877,18 +4879,6 @@ fn netSendUnavailable(
48774879 return .{ error.NetworkDown, 0 };
48784880}
48794881
4880fn netReadUnavailable(
4881 userdata: ?*anyopaque,
4882 fd: net.Socket.Handle,
4883 data: [][]u8,
4884) net.Stream.Reader.Error!usize {
4885 const ev: *Evented = @ptrCast(@alignCast(userdata));
4886 _ = ev;
4887 _ = fd;
4888 _ = data;
4889 return error.NetworkDown;
4890}
4891
48924882fn netWriteUnavailable(
48934883 userdata: ?*anyopaque,
48944884 handle: net.Socket.Handle,
lib/std/Io/Threaded.zig+33-14
......@@ -1943,10 +1943,6 @@ pub fn io(t: *Threaded) Io {
19431943 .windows => netShutdownWindows,
19441944 else => netShutdownPosix,
19451945 },
1946 .netRead = switch (native_os) {
1947 .windows => netReadWindows,
1948 else => netReadPosix,
1949 },
19501946 .netWrite = switch (native_os) {
19511947 .windows => netWriteWindows,
19521948 else => netWritePosix,
......@@ -2566,6 +2562,12 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper
25662562 };
25672563 break :o .{ null, 1 };
25682564 } },
2565 .net_read => |o| return .{
2566 .net_read = netRead(o.socket_handle, o.data) catch |err| switch (err) {
2567 error.Canceled => |e| return e,
2568 else => |e| e,
2569 },
2570 },
25692571 }
25702572}
25712573
......@@ -2621,6 +2623,14 @@ fn batchAwaitAsync(userdata: ?*anyopaque, b: *Io.Batch) Io.Cancelable!void {
26212623 };
26222624 poll_len += 1;
26232625 },
2626 .net_read => |o| {
2627 poll_buffer[poll_len] = .{
2628 .fd = o.socket_handle,
2629 .events = posix.POLL.IN | posix.POLL.ERR,
2630 .revents = 0,
2631 };
2632 poll_len += 1;
2633 },
26242634 }
26252635 index = submission.node.next;
26262636 }
......@@ -2798,6 +2808,7 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout
27982808 storage.* = .{ .completion = .{ .node = .{ .next = .none }, .result = result } };
27992809 b.completed.tail = index;
28002810 },
2811 .net_read => |o| try poll_storage.add(o.socket_handle, posix.POLL.IN | posix.POLL.ERR),
28012812 }
28022813 index = submission.node.next;
28032814 }
......@@ -2993,6 +3004,7 @@ fn batchApc(
29933004 .file_write_streaming => .{ .file_write_streaming = ntWriteFileResult(iosb) },
29943005 .device_io_control => .{ .device_io_control = iosb.* },
29953006 .net_receive => unreachable,
3007 .net_read => unreachable,
29963008 };
29973009 storage.* = .{ .completion = .{ .node = .{ .next = .none }, .result = result } };
29983010 },
......@@ -3201,6 +3213,16 @@ fn batchDrainSubmittedWindows(t: *Threaded, b: *Io.Batch, concurrency: bool) (Io
32013213 .net_receive = netReceiveWindows(t, o.socket_handle, o.message_buffer, o.data_buffer, o.flags),
32023214 });
32033215 },
3216 .net_read => |*o| {
3217 // TODO integrate with overlapped I/O or equivalent to avoid this error
3218 if (concurrency) return error.ConcurrencyUnavailable;
3219 batchCompleteBlockingWindows(b, operation_userdata, .{
3220 .net_read = netRead(o.socket_handle, o.data) catch |err| switch (err) {
3221 error.Canceled => |e| return e,
3222 else => |e| e,
3223 },
3224 });
3225 },
32043226 }
32053227 index = submission.node.next;
32063228 }
......@@ -12549,11 +12571,14 @@ fn deferAcceptAfd(t: *Threaded, listen_handle: net.Socket.Handle, info: windows.
1254912571 }
1255012572}
1255112573
12552fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize {
12574fn netRead(socket_handle: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize {
1255312575 if (!have_networking) return error.NetworkDown;
12554 const t: *Threaded = @ptrCast(@alignCast(userdata));
12555 _ = t;
1255612576
12577 if (is_windows) return netReadWindows(socket_handle, data);
12578 return netReadPosix(socket_handle, data);
12579}
12580
12581fn netReadPosix(fd: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize {
1255712582 var iovecs_buffer: [max_iovecs_len]posix.iovec = undefined;
1255812583 var i: usize = 0;
1255912584 for (data) |buf| {
......@@ -12590,7 +12615,6 @@ fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.
1259012615 .NOMEM => return error.SystemResources,
1259112616 .NOTCONN => return error.SocketUnconnected,
1259212617 .CONNRESET => return error.ConnectionResetByPeer,
12593 .TIMEDOUT => return error.Timeout,
1259412618 .NOTCAPABLE => return error.AccessDenied,
1259512619 else => |err| return posix.unexpectedErrno(err),
1259612620 }
......@@ -12622,7 +12646,6 @@ fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.
1262212646 .NOMEM => return error.SystemResources,
1262312647 .NOTCONN => return error.SocketUnconnected,
1262412648 .CONNRESET => return error.ConnectionResetByPeer,
12625 .TIMEDOUT => return error.Timeout,
1262612649 .PIPE => return error.SocketUnconnected,
1262712650 .NETDOWN => return error.NetworkDown,
1262812651 else => |err| return posix.unexpectedErrno(err),
......@@ -12632,11 +12655,7 @@ fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.
1263212655 }
1263312656}
1263412657
12635fn netReadWindows(userdata: ?*anyopaque, socket_handle: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize {
12636 if (!have_networking) return error.NetworkDown;
12637 const t: *Threaded = @ptrCast(@alignCast(userdata));
12638 _ = t;
12639
12658fn netReadWindows(socket_handle: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize {
1264012659 var iovecs: [max_iovecs_len]windows.AFD.WSABUF(.@"var") = undefined;
1264112660 var len: u32 = 0;
1264212661 for (data) |buf| {
lib/std/Io/Uring.zig+11-13
......@@ -779,7 +779,6 @@ pub fn io(ev: *Evented) Io {
779779 .netConnectUnix = netConnectUnixUnavailable,
780780 .netSocketCreatePair = netSocketCreatePairUnavailable,
781781 .netSend = netSendUnavailable,
782 .netRead = netReadUnavailable,
783782 .netWrite = netWriteUnavailable,
784783 .netWriteFile = netWriteFileUnavailable,
785784 .netClose = netClose,
......@@ -2105,6 +2104,12 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper
21052104 };
21062105 },
21072106 },
2107 .net_read => |o| .{
2108 .net_read = r: {
2109 _ = o;
2110 break :r error.NetworkDown; // TODO
2111 },
2112 },
21082113 };
21092114}
21102115
......@@ -2392,6 +2397,10 @@ fn batchDrainSubmitted(
23922397 _ = o;
23932398 @panic("TODO implement batchDrainSubmitted for net_receive");
23942399 },
2400 .net_read => |o| {
2401 _ = o;
2402 @panic("TODO implement batchDrainSubmitted for net_read");
2403 },
23952404 })) |result| {
23962405 switch (batch.completed.tail) {
23972406 .none => batch.completed.head = index,
......@@ -2493,6 +2502,7 @@ fn batchDrainReady(batch: *Io.Batch) Io.Timeout.Error!void {
24932502 },
24942503 .device_io_control => unreachable,
24952504 .net_receive => @panic("TODO"),
2505 .net_read => @panic("TODO"),
24962506 })) |result| {
24972507 switch (batch.completed.tail) {
24982508 .none => batch.completed.head = index,
......@@ -5142,18 +5152,6 @@ fn netReceive(
51425152 }
51435153}
51445154
5145fn netReadUnavailable(
5146 userdata: ?*anyopaque,
5147 fd: net.Socket.Handle,
5148 data: [][]u8,
5149) net.Stream.Reader.Error!usize {
5150 const ev: *Evented = @ptrCast(@alignCast(userdata));
5151 _ = ev;
5152 _ = fd;
5153 _ = data;
5154 return error.NetworkDown;
5155}
5156
51575155fn netWriteUnavailable(
51585156 userdata: ?*anyopaque,
51595157 handle: net.Socket.Handle,
lib/std/Io/net.zig+11-11
......@@ -1245,6 +1245,15 @@ pub const Stream = struct {
12451245
12461246 const max_iovecs_len = 8;
12471247
1248 /// This is a low-level API that calls the `Io` interface function directly.
1249 /// For a higher level API, see `reader`.
1250 pub fn read(s: *const Stream, io: Io, data: [][]u8) Reader.Error!usize {
1251 return (try io.operate(.{ .net_read = .{
1252 .socket_handle = s.socket.handle,
1253 .data = data,
1254 } })).net_read;
1255 }
1256
12481257 pub fn close(s: *const Stream, io: Io) void {
12491258 io.vtable.netClose(io.userdata, (&s.socket.handle)[0..1]);
12501259 }
......@@ -1259,16 +1268,7 @@ pub const Stream = struct {
12591268 stream: Stream,
12601269 err: ?Error,
12611270
1262 pub const Error = error{
1263 SystemResources,
1264 ConnectionResetByPeer,
1265 Timeout,
1266 SocketUnconnected,
1267 /// The file descriptor does not hold the required rights to read
1268 /// from it.
1269 AccessDenied,
1270 NetworkDown,
1271 } || Io.Cancelable || Io.UnexpectedError;
1271 pub const Error = Io.Operation.NetRead.Error || Io.Cancelable;
12721272
12731273 pub fn init(stream: Stream, io: Io, buffer: []u8) Reader {
12741274 return .{
......@@ -1302,7 +1302,7 @@ pub const Stream = struct {
13021302 const dest_n, const data_size = try io_r.writableVector(&iovecs_buffer, data);
13031303 const dest = iovecs_buffer[0..dest_n];
13041304 assert(dest[0].len > 0);
1305 const n = io.vtable.netRead(io.userdata, r.stream.socket.handle, dest) catch |err| {
1305 const n = r.stream.read(io, dest) catch |err| {
13061306 r.err = err;
13071307 return error.ReadFailed;
13081308 };
src/IncrementalDebugServer.zig-1
......@@ -86,7 +86,6 @@ fn runServer(ids: *IncrementalDebugServer) void {
8686 error.OutOfMemory,
8787 error.Unexpected,
8888 error.SystemResources,
89 error.Timeout,
9089 error.NetworkDown,
9190 error.NetworkUnreachable,
9291 error.HostUnreachable,