| author | |
| committer | |
| log | 3b515fbede945a2927d5aba59212553a8b26b944 |
| tree | 76f7583b67d1e817efb0d2f401836d9a229aaf83 |
| parent | 6be202f46633d02e20d0f068a32296113ecb95ca |
| parent | 80625990d5ce82b781de54c4587b489cbd2cd55f |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/3108945 files changed, 517 insertions(+), 487 deletions(-)
lib/compiler/test_runner.zig+1-1| ... | @@ -17,7 +17,7 @@ var fba: std.heap.FixedBufferAllocator = .init(&fba_buffer); | ... | @@ -17,7 +17,7 @@ var fba: std.heap.FixedBufferAllocator = .init(&fba_buffer); |
| 17 | var fba_buffer: [8192]u8 = undefined; | 17 | var fba_buffer: [8192]u8 = undefined; |
| 18 | var stdin_buffer: [4096]u8 = undefined; | 18 | var stdin_buffer: [4096]u8 = undefined; |
| 19 | var stdout_buffer: [4096]u8 = undefined; | 19 | var stdout_buffer: [4096]u8 = undefined; |
| 20 | const runner_threaded_io: Io = Io.Threaded.global_single_threaded.ioBasic(); | 20 | const runner_threaded_io: Io = Io.Threaded.global_single_threaded.io(); |
| 21 | 21 | ||
| 22 | /// Keep in sync with logic in `std.Build.addRunArtifact` which decides whether | 22 | /// Keep in sync with logic in `std.Build.addRunArtifact` which decides whether |
| 23 | /// the test runner will communicate with the build runner via `std.zig.Server`. | 23 | /// the test runner will communicate with the build runner via `std.zig.Server`. |
lib/compiler_rt.zig+1-1| ... | @@ -17,7 +17,7 @@ else | ... | @@ -17,7 +17,7 @@ else |
| 17 | null; | 17 | null; |
| 18 | 18 | ||
| 19 | pub const std_options_debug_io: std.Io = if (builtin.is_test) | 19 | pub const std_options_debug_io: std.Io = if (builtin.is_test) |
| 20 | std.Io.Threaded.global_single_threaded.ioBasic() | 20 | std.Io.Threaded.global_single_threaded.io() |
| 21 | else | 21 | else |
| 22 | unreachable; | 22 | unreachable; |
| 23 | 23 |
lib/fuzzer.zig+1-1| ... | @@ -13,7 +13,7 @@ pub const std_options = std.Options{ | ... | @@ -13,7 +13,7 @@ pub const std_options = std.Options{ |
| 13 | .logFn = logOverride, | 13 | .logFn = logOverride, |
| 14 | }; | 14 | }; |
| 15 | 15 | ||
| 16 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 16 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 17 | 17 | ||
| 18 | fn logOverride( | 18 | fn logOverride( |
| 19 | comptime level: std.log.Level, | 19 | comptime level: std.log.Level, |
lib/std/Io.zig+44-2| ... | @@ -243,7 +243,6 @@ pub const VTable = struct { | ... | @@ -243,7 +243,6 @@ pub const VTable = struct { |
| 243 | netConnectUnix: *const fn (?*anyopaque, *const net.UnixAddress) net.UnixAddress.ConnectError!net.Socket.Handle, | 243 | netConnectUnix: *const fn (?*anyopaque, *const net.UnixAddress) net.UnixAddress.ConnectError!net.Socket.Handle, |
| 244 | netSocketCreatePair: *const fn (?*anyopaque, net.Socket.CreatePairOptions) net.Socket.CreatePairError![2]net.Socket, | 244 | netSocketCreatePair: *const fn (?*anyopaque, net.Socket.CreatePairOptions) net.Socket.CreatePairError![2]net.Socket, |
| 245 | netSend: *const fn (?*anyopaque, net.Socket.Handle, []net.OutgoingMessage, net.SendFlags) struct { ?net.Socket.SendError, usize }, | 245 | netSend: *const fn (?*anyopaque, net.Socket.Handle, []net.OutgoingMessage, net.SendFlags) struct { ?net.Socket.SendError, usize }, |
| 246 | netReceive: *const fn (?*anyopaque, net.Socket.Handle, message_buffer: []net.IncomingMessage, data_buffer: []u8, net.ReceiveFlags, Timeout) struct { ?net.Socket.ReceiveTimeoutError, usize }, | ||
| 247 | /// Returns 0 on end of stream. | 246 | /// Returns 0 on end of stream. |
| 248 | netRead: *const fn (?*anyopaque, src: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize, | 247 | netRead: *const fn (?*anyopaque, src: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize, |
| 249 | netWrite: *const fn (?*anyopaque, dest: net.Socket.Handle, header: []const u8, data: []const []const u8, splat: usize) net.Stream.Writer.Error!usize, | 248 | netWrite: *const fn (?*anyopaque, dest: net.Socket.Handle, header: []const u8, data: []const []const u8, splat: usize) net.Stream.Writer.Error!usize, |
| ... | @@ -261,6 +260,7 @@ pub const Operation = union(enum) { | ... | @@ -261,6 +260,7 @@ pub const Operation = union(enum) { |
| 261 | /// On Windows this is NtDeviceIoControlFile. On POSIX this is ioctl. On | 260 | /// On Windows this is NtDeviceIoControlFile. On POSIX this is ioctl. On |
| 262 | /// other systems this tag is unreachable. | 261 | /// other systems this tag is unreachable. |
| 263 | device_io_control: DeviceIoControl, | 262 | device_io_control: DeviceIoControl, |
| 263 | net_receive: NetReceive, | ||
| 264 | 264 | ||
| 265 | pub const Tag = @typeInfo(Operation).@"union".tag_type.?; | 265 | pub const Tag = @typeInfo(Operation).@"union".tag_type.?; |
| 266 | 266 | ||
| ... | @@ -350,6 +350,35 @@ pub const Operation = union(enum) { | ... | @@ -350,6 +350,35 @@ pub const Operation = union(enum) { |
| 350 | }, | 350 | }, |
| 351 | }; | 351 | }; |
| 352 | 352 | ||
| 353 | pub const NetReceive = struct { | ||
| 354 | socket_handle: net.Socket.Handle, | ||
| 355 | message_buffer: []net.IncomingMessage, | ||
| 356 | data_buffer: []u8, | ||
| 357 | flags: net.ReceiveFlags, | ||
| 358 | |||
| 359 | pub const Error = error{ | ||
| 360 | /// Insufficient memory or other resource internal to the operating system. | ||
| 361 | SystemResources, | ||
| 362 | /// Per-process limit on the number of open file descriptors has been reached. | ||
| 363 | ProcessFdQuotaExceeded, | ||
| 364 | /// System-wide limit on the total number of open files has been reached. | ||
| 365 | SystemFdQuotaExceeded, | ||
| 366 | /// Local end has been shut down on a connection-oriented socket, or | ||
| 367 | /// the socket was never connected. | ||
| 368 | SocketUnconnected, | ||
| 369 | /// The socket type requires that message be sent atomically, and the | ||
| 370 | /// size of the message to be sent made this impossible. The message | ||
| 371 | /// was not transmitted, or was partially transmitted. | ||
| 372 | MessageOversize, | ||
| 373 | /// Network connection was unexpectedly closed by sender. | ||
| 374 | ConnectionResetByPeer, | ||
| 375 | /// The local network interface used to reach the destination is offline. | ||
| 376 | NetworkDown, | ||
| 377 | } || Io.UnexpectedError; | ||
| 378 | |||
| 379 | pub const Result = struct { ?net.Socket.ReceiveError, usize }; | ||
| 380 | }; | ||
| 381 | |||
| 353 | pub const Result = Result: { | 382 | pub const Result = Result: { |
| 354 | const operation_fields = @typeInfo(Operation).@"union".fields; | 383 | const operation_fields = @typeInfo(Operation).@"union".fields; |
| 355 | var field_names: [operation_fields.len][]const u8 = undefined; | 384 | var field_names: [operation_fields.len][]const u8 = undefined; |
| ... | @@ -417,6 +446,19 @@ pub fn operate(io: Io, operation: Operation) Cancelable!Operation.Result { | ... | @@ -417,6 +446,19 @@ pub fn operate(io: Io, operation: Operation) Cancelable!Operation.Result { |
| 417 | return io.vtable.operate(io.userdata, operation); | 446 | return io.vtable.operate(io.userdata, operation); |
| 418 | } | 447 | } |
| 419 | 448 | ||
| 449 | pub const OperateTimeoutError = Cancelable || Timeout.Error || ConcurrentError; | ||
| 450 | |||
| 451 | /// Performs one `Operation` with provided `timeout`. | ||
| 452 | pub fn operateTimeout(io: Io, operation: Operation, timeout: Timeout) OperateTimeoutError!Operation.Result { | ||
| 453 | var storage: [1]Operation.Storage = undefined; | ||
| 454 | var batch: Batch = .init(&storage); | ||
| 455 | batch.addAt(0, operation); | ||
| 456 | try batch.awaitConcurrent(io, timeout); | ||
| 457 | const completion = batch.next().?; | ||
| 458 | assert(completion.index == 0); | ||
| 459 | return completion.result; | ||
| 460 | } | ||
| 461 | |||
| 420 | /// Submits many operations together without waiting for all of them to | 462 | /// Submits many operations together without waiting for all of them to |
| 421 | /// complete. | 463 | /// complete. |
| 422 | /// | 464 | /// |
| ... | @@ -1716,7 +1758,7 @@ pub const Event = enum(u32) { | ... | @@ -1716,7 +1758,7 @@ pub const Event = enum(u32) { |
| 1716 | } | 1758 | } |
| 1717 | 1759 | ||
| 1718 | /// Blocks until the logical boolean is `true`. | 1760 | /// Blocks until the logical boolean is `true`. |
| 1719 | pub fn wait(event: *Event, io: Io) Io.Cancelable!void { | 1761 | pub fn wait(event: *Event, io: Io) Cancelable!void { |
| 1720 | if (@cmpxchgStrong(Event, event, .unset, .waiting, .acquire, .acquire)) |prev| switch (prev) { | 1762 | if (@cmpxchgStrong(Event, event, .unset, .waiting, .acquire, .acquire)) |prev| switch (prev) { |
| 1721 | .unset => unreachable, | 1763 | .unset => unreachable, |
| 1722 | .waiting => {}, | 1764 | .waiting => {}, |
lib/std/Io/Dispatch.zig+3-19| ... | @@ -459,7 +459,6 @@ pub fn io(ev: *Evented) Io { | ... | @@ -459,7 +459,6 @@ pub fn io(ev: *Evented) Io { |
| 459 | .netConnectUnix = netConnectUnixUnavailable, | 459 | .netConnectUnix = netConnectUnixUnavailable, |
| 460 | .netSocketCreatePair = netSocketCreatePairUnavailable, | 460 | .netSocketCreatePair = netSocketCreatePairUnavailable, |
| 461 | .netSend = netSendUnavailable, | 461 | .netSend = netSendUnavailable, |
| 462 | .netReceive = netReceiveUnavailable, | ||
| 463 | .netRead = netReadUnavailable, | 462 | .netRead = netReadUnavailable, |
| 464 | .netWrite = netWriteUnavailable, | 463 | .netWrite = netWriteUnavailable, |
| 465 | .netWriteFile = netWriteFileUnavailable, | 464 | .netWriteFile = netWriteFileUnavailable, |
| ... | @@ -1714,6 +1713,7 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper | ... | @@ -1714,6 +1713,7 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper |
| 1714 | }, | 1713 | }, |
| 1715 | }, | 1714 | }, |
| 1716 | .device_io_control => |*o| return .{ .device_io_control = try deviceIoControl(o) }, | 1715 | .device_io_control => |*o| return .{ .device_io_control = try deviceIoControl(o) }, |
| 1716 | .net_receive => @panic("TODO implement net_receive operation"), | ||
| 1717 | } | 1717 | } |
| 1718 | } | 1718 | } |
| 1719 | 1719 | ||
| ... | @@ -2134,6 +2134,7 @@ fn batchDrainSubmitted( | ... | @@ -2134,6 +2134,7 @@ fn batchDrainSubmitted( |
| 2134 | break :result null; | 2134 | break :result null; |
| 2135 | }, | 2135 | }, |
| 2136 | .device_io_control => {}, | 2136 | .device_io_control => {}, |
| 2137 | .net_receive => @panic("TODO implement batched net_receive"), | ||
| 2137 | }; | 2138 | }; |
| 2138 | if (concurrency) return error.ConcurrencyUnavailable; | 2139 | if (concurrency) return error.ConcurrencyUnavailable; |
| 2139 | break :result try operate(ev, storage.submission.operation); | 2140 | break :result try operate(ev, storage.submission.operation); |
| ... | @@ -2192,6 +2193,7 @@ fn batchSourceEvent(context: ?*anyopaque) callconv(.c) void { | ... | @@ -2192,6 +2193,7 @@ fn batchSourceEvent(context: ?*anyopaque) callconv(.c) void { |
| 2192 | } }; | 2193 | } }; |
| 2193 | }, | 2194 | }, |
| 2194 | .device_io_control => unreachable, | 2195 | .device_io_control => unreachable, |
| 2196 | .net_receive => @panic("TODO implement batched net_receive"), | ||
| 2195 | }; | 2197 | }; |
| 2196 | 2198 | ||
| 2197 | switch (pending.node.prev) { | 2199 | switch (pending.node.prev) { |
| ... | @@ -4872,24 +4874,6 @@ fn netSendUnavailable( | ... | @@ -4872,24 +4874,6 @@ fn netSendUnavailable( |
| 4872 | return .{ error.NetworkDown, 0 }; | 4874 | return .{ error.NetworkDown, 0 }; |
| 4873 | } | 4875 | } |
| 4874 | 4876 | ||
| 4875 | fn netReceiveUnavailable( | ||
| 4876 | userdata: ?*anyopaque, | ||
| 4877 | handle: net.Socket.Handle, | ||
| 4878 | message_buffer: []net.IncomingMessage, | ||
| 4879 | data_buffer: []u8, | ||
| 4880 | flags: net.ReceiveFlags, | ||
| 4881 | timeout: Io.Timeout, | ||
| 4882 | ) struct { ?net.Socket.ReceiveTimeoutError, usize } { | ||
| 4883 | const ev: *Evented = @ptrCast(@alignCast(userdata)); | ||
| 4884 | _ = ev; | ||
| 4885 | _ = handle; | ||
| 4886 | _ = message_buffer; | ||
| 4887 | _ = data_buffer; | ||
| 4888 | _ = flags; | ||
| 4889 | _ = timeout; | ||
| 4890 | return .{ error.NetworkDown, 0 }; | ||
| 4891 | } | ||
| 4892 | |||
| 4893 | fn netReadUnavailable( | 4877 | fn netReadUnavailable( |
| 4894 | userdata: ?*anyopaque, | 4878 | userdata: ?*anyopaque, |
| 4895 | fd: net.Socket.Handle, | 4879 | fd: net.Socket.Handle, |
lib/std/Io/Threaded.zig+309-295| ... | @@ -61,7 +61,7 @@ disable_memory_mapping: bool, | ... | @@ -61,7 +61,7 @@ disable_memory_mapping: bool, |
| 61 | 61 | ||
| 62 | stderr_writer: File.Writer = .{ | 62 | stderr_writer: File.Writer = .{ |
| 63 | .io = undefined, | 63 | .io = undefined, |
| 64 | .interface = Io.File.Writer.initInterface(&.{}), | 64 | .interface = File.Writer.initInterface(&.{}), |
| 65 | .file = if (is_windows) undefined else .stderr(), | 65 | .file = if (is_windows) undefined else .stderr(), |
| 66 | .mode = .streaming, | 66 | .mode = .streaming, |
| 67 | }, | 67 | }, |
| ... | @@ -160,7 +160,7 @@ pub const Environ = struct { | ... | @@ -160,7 +160,7 @@ pub const Environ = struct { |
| 160 | }, | 160 | }, |
| 161 | }; | 161 | }; |
| 162 | 162 | ||
| 163 | pub fn scan(environ: *Environ, allocator: std.mem.Allocator) void { | 163 | pub fn scan(environ: *Environ, allocator: Allocator) void { |
| 164 | if (is_windows) { | 164 | if (is_windows) { |
| 165 | // This value expires with any call that modifies the environment, | 165 | // This value expires with any call that modifies the environment, |
| 166 | // which is outside of this Io implementation's control, so references | 166 | // which is outside of this Io implementation's control, so references |
| ... | @@ -1901,10 +1901,6 @@ pub fn io(t: *Threaded) Io { | ... | @@ -1901,10 +1901,6 @@ pub fn io(t: *Threaded) Io { |
| 1901 | .windows => netSendWindows, | 1901 | .windows => netSendWindows, |
| 1902 | else => netSendPosix, | 1902 | else => netSendPosix, |
| 1903 | }, | 1903 | }, |
| 1904 | .netReceive = switch (native_os) { | ||
| 1905 | .windows => netReceiveWindows, | ||
| 1906 | else => netReceivePosix, | ||
| 1907 | }, | ||
| 1908 | .netInterfaceNameResolve = netInterfaceNameResolve, | 1904 | .netInterfaceNameResolve = netInterfaceNameResolve, |
| 1909 | .netInterfaceName = netInterfaceName, | 1905 | .netInterfaceName = netInterfaceName, |
| 1910 | .netLookup = netLookup, | 1906 | .netLookup = netLookup, |
| ... | @@ -1912,143 +1908,10 @@ pub fn io(t: *Threaded) Io { | ... | @@ -1912,143 +1908,10 @@ pub fn io(t: *Threaded) Io { |
| 1912 | }; | 1908 | }; |
| 1913 | } | 1909 | } |
| 1914 | 1910 | ||
| 1915 | /// Same as `io` but disables all networking functionality, which has | ||
| 1916 | /// an additional dependency on Windows (ws2_32). | ||
| 1917 | pub fn ioBasic(t: *Threaded) Io { | ||
| 1918 | return .{ | ||
| 1919 | .userdata = t, | ||
| 1920 | .vtable = &.{ | ||
| 1921 | .crashHandler = crashHandler, | ||
| 1922 | |||
| 1923 | .async = async, | ||
| 1924 | .concurrent = concurrent, | ||
| 1925 | .await = await, | ||
| 1926 | .cancel = cancel, | ||
| 1927 | |||
| 1928 | .groupAsync = groupAsync, | ||
| 1929 | .groupConcurrent = groupConcurrent, | ||
| 1930 | .groupAwait = groupAwait, | ||
| 1931 | .groupCancel = groupCancel, | ||
| 1932 | |||
| 1933 | .recancel = recancel, | ||
| 1934 | .swapCancelProtection = swapCancelProtection, | ||
| 1935 | .checkCancel = checkCancel, | ||
| 1936 | |||
| 1937 | .futexWait = futexWait, | ||
| 1938 | .futexWaitUncancelable = futexWaitUncancelable, | ||
| 1939 | .futexWake = futexWake, | ||
| 1940 | |||
| 1941 | .operate = operate, | ||
| 1942 | .batchAwaitAsync = batchAwaitAsync, | ||
| 1943 | .batchAwaitConcurrent = batchAwaitConcurrent, | ||
| 1944 | .batchCancel = batchCancel, | ||
| 1945 | |||
| 1946 | .dirCreateDir = dirCreateDir, | ||
| 1947 | .dirCreateDirPath = dirCreateDirPath, | ||
| 1948 | .dirCreateDirPathOpen = dirCreateDirPathOpen, | ||
| 1949 | .dirStat = dirStat, | ||
| 1950 | .dirStatFile = dirStatFile, | ||
| 1951 | .dirAccess = dirAccess, | ||
| 1952 | .dirCreateFile = dirCreateFile, | ||
| 1953 | .dirCreateFileAtomic = dirCreateFileAtomic, | ||
| 1954 | .dirOpenFile = dirOpenFile, | ||
| 1955 | .dirOpenDir = dirOpenDir, | ||
| 1956 | .dirClose = dirClose, | ||
| 1957 | .dirRead = dirRead, | ||
| 1958 | .dirRealPath = dirRealPath, | ||
| 1959 | .dirRealPathFile = dirRealPathFile, | ||
| 1960 | .dirDeleteFile = dirDeleteFile, | ||
| 1961 | .dirDeleteDir = dirDeleteDir, | ||
| 1962 | .dirRename = dirRename, | ||
| 1963 | .dirRenamePreserve = dirRenamePreserve, | ||
| 1964 | .dirSymLink = dirSymLink, | ||
| 1965 | .dirReadLink = dirReadLink, | ||
| 1966 | .dirSetOwner = dirSetOwner, | ||
| 1967 | .dirSetFileOwner = dirSetFileOwner, | ||
| 1968 | .dirSetPermissions = dirSetPermissions, | ||
| 1969 | .dirSetFilePermissions = dirSetFilePermissions, | ||
| 1970 | .dirSetTimestamps = dirSetTimestamps, | ||
| 1971 | .dirHardLink = dirHardLink, | ||
| 1972 | |||
| 1973 | .fileStat = fileStat, | ||
| 1974 | .fileLength = fileLength, | ||
| 1975 | .fileClose = fileClose, | ||
| 1976 | .fileWritePositional = fileWritePositional, | ||
| 1977 | .fileWriteFileStreaming = fileWriteFileStreaming, | ||
| 1978 | .fileWriteFilePositional = fileWriteFilePositional, | ||
| 1979 | .fileReadPositional = fileReadPositional, | ||
| 1980 | .fileSeekBy = fileSeekBy, | ||
| 1981 | .fileSeekTo = fileSeekTo, | ||
| 1982 | .fileSync = fileSync, | ||
| 1983 | .fileIsTty = fileIsTty, | ||
| 1984 | .fileEnableAnsiEscapeCodes = fileEnableAnsiEscapeCodes, | ||
| 1985 | .fileSupportsAnsiEscapeCodes = fileSupportsAnsiEscapeCodes, | ||
| 1986 | .fileSetLength = fileSetLength, | ||
| 1987 | .fileSetOwner = fileSetOwner, | ||
| 1988 | .fileSetPermissions = fileSetPermissions, | ||
| 1989 | .fileSetTimestamps = fileSetTimestamps, | ||
| 1990 | .fileLock = fileLock, | ||
| 1991 | .fileTryLock = fileTryLock, | ||
| 1992 | .fileUnlock = fileUnlock, | ||
| 1993 | .fileDowngradeLock = fileDowngradeLock, | ||
| 1994 | .fileRealPath = fileRealPath, | ||
| 1995 | .fileHardLink = fileHardLink, | ||
| 1996 | |||
| 1997 | .fileMemoryMapCreate = fileMemoryMapCreate, | ||
| 1998 | .fileMemoryMapDestroy = fileMemoryMapDestroy, | ||
| 1999 | .fileMemoryMapSetLength = fileMemoryMapSetLength, | ||
| 2000 | .fileMemoryMapRead = fileMemoryMapRead, | ||
| 2001 | .fileMemoryMapWrite = fileMemoryMapWrite, | ||
| 2002 | |||
| 2003 | .processExecutableOpen = processExecutableOpen, | ||
| 2004 | .processExecutablePath = processExecutablePath, | ||
| 2005 | .lockStderr = lockStderr, | ||
| 2006 | .tryLockStderr = tryLockStderr, | ||
| 2007 | .unlockStderr = unlockStderr, | ||
| 2008 | .processCurrentPath = processCurrentPath, | ||
| 2009 | .processSetCurrentDir = processSetCurrentDir, | ||
| 2010 | .processSetCurrentPath = processSetCurrentPath, | ||
| 2011 | .processReplace = processReplace, | ||
| 2012 | .processReplacePath = processReplacePath, | ||
| 2013 | .processSpawn = processSpawn, | ||
| 2014 | .processSpawnPath = processSpawnPath, | ||
| 2015 | .childWait = childWait, | ||
| 2016 | .childKill = childKill, | ||
| 2017 | |||
| 2018 | .progressParentFile = progressParentFile, | ||
| 2019 | |||
| 2020 | .now = now, | ||
| 2021 | .clockResolution = clockResolution, | ||
| 2022 | .sleep = sleep, | ||
| 2023 | |||
| 2024 | .random = random, | ||
| 2025 | .randomSecure = randomSecure, | ||
| 2026 | |||
| 2027 | .netListenIp = netListenIpUnavailable, | ||
| 2028 | .netListenUnix = netListenUnixUnavailable, | ||
| 2029 | .netAccept = netAcceptUnavailable, | ||
| 2030 | .netBindIp = netBindIpUnavailable, | ||
| 2031 | .netConnectIp = netConnectIpUnavailable, | ||
| 2032 | .netSocketCreatePair = netSocketCreatePairUnavailable, | ||
| 2033 | .netConnectUnix = netConnectUnixUnavailable, | ||
| 2034 | .netClose = netCloseUnavailable, | ||
| 2035 | .netShutdown = netShutdownUnavailable, | ||
| 2036 | .netRead = netReadUnavailable, | ||
| 2037 | .netWrite = netWriteUnavailable, | ||
| 2038 | .netWriteFile = netWriteFileUnavailable, | ||
| 2039 | .netSend = netSendUnavailable, | ||
| 2040 | .netReceive = netReceiveUnavailable, | ||
| 2041 | .netInterfaceNameResolve = netInterfaceNameResolveUnavailable, | ||
| 2042 | .netInterfaceName = netInterfaceNameUnavailable, | ||
| 2043 | .netLookup = netLookupUnavailable, | ||
| 2044 | }, | ||
| 2045 | }; | ||
| 2046 | } | ||
| 2047 | |||
| 2048 | pub const socket_flags_unsupported = is_darwin or native_os == .haiku; | 1911 | pub const socket_flags_unsupported = is_darwin or native_os == .haiku; |
| 2049 | const have_accept4 = !socket_flags_unsupported; | 1912 | const have_accept4 = !socket_flags_unsupported; |
| 2050 | const have_flock_open_flags = @hasField(posix.O, "EXLOCK"); | 1913 | const have_flock_open_flags = @hasField(posix.O, "EXLOCK"); |
| 2051 | const have_networking = native_os != .wasi; | 1914 | const have_networking = std.options.networking and native_os != .wasi; |
| 2052 | const have_flock = @TypeOf(posix.system.flock) != void; | 1915 | const have_flock = @TypeOf(posix.system.flock) != void; |
| 2053 | const have_sendmmsg = native_os == .linux; | 1916 | const have_sendmmsg = native_os == .linux; |
| 2054 | const have_futex = switch (builtin.cpu.arch) { | 1917 | const have_futex = switch (builtin.cpu.arch) { |
| ... | @@ -2600,7 +2463,7 @@ fn futexWait(userdata: ?*anyopaque, ptr: *const u32, expected: u32, timeout: Io. | ... | @@ -2600,7 +2463,7 @@ fn futexWait(userdata: ?*anyopaque, ptr: *const u32, expected: u32, timeout: Io. |
| 2600 | return; | 2463 | return; |
| 2601 | } | 2464 | } |
| 2602 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 2465 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2603 | const t_io = ioBasic(t); | 2466 | const t_io = io(t); |
| 2604 | const timeout_ns: ?u64 = ns: { | 2467 | const timeout_ns: ?u64 = ns: { |
| 2605 | const d = timeout.toDurationFromNow(t_io) orelse break :ns null; | 2468 | const d = timeout.toDurationFromNow(t_io) orelse break :ns null; |
| 2606 | break :ns std.math.lossyCast(u64, d.raw.toNanoseconds()); | 2469 | break :ns std.math.lossyCast(u64, d.raw.toNanoseconds()); |
| ... | @@ -2638,13 +2501,23 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper | ... | @@ -2638,13 +2501,23 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper |
| 2638 | }, | 2501 | }, |
| 2639 | }, | 2502 | }, |
| 2640 | .device_io_control => |*o| return .{ .device_io_control = try deviceIoControl(o) }, | 2503 | .device_io_control => |*o| return .{ .device_io_control = try deviceIoControl(o) }, |
| 2504 | .net_receive => |*o| return .{ .net_receive = o: { | ||
| 2505 | if (!have_networking) break :o .{ error.NetworkDown, 0 }; | ||
| 2506 | if (is_windows) break :o netReceiveWindows(t, o.socket_handle, o.message_buffer, o.data_buffer, o.flags); | ||
| 2507 | netReceivePosix(o.socket_handle, &o.message_buffer[0], o.data_buffer, o.flags, false) catch |err| switch (err) { | ||
| 2508 | error.Canceled => |e| return e, | ||
| 2509 | error.WouldBlock => unreachable, | ||
| 2510 | else => |e| break :o .{ e, 0 }, | ||
| 2511 | }; | ||
| 2512 | break :o .{ null, 1 }; | ||
| 2513 | } }, | ||
| 2641 | } | 2514 | } |
| 2642 | } | 2515 | } |
| 2643 | 2516 | ||
| 2644 | fn batchAwaitAsync(userdata: ?*anyopaque, b: *Io.Batch) Io.Cancelable!void { | 2517 | fn batchAwaitAsync(userdata: ?*anyopaque, b: *Io.Batch) Io.Cancelable!void { |
| 2645 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 2518 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2646 | if (is_windows) { | 2519 | if (is_windows) { |
| 2647 | batchDrainSubmittedWindows(b, false) catch |err| switch (err) { | 2520 | batchDrainSubmittedWindows(t, b, false) catch |err| switch (err) { |
| 2648 | error.ConcurrencyUnavailable => unreachable, // passed concurrency=false | 2521 | error.ConcurrencyUnavailable => unreachable, // passed concurrency=false |
| 2649 | else => |e| return e, | 2522 | else => |e| return e, |
| 2650 | }; | 2523 | }; |
| ... | @@ -2662,11 +2535,19 @@ fn batchAwaitAsync(userdata: ?*anyopaque, b: *Io.Batch) Io.Cancelable!void { | ... | @@ -2662,11 +2535,19 @@ fn batchAwaitAsync(userdata: ?*anyopaque, b: *Io.Batch) Io.Cancelable!void { |
| 2662 | const submission = &b.storage[index.toIndex()].submission; | 2535 | const submission = &b.storage[index.toIndex()].submission; |
| 2663 | switch (submission.operation) { | 2536 | switch (submission.operation) { |
| 2664 | .file_read_streaming => |o| { | 2537 | .file_read_streaming => |o| { |
| 2665 | poll_buffer[poll_len] = .{ .fd = o.file.handle, .events = posix.POLL.IN, .revents = 0 }; | 2538 | poll_buffer[poll_len] = .{ |
| 2539 | .fd = o.file.handle, | ||
| 2540 | .events = posix.POLL.IN | posix.POLL.ERR, | ||
| 2541 | .revents = 0, | ||
| 2542 | }; | ||
| 2666 | poll_len += 1; | 2543 | poll_len += 1; |
| 2667 | }, | 2544 | }, |
| 2668 | .file_write_streaming => |o| { | 2545 | .file_write_streaming => |o| { |
| 2669 | poll_buffer[poll_len] = .{ .fd = o.file.handle, .events = posix.POLL.OUT, .revents = 0 }; | 2546 | poll_buffer[poll_len] = .{ |
| 2547 | .fd = o.file.handle, | ||
| 2548 | .events = posix.POLL.OUT | posix.POLL.ERR, | ||
| 2549 | .revents = 0, | ||
| 2550 | }; | ||
| 2670 | poll_len += 1; | 2551 | poll_len += 1; |
| 2671 | }, | 2552 | }, |
| 2672 | .device_io_control => |o| { | 2553 | .device_io_control => |o| { |
| ... | @@ -2677,6 +2558,14 @@ fn batchAwaitAsync(userdata: ?*anyopaque, b: *Io.Batch) Io.Cancelable!void { | ... | @@ -2677,6 +2558,14 @@ fn batchAwaitAsync(userdata: ?*anyopaque, b: *Io.Batch) Io.Cancelable!void { |
| 2677 | }; | 2558 | }; |
| 2678 | poll_len += 1; | 2559 | poll_len += 1; |
| 2679 | }, | 2560 | }, |
| 2561 | .net_receive => |*o| { | ||
| 2562 | poll_buffer[poll_len] = .{ | ||
| 2563 | .fd = o.socket_handle, | ||
| 2564 | .events = posix.POLL.IN | posix.POLL.ERR, | ||
| 2565 | .revents = 0, | ||
| 2566 | }; | ||
| 2567 | poll_len += 1; | ||
| 2568 | }, | ||
| 2680 | } | 2569 | } |
| 2681 | index = submission.node.next; | 2570 | index = submission.node.next; |
| 2682 | } | 2571 | } |
| ... | @@ -2767,8 +2656,8 @@ fn batchAwaitAsync(userdata: ?*anyopaque, b: *Io.Batch) Io.Cancelable!void { | ... | @@ -2767,8 +2656,8 @@ fn batchAwaitAsync(userdata: ?*anyopaque, b: *Io.Batch) Io.Cancelable!void { |
| 2767 | fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout) Io.Batch.AwaitConcurrentError!void { | 2656 | fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout) Io.Batch.AwaitConcurrentError!void { |
| 2768 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 2657 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2769 | if (is_windows) { | 2658 | if (is_windows) { |
| 2770 | const deadline: ?Io.Clock.Timestamp = timeout.toTimestamp(ioBasic(t)); | 2659 | const deadline: ?Io.Clock.Timestamp = timeout.toTimestamp(io(t)); |
| 2771 | try batchDrainSubmittedWindows(b, true); | 2660 | try batchDrainSubmittedWindows(t, b, true); |
| 2772 | while (b.pending.head != .none and b.completed.head == .none) { | 2661 | while (b.pending.head != .none and b.completed.head == .none) { |
| 2773 | var delay_interval: windows.LARGE_INTEGER = interval: { | 2662 | var delay_interval: windows.LARGE_INTEGER = interval: { |
| 2774 | const d = deadline orelse break :interval std.math.minInt(windows.LARGE_INTEGER); | 2663 | const d = deadline orelse break :interval std.math.minInt(windows.LARGE_INTEGER); |
| ... | @@ -2796,12 +2685,12 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout | ... | @@ -2796,12 +2685,12 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout |
| 2796 | if (!have_poll) return error.ConcurrencyUnavailable; | 2685 | if (!have_poll) return error.ConcurrencyUnavailable; |
| 2797 | var poll_buffer: [poll_buffer_len]posix.pollfd = undefined; | 2686 | var poll_buffer: [poll_buffer_len]posix.pollfd = undefined; |
| 2798 | var poll_storage: struct { | 2687 | var poll_storage: struct { |
| 2799 | gpa: std.mem.Allocator, | 2688 | gpa: Allocator, |
| 2800 | batch: *Io.Batch, | 2689 | batch: *Io.Batch, |
| 2801 | slice: []posix.pollfd, | 2690 | slice: []posix.pollfd, |
| 2802 | len: u32, | 2691 | len: u32, |
| 2803 | 2692 | ||
| 2804 | fn add(storage: *@This(), file: Io.File, events: @FieldType(posix.pollfd, "events")) Io.ConcurrentError!void { | 2693 | fn add(storage: *@This(), fd: File.Handle, events: @FieldType(posix.pollfd, "events")) Io.ConcurrentError!void { |
| 2805 | const len = storage.len; | 2694 | const len = storage.len; |
| 2806 | if (len == poll_buffer_len) { | 2695 | if (len == poll_buffer_len) { |
| 2807 | const slice: []posix.pollfd = if (storage.batch.userdata) |batch_userdata| | 2696 | const slice: []posix.pollfd = if (storage.batch.userdata) |batch_userdata| |
| ... | @@ -2816,7 +2705,7 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout | ... | @@ -2816,7 +2705,7 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout |
| 2816 | storage.slice = slice; | 2705 | storage.slice = slice; |
| 2817 | } | 2706 | } |
| 2818 | storage.slice[len] = .{ | 2707 | storage.slice[len] = .{ |
| 2819 | .fd = file.handle, | 2708 | .fd = fd, |
| 2820 | .events = events, | 2709 | .events = events, |
| 2821 | .revents = 0, | 2710 | .revents = 0, |
| 2822 | }; | 2711 | }; |
| ... | @@ -2826,18 +2715,41 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout | ... | @@ -2826,18 +2715,41 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout |
| 2826 | { | 2715 | { |
| 2827 | var index = b.submitted.head; | 2716 | var index = b.submitted.head; |
| 2828 | while (index != .none) { | 2717 | while (index != .none) { |
| 2829 | const submission = &b.storage[index.toIndex()].submission; | 2718 | const storage = &b.storage[index.toIndex()]; |
| 2719 | const submission = storage.submission; | ||
| 2830 | switch (submission.operation) { | 2720 | switch (submission.operation) { |
| 2831 | .file_read_streaming => |o| try poll_storage.add(o.file, posix.POLL.IN), | 2721 | .file_read_streaming => |o| try poll_storage.add(o.file.handle, posix.POLL.IN | posix.POLL.ERR), |
| 2832 | .file_write_streaming => |o| try poll_storage.add(o.file, posix.POLL.OUT), | 2722 | .file_write_streaming => |o| try poll_storage.add(o.file.handle, posix.POLL.OUT | posix.POLL.ERR), |
| 2833 | .device_io_control => |o| try poll_storage.add(o.file, posix.POLL.IN | posix.POLL.OUT | posix.POLL.ERR), | 2723 | .device_io_control => |o| try poll_storage.add(o.file.handle, posix.POLL.IN | posix.POLL.OUT | posix.POLL.ERR), |
| 2724 | .net_receive => |*o| nb: { | ||
| 2725 | var data_i: usize = 0; | ||
| 2726 | const result: Io.Operation.Result = .{ .net_receive = for (o.message_buffer, 0..) |*msg, msg_i| { | ||
| 2727 | const remaining_data_buffer = o.data_buffer[data_i..]; | ||
| 2728 | netReceivePosix(o.socket_handle, msg, remaining_data_buffer, o.flags, true) catch |err| switch (err) { | ||
| 2729 | error.Canceled => |e| return e, | ||
| 2730 | error.WouldBlock => { | ||
| 2731 | if (msg_i != 0) break .{ null, msg_i }; | ||
| 2732 | try poll_storage.add(o.socket_handle, posix.POLL.IN | posix.POLL.ERR); | ||
| 2733 | break :nb; | ||
| 2734 | }, | ||
| 2735 | else => |e| break .{ e, 0 }, | ||
| 2736 | }; | ||
| 2737 | data_i += msg.data.len; | ||
| 2738 | } else .{ null, o.message_buffer.len } }; | ||
| 2739 | switch (b.completed.tail) { | ||
| 2740 | .none => b.completed.head = index, | ||
| 2741 | else => |tail_index| b.storage[tail_index.toIndex()].completion.node.next = index, | ||
| 2742 | } | ||
| 2743 | storage.* = .{ .completion = .{ .node = .{ .next = .none }, .result = result } }; | ||
| 2744 | b.completed.tail = index; | ||
| 2745 | }, | ||
| 2834 | } | 2746 | } |
| 2835 | index = submission.node.next; | 2747 | index = submission.node.next; |
| 2836 | } | 2748 | } |
| 2837 | } | 2749 | } |
| 2838 | switch (poll_storage.len) { | 2750 | switch (poll_storage.len) { |
| 2839 | 0 => return, | 2751 | 0 => return, |
| 2840 | 1 => if (timeout == .none) { | 2752 | 1 => if (timeout == .none and b.completed.head == .none) { |
| 2841 | const index = b.submitted.head; | 2753 | const index = b.submitted.head; |
| 2842 | const storage = &b.storage[index.toIndex()]; | 2754 | const storage = &b.storage[index.toIndex()]; |
| 2843 | const result = try operate(t, storage.submission.operation); | 2755 | const result = try operate(t, storage.submission.operation); |
| ... | @@ -2854,7 +2766,7 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout | ... | @@ -2854,7 +2766,7 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout |
| 2854 | }, | 2766 | }, |
| 2855 | else => {}, | 2767 | else => {}, |
| 2856 | } | 2768 | } |
| 2857 | const t_io = ioBasic(t); | 2769 | const t_io = io(t); |
| 2858 | const deadline = timeout.toTimestamp(t_io); | 2770 | const deadline = timeout.toTimestamp(t_io); |
| 2859 | while (true) { | 2771 | while (true) { |
| 2860 | const timeout_ms: i32 = t: { | 2772 | const timeout_ms: i32 = t: { |
| ... | @@ -2961,6 +2873,31 @@ fn batchCancel(userdata: ?*anyopaque, b: *Io.Batch) void { | ... | @@ -2961,6 +2873,31 @@ fn batchCancel(userdata: ?*anyopaque, b: *Io.Batch) void { |
| 2961 | } | 2873 | } |
| 2962 | } | 2874 | } |
| 2963 | 2875 | ||
| 2876 | fn batchCompleteBlockingWindows( | ||
| 2877 | b: *Io.Batch, | ||
| 2878 | operation_userdata: *WindowsBatchOperationUserdata, | ||
| 2879 | result: Io.Operation.Result, | ||
| 2880 | ) void { | ||
| 2881 | const erased_userdata = operation_userdata.toErased(); | ||
| 2882 | const pending: *Io.Operation.Storage.Pending = @fieldParentPtr("userdata", erased_userdata); | ||
| 2883 | switch (pending.node.prev) { | ||
| 2884 | .none => b.pending.head = pending.node.next, | ||
| 2885 | else => |prev_index| b.storage[prev_index.toIndex()].pending.node.next = pending.node.next, | ||
| 2886 | } | ||
| 2887 | switch (pending.node.next) { | ||
| 2888 | .none => b.pending.tail = pending.node.prev, | ||
| 2889 | else => |next_index| b.storage[next_index.toIndex()].pending.node.prev = pending.node.prev, | ||
| 2890 | } | ||
| 2891 | const storage: *Io.Operation.Storage = @fieldParentPtr("pending", pending); | ||
| 2892 | const index: Io.Operation.OptionalIndex = .fromIndex(storage - b.storage.ptr); | ||
| 2893 | switch (b.completed.tail) { | ||
| 2894 | .none => b.completed.head = index, | ||
| 2895 | else => |tail_index| b.storage[tail_index.toIndex()].completion.node.next = index, | ||
| 2896 | } | ||
| 2897 | b.completed.tail = index; | ||
| 2898 | storage.* = .{ .completion = .{ .node = .{ .next = .none }, .result = result } }; | ||
| 2899 | } | ||
| 2900 | |||
| 2964 | fn batchApc( | 2901 | fn batchApc( |
| 2965 | apc_context: ?*anyopaque, | 2902 | apc_context: ?*anyopaque, |
| 2966 | iosb: *windows.IO_STATUS_BLOCK, | 2903 | iosb: *windows.IO_STATUS_BLOCK, |
| ... | @@ -3000,6 +2937,7 @@ fn batchApc( | ... | @@ -3000,6 +2937,7 @@ fn batchApc( |
| 3000 | .file_read_streaming => .{ .file_read_streaming = ntReadFileResult(iosb) }, | 2937 | .file_read_streaming => .{ .file_read_streaming = ntReadFileResult(iosb) }, |
| 3001 | .file_write_streaming => .{ .file_write_streaming = ntWriteFileResult(iosb) }, | 2938 | .file_write_streaming => .{ .file_write_streaming = ntWriteFileResult(iosb) }, |
| 3002 | .device_io_control => .{ .device_io_control = iosb.* }, | 2939 | .device_io_control => .{ .device_io_control = iosb.* }, |
| 2940 | .net_receive => unreachable, | ||
| 3003 | }; | 2941 | }; |
| 3004 | storage.* = .{ .completion = .{ .node = .{ .next = .none }, .result = result } }; | 2942 | storage.* = .{ .completion = .{ .node = .{ .next = .none }, .result = result } }; |
| 3005 | }, | 2943 | }, |
| ... | @@ -3007,7 +2945,7 @@ fn batchApc( | ... | @@ -3007,7 +2945,7 @@ fn batchApc( |
| 3007 | } | 2945 | } |
| 3008 | 2946 | ||
| 3009 | /// If `concurrency` is false, `error.ConcurrencyUnavailable` is unreachable. | 2947 | /// If `concurrency` is false, `error.ConcurrencyUnavailable` is unreachable. |
| 3010 | fn batchDrainSubmittedWindows(b: *Io.Batch, concurrency: bool) (Io.ConcurrentError || Io.Cancelable)!void { | 2948 | fn batchDrainSubmittedWindows(t: *Threaded, b: *Io.Batch, concurrency: bool) (Io.ConcurrentError || Io.Cancelable)!void { |
| 3011 | var index = b.submitted.head; | 2949 | var index = b.submitted.head; |
| 3012 | errdefer b.submitted.head = index; | 2950 | errdefer b.submitted.head = index; |
| 3013 | while (index != .none) { | 2951 | while (index != .none) { |
| ... | @@ -3201,6 +3139,13 @@ fn batchDrainSubmittedWindows(b: *Io.Batch, concurrency: bool) (Io.ConcurrentErr | ... | @@ -3201,6 +3139,13 @@ fn batchDrainSubmittedWindows(b: *Io.Batch, concurrency: bool) (Io.ConcurrentErr |
| 3201 | }; | 3139 | }; |
| 3202 | } | 3140 | } |
| 3203 | }, | 3141 | }, |
| 3142 | .net_receive => |*o| { | ||
| 3143 | // TODO integrate with overlapped I/O or equivalent to avoid this error | ||
| 3144 | if (concurrency) return error.ConcurrencyUnavailable; | ||
| 3145 | batchCompleteBlockingWindows(b, operation_userdata, .{ | ||
| 3146 | .net_receive = netReceiveWindows(t, o.socket_handle, o.message_buffer, o.data_buffer, o.flags), | ||
| 3147 | }); | ||
| 3148 | }, | ||
| 3204 | } | 3149 | } |
| 3205 | index = submission.node.next; | 3150 | index = submission.node.next; |
| 3206 | } | 3151 | } |
| ... | @@ -3459,7 +3404,7 @@ fn dirCreateDirPathOpenPosix( | ... | @@ -3459,7 +3404,7 @@ fn dirCreateDirPathOpenPosix( |
| 3459 | options: Dir.OpenOptions, | 3404 | options: Dir.OpenOptions, |
| 3460 | ) Dir.CreateDirPathOpenError!Dir { | 3405 | ) Dir.CreateDirPathOpenError!Dir { |
| 3461 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 3406 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 3462 | const t_io = ioBasic(t); | 3407 | const t_io = io(t); |
| 3463 | return dirOpenDirPosix(t, dir, sub_path, options) catch |err| switch (err) { | 3408 | return dirOpenDirPosix(t, dir, sub_path, options) catch |err| switch (err) { |
| 3464 | error.FileNotFound => { | 3409 | error.FileNotFound => { |
| 3465 | _ = try dir.createDirPathStatus(t_io, sub_path, permissions); | 3410 | _ = try dir.createDirPathStatus(t_io, sub_path, permissions); |
| ... | @@ -3580,7 +3525,7 @@ fn dirCreateDirPathOpenWasi( | ... | @@ -3580,7 +3525,7 @@ fn dirCreateDirPathOpenWasi( |
| 3580 | options: Dir.OpenOptions, | 3525 | options: Dir.OpenOptions, |
| 3581 | ) Dir.CreateDirPathOpenError!Dir { | 3526 | ) Dir.CreateDirPathOpenError!Dir { |
| 3582 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 3527 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 3583 | const t_io = ioBasic(t); | 3528 | const t_io = io(t); |
| 3584 | return dirOpenDirWasi(t, dir, sub_path, options) catch |err| switch (err) { | 3529 | return dirOpenDirWasi(t, dir, sub_path, options) catch |err| switch (err) { |
| 3585 | error.FileNotFound => { | 3530 | error.FileNotFound => { |
| 3586 | _ = try dir.createDirPathStatus(t_io, sub_path, permissions); | 3531 | _ = try dir.createDirPathStatus(t_io, sub_path, permissions); |
| ... | @@ -4621,7 +4566,7 @@ fn dirCreateFileAtomic( | ... | @@ -4621,7 +4566,7 @@ fn dirCreateFileAtomic( |
| 4621 | options: Dir.CreateFileAtomicOptions, | 4566 | options: Dir.CreateFileAtomicOptions, |
| 4622 | ) Dir.CreateFileAtomicError!File.Atomic { | 4567 | ) Dir.CreateFileAtomicError!File.Atomic { |
| 4623 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 4568 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 4624 | const t_io = ioBasic(t); | 4569 | const t_io = io(t); |
| 4625 | 4570 | ||
| 4626 | // Linux has O_TMPFILE, but linkat() does not support AT_REPLACE, so it's | 4571 | // Linux has O_TMPFILE, but linkat() does not support AT_REPLACE, so it's |
| 4627 | // useless when we have to make up a bogus path name to do the rename() | 4572 | // useless when we have to make up a bogus path name to do the rename() |
| ... | @@ -10249,19 +10194,19 @@ fn processExecutablePath(userdata: ?*anyopaque, out_buffer: []u8) process.Execut | ... | @@ -10249,19 +10194,19 @@ fn processExecutablePath(userdata: ?*anyopaque, out_buffer: []u8) process.Execut |
| 10249 | const rc = std.c._NSGetExecutablePath(&symlink_path_buf, &n); | 10194 | const rc = std.c._NSGetExecutablePath(&symlink_path_buf, &n); |
| 10250 | if (rc != 0) return error.NameTooLong; | 10195 | if (rc != 0) return error.NameTooLong; |
| 10251 | const symlink_path = std.mem.sliceTo(&symlink_path_buf, 0); | 10196 | const symlink_path = std.mem.sliceTo(&symlink_path_buf, 0); |
| 10252 | return Io.Dir.realPathFileAbsolute(ioBasic(t), symlink_path, out_buffer) catch |err| switch (err) { | 10197 | return Io.Dir.realPathFileAbsolute(io(t), symlink_path, out_buffer) catch |err| switch (err) { |
| 10253 | error.NetworkNotFound => unreachable, // Windows-only | 10198 | error.NetworkNotFound => unreachable, // Windows-only |
| 10254 | error.FileBusy => unreachable, // Windows-only | 10199 | error.FileBusy => unreachable, // Windows-only |
| 10255 | else => |e| return e, | 10200 | else => |e| return e, |
| 10256 | }; | 10201 | }; |
| 10257 | }, | 10202 | }, |
| 10258 | .linux, .serenity => return Io.Dir.readLinkAbsolute(ioBasic(t), "/proc/self/exe", out_buffer) catch |err| switch (err) { | 10203 | .linux, .serenity => return Io.Dir.readLinkAbsolute(io(t), "/proc/self/exe", out_buffer) catch |err| switch (err) { |
| 10259 | error.UnsupportedReparsePointType => unreachable, // Windows-only | 10204 | error.UnsupportedReparsePointType => unreachable, // Windows-only |
| 10260 | error.NetworkNotFound => unreachable, // Windows-only | 10205 | error.NetworkNotFound => unreachable, // Windows-only |
| 10261 | error.FileBusy => unreachable, // Windows-only | 10206 | error.FileBusy => unreachable, // Windows-only |
| 10262 | else => |e| return e, | 10207 | else => |e| return e, |
| 10263 | }, | 10208 | }, |
| 10264 | .illumos => return Io.Dir.readLinkAbsolute(ioBasic(t), "/proc/self/path/a.out", out_buffer) catch |err| switch (err) { | 10209 | .illumos => return Io.Dir.readLinkAbsolute(io(t), "/proc/self/path/a.out", out_buffer) catch |err| switch (err) { |
| 10265 | error.UnsupportedReparsePointType => unreachable, // Windows-only | 10210 | error.UnsupportedReparsePointType => unreachable, // Windows-only |
| 10266 | error.NetworkNotFound => unreachable, // Windows-only | 10211 | error.NetworkNotFound => unreachable, // Windows-only |
| 10267 | error.FileBusy => unreachable, // Windows-only | 10212 | error.FileBusy => unreachable, // Windows-only |
| ... | @@ -11623,7 +11568,7 @@ fn sleepPosix(timeout: Io.Timeout) Io.Cancelable!void { | ... | @@ -11623,7 +11568,7 @@ fn sleepPosix(timeout: Io.Timeout) Io.Cancelable!void { |
| 11623 | } | 11568 | } |
| 11624 | 11569 | ||
| 11625 | fn sleepWasi(t: *Threaded, timeout: Io.Timeout) Io.Cancelable!void { | 11570 | fn sleepWasi(t: *Threaded, timeout: Io.Timeout) Io.Cancelable!void { |
| 11626 | const t_io = ioBasic(t); | 11571 | const t_io = io(t); |
| 11627 | const w = std.os.wasi; | 11572 | const w = std.os.wasi; |
| 11628 | 11573 | ||
| 11629 | const clock: w.subscription_clock_t = if (timeout.toDurationFromNow(t_io)) |d| .{ | 11574 | const clock: w.subscription_clock_t = if (timeout.toDurationFromNow(t_io)) |d| .{ |
| ... | @@ -11652,7 +11597,7 @@ fn sleepWasi(t: *Threaded, timeout: Io.Timeout) Io.Cancelable!void { | ... | @@ -11652,7 +11597,7 @@ fn sleepWasi(t: *Threaded, timeout: Io.Timeout) Io.Cancelable!void { |
| 11652 | } | 11597 | } |
| 11653 | 11598 | ||
| 11654 | fn sleepNanosleep(t: *Threaded, timeout: Io.Timeout) Io.Cancelable!void { | 11599 | fn sleepNanosleep(t: *Threaded, timeout: Io.Timeout) Io.Cancelable!void { |
| 11655 | const t_io = ioBasic(t); | 11600 | const t_io = io(t); |
| 11656 | const sec_type = @typeInfo(posix.timespec).@"struct".fields[0].type; | 11601 | const sec_type = @typeInfo(posix.timespec).@"struct".fields[0].type; |
| 11657 | const nsec_type = @typeInfo(posix.timespec).@"struct".fields[1].type; | 11602 | const nsec_type = @typeInfo(posix.timespec).@"struct".fields[1].type; |
| 11658 | 11603 | ||
| ... | @@ -11884,6 +11829,7 @@ fn netListenUnixWindows( | ... | @@ -11884,6 +11829,7 @@ fn netListenUnixWindows( |
| 11884 | options: net.UnixAddress.ListenOptions, | 11829 | options: net.UnixAddress.ListenOptions, |
| 11885 | ) net.UnixAddress.ListenError!net.Socket.Handle { | 11830 | ) net.UnixAddress.ListenError!net.Socket.Handle { |
| 11886 | if (!net.has_unix_sockets) return error.AddressFamilyUnsupported; | 11831 | if (!net.has_unix_sockets) return error.AddressFamilyUnsupported; |
| 11832 | if (!have_networking) return error.NetworkDown; | ||
| 11887 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 11833 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 11888 | 11834 | ||
| 11889 | const socket_handle = openSocketWsa(t, posix.AF.UNIX, .{ .mode = .stream }) catch |err| switch (err) { | 11835 | const socket_handle = openSocketWsa(t, posix.AF.UNIX, .{ .mode = .stream }) catch |err| switch (err) { |
| ... | @@ -12380,6 +12326,7 @@ fn netConnectUnixWindows( | ... | @@ -12380,6 +12326,7 @@ fn netConnectUnixWindows( |
| 12380 | address: *const net.UnixAddress, | 12326 | address: *const net.UnixAddress, |
| 12381 | ) net.UnixAddress.ConnectError!net.Socket.Handle { | 12327 | ) net.UnixAddress.ConnectError!net.Socket.Handle { |
| 12382 | if (!net.has_unix_sockets) return error.AddressFamilyUnsupported; | 12328 | if (!net.has_unix_sockets) return error.AddressFamilyUnsupported; |
| 12329 | if (!have_networking) return error.NetworkDown; | ||
| 12383 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 12330 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 12384 | 12331 | ||
| 12385 | const socket_handle = try openSocketWsa(t, posix.AF.UNIX, .{ .mode = .stream }); | 12332 | const socket_handle = try openSocketWsa(t, posix.AF.UNIX, .{ .mode = .stream }); |
| ... | @@ -12995,11 +12942,76 @@ fn netSendWindows( | ... | @@ -12995,11 +12942,76 @@ fn netSendWindows( |
| 12995 | ) struct { ?net.Socket.SendError, usize } { | 12942 | ) struct { ?net.Socket.SendError, usize } { |
| 12996 | if (!have_networking) return .{ error.NetworkDown, 0 }; | 12943 | if (!have_networking) return .{ error.NetworkDown, 0 }; |
| 12997 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 12944 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 12998 | _ = t; | 12945 | |
| 12999 | _ = handle; | 12946 | // Ignored flags: confirm, eor, fastopen |
| 13000 | _ = messages; | 12947 | const windows_flags: u32 = |
| 13001 | _ = flags; | 12948 | @as(u32, if (flags.oob) ws2_32.MSG.OOB else 0) | |
| 13002 | @panic("TODO netSendWindows"); | 12949 | @as(u32, if (flags.dont_route) ws2_32.MSG.DONTROUTE else 0); |
| 12950 | |||
| 12951 | for (messages, 0..) |*m, i| { | ||
| 12952 | netSendWindowsOne(t, handle, m, windows_flags) catch |err| return .{ err, i }; | ||
| 12953 | } | ||
| 12954 | return .{ null, messages.len }; | ||
| 12955 | } | ||
| 12956 | |||
| 12957 | fn netSendWindowsOne( | ||
| 12958 | t: *Threaded, | ||
| 12959 | handle: net.Socket.Handle, | ||
| 12960 | message: *net.OutgoingMessage, | ||
| 12961 | flags: u32, | ||
| 12962 | ) net.Socket.SendError!void { | ||
| 12963 | var buf: ws2_32.WSABUF = .{ | ||
| 12964 | .buf = @constCast(message.data_ptr), | ||
| 12965 | .len = std.math.cast(u32, message.data_len) orelse return error.MessageOversize, | ||
| 12966 | }; | ||
| 12967 | var n: u32 = undefined; | ||
| 12968 | var address: WsaAddress = undefined; | ||
| 12969 | const address_size = addressToWsa(message.address, &address); | ||
| 12970 | var syscall: Syscall = try .start(); | ||
| 12971 | while (true) { | ||
| 12972 | const rc = ws2_32.WSASendTo( | ||
| 12973 | handle, | ||
| 12974 | (&buf)[0..1], | ||
| 12975 | 1, | ||
| 12976 | &n, | ||
| 12977 | flags, | ||
| 12978 | &address.any, | ||
| 12979 | address_size, | ||
| 12980 | null, | ||
| 12981 | null, | ||
| 12982 | ); | ||
| 12983 | if (rc != ws2_32.SOCKET_ERROR) { | ||
| 12984 | syscall.finish(); | ||
| 12985 | return; | ||
| 12986 | } | ||
| 12987 | switch (ws2_32.WSAGetLastError()) { | ||
| 12988 | .EINTR, .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => { | ||
| 12989 | try syscall.checkCancel(); | ||
| 12990 | continue; | ||
| 12991 | }, | ||
| 12992 | .NOTINITIALISED => { | ||
| 12993 | syscall.finish(); | ||
| 12994 | try initializeWsa(t); | ||
| 12995 | syscall = try .start(); | ||
| 12996 | continue; | ||
| 12997 | }, | ||
| 12998 | |||
| 12999 | .ECONNRESET => return syscall.fail(error.ConnectionResetByPeer), | ||
| 13000 | .ENETDOWN => return syscall.fail(error.NetworkDown), | ||
| 13001 | .ENETRESET => return syscall.fail(error.ConnectionResetByPeer), | ||
| 13002 | .ENOTCONN => return syscall.fail(error.SocketUnconnected), | ||
| 13003 | .EFAULT => unreachable, // a pointer is not completely contained in user address space. | ||
| 13004 | |||
| 13005 | else => |err| { | ||
| 13006 | syscall.finish(); | ||
| 13007 | switch (err) { | ||
| 13008 | .EINVAL => return wsaErrorBug(err), | ||
| 13009 | .EMSGSIZE => return wsaErrorBug(err), | ||
| 13010 | else => return windows.unexpectedWSAError(err), | ||
| 13011 | } | ||
| 13012 | }, | ||
| 13013 | } | ||
| 13014 | } | ||
| 13003 | } | 13015 | } |
| 13004 | 13016 | ||
| 13005 | fn netSendUnavailable( | 13017 | fn netSendUnavailable( |
| ... | @@ -13190,70 +13202,44 @@ fn netSendMany( | ... | @@ -13190,70 +13202,44 @@ fn netSendMany( |
| 13190 | } | 13202 | } |
| 13191 | 13203 | ||
| 13192 | fn netReceivePosix( | 13204 | fn netReceivePosix( |
| 13193 | userdata: ?*anyopaque, | 13205 | socket_handle: net.Socket.Handle, |
| 13194 | handle: net.Socket.Handle, | 13206 | message: *net.IncomingMessage, |
| 13195 | message_buffer: []net.IncomingMessage, | ||
| 13196 | data_buffer: []u8, | 13207 | data_buffer: []u8, |
| 13197 | flags: net.ReceiveFlags, | 13208 | flags: net.ReceiveFlags, |
| 13198 | timeout: Io.Timeout, | 13209 | nonblocking: bool, |
| 13199 | ) struct { ?net.Socket.ReceiveTimeoutError, usize } { | 13210 | ) (net.Socket.ReceiveError || error{WouldBlock})!void { |
| 13200 | if (!have_networking) return .{ error.NetworkDown, 0 }; | ||
| 13201 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | ||
| 13202 | const t_io = io(t); | ||
| 13203 | |||
| 13204 | // recvmmsg is useless, here's why: | 13211 | // recvmmsg is useless, here's why: |
| 13205 | // * [timeout bug](https://bugzilla.kernel.org/show_bug.cgi?id=75371) | 13212 | // * [timeout bug](https://bugzilla.kernel.org/show_bug.cgi?id=75371) |
| 13206 | // * it wants iovecs for each message but we have a better API: one data | 13213 | // * it wants iovecs for each message but we have a better API: one data |
| 13207 | // buffer to handle all the messages. The better API cannot be lowered to | 13214 | // buffer to handle all the messages. The better API cannot be lowered to |
| 13208 | // the split vectors though because reducing the buffer size might make | 13215 | // the split vectors though because reducing the buffer size might make |
| 13209 | // some messages unreceivable. | 13216 | // some messages unreceivable. |
| 13210 | |||
| 13211 | // So the strategy instead is to use non-blocking recvmsg calls, calling | ||
| 13212 | // poll() with timeout if the first one returns EAGAIN. | ||
| 13213 | const posix_flags: u32 = | 13217 | const posix_flags: u32 = |
| 13214 | @as(u32, if (flags.oob) posix.MSG.OOB else 0) | | 13218 | @as(u32, if (flags.oob) posix.MSG.OOB else 0) | |
| 13215 | @as(u32, if (flags.peek) posix.MSG.PEEK else 0) | | 13219 | @as(u32, if (flags.peek) posix.MSG.PEEK else 0) | |
| 13216 | @as(u32, if (flags.trunc) posix.MSG.TRUNC else 0) | | 13220 | @as(u32, if (flags.trunc) posix.MSG.TRUNC else 0) | |
| 13217 | posix.MSG.DONTWAIT | posix.MSG.NOSIGNAL; | 13221 | posix.MSG.NOSIGNAL | |
| 13222 | @as(u32, if (nonblocking) posix.MSG.DONTWAIT else 0); | ||
| 13218 | 13223 | ||
| 13219 | var poll_fds: [1]posix.pollfd = .{ | 13224 | var storage: PosixAddress = undefined; |
| 13220 | .{ | 13225 | var iov: posix.iovec = .{ .base = data_buffer.ptr, .len = data_buffer.len }; |
| 13221 | .fd = handle, | 13226 | var msg: posix.msghdr = .{ |
| 13222 | .events = posix.POLL.IN, | 13227 | .name = &storage.any, |
| 13223 | .revents = undefined, | 13228 | .namelen = @sizeOf(PosixAddress), |
| 13224 | }, | 13229 | .iov = (&iov)[0..1], |
| 13230 | .iovlen = 1, | ||
| 13231 | .control = message.control.ptr, | ||
| 13232 | .controllen = @intCast(message.control.len), | ||
| 13233 | .flags = undefined, | ||
| 13225 | }; | 13234 | }; |
| 13226 | var message_i: usize = 0; | ||
| 13227 | var data_i: usize = 0; | ||
| 13228 | 13235 | ||
| 13229 | const deadline = timeout.toTimestamp(t_io); | 13236 | const syscall = try Syscall.start(); |
| 13230 | 13237 | while (true) { | |
| 13231 | recv: while (true) { | 13238 | const rc = posix.system.recvmsg(socket_handle, &msg, posix_flags); |
| 13232 | if (message_buffer.len - message_i == 0) return .{ null, message_i }; | 13239 | switch (posix.errno(rc)) { |
| 13233 | const message = &message_buffer[message_i]; | ||
| 13234 | const remaining_data_buffer = data_buffer[data_i..]; | ||
| 13235 | var storage: PosixAddress = undefined; | ||
| 13236 | var iov: posix.iovec = .{ .base = remaining_data_buffer.ptr, .len = remaining_data_buffer.len }; | ||
| 13237 | var msg: posix.msghdr = .{ | ||
| 13238 | .name = &storage.any, | ||
| 13239 | .namelen = @sizeOf(PosixAddress), | ||
| 13240 | .iov = (&iov)[0..1], | ||
| 13241 | .iovlen = 1, | ||
| 13242 | .control = message.control.ptr, | ||
| 13243 | .controllen = @intCast(message.control.len), | ||
| 13244 | .flags = undefined, | ||
| 13245 | }; | ||
| 13246 | |||
| 13247 | const recv_rc = rc: { | ||
| 13248 | const syscall = Syscall.start() catch |err| return .{ err, message_i }; | ||
| 13249 | const rc = posix.system.recvmsg(handle, &msg, posix_flags); | ||
| 13250 | syscall.finish(); | ||
| 13251 | break :rc rc; | ||
| 13252 | }; | ||
| 13253 | switch (posix.errno(recv_rc)) { | ||
| 13254 | .SUCCESS => { | 13240 | .SUCCESS => { |
| 13255 | const data = remaining_data_buffer[0..@intCast(recv_rc)]; | 13241 | syscall.finish(); |
| 13256 | data_i += data.len; | 13242 | const data = data_buffer[0..@intCast(rc)]; |
| 13257 | message.* = .{ | 13243 | message.* = .{ |
| 13258 | .from = addressFromPosix(&storage), | 13244 | .from = addressFromPosix(&storage), |
| 13259 | .data = data, | 13245 | .data = data, |
| ... | @@ -13266,96 +13252,122 @@ fn netReceivePosix( | ... | @@ -13266,96 +13252,122 @@ fn netReceivePosix( |
| 13266 | .errqueue = if (@hasDecl(posix.MSG, "ERRQUEUE")) (msg.flags & posix.MSG.ERRQUEUE) != 0 else false, | 13252 | .errqueue = if (@hasDecl(posix.MSG, "ERRQUEUE")) (msg.flags & posix.MSG.ERRQUEUE) != 0 else false, |
| 13267 | }, | 13253 | }, |
| 13268 | }; | 13254 | }; |
| 13269 | message_i += 1; | 13255 | return; |
| 13270 | continue; | ||
| 13271 | }, | 13256 | }, |
| 13272 | .AGAIN => while (true) { | 13257 | .INTR => { |
| 13273 | if (message_i != 0) return .{ null, message_i }; | 13258 | try syscall.checkCancel(); |
| 13274 | 13259 | continue; | |
| 13275 | const max_poll_ms = std.math.maxInt(u31); | ||
| 13276 | const timeout_ms: u31 = if (deadline) |d| t: { | ||
| 13277 | const duration = d.durationFromNow(t_io); | ||
| 13278 | if (duration.raw.nanoseconds <= 0) return .{ error.Timeout, message_i }; | ||
| 13279 | break :t @intCast(@min(max_poll_ms, duration.raw.toMilliseconds())); | ||
| 13280 | } else max_poll_ms; | ||
| 13281 | |||
| 13282 | const syscall = Syscall.start() catch |err| return .{ err, message_i }; | ||
| 13283 | const poll_rc = posix.system.poll(&poll_fds, poll_fds.len, timeout_ms); | ||
| 13284 | syscall.finish(); | ||
| 13285 | |||
| 13286 | switch (posix.errno(poll_rc)) { | ||
| 13287 | .SUCCESS => { | ||
| 13288 | if (poll_rc == 0) { | ||
| 13289 | // Although spurious timeouts are OK, when no deadline | ||
| 13290 | // is passed we must not return `error.Timeout`. | ||
| 13291 | if (deadline == null) continue; | ||
| 13292 | return .{ error.Timeout, message_i }; | ||
| 13293 | } | ||
| 13294 | continue :recv; | ||
| 13295 | }, | ||
| 13296 | .INTR => continue, | ||
| 13297 | |||
| 13298 | .FAULT => |err| return .{ errnoBug(err), message_i }, | ||
| 13299 | .INVAL => |err| return .{ errnoBug(err), message_i }, | ||
| 13300 | .NOMEM => return .{ error.SystemResources, message_i }, | ||
| 13301 | else => |err| return .{ posix.unexpectedErrno(err), message_i }, | ||
| 13302 | } | ||
| 13303 | }, | 13260 | }, |
| 13304 | .INTR => continue, | 13261 | .NFILE => return syscall.fail(error.SystemFdQuotaExceeded), |
| 13305 | 13262 | .MFILE => return syscall.fail(error.ProcessFdQuotaExceeded), | |
| 13306 | .BADF => |err| return .{ errnoBug(err), message_i }, | 13263 | .NOBUFS => return syscall.fail(error.SystemResources), |
| 13307 | .NFILE => return .{ error.SystemFdQuotaExceeded, message_i }, | 13264 | .NOMEM => return syscall.fail(error.SystemResources), |
| 13308 | .MFILE => return .{ error.ProcessFdQuotaExceeded, message_i }, | 13265 | .NOTCONN => return syscall.fail(error.SocketUnconnected), |
| 13309 | .FAULT => |err| return .{ errnoBug(err), message_i }, | 13266 | .MSGSIZE => return syscall.fail(error.MessageOversize), |
| 13310 | .INVAL => |err| return .{ errnoBug(err), message_i }, | 13267 | .PIPE => return syscall.fail(error.SocketUnconnected), |
| 13311 | .NOBUFS => return .{ error.SystemResources, message_i }, | 13268 | .CONNRESET => return syscall.fail(error.ConnectionResetByPeer), |
| 13312 | .NOMEM => return .{ error.SystemResources, message_i }, | 13269 | .NETDOWN => return syscall.fail(error.NetworkDown), |
| 13313 | .NOTCONN => return .{ error.SocketUnconnected, message_i }, | 13270 | .AGAIN => return syscall.fail(error.WouldBlock), |
| 13314 | .NOTSOCK => |err| return .{ errnoBug(err), message_i }, | 13271 | .BADF => |err| return syscall.errnoBug(err), |
| 13315 | .MSGSIZE => return .{ error.MessageOversize, message_i }, | 13272 | .FAULT => |err| return syscall.errnoBug(err), |
| 13316 | .PIPE => return .{ error.SocketUnconnected, message_i }, | 13273 | .INVAL => |err| return syscall.errnoBug(err), |
| 13317 | .OPNOTSUPP => |err| return .{ errnoBug(err), message_i }, | 13274 | .NOTSOCK => |err| return syscall.errnoBug(err), |
| 13318 | .CONNRESET => return .{ error.ConnectionResetByPeer, message_i }, | 13275 | .OPNOTSUPP => |err| return syscall.errnoBug(err), |
| 13319 | .NETDOWN => return .{ error.NetworkDown, message_i }, | 13276 | else => |err| return syscall.unexpectedErrno(err), |
| 13320 | else => |err| return .{ posix.unexpectedErrno(err), message_i }, | ||
| 13321 | } | 13277 | } |
| 13322 | } | 13278 | } |
| 13323 | } | 13279 | } |
| 13324 | 13280 | ||
| 13325 | fn netReceiveWindows( | 13281 | fn netReceiveWindows( |
| 13326 | userdata: ?*anyopaque, | 13282 | t: *Threaded, |
| 13327 | handle: net.Socket.Handle, | 13283 | socket_handle: net.Socket.Handle, |
| 13328 | message_buffer: []net.IncomingMessage, | 13284 | message_buffer: []net.IncomingMessage, |
| 13329 | data_buffer: []u8, | 13285 | data_buffer: []u8, |
| 13330 | flags: net.ReceiveFlags, | 13286 | flags: net.ReceiveFlags, |
| 13331 | timeout: Io.Timeout, | 13287 | ) struct { ?net.Socket.ReceiveError, usize } { |
| 13332 | ) struct { ?net.Socket.ReceiveTimeoutError, usize } { | 13288 | netReceiveWindowsOne(t, socket_handle, &message_buffer[0], data_buffer, flags) catch |err| return .{ err, 0 }; |
| 13333 | if (!have_networking) return .{ error.NetworkDown, 0 }; | 13289 | return .{ null, 1 }; |
| 13334 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | ||
| 13335 | _ = t; | ||
| 13336 | _ = handle; | ||
| 13337 | _ = message_buffer; | ||
| 13338 | _ = data_buffer; | ||
| 13339 | _ = flags; | ||
| 13340 | _ = timeout; | ||
| 13341 | @panic("TODO implement netReceiveWindows"); | ||
| 13342 | } | 13290 | } |
| 13343 | 13291 | ||
| 13344 | fn netReceiveUnavailable( | 13292 | fn netReceiveWindowsOne( |
| 13345 | userdata: ?*anyopaque, | 13293 | t: *Threaded, |
| 13346 | handle: net.Socket.Handle, | 13294 | socket_handle: net.Socket.Handle, |
| 13347 | message_buffer: []net.IncomingMessage, | 13295 | message: *net.IncomingMessage, |
| 13348 | data_buffer: []u8, | 13296 | data_buffer: []u8, |
| 13349 | flags: net.ReceiveFlags, | 13297 | flags: net.ReceiveFlags, |
| 13350 | timeout: Io.Timeout, | 13298 | ) net.Socket.ReceiveError!void { |
| 13351 | ) struct { ?net.Socket.ReceiveTimeoutError, usize } { | 13299 | if (!have_networking) return error.NetworkDown; |
| 13352 | _ = userdata; | 13300 | |
| 13353 | _ = handle; | 13301 | var windows_flags: u32 = |
| 13354 | _ = message_buffer; | 13302 | @as(u32, if (flags.oob) ws2_32.MSG.OOB else 0) | |
| 13355 | _ = data_buffer; | 13303 | @as(u32, if (flags.peek) ws2_32.MSG.PEEK else 0) | |
| 13356 | _ = flags; | 13304 | @as(u32, if (flags.trunc) ws2_32.MSG.TRUNC else 0); |
| 13357 | _ = timeout; | 13305 | |
| 13358 | return .{ error.NetworkDown, 0 }; | 13306 | var buf: ws2_32.WSABUF = .{ |
| 13307 | .buf = data_buffer.ptr, | ||
| 13308 | .len = std.math.cast(u32, data_buffer.len) orelse return error.MessageOversize, | ||
| 13309 | }; | ||
| 13310 | var n: u32 = undefined; | ||
| 13311 | var syscall: Syscall = try .start(); | ||
| 13312 | var from_storage: WsaAddress = undefined; | ||
| 13313 | var from_storage_len: i32 = @sizeOf(WsaAddress); | ||
| 13314 | |||
| 13315 | while (true) { | ||
| 13316 | const rc = ws2_32.WSARecvFrom( | ||
| 13317 | socket_handle, | ||
| 13318 | (&buf)[0..1], | ||
| 13319 | 1, | ||
| 13320 | &n, | ||
| 13321 | &windows_flags, | ||
| 13322 | &from_storage.any, | ||
| 13323 | &from_storage_len, | ||
| 13324 | null, | ||
| 13325 | null, | ||
| 13326 | ); | ||
| 13327 | if (rc != ws2_32.SOCKET_ERROR) { | ||
| 13328 | syscall.finish(); | ||
| 13329 | message.* = .{ | ||
| 13330 | .from = addressFromWsa(&from_storage), | ||
| 13331 | .data = data_buffer[0..n], | ||
| 13332 | .control = &.{}, | ||
| 13333 | .flags = .{ | ||
| 13334 | .eor = false, | ||
| 13335 | .trunc = (windows_flags & ws2_32.MSG.TRUNC) != 0, | ||
| 13336 | .ctrunc = (windows_flags & ws2_32.MSG.CTRUNC) != 0, | ||
| 13337 | .oob = false, | ||
| 13338 | .errqueue = false, | ||
| 13339 | }, | ||
| 13340 | }; | ||
| 13341 | return; | ||
| 13342 | } | ||
| 13343 | switch (ws2_32.WSAGetLastError()) { | ||
| 13344 | .EINTR, .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => { | ||
| 13345 | try syscall.checkCancel(); | ||
| 13346 | continue; | ||
| 13347 | }, | ||
| 13348 | .NOTINITIALISED => { | ||
| 13349 | syscall.finish(); | ||
| 13350 | try initializeWsa(t); | ||
| 13351 | syscall = try .start(); | ||
| 13352 | continue; | ||
| 13353 | }, | ||
| 13354 | |||
| 13355 | .ECONNRESET => return syscall.fail(error.ConnectionResetByPeer), | ||
| 13356 | .ENETDOWN => return syscall.fail(error.NetworkDown), | ||
| 13357 | .ENETRESET => return syscall.fail(error.ConnectionResetByPeer), | ||
| 13358 | .ENOTCONN => return syscall.fail(error.SocketUnconnected), | ||
| 13359 | .EFAULT => unreachable, // a pointer is not completely contained in user address space. | ||
| 13360 | |||
| 13361 | else => |err| { | ||
| 13362 | syscall.finish(); | ||
| 13363 | switch (err) { | ||
| 13364 | .EINVAL => return wsaErrorBug(err), | ||
| 13365 | .EMSGSIZE => return wsaErrorBug(err), | ||
| 13366 | else => return windows.unexpectedWSAError(err), | ||
| 13367 | } | ||
| 13368 | }, | ||
| 13369 | } | ||
| 13370 | } | ||
| 13359 | } | 13371 | } |
| 13360 | 13372 | ||
| 13361 | fn netWritePosix( | 13373 | fn netWritePosix( |
| ... | @@ -13459,6 +13471,7 @@ fn netWriteWindows( | ... | @@ -13459,6 +13471,7 @@ fn netWriteWindows( |
| 13459 | data: []const []const u8, | 13471 | data: []const []const u8, |
| 13460 | splat: usize, | 13472 | splat: usize, |
| 13461 | ) net.Stream.Writer.Error!usize { | 13473 | ) net.Stream.Writer.Error!usize { |
| 13474 | if (!have_networking) return error.NetworkDown; | ||
| 13462 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 13475 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 13463 | comptime assert(is_windows); | 13476 | comptime assert(is_windows); |
| 13464 | 13477 | ||
| ... | @@ -13581,6 +13594,7 @@ fn addBuf(v: []posix.iovec_const, i: *iovlen_t, bytes: []const u8) void { | ... | @@ -13581,6 +13594,7 @@ fn addBuf(v: []posix.iovec_const, i: *iovlen_t, bytes: []const u8) void { |
| 13581 | } | 13594 | } |
| 13582 | 13595 | ||
| 13583 | fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void { | 13596 | fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void { |
| 13597 | if (!have_networking) unreachable; | ||
| 13584 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 13598 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 13585 | _ = t; | 13599 | _ = t; |
| 13586 | switch (native_os) { | 13600 | switch (native_os) { |
| ... | @@ -13789,7 +13803,7 @@ fn netLookupUnavailable( | ... | @@ -13789,7 +13803,7 @@ fn netLookupUnavailable( |
| 13789 | _ = host_name; | 13803 | _ = host_name; |
| 13790 | _ = options; | 13804 | _ = options; |
| 13791 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 13805 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 13792 | resolved.close(ioBasic(t)); | 13806 | resolved.close(io(t)); |
| 13793 | return error.NetworkDown; | 13807 | return error.NetworkDown; |
| 13794 | } | 13808 | } |
| 13795 | 13809 | ||
| ... | @@ -14072,7 +14086,7 @@ fn tryLockStderr(userdata: ?*anyopaque, terminal_mode: ?Io.Terminal.Mode) Io.Can | ... | @@ -14072,7 +14086,7 @@ fn tryLockStderr(userdata: ?*anyopaque, terminal_mode: ?Io.Terminal.Mode) Io.Can |
| 14072 | 14086 | ||
| 14073 | fn initLockedStderr(t: *Threaded, terminal_mode: ?Io.Terminal.Mode) Io.Cancelable!Io.LockedStderr { | 14087 | fn initLockedStderr(t: *Threaded, terminal_mode: ?Io.Terminal.Mode) Io.Cancelable!Io.LockedStderr { |
| 14074 | if (!t.stderr_writer_initialized) { | 14088 | if (!t.stderr_writer_initialized) { |
| 14075 | const io_t = ioBasic(t); | 14089 | const io_t = io(t); |
| 14076 | if (is_windows) t.stderr_writer.file = .stderr(); | 14090 | if (is_windows) t.stderr_writer.file = .stderr(); |
| 14077 | t.stderr_writer.io = io_t; | 14091 | t.stderr_writer.io = io_t; |
| 14078 | t.stderr_writer_initialized = true; | 14092 | t.stderr_writer_initialized = true; |
lib/std/Io/Uring.zig+22-49| ... | @@ -777,7 +777,6 @@ pub fn io(ev: *Evented) Io { | ... | @@ -777,7 +777,6 @@ pub fn io(ev: *Evented) Io { |
| 777 | .netConnectUnix = netConnectUnixUnavailable, | 777 | .netConnectUnix = netConnectUnixUnavailable, |
| 778 | .netSocketCreatePair = netSocketCreatePairUnavailable, | 778 | .netSocketCreatePair = netSocketCreatePairUnavailable, |
| 779 | .netSend = netSendUnavailable, | 779 | .netSend = netSendUnavailable, |
| 780 | .netReceive = netReceive, | ||
| 781 | .netRead = netReadUnavailable, | 780 | .netRead = netReadUnavailable, |
| 782 | .netWrite = netWriteUnavailable, | 781 | .netWrite = netWriteUnavailable, |
| 783 | .netWriteFile = netWriteFileUnavailable, | 782 | .netWriteFile = netWriteFileUnavailable, |
| ... | @@ -2092,6 +2091,18 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper | ... | @@ -2092,6 +2091,18 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper |
| 2092 | .device_io_control => |o| .{ | 2091 | .device_io_control => |o| .{ |
| 2093 | .device_io_control = try ev.deviceIoControl(try maybe_sync.enterSync(ev), o), | 2092 | .device_io_control = try ev.deviceIoControl(try maybe_sync.enterSync(ev), o), |
| 2094 | }, | 2093 | }, |
| 2094 | .net_receive => |o| .{ | ||
| 2095 | .net_receive = r: { | ||
| 2096 | const opt_err, const n = ev.netReceive(&maybe_sync.cancel_region, o.socket_handle, o.message_buffer, o.data_buffer, o.flags); | ||
| 2097 | break :r .{ | ||
| 2098 | if (opt_err) |err| switch (err) { | ||
| 2099 | error.Canceled => |e| return e, | ||
| 2100 | else => |e| e, | ||
| 2101 | } else null, | ||
| 2102 | n, | ||
| 2103 | }; | ||
| 2104 | }, | ||
| 2105 | }, | ||
| 2095 | }; | 2106 | }; |
| 2096 | } | 2107 | } |
| 2097 | 2108 | ||
| ... | @@ -2375,6 +2386,10 @@ fn batchDrainSubmitted( | ... | @@ -2375,6 +2386,10 @@ fn batchDrainSubmitted( |
| 2375 | return error.ConcurrencyUnavailable | 2386 | return error.ConcurrencyUnavailable |
| 2376 | else | 2387 | else |
| 2377 | .{ .device_io_control = try ev.deviceIoControl(try maybe_sync.enterSync(ev), o) }, | 2388 | .{ .device_io_control = try ev.deviceIoControl(try maybe_sync.enterSync(ev), o) }, |
| 2389 | .net_receive => |o| { | ||
| 2390 | _ = o; | ||
| 2391 | @panic("TODO implement batchDrainSubmitted for net_receive"); | ||
| 2392 | }, | ||
| 2378 | })) |result| { | 2393 | })) |result| { |
| 2379 | switch (batch.completed.tail) { | 2394 | switch (batch.completed.tail) { |
| 2380 | .none => batch.completed.head = index, | 2395 | .none => batch.completed.head = index, |
| ... | @@ -2475,6 +2490,7 @@ fn batchDrainReady(batch: *Io.Batch) Io.Timeout.Error!void { | ... | @@ -2475,6 +2490,7 @@ fn batchDrainReady(batch: *Io.Batch) Io.Timeout.Error!void { |
| 2475 | }, | 2490 | }, |
| 2476 | }, | 2491 | }, |
| 2477 | .device_io_control => unreachable, | 2492 | .device_io_control => unreachable, |
| 2493 | .net_receive => @panic("TODO"), | ||
| 2478 | })) |result| { | 2494 | })) |result| { |
| 2479 | switch (batch.completed.tail) { | 2495 | switch (batch.completed.tail) { |
| 2480 | .none => batch.completed.head = index, | 2496 | .none => batch.completed.head = index, |
| ... | @@ -5035,37 +5051,16 @@ fn netSendUnavailable( | ... | @@ -5035,37 +5051,16 @@ fn netSendUnavailable( |
| 5035 | } | 5051 | } |
| 5036 | 5052 | ||
| 5037 | fn netReceive( | 5053 | fn netReceive( |
| 5038 | userdata: ?*anyopaque, | 5054 | ev: *Evented, |
| 5055 | cancel_region: *CancelRegion, | ||
| 5039 | handle: net.Socket.Handle, | 5056 | handle: net.Socket.Handle, |
| 5040 | message_buffer: []net.IncomingMessage, | 5057 | message_buffer: []net.IncomingMessage, |
| 5041 | data_buffer: []u8, | 5058 | data_buffer: []u8, |
| 5042 | flags: net.ReceiveFlags, | 5059 | flags: net.ReceiveFlags, |
| 5043 | timeout: Io.Timeout, | 5060 | ) struct { ?net.Socket.ReceiveError, usize } { |
| 5044 | ) struct { ?net.Socket.ReceiveTimeoutError, usize } { | ||
| 5045 | const ev: *Evented = @ptrCast(@alignCast(userdata)); | ||
| 5046 | const ev_io = ev.io(); | ||
| 5047 | |||
| 5048 | var message_i: usize = 0; | 5061 | var message_i: usize = 0; |
| 5049 | var data_i: usize = 0; | 5062 | var data_i: usize = 0; |
| 5050 | 5063 | ||
| 5051 | const deadline: ?struct { | ||
| 5052 | raw: Io.Timestamp, | ||
| 5053 | timespec: linux.kernel_timespec, | ||
| 5054 | clock: Io.Clock, | ||
| 5055 | } = if (timeout.toTimestamp(ev_io)) |deadline| deadline: { | ||
| 5056 | const ns = deadline.raw.toNanoseconds(); | ||
| 5057 | break :deadline .{ | ||
| 5058 | .raw = deadline.raw, | ||
| 5059 | .timespec = .{ | ||
| 5060 | .sec = @intCast(@divFloor(ns, std.time.ns_per_s)), | ||
| 5061 | .nsec = @intCast(@mod(ns, std.time.ns_per_s)), | ||
| 5062 | }, | ||
| 5063 | .clock = deadline.clock, | ||
| 5064 | }; | ||
| 5065 | } else null; | ||
| 5066 | |||
| 5067 | var cancel_region: CancelRegion = .init(); | ||
| 5068 | defer cancel_region.deinit(); | ||
| 5069 | while (true) { | 5064 | while (true) { |
| 5070 | if (message_buffer.len - message_i == 0) return .{ null, message_i }; | 5065 | if (message_buffer.len - message_i == 0) return .{ null, message_i }; |
| 5071 | const message = &message_buffer[message_i]; | 5066 | const message = &message_buffer[message_i]; |
| ... | @@ -5085,7 +5080,7 @@ fn netReceive( | ... | @@ -5085,7 +5080,7 @@ fn netReceive( |
| 5085 | const thread = cancel_region.awaitIoUring() catch |err| return .{ err, message_i }; | 5080 | const thread = cancel_region.awaitIoUring() catch |err| return .{ err, message_i }; |
| 5086 | thread.enqueue().* = .{ | 5081 | thread.enqueue().* = .{ |
| 5087 | .opcode = .RECVMSG, | 5082 | .opcode = .RECVMSG, |
| 5088 | .flags = if (deadline) |_| linux.IOSQE_IO_LINK else 0, | 5083 | .flags = 0, |
| 5089 | .ioprio = 0, | 5084 | .ioprio = 0, |
| 5090 | .fd = handle, | 5085 | .fd = handle, |
| 5091 | .off = 0, | 5086 | .off = 0, |
| ... | @@ -5102,26 +5097,6 @@ fn netReceive( | ... | @@ -5102,26 +5097,6 @@ fn netReceive( |
| 5102 | .addr3 = 0, | 5097 | .addr3 = 0, |
| 5103 | .resv = 0, | 5098 | .resv = 0, |
| 5104 | }; | 5099 | }; |
| 5105 | if (deadline) |*deadline_ptr| thread.enqueue().* = .{ | ||
| 5106 | .opcode = .LINK_TIMEOUT, | ||
| 5107 | .flags = linux.IOSQE_CQE_SKIP_SUCCESS, | ||
| 5108 | .ioprio = 0, | ||
| 5109 | .fd = 0, | ||
| 5110 | .off = 0, | ||
| 5111 | .addr = @intFromPtr(&deadline_ptr.timespec), | ||
| 5112 | .len = 1, | ||
| 5113 | .rw_flags = linux.IORING_TIMEOUT_ABS | @as(u32, switch (deadline_ptr.clock) { | ||
| 5114 | .real => linux.IORING_TIMEOUT_REALTIME, | ||
| 5115 | else => 0, | ||
| 5116 | .boot => linux.IORING_TIMEOUT_BOOTTIME, | ||
| 5117 | }), | ||
| 5118 | .user_data = @intFromEnum(Completion.Userdata.wakeup), | ||
| 5119 | .buf_index = 0, | ||
| 5120 | .personality = 0, | ||
| 5121 | .splice_fd_in = 0, | ||
| 5122 | .addr3 = 0, | ||
| 5123 | .resv = 0, | ||
| 5124 | }; | ||
| 5125 | ev.yield(null, .nothing); | 5100 | ev.yield(null, .nothing); |
| 5126 | const completion = cancel_region.completion(); | 5101 | const completion = cancel_region.completion(); |
| 5127 | switch (completion.errno()) { | 5102 | switch (completion.errno()) { |
| ... | @@ -5144,9 +5119,7 @@ fn netReceive( | ... | @@ -5144,9 +5119,7 @@ fn netReceive( |
| 5144 | continue; | 5119 | continue; |
| 5145 | }, | 5120 | }, |
| 5146 | .AGAIN => unreachable, | 5121 | .AGAIN => unreachable, |
| 5147 | .INTR, .CANCELED => if (deadline) |d| if (now(ev, d.clock).nanoseconds >= d.raw.nanoseconds) | 5122 | .INTR, .CANCELED => {}, |
| 5148 | return .{ error.Timeout, message_i }, | ||
| 5149 | |||
| 5150 | .BADF => |err| return .{ errnoBug(err), message_i }, | 5123 | .BADF => |err| return .{ errnoBug(err), message_i }, |
| 5151 | .NFILE => return .{ error.SystemFdQuotaExceeded, message_i }, | 5124 | .NFILE => return .{ error.SystemFdQuotaExceeded, message_i }, |
| 5152 | .MFILE => return .{ error.ProcessFdQuotaExceeded, message_i }, | 5125 | .MFILE => return .{ error.ProcessFdQuotaExceeded, message_i }, |
lib/std/Io/net.zig+22-28| ... | @@ -1109,25 +1109,7 @@ pub const Socket = struct { | ... | @@ -1109,25 +1109,7 @@ pub const Socket = struct { |
| 1109 | if (n != messages.len) return err.?; | 1109 | if (n != messages.len) return err.?; |
| 1110 | } | 1110 | } |
| 1111 | 1111 | ||
| 1112 | pub const ReceiveError = error{ | 1112 | pub const ReceiveError = Io.Operation.NetReceive.Error || Io.Cancelable; |
| 1113 | /// Insufficient memory or other resource internal to the operating system. | ||
| 1114 | SystemResources, | ||
| 1115 | /// Per-process limit on the number of open file descriptors has been reached. | ||
| 1116 | ProcessFdQuotaExceeded, | ||
| 1117 | /// System-wide limit on the total number of open files has been reached. | ||
| 1118 | SystemFdQuotaExceeded, | ||
| 1119 | /// Local end has been shut down on a connection-oriented socket, or | ||
| 1120 | /// the socket was never connected. | ||
| 1121 | SocketUnconnected, | ||
| 1122 | /// The socket type requires that message be sent atomically, and the | ||
| 1123 | /// size of the message to be sent made this impossible. The message | ||
| 1124 | /// was not transmitted, or was partially transmitted. | ||
| 1125 | MessageOversize, | ||
| 1126 | /// Network connection was unexpectedly closed by sender. | ||
| 1127 | ConnectionResetByPeer, | ||
| 1128 | /// The local network interface used to reach the destination is offline. | ||
| 1129 | NetworkDown, | ||
| 1130 | } || Io.UnexpectedError || Io.Cancelable; | ||
| 1131 | 1113 | ||
| 1132 | /// Waits for data. Connectionless. | 1114 | /// Waits for data. Connectionless. |
| 1133 | /// | 1115 | /// |
| ... | @@ -1135,17 +1117,18 @@ pub const Socket = struct { | ... | @@ -1135,17 +1117,18 @@ pub const Socket = struct { |
| 1135 | /// * `receiveTimeout` | 1117 | /// * `receiveTimeout` |
| 1136 | pub fn receive(s: *const Socket, io: Io, buffer: []u8) ReceiveError!IncomingMessage { | 1118 | pub fn receive(s: *const Socket, io: Io, buffer: []u8) ReceiveError!IncomingMessage { |
| 1137 | var message: IncomingMessage = .init; | 1119 | var message: IncomingMessage = .init; |
| 1138 | const maybe_err, const count = io.vtable.netReceive(io.userdata, s.handle, (&message)[0..1], buffer, .{}, .none); | 1120 | const maybe_err, const count = (try io.operate(.{ .net_receive = .{ |
| 1139 | if (maybe_err) |err| switch (err) { | 1121 | .socket_handle = s.handle, |
| 1140 | // No timeout is passed to `netReceieve`, so it must not return timeout related errors. | 1122 | .message_buffer = (&message)[0..1], |
| 1141 | error.Timeout => unreachable, | 1123 | .data_buffer = buffer, |
| 1142 | else => |e| return e, | 1124 | .flags = .{}, |
| 1143 | }; | 1125 | } })).net_receive; |
| 1126 | if (maybe_err) |err| return err; | ||
| 1144 | assert(1 == count); | 1127 | assert(1 == count); |
| 1145 | return message; | 1128 | return message; |
| 1146 | } | 1129 | } |
| 1147 | 1130 | ||
| 1148 | pub const ReceiveTimeoutError = ReceiveError || Io.Timeout.Error; | 1131 | pub const ReceiveTimeoutError = ReceiveError || Io.Timeout.Error || Io.ConcurrentError; |
| 1149 | 1132 | ||
| 1150 | /// Waits for data. Connectionless. | 1133 | /// Waits for data. Connectionless. |
| 1151 | /// | 1134 | /// |
| ... | @@ -1161,7 +1144,12 @@ pub const Socket = struct { | ... | @@ -1161,7 +1144,12 @@ pub const Socket = struct { |
| 1161 | timeout: Io.Timeout, | 1144 | timeout: Io.Timeout, |
| 1162 | ) ReceiveTimeoutError!IncomingMessage { | 1145 | ) ReceiveTimeoutError!IncomingMessage { |
| 1163 | var message: IncomingMessage = .init; | 1146 | var message: IncomingMessage = .init; |
| 1164 | const maybe_err, const count = io.vtable.netReceive(io.userdata, s.handle, (&message)[0..1], buffer, .{}, timeout); | 1147 | const maybe_err, const count = (try io.operateTimeout(.{ .net_receive = .{ |
| 1148 | .socket_handle = s.handle, | ||
| 1149 | .message_buffer = (&message)[0..1], | ||
| 1150 | .data_buffer = buffer, | ||
| 1151 | .flags = .{}, | ||
| 1152 | } }, timeout)).net_receive; | ||
| 1165 | if (maybe_err) |err| return err; | 1153 | if (maybe_err) |err| return err; |
| 1166 | assert(1 == count); | 1154 | assert(1 == count); |
| 1167 | return message; | 1155 | return message; |
| ... | @@ -1186,7 +1174,13 @@ pub const Socket = struct { | ... | @@ -1186,7 +1174,13 @@ pub const Socket = struct { |
| 1186 | flags: ReceiveFlags, | 1174 | flags: ReceiveFlags, |
| 1187 | timeout: Io.Timeout, | 1175 | timeout: Io.Timeout, |
| 1188 | ) struct { ?ReceiveTimeoutError, usize } { | 1176 | ) struct { ?ReceiveTimeoutError, usize } { |
| 1189 | return io.vtable.netReceive(io.userdata, s.handle, message_buffer, data_buffer, flags, timeout); | 1177 | const result = io.operateTimeout(.{ .net_receive = .{ |
| 1178 | .socket_handle = s.handle, | ||
| 1179 | .message_buffer = message_buffer, | ||
| 1180 | .data_buffer = data_buffer, | ||
| 1181 | .flags = flags, | ||
| 1182 | } }, timeout) catch |err| return .{ err, 0 }; | ||
| 1183 | return result.net_receive; | ||
| 1190 | } | 1184 | } |
| 1191 | 1185 | ||
| 1192 | pub const CreatePairError = error{ | 1186 | pub const CreatePairError = error{ |
lib/std/os/windows/ws2_32.zig+14-11| ... | @@ -661,17 +661,20 @@ pub const IOC_OUT = 1073741824; | ... | @@ -661,17 +661,20 @@ pub const IOC_OUT = 1073741824; |
| 661 | pub const IOC_IN = 2147483648; | 661 | pub const IOC_IN = 2147483648; |
| 662 | 662 | ||
| 663 | pub const MSG = struct { | 663 | pub const MSG = struct { |
| 664 | pub const TRUNC = 256; | 664 | pub const OOB = 0x1; |
| 665 | pub const CTRUNC = 512; | 665 | pub const PEEK = 0x2; |
| 666 | pub const BCAST = 1024; | 666 | pub const DONTROUTE = 0x4; |
| 667 | pub const MCAST = 2048; | 667 | pub const WAITALL = 0x8; |
| 668 | pub const ERRQUEUE = 4096; | 668 | pub const INTERRUPT = 0x10; |
| 669 | 669 | pub const PUSH_IMMEDIATE = 0x20; | |
| 670 | pub const PEEK = 2; | 670 | |
| 671 | pub const WAITALL = 8; | 671 | pub const TRUNC = 0x0100; |
| 672 | pub const PUSH_IMMEDIATE = 32; | 672 | pub const CTRUNC = 0x0200; |
| 673 | pub const PARTIAL = 32768; | 673 | pub const BCAST = 0x0400; |
| 674 | pub const INTERRUPT = 16; | 674 | pub const MCAST = 0x0800; |
| 675 | |||
| 676 | pub const PARTIAL = 0x8000; | ||
| 677 | |||
| 675 | pub const MAXIOVLEN = 16; | 678 | pub const MAXIOVLEN = 16; |
| 676 | }; | 679 | }; |
| 677 | 680 |
lib/std/std.zig+4-1| ... | @@ -174,6 +174,9 @@ pub const Options = struct { | ... | @@ -174,6 +174,9 @@ pub const Options = struct { |
| 174 | /// stack traces will just print an error to the relevant `Io.Writer` and return. | 174 | /// stack traces will just print an error to the relevant `Io.Writer` and return. |
| 175 | allow_stack_tracing: bool = !@import("builtin").strip_debug_info, | 175 | allow_stack_tracing: bool = !@import("builtin").strip_debug_info, |
| 176 | 176 | ||
| 177 | /// Allows disabling networking in std.Io implementations. | ||
| 178 | networking: bool = true, | ||
| 179 | |||
| 177 | /// TODO This is a separate decl instead of a field as a workaround around | 180 | /// TODO This is a separate decl instead of a field as a workaround around |
| 178 | /// compilation errors due to zig not being lazy enough. | 181 | /// compilation errors due to zig not being lazy enough. |
| 179 | pub const logTerminalMode: fn () Io.Terminal.Mode = log.defaultTerminalMode; | 182 | pub const logTerminalMode: fn () Io.Terminal.Mode = log.defaultTerminalMode; |
| ... | @@ -202,7 +205,7 @@ pub const Options = struct { | ... | @@ -202,7 +205,7 @@ pub const Options = struct { |
| 202 | /// implementation based on coroutines, one likely wants `std.debug.print` | 205 | /// implementation based on coroutines, one likely wants `std.debug.print` |
| 203 | /// to directly write to stderr without trying to interact with the code | 206 | /// to directly write to stderr without trying to interact with the code |
| 204 | /// being debugged. | 207 | /// being debugged. |
| 205 | pub const debug_io: Io = if (@hasDecl(root, "std_options_debug_io")) root.std_options_debug_io else debug_threaded_io.?.ioBasic(); | 208 | pub const debug_io: Io = if (@hasDecl(root, "std_options_debug_io")) root.std_options_debug_io else debug_threaded_io.?.io(); |
| 206 | 209 | ||
| 207 | /// Overrides `std.Io.File.Permissions`. | 210 | /// Overrides `std.Io.File.Permissions`. |
| 208 | pub const FilePermissions: ?type = if (@hasDecl(root, "std_options_FilePermissions")) root.std_options_FilePermissions else null; | 211 | pub const FilePermissions: ?type = if (@hasDecl(root, "std_options_FilePermissions")) root.std_options_FilePermissions else null; |
lib/ubsan_rt.zig+4| ... | @@ -3,6 +3,10 @@ const builtin = @import("builtin"); | ... | @@ -3,6 +3,10 @@ const builtin = @import("builtin"); |
| 3 | const assert = std.debug.assert; | 3 | const assert = std.debug.assert; |
| 4 | const panic = std.debug.panicExtra; | 4 | const panic = std.debug.panicExtra; |
| 5 | 5 | ||
| 6 | pub const std_options: std.Options = .{ | ||
| 7 | .networking = false, | ||
| 8 | }; | ||
| 9 | |||
| 6 | const SourceLocation = extern struct { | 10 | const SourceLocation = extern struct { |
| 7 | file_name: ?[*:0]const u8, | 11 | file_name: ?[*:0]const u8, |
| 8 | line: u32, | 12 | line: u32, |
test/incremental/add_decl+6-6| ... | @@ -10,7 +10,7 @@ pub fn main() !void { | ... | @@ -10,7 +10,7 @@ pub fn main() !void { |
| 10 | try std.Io.File.stdout().writeStreamingAll(io, foo); | 10 | try std.Io.File.stdout().writeStreamingAll(io, foo); |
| 11 | } | 11 | } |
| 12 | const foo = "good morning\n"; | 12 | const foo = "good morning\n"; |
| 13 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 13 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 14 | #expect_stdout="good morning\n" | 14 | #expect_stdout="good morning\n" |
| 15 | 15 | ||
| 16 | #update=add new declaration | 16 | #update=add new declaration |
| ... | @@ -21,7 +21,7 @@ pub fn main() !void { | ... | @@ -21,7 +21,7 @@ pub fn main() !void { |
| 21 | } | 21 | } |
| 22 | const foo = "good morning\n"; | 22 | const foo = "good morning\n"; |
| 23 | const bar = "good evening\n"; | 23 | const bar = "good evening\n"; |
| 24 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 24 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 25 | #expect_stdout="good morning\n" | 25 | #expect_stdout="good morning\n" |
| 26 | 26 | ||
| 27 | #update=reference new declaration | 27 | #update=reference new declaration |
| ... | @@ -32,7 +32,7 @@ pub fn main() !void { | ... | @@ -32,7 +32,7 @@ pub fn main() !void { |
| 32 | } | 32 | } |
| 33 | const foo = "good morning\n"; | 33 | const foo = "good morning\n"; |
| 34 | const bar = "good evening\n"; | 34 | const bar = "good evening\n"; |
| 35 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 35 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 36 | #expect_stdout="good evening\n" | 36 | #expect_stdout="good evening\n" |
| 37 | 37 | ||
| 38 | #update=reference missing declaration | 38 | #update=reference missing declaration |
| ... | @@ -43,7 +43,7 @@ pub fn main() !void { | ... | @@ -43,7 +43,7 @@ pub fn main() !void { |
| 43 | } | 43 | } |
| 44 | const foo = "good morning\n"; | 44 | const foo = "good morning\n"; |
| 45 | const bar = "good evening\n"; | 45 | const bar = "good evening\n"; |
| 46 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 46 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 47 | #expect_error=main.zig:3:52: error: use of undeclared identifier 'qux' | 47 | #expect_error=main.zig:3:52: error: use of undeclared identifier 'qux' |
| 48 | 48 | ||
| 49 | #update=add missing declaration | 49 | #update=add missing declaration |
| ... | @@ -55,7 +55,7 @@ pub fn main() !void { | ... | @@ -55,7 +55,7 @@ pub fn main() !void { |
| 55 | const foo = "good morning\n"; | 55 | const foo = "good morning\n"; |
| 56 | const bar = "good evening\n"; | 56 | const bar = "good evening\n"; |
| 57 | const qux = "good night\n"; | 57 | const qux = "good night\n"; |
| 58 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 58 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 59 | #expect_stdout="good night\n" | 59 | #expect_stdout="good night\n" |
| 60 | 60 | ||
| 61 | #update=remove unused declarations | 61 | #update=remove unused declarations |
| ... | @@ -65,5 +65,5 @@ pub fn main() !void { | ... | @@ -65,5 +65,5 @@ pub fn main() !void { |
| 65 | try std.Io.File.stdout().writeStreamingAll(io, qux); | 65 | try std.Io.File.stdout().writeStreamingAll(io, qux); |
| 66 | } | 66 | } |
| 67 | const qux = "good night\n"; | 67 | const qux = "good night\n"; |
| 68 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 68 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 69 | #expect_stdout="good night\n" | 69 | #expect_stdout="good night\n" |
test/incremental/add_decl_namespaced+6-6| ... | @@ -10,7 +10,7 @@ pub fn main() !void { | ... | @@ -10,7 +10,7 @@ pub fn main() !void { |
| 10 | try std.Io.File.stdout().writeStreamingAll(io, @This().foo); | 10 | try std.Io.File.stdout().writeStreamingAll(io, @This().foo); |
| 11 | } | 11 | } |
| 12 | const foo = "good morning\n"; | 12 | const foo = "good morning\n"; |
| 13 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 13 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 14 | #expect_stdout="good morning\n" | 14 | #expect_stdout="good morning\n" |
| 15 | 15 | ||
| 16 | #update=add new declaration | 16 | #update=add new declaration |
| ... | @@ -21,7 +21,7 @@ pub fn main() !void { | ... | @@ -21,7 +21,7 @@ pub fn main() !void { |
| 21 | } | 21 | } |
| 22 | const foo = "good morning\n"; | 22 | const foo = "good morning\n"; |
| 23 | const bar = "good evening\n"; | 23 | const bar = "good evening\n"; |
| 24 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 24 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 25 | #expect_stdout="good morning\n" | 25 | #expect_stdout="good morning\n" |
| 26 | 26 | ||
| 27 | #update=reference new declaration | 27 | #update=reference new declaration |
| ... | @@ -32,7 +32,7 @@ pub fn main() !void { | ... | @@ -32,7 +32,7 @@ pub fn main() !void { |
| 32 | } | 32 | } |
| 33 | const foo = "good morning\n"; | 33 | const foo = "good morning\n"; |
| 34 | const bar = "good evening\n"; | 34 | const bar = "good evening\n"; |
| 35 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 35 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 36 | #expect_stdout="good evening\n" | 36 | #expect_stdout="good evening\n" |
| 37 | 37 | ||
| 38 | #update=reference missing declaration | 38 | #update=reference missing declaration |
| ... | @@ -43,7 +43,7 @@ pub fn main() !void { | ... | @@ -43,7 +43,7 @@ pub fn main() !void { |
| 43 | } | 43 | } |
| 44 | const foo = "good morning\n"; | 44 | const foo = "good morning\n"; |
| 45 | const bar = "good evening\n"; | 45 | const bar = "good evening\n"; |
| 46 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 46 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 47 | #expect_error=main.zig:3:59: error: root source file struct 'main' has no member named 'qux' | 47 | #expect_error=main.zig:3:59: error: root source file struct 'main' has no member named 'qux' |
| 48 | #expect_error=main.zig:1:1: note: struct declared here | 48 | #expect_error=main.zig:1:1: note: struct declared here |
| 49 | 49 | ||
| ... | @@ -56,7 +56,7 @@ pub fn main() !void { | ... | @@ -56,7 +56,7 @@ pub fn main() !void { |
| 56 | const foo = "good morning\n"; | 56 | const foo = "good morning\n"; |
| 57 | const bar = "good evening\n"; | 57 | const bar = "good evening\n"; |
| 58 | const qux = "good night\n"; | 58 | const qux = "good night\n"; |
| 59 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 59 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 60 | #expect_stdout="good night\n" | 60 | #expect_stdout="good night\n" |
| 61 | 61 | ||
| 62 | #update=remove unused declarations | 62 | #update=remove unused declarations |
| ... | @@ -66,5 +66,5 @@ pub fn main() !void { | ... | @@ -66,5 +66,5 @@ pub fn main() !void { |
| 66 | try std.Io.File.stdout().writeStreamingAll(io, @This().qux); | 66 | try std.Io.File.stdout().writeStreamingAll(io, @This().qux); |
| 67 | } | 67 | } |
| 68 | const qux = "good night\n"; | 68 | const qux = "good night\n"; |
| 69 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 69 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 70 | #expect_stdout="good night\n" | 70 | #expect_stdout="good night\n" |
test/incremental/bad_import+2-2| ... | @@ -11,7 +11,7 @@ pub fn main() !void { | ... | @@ -11,7 +11,7 @@ pub fn main() !void { |
| 11 | try std.Io.File.stdout().writeStreamingAll(io, "success\n"); | 11 | try std.Io.File.stdout().writeStreamingAll(io, "success\n"); |
| 12 | } | 12 | } |
| 13 | const std = @import("std"); | 13 | const std = @import("std"); |
| 14 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 14 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 15 | #file=foo.zig | 15 | #file=foo.zig |
| 16 | comptime { | 16 | comptime { |
| 17 | _ = @import("bad.zig"); | 17 | _ = @import("bad.zig"); |
| ... | @@ -34,5 +34,5 @@ pub fn main() !void { | ... | @@ -34,5 +34,5 @@ pub fn main() !void { |
| 34 | try std.Io.File.stdout().writeStreamingAll(io, "success\n"); | 34 | try std.Io.File.stdout().writeStreamingAll(io, "success\n"); |
| 35 | } | 35 | } |
| 36 | const std = @import("std"); | 36 | const std = @import("std"); |
| 37 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 37 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 38 | #expect_stdout="success\n" | 38 | #expect_stdout="success\n" |
test/incremental/change_embed_file+3-3| ... | @@ -10,7 +10,7 @@ const string = @embedFile("string.txt"); | ... | @@ -10,7 +10,7 @@ const string = @embedFile("string.txt"); |
| 10 | pub fn main() !void { | 10 | pub fn main() !void { |
| 11 | try std.Io.File.stdout().writeStreamingAll(io, string); | 11 | try std.Io.File.stdout().writeStreamingAll(io, string); |
| 12 | } | 12 | } |
| 13 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 13 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 14 | #file=string.txt | 14 | #file=string.txt |
| 15 | Hello, World! | 15 | Hello, World! |
| 16 | #expect_stdout="Hello, World!\n" | 16 | #expect_stdout="Hello, World!\n" |
| ... | @@ -31,7 +31,7 @@ const string = @embedFile("string.txt"); | ... | @@ -31,7 +31,7 @@ const string = @embedFile("string.txt"); |
| 31 | pub fn main() !void { | 31 | pub fn main() !void { |
| 32 | try std.Io.File.stdout().writeStreamingAll(io, "a hardcoded string\n"); | 32 | try std.Io.File.stdout().writeStreamingAll(io, "a hardcoded string\n"); |
| 33 | } | 33 | } |
| 34 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 34 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 35 | #expect_stdout="a hardcoded string\n" | 35 | #expect_stdout="a hardcoded string\n" |
| 36 | 36 | ||
| 37 | #update=re-introduce reference to file | 37 | #update=re-introduce reference to file |
| ... | @@ -41,7 +41,7 @@ const string = @embedFile("string.txt"); | ... | @@ -41,7 +41,7 @@ const string = @embedFile("string.txt"); |
| 41 | pub fn main() !void { | 41 | pub fn main() !void { |
| 42 | try std.Io.File.stdout().writeStreamingAll(io, string); | 42 | try std.Io.File.stdout().writeStreamingAll(io, string); |
| 43 | } | 43 | } |
| 44 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 44 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 45 | #expect_error=main.zig:2:27: error: unable to open 'string.txt': FileNotFound | 45 | #expect_error=main.zig:2:27: error: unable to open 'string.txt': FileNotFound |
| 46 | 46 | ||
| 47 | #update=recreate file | 47 | #update=recreate file |
test/incremental/change_enum_tag_type+3-3| ... | @@ -19,7 +19,7 @@ pub fn main() !void { | ... | @@ -19,7 +19,7 @@ pub fn main() !void { |
| 19 | try stdout_writer.interface.print("{s}\n", .{@tagName(val)}); | 19 | try stdout_writer.interface.print("{s}\n", .{@tagName(val)}); |
| 20 | } | 20 | } |
| 21 | const std = @import("std"); | 21 | const std = @import("std"); |
| 22 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 22 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 23 | #expect_stdout="a\n" | 23 | #expect_stdout="a\n" |
| 24 | #update=too many enum fields | 24 | #update=too many enum fields |
| 25 | #file=main.zig | 25 | #file=main.zig |
| ... | @@ -43,7 +43,7 @@ comptime { | ... | @@ -43,7 +43,7 @@ comptime { |
| 43 | std.debug.assert(@TypeOf(@intFromEnum(Foo.e)) == Tag); | 43 | std.debug.assert(@TypeOf(@intFromEnum(Foo.e)) == Tag); |
| 44 | } | 44 | } |
| 45 | const std = @import("std"); | 45 | const std = @import("std"); |
| 46 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 46 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 47 | #expect_error=main.zig:7:5: error: enumeration value '4' too large for type 'u2' | 47 | #expect_error=main.zig:7:5: error: enumeration value '4' too large for type 'u2' |
| 48 | #update=increase tag size | 48 | #update=increase tag size |
| 49 | #file=main.zig | 49 | #file=main.zig |
| ... | @@ -62,5 +62,5 @@ pub fn main() !void { | ... | @@ -62,5 +62,5 @@ pub fn main() !void { |
| 62 | try stdout_writer.interface.print("{s}\n", .{@tagName(val)}); | 62 | try stdout_writer.interface.print("{s}\n", .{@tagName(val)}); |
| 63 | } | 63 | } |
| 64 | const std = @import("std"); | 64 | const std = @import("std"); |
| 65 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 65 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 66 | #expect_stdout="a\n" | 66 | #expect_stdout="a\n" |
test/incremental/change_exports+6-6| ... | @@ -21,7 +21,7 @@ pub fn main() !void { | ... | @@ -21,7 +21,7 @@ pub fn main() !void { |
| 21 | try stdout_writer.interface.print("{}\n", .{S.bar}); | 21 | try stdout_writer.interface.print("{}\n", .{S.bar}); |
| 22 | } | 22 | } |
| 23 | const std = @import("std"); | 23 | const std = @import("std"); |
| 24 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 24 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 25 | #expect_stdout="123\n" | 25 | #expect_stdout="123\n" |
| 26 | 26 | ||
| 27 | #update=add conflict | 27 | #update=add conflict |
| ... | @@ -44,7 +44,7 @@ pub fn main() !void { | ... | @@ -44,7 +44,7 @@ pub fn main() !void { |
| 44 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); | 44 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); |
| 45 | } | 45 | } |
| 46 | const std = @import("std"); | 46 | const std = @import("std"); |
| 47 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 47 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 48 | #expect_error=main.zig:6:5: error: exported symbol collision: foo | 48 | #expect_error=main.zig:6:5: error: exported symbol collision: foo |
| 49 | #expect_error=main.zig:1:1: note: other symbol here | 49 | #expect_error=main.zig:1:1: note: other symbol here |
| 50 | 50 | ||
| ... | @@ -68,7 +68,7 @@ pub fn main() !void { | ... | @@ -68,7 +68,7 @@ pub fn main() !void { |
| 68 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); | 68 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); |
| 69 | } | 69 | } |
| 70 | const std = @import("std"); | 70 | const std = @import("std"); |
| 71 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 71 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 72 | #expect_stdout="123 456\n" | 72 | #expect_stdout="123 456\n" |
| 73 | 73 | ||
| 74 | #update=put exports in decl | 74 | #update=put exports in decl |
| ... | @@ -94,7 +94,7 @@ pub fn main() !void { | ... | @@ -94,7 +94,7 @@ pub fn main() !void { |
| 94 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); | 94 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); |
| 95 | } | 95 | } |
| 96 | const std = @import("std"); | 96 | const std = @import("std"); |
| 97 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 97 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 98 | #expect_stdout="123 456\n" | 98 | #expect_stdout="123 456\n" |
| 99 | 99 | ||
| 100 | #update=remove reference to exporting decl | 100 | #update=remove reference to exporting decl |
| ... | @@ -141,7 +141,7 @@ pub fn main() !void { | ... | @@ -141,7 +141,7 @@ pub fn main() !void { |
| 141 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); | 141 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); |
| 142 | } | 142 | } |
| 143 | const std = @import("std"); | 143 | const std = @import("std"); |
| 144 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 144 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 145 | #expect_stdout="123 456\n" | 145 | #expect_stdout="123 456\n" |
| 146 | 146 | ||
| 147 | #update=reintroduce reference to exporting decl, introducing conflict | 147 | #update=reintroduce reference to exporting decl, introducing conflict |
| ... | @@ -167,7 +167,7 @@ pub fn main() !void { | ... | @@ -167,7 +167,7 @@ pub fn main() !void { |
| 167 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); | 167 | try stdout_writer.interface.print("{} {}\n", .{ S.bar, S.other }); |
| 168 | } | 168 | } |
| 169 | const std = @import("std"); | 169 | const std = @import("std"); |
| 170 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 170 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 171 | #expect_error=main.zig:5:5: error: exported symbol collision: bar | 171 | #expect_error=main.zig:5:5: error: exported symbol collision: bar |
| 172 | #expect_error=main.zig:2:1: note: other symbol here | 172 | #expect_error=main.zig:2:1: note: other symbol here |
| 173 | #expect_error=main.zig:6:5: error: exported symbol collision: other | 173 | #expect_error=main.zig:6:5: error: exported symbol collision: other |
test/incremental/change_fn_type+3-3| ... | @@ -12,7 +12,7 @@ fn foo(x: u8) !void { | ... | @@ -12,7 +12,7 @@ fn foo(x: u8) !void { |
| 12 | return stdout_writer.interface.print("{d}\n", .{x}); | 12 | return stdout_writer.interface.print("{d}\n", .{x}); |
| 13 | } | 13 | } |
| 14 | const std = @import("std"); | 14 | const std = @import("std"); |
| 15 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 15 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 16 | #expect_stdout="123\n" | 16 | #expect_stdout="123\n" |
| 17 | 17 | ||
| 18 | #update=change function type | 18 | #update=change function type |
| ... | @@ -25,7 +25,7 @@ fn foo(x: i64) !void { | ... | @@ -25,7 +25,7 @@ fn foo(x: i64) !void { |
| 25 | return stdout_writer.interface.print("{d}\n", .{x}); | 25 | return stdout_writer.interface.print("{d}\n", .{x}); |
| 26 | } | 26 | } |
| 27 | const std = @import("std"); | 27 | const std = @import("std"); |
| 28 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 28 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 29 | #expect_stdout="123\n" | 29 | #expect_stdout="123\n" |
| 30 | 30 | ||
| 31 | #update=change function argument | 31 | #update=change function argument |
| ... | @@ -38,5 +38,5 @@ fn foo(x: i64) !void { | ... | @@ -38,5 +38,5 @@ fn foo(x: i64) !void { |
| 38 | return stdout_writer.interface.print("{d}\n", .{x}); | 38 | return stdout_writer.interface.print("{d}\n", .{x}); |
| 39 | } | 39 | } |
| 40 | const std = @import("std"); | 40 | const std = @import("std"); |
| 41 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 41 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 42 | #expect_stdout="-42\n" | 42 | #expect_stdout="-42\n" |
test/incremental/change_generic_line_number+2-2| ... | @@ -4,7 +4,7 @@ | ... | @@ -4,7 +4,7 @@ |
| 4 | #update=initial version | 4 | #update=initial version |
| 5 | #file=main.zig | 5 | #file=main.zig |
| 6 | const std = @import("std"); | 6 | const std = @import("std"); |
| 7 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 7 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 8 | fn Printer(message: []const u8) type { | 8 | fn Printer(message: []const u8) type { |
| 9 | return struct { | 9 | return struct { |
| 10 | fn print() !void { | 10 | fn print() !void { |
| ... | @@ -20,7 +20,7 @@ pub fn main() !void { | ... | @@ -20,7 +20,7 @@ pub fn main() !void { |
| 20 | #update=change line number | 20 | #update=change line number |
| 21 | #file=main.zig | 21 | #file=main.zig |
| 22 | const std = @import("std"); | 22 | const std = @import("std"); |
| 23 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 23 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 24 | 24 | ||
| 25 | fn Printer(message: []const u8) type { | 25 | fn Printer(message: []const u8) type { |
| 26 | return struct { | 26 | return struct { |
test/incremental/change_line_number+2-2| ... | @@ -7,7 +7,7 @@ const std = @import("std"); | ... | @@ -7,7 +7,7 @@ const std = @import("std"); |
| 7 | pub fn main() !void { | 7 | pub fn main() !void { |
| 8 | try std.Io.File.stdout().writeStreamingAll(io, "foo\n"); | 8 | try std.Io.File.stdout().writeStreamingAll(io, "foo\n"); |
| 9 | } | 9 | } |
| 10 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 10 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 11 | #expect_stdout="foo\n" | 11 | #expect_stdout="foo\n" |
| 12 | #update=change line number | 12 | #update=change line number |
| 13 | #file=main.zig | 13 | #file=main.zig |
| ... | @@ -16,5 +16,5 @@ const std = @import("std"); | ... | @@ -16,5 +16,5 @@ const std = @import("std"); |
| 16 | pub fn main() !void { | 16 | pub fn main() !void { |
| 17 | try std.Io.File.stdout().writeStreamingAll(io, "foo\n"); | 17 | try std.Io.File.stdout().writeStreamingAll(io, "foo\n"); |
| 18 | } | 18 | } |
| 19 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 19 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 20 | #expect_stdout="foo\n" | 20 | #expect_stdout="foo\n" |
test/incremental/change_panic_handler+3-3| ... | @@ -17,7 +17,7 @@ fn myPanic(msg: []const u8, _: ?usize) noreturn { | ... | @@ -17,7 +17,7 @@ fn myPanic(msg: []const u8, _: ?usize) noreturn { |
| 17 | std.process.exit(0); | 17 | std.process.exit(0); |
| 18 | } | 18 | } |
| 19 | const std = @import("std"); | 19 | const std = @import("std"); |
| 20 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 20 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 21 | #expect_stdout="panic message: integer overflow\n" | 21 | #expect_stdout="panic message: integer overflow\n" |
| 22 | 22 | ||
| 23 | #update=change the panic handler body | 23 | #update=change the panic handler body |
| ... | @@ -35,7 +35,7 @@ fn myPanic(msg: []const u8, _: ?usize) noreturn { | ... | @@ -35,7 +35,7 @@ fn myPanic(msg: []const u8, _: ?usize) noreturn { |
| 35 | std.process.exit(0); | 35 | std.process.exit(0); |
| 36 | } | 36 | } |
| 37 | const std = @import("std"); | 37 | const std = @import("std"); |
| 38 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 38 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 39 | #expect_stdout="new panic message: integer overflow\n" | 39 | #expect_stdout="new panic message: integer overflow\n" |
| 40 | 40 | ||
| 41 | #update=change the panic handler function value | 41 | #update=change the panic handler function value |
| ... | @@ -53,5 +53,5 @@ fn myPanicNew(msg: []const u8, _: ?usize) noreturn { | ... | @@ -53,5 +53,5 @@ fn myPanicNew(msg: []const u8, _: ?usize) noreturn { |
| 53 | std.process.exit(0); | 53 | std.process.exit(0); |
| 54 | } | 54 | } |
| 55 | const std = @import("std"); | 55 | const std = @import("std"); |
| 56 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 56 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 57 | #expect_stdout="third panic message: integer overflow\n" | 57 | #expect_stdout="third panic message: integer overflow\n" |
test/incremental/change_panic_handler_explicit+3-3| ... | @@ -47,7 +47,7 @@ fn myPanic(msg: []const u8, _: ?usize) noreturn { | ... | @@ -47,7 +47,7 @@ fn myPanic(msg: []const u8, _: ?usize) noreturn { |
| 47 | std.process.exit(0); | 47 | std.process.exit(0); |
| 48 | } | 48 | } |
| 49 | const std = @import("std"); | 49 | const std = @import("std"); |
| 50 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 50 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 51 | #expect_stdout="panic message: integer overflow\n" | 51 | #expect_stdout="panic message: integer overflow\n" |
| 52 | 52 | ||
| 53 | #update=change the panic handler body | 53 | #update=change the panic handler body |
| ... | @@ -95,7 +95,7 @@ fn myPanic(msg: []const u8, _: ?usize) noreturn { | ... | @@ -95,7 +95,7 @@ fn myPanic(msg: []const u8, _: ?usize) noreturn { |
| 95 | std.process.exit(0); | 95 | std.process.exit(0); |
| 96 | } | 96 | } |
| 97 | const std = @import("std"); | 97 | const std = @import("std"); |
| 98 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 98 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 99 | #expect_stdout="new panic message: integer overflow\n" | 99 | #expect_stdout="new panic message: integer overflow\n" |
| 100 | 100 | ||
| 101 | #update=change the panic handler function value | 101 | #update=change the panic handler function value |
| ... | @@ -143,5 +143,5 @@ fn myPanicNew(msg: []const u8, _: ?usize) noreturn { | ... | @@ -143,5 +143,5 @@ fn myPanicNew(msg: []const u8, _: ?usize) noreturn { |
| 143 | std.process.exit(0); | 143 | std.process.exit(0); |
| 144 | } | 144 | } |
| 145 | const std = @import("std"); | 145 | const std = @import("std"); |
| 146 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 146 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 147 | #expect_stdout="third panic message: integer overflow\n" | 147 | #expect_stdout="third panic message: integer overflow\n" |
test/incremental/change_shift_op+2-2| ... | @@ -13,7 +13,7 @@ fn foo(x: u16) !void { | ... | @@ -13,7 +13,7 @@ fn foo(x: u16) !void { |
| 13 | try stdout_writer.interface.print("0x{x}\n", .{x << 4}); | 13 | try stdout_writer.interface.print("0x{x}\n", .{x << 4}); |
| 14 | } | 14 | } |
| 15 | const std = @import("std"); | 15 | const std = @import("std"); |
| 16 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 16 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 17 | #expect_stdout="0x3000\n" | 17 | #expect_stdout="0x3000\n" |
| 18 | #update=change to right shift | 18 | #update=change to right shift |
| 19 | #file=main.zig | 19 | #file=main.zig |
| ... | @@ -25,5 +25,5 @@ fn foo(x: u16) !void { | ... | @@ -25,5 +25,5 @@ fn foo(x: u16) !void { |
| 25 | try stdout_writer.interface.print("0x{x}\n", .{x >> 4}); | 25 | try stdout_writer.interface.print("0x{x}\n", .{x >> 4}); |
| 26 | } | 26 | } |
| 27 | const std = @import("std"); | 27 | const std = @import("std"); |
| 28 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 28 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 29 | #expect_stdout="0x130\n" | 29 | #expect_stdout="0x130\n" |
test/incremental/change_struct_same_fields+3-3| ... | @@ -18,7 +18,7 @@ fn foo(val: *const S) !void { | ... | @@ -18,7 +18,7 @@ fn foo(val: *const S) !void { |
| 18 | ); | 18 | ); |
| 19 | } | 19 | } |
| 20 | const std = @import("std"); | 20 | const std = @import("std"); |
| 21 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 21 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 22 | #expect_stdout="100 200\n" | 22 | #expect_stdout="100 200\n" |
| 23 | 23 | ||
| 24 | #update=change struct layout | 24 | #update=change struct layout |
| ... | @@ -36,7 +36,7 @@ fn foo(val: *const S) !void { | ... | @@ -36,7 +36,7 @@ fn foo(val: *const S) !void { |
| 36 | ); | 36 | ); |
| 37 | } | 37 | } |
| 38 | const std = @import("std"); | 38 | const std = @import("std"); |
| 39 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 39 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 40 | #expect_stdout="100 200\n" | 40 | #expect_stdout="100 200\n" |
| 41 | 41 | ||
| 42 | #update=change values | 42 | #update=change values |
| ... | @@ -54,5 +54,5 @@ fn foo(val: *const S) !void { | ... | @@ -54,5 +54,5 @@ fn foo(val: *const S) !void { |
| 54 | ); | 54 | ); |
| 55 | } | 55 | } |
| 56 | const std = @import("std"); | 56 | const std = @import("std"); |
| 57 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 57 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 58 | #expect_stdout="1234 5678\n" | 58 | #expect_stdout="1234 5678\n" |
test/incremental/change_zon_file+3-3| ... | @@ -10,7 +10,7 @@ const message: []const u8 = @import("message.zon"); | ... | @@ -10,7 +10,7 @@ const message: []const u8 = @import("message.zon"); |
| 10 | pub fn main() !void { | 10 | pub fn main() !void { |
| 11 | try std.Io.File.stdout().writeStreamingAll(io, message); | 11 | try std.Io.File.stdout().writeStreamingAll(io, message); |
| 12 | } | 12 | } |
| 13 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 13 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 14 | #file=message.zon | 14 | #file=message.zon |
| 15 | "Hello, World!\n" | 15 | "Hello, World!\n" |
| 16 | #expect_stdout="Hello, World!\n" | 16 | #expect_stdout="Hello, World!\n" |
| ... | @@ -32,7 +32,7 @@ const message: []const u8 = @import("message.zon"); | ... | @@ -32,7 +32,7 @@ const message: []const u8 = @import("message.zon"); |
| 32 | pub fn main() !void { | 32 | pub fn main() !void { |
| 33 | try std.Io.File.stdout().writeStreamingAll(io, "a hardcoded string\n"); | 33 | try std.Io.File.stdout().writeStreamingAll(io, "a hardcoded string\n"); |
| 34 | } | 34 | } |
| 35 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 35 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 36 | #expect_error=message.zon:1:1: error: unable to load 'message.zon': FileNotFound | 36 | #expect_error=message.zon:1:1: error: unable to load 'message.zon': FileNotFound |
| 37 | #expect_error=main.zig:2:37: note: file imported here | 37 | #expect_error=main.zig:2:37: note: file imported here |
| 38 | 38 | ||
| ... | @@ -48,5 +48,5 @@ const message: []const u8 = @import("message.zon"); | ... | @@ -48,5 +48,5 @@ const message: []const u8 = @import("message.zon"); |
| 48 | pub fn main() !void { | 48 | pub fn main() !void { |
| 49 | try std.Io.File.stdout().writeStreamingAll(io, message); | 49 | try std.Io.File.stdout().writeStreamingAll(io, message); |
| 50 | } | 50 | } |
| 51 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 51 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 52 | #expect_stdout="We're back, World!\n" | 52 | #expect_stdout="We're back, World!\n" |
test/incremental/change_zon_file_no_result_type+1-1| ... | @@ -6,7 +6,7 @@ | ... | @@ -6,7 +6,7 @@ |
| 6 | #update=initial version | 6 | #update=initial version |
| 7 | #file=main.zig | 7 | #file=main.zig |
| 8 | const std = @import("std"); | 8 | const std = @import("std"); |
| 9 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 9 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 10 | pub fn main() !void { | 10 | pub fn main() !void { |
| 11 | try std.Io.File.stdout().writeStreamingAll(io, @import("foo.zon").message); | 11 | try std.Io.File.stdout().writeStreamingAll(io, @import("foo.zon").message); |
| 12 | } | 12 | } |
test/incremental/compile_log+3-3| ... | @@ -10,7 +10,7 @@ const std = @import("std"); | ... | @@ -10,7 +10,7 @@ const std = @import("std"); |
| 10 | pub fn main() !void { | 10 | pub fn main() !void { |
| 11 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); | 11 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 12 | } | 12 | } |
| 13 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 13 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 14 | #expect_stdout="Hello, World!\n" | 14 | #expect_stdout="Hello, World!\n" |
| 15 | 15 | ||
| 16 | #update=add compile log | 16 | #update=add compile log |
| ... | @@ -20,7 +20,7 @@ pub fn main() !void { | ... | @@ -20,7 +20,7 @@ pub fn main() !void { |
| 20 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); | 20 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 21 | @compileLog("this is a log"); | 21 | @compileLog("this is a log"); |
| 22 | } | 22 | } |
| 23 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 23 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 24 | #expect_error=main.zig:4:5: error: found compile log statement | 24 | #expect_error=main.zig:4:5: error: found compile log statement |
| 25 | #expect_compile_log=@as(*const [13:0]u8, "this is a log") | 25 | #expect_compile_log=@as(*const [13:0]u8, "this is a log") |
| 26 | 26 | ||
| ... | @@ -30,5 +30,5 @@ const std = @import("std"); | ... | @@ -30,5 +30,5 @@ const std = @import("std"); |
| 30 | pub fn main() !void { | 30 | pub fn main() !void { |
| 31 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); | 31 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 32 | } | 32 | } |
| 33 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 33 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 34 | #expect_stdout="Hello, World!\n" | 34 | #expect_stdout="Hello, World!\n" |
test/incremental/fix_astgen_failure+3-3| ... | @@ -19,7 +19,7 @@ const std = @import("std"); | ... | @@ -19,7 +19,7 @@ const std = @import("std"); |
| 19 | pub fn hello() !void { | 19 | pub fn hello() !void { |
| 20 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); | 20 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 21 | } | 21 | } |
| 22 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 22 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 23 | #expect_stdout="Hello, World!\n" | 23 | #expect_stdout="Hello, World!\n" |
| 24 | #update=add new error | 24 | #update=add new error |
| 25 | #file=foo.zig | 25 | #file=foo.zig |
| ... | @@ -27,7 +27,7 @@ const std = @import("std"); | ... | @@ -27,7 +27,7 @@ const std = @import("std"); |
| 27 | pub fn hello() !void { | 27 | pub fn hello() !void { |
| 28 | try std.Io.File.stdout().writeStreamingAll(io, hello_str); | 28 | try std.Io.File.stdout().writeStreamingAll(io, hello_str); |
| 29 | } | 29 | } |
| 30 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 30 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 31 | #expect_error=foo.zig:3:52: error: use of undeclared identifier 'hello_str' | 31 | #expect_error=foo.zig:3:52: error: use of undeclared identifier 'hello_str' |
| 32 | #update=fix the new error | 32 | #update=fix the new error |
| 33 | #file=foo.zig | 33 | #file=foo.zig |
| ... | @@ -36,5 +36,5 @@ const hello_str = "Hello, World! Again!\n"; | ... | @@ -36,5 +36,5 @@ const hello_str = "Hello, World! Again!\n"; |
| 36 | pub fn hello() !void { | 36 | pub fn hello() !void { |
| 37 | try std.Io.File.stdout().writeStreamingAll(io, hello_str); | 37 | try std.Io.File.stdout().writeStreamingAll(io, hello_str); |
| 38 | } | 38 | } |
| 39 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 39 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 40 | #expect_stdout="Hello, World! Again!\n" | 40 | #expect_stdout="Hello, World! Again!\n" |
test/incremental/function_becomes_inline+3-3| ... | @@ -11,7 +11,7 @@ fn foo() !void { | ... | @@ -11,7 +11,7 @@ fn foo() !void { |
| 11 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); | 11 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 12 | } | 12 | } |
| 13 | const std = @import("std"); | 13 | const std = @import("std"); |
| 14 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 14 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 15 | #expect_stdout="Hello, World!\n" | 15 | #expect_stdout="Hello, World!\n" |
| 16 | 16 | ||
| 17 | #update=make function inline | 17 | #update=make function inline |
| ... | @@ -23,7 +23,7 @@ inline fn foo() !void { | ... | @@ -23,7 +23,7 @@ inline fn foo() !void { |
| 23 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); | 23 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 24 | } | 24 | } |
| 25 | const std = @import("std"); | 25 | const std = @import("std"); |
| 26 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 26 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 27 | #expect_stdout="Hello, World!\n" | 27 | #expect_stdout="Hello, World!\n" |
| 28 | 28 | ||
| 29 | #update=change string | 29 | #update=change string |
| ... | @@ -35,5 +35,5 @@ inline fn foo() !void { | ... | @@ -35,5 +35,5 @@ inline fn foo() !void { |
| 35 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, `inline` World!\n"); | 35 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, `inline` World!\n"); |
| 36 | } | 36 | } |
| 37 | const std = @import("std"); | 37 | const std = @import("std"); |
| 38 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 38 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 39 | #expect_stdout="Hello, `inline` World!\n" | 39 | #expect_stdout="Hello, `inline` World!\n" |
test/incremental/hello+2-2| ... | @@ -6,7 +6,7 @@ | ... | @@ -6,7 +6,7 @@ |
| 6 | #update=initial version | 6 | #update=initial version |
| 7 | #file=main.zig | 7 | #file=main.zig |
| 8 | const std = @import("std"); | 8 | const std = @import("std"); |
| 9 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 9 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 10 | pub fn main() !void { | 10 | pub fn main() !void { |
| 11 | try std.Io.File.stdout().writeStreamingAll(io, "good morning\n"); | 11 | try std.Io.File.stdout().writeStreamingAll(io, "good morning\n"); |
| 12 | } | 12 | } |
| ... | @@ -14,7 +14,7 @@ pub fn main() !void { | ... | @@ -14,7 +14,7 @@ pub fn main() !void { |
| 14 | #update=change the string | 14 | #update=change the string |
| 15 | #file=main.zig | 15 | #file=main.zig |
| 16 | const std = @import("std"); | 16 | const std = @import("std"); |
| 17 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 17 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 18 | pub fn main() !void { | 18 | pub fn main() !void { |
| 19 | try std.Io.File.stdout().writeStreamingAll(io, "おはようございます\n"); | 19 | try std.Io.File.stdout().writeStreamingAll(io, "おはようございます\n"); |
| 20 | } | 20 | } |
test/incremental/make_decl_pub+2-2| ... | @@ -14,7 +14,7 @@ const std = @import("std"); | ... | @@ -14,7 +14,7 @@ const std = @import("std"); |
| 14 | fn hello() !void { | 14 | fn hello() !void { |
| 15 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); | 15 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 16 | } | 16 | } |
| 17 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 17 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 18 | #expect_error=main.zig:3:12: error: 'hello' is not marked 'pub' | 18 | #expect_error=main.zig:3:12: error: 'hello' is not marked 'pub' |
| 19 | #expect_error=foo.zig:2:1: note: declared here | 19 | #expect_error=foo.zig:2:1: note: declared here |
| 20 | 20 | ||
| ... | @@ -24,5 +24,5 @@ const std = @import("std"); | ... | @@ -24,5 +24,5 @@ const std = @import("std"); |
| 24 | pub fn hello() !void { | 24 | pub fn hello() !void { |
| 25 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); | 25 | try std.Io.File.stdout().writeStreamingAll(io, "Hello, World!\n"); |
| 26 | } | 26 | } |
| 27 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 27 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 28 | #expect_stdout="Hello, World!\n" | 28 | #expect_stdout="Hello, World!\n" |
test/incremental/modify_inline_fn+2-2| ... | @@ -13,7 +13,7 @@ pub fn main() !void { | ... | @@ -13,7 +13,7 @@ pub fn main() !void { |
| 13 | inline fn getStr() []const u8 { | 13 | inline fn getStr() []const u8 { |
| 14 | return "foo\n"; | 14 | return "foo\n"; |
| 15 | } | 15 | } |
| 16 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 16 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 17 | #expect_stdout="foo\n" | 17 | #expect_stdout="foo\n" |
| 18 | #update=change the string | 18 | #update=change the string |
| 19 | #file=main.zig | 19 | #file=main.zig |
| ... | @@ -25,5 +25,5 @@ pub fn main() !void { | ... | @@ -25,5 +25,5 @@ pub fn main() !void { |
| 25 | inline fn getStr() []const u8 { | 25 | inline fn getStr() []const u8 { |
| 26 | return "bar\n"; | 26 | return "bar\n"; |
| 27 | } | 27 | } |
| 28 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 28 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 29 | #expect_stdout="bar\n" | 29 | #expect_stdout="bar\n" |
test/incremental/move_src+2-2| ... | @@ -16,7 +16,7 @@ fn foo() u32 { | ... | @@ -16,7 +16,7 @@ fn foo() u32 { |
| 16 | fn bar() u32 { | 16 | fn bar() u32 { |
| 17 | return 123; | 17 | return 123; |
| 18 | } | 18 | } |
| 19 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 19 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 20 | #expect_stdout="7 123\n" | 20 | #expect_stdout="7 123\n" |
| 21 | 21 | ||
| 22 | #update=add newline | 22 | #update=add newline |
| ... | @@ -33,5 +33,5 @@ fn foo() u32 { | ... | @@ -33,5 +33,5 @@ fn foo() u32 { |
| 33 | fn bar() u32 { | 33 | fn bar() u32 { |
| 34 | return 123; | 34 | return 123; |
| 35 | } | 35 | } |
| 36 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 36 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 37 | #expect_stdout="8 123\n" | 37 | #expect_stdout="8 123\n" |
test/incremental/no_change_preserves_tag_names+2-2| ... | @@ -7,7 +7,7 @@ | ... | @@ -7,7 +7,7 @@ |
| 7 | #file=main.zig | 7 | #file=main.zig |
| 8 | const std = @import("std"); | 8 | const std = @import("std"); |
| 9 | var some_enum: enum { first, second } = .first; | 9 | var some_enum: enum { first, second } = .first; |
| 10 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 10 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 11 | pub fn main() !void { | 11 | pub fn main() !void { |
| 12 | try std.Io.File.stdout().writeStreamingAll(io, @tagName(some_enum)); | 12 | try std.Io.File.stdout().writeStreamingAll(io, @tagName(some_enum)); |
| 13 | } | 13 | } |
| ... | @@ -16,7 +16,7 @@ pub fn main() !void { | ... | @@ -16,7 +16,7 @@ pub fn main() !void { |
| 16 | #file=main.zig | 16 | #file=main.zig |
| 17 | const std = @import("std"); | 17 | const std = @import("std"); |
| 18 | var some_enum: enum { first, second } = .first; | 18 | var some_enum: enum { first, second } = .first; |
| 19 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 19 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 20 | pub fn main() !void { | 20 | pub fn main() !void { |
| 21 | try std.Io.File.stdout().writeStreamingAll(io, @tagName(some_enum)); | 21 | try std.Io.File.stdout().writeStreamingAll(io, @tagName(some_enum)); |
| 22 | } | 22 | } |
test/incremental/recursive_function_becomes_non_recursive+2-2| ... | @@ -14,7 +14,7 @@ fn foo(recurse: bool) !void { | ... | @@ -14,7 +14,7 @@ fn foo(recurse: bool) !void { |
| 14 | try stdout.writeStreamingAll(io, "non-recursive path\n"); | 14 | try stdout.writeStreamingAll(io, "non-recursive path\n"); |
| 15 | } | 15 | } |
| 16 | const std = @import("std"); | 16 | const std = @import("std"); |
| 17 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 17 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 18 | #expect_stdout="non-recursive path\n" | 18 | #expect_stdout="non-recursive path\n" |
| 19 | 19 | ||
| 20 | #update=eliminate recursion and change argument | 20 | #update=eliminate recursion and change argument |
| ... | @@ -28,5 +28,5 @@ fn foo(recurse: bool) !void { | ... | @@ -28,5 +28,5 @@ fn foo(recurse: bool) !void { |
| 28 | try stdout.writeStreamingAll(io, "non-recursive path\n"); | 28 | try stdout.writeStreamingAll(io, "non-recursive path\n"); |
| 29 | } | 29 | } |
| 30 | const std = @import("std"); | 30 | const std = @import("std"); |
| 31 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 31 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 32 | #expect_stdout="x==1\n" | 32 | #expect_stdout="x==1\n" |
test/incremental/remove_enum_field+2-2| ... | @@ -14,7 +14,7 @@ pub fn main() !void { | ... | @@ -14,7 +14,7 @@ pub fn main() !void { |
| 14 | try stdout_writer.interface.print("{}\n", .{@intFromEnum(MyEnum.foo)}); | 14 | try stdout_writer.interface.print("{}\n", .{@intFromEnum(MyEnum.foo)}); |
| 15 | } | 15 | } |
| 16 | const std = @import("std"); | 16 | const std = @import("std"); |
| 17 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 17 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 18 | #expect_stdout="1\n" | 18 | #expect_stdout="1\n" |
| 19 | #update=remove enum field | 19 | #update=remove enum field |
| 20 | #file=main.zig | 20 | #file=main.zig |
| ... | @@ -27,6 +27,6 @@ pub fn main() !void { | ... | @@ -27,6 +27,6 @@ pub fn main() !void { |
| 27 | try stdout_writer.interface.print("{}\n", .{@intFromEnum(MyEnum.foo)}); | 27 | try stdout_writer.interface.print("{}\n", .{@intFromEnum(MyEnum.foo)}); |
| 28 | } | 28 | } |
| 29 | const std = @import("std"); | 29 | const std = @import("std"); |
| 30 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 30 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 31 | #expect_error=main.zig:7:69: error: enum 'main.MyEnum' has no member named 'foo' | 31 | #expect_error=main.zig:7:69: error: enum 'main.MyEnum' has no member named 'foo' |
| 32 | #expect_error=main.zig:1:16: note: enum declared here | 32 | #expect_error=main.zig:1:16: note: enum declared here |
test/incremental/unreferenced_error+4-4| ... | @@ -10,7 +10,7 @@ pub fn main() !void { | ... | @@ -10,7 +10,7 @@ pub fn main() !void { |
| 10 | try std.Io.File.stdout().writeStreamingAll(io, a); | 10 | try std.Io.File.stdout().writeStreamingAll(io, a); |
| 11 | } | 11 | } |
| 12 | const a = "Hello, World!\n"; | 12 | const a = "Hello, World!\n"; |
| 13 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 13 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 14 | #expect_stdout="Hello, World!\n" | 14 | #expect_stdout="Hello, World!\n" |
| 15 | 15 | ||
| 16 | #update=introduce compile error | 16 | #update=introduce compile error |
| ... | @@ -20,7 +20,7 @@ pub fn main() !void { | ... | @@ -20,7 +20,7 @@ pub fn main() !void { |
| 20 | try std.Io.File.stdout().writeStreamingAll(io, a); | 20 | try std.Io.File.stdout().writeStreamingAll(io, a); |
| 21 | } | 21 | } |
| 22 | const a = @compileError("bad a"); | 22 | const a = @compileError("bad a"); |
| 23 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 23 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 24 | #expect_error=main.zig:5:11: error: bad a | 24 | #expect_error=main.zig:5:11: error: bad a |
| 25 | 25 | ||
| 26 | #update=remove error reference | 26 | #update=remove error reference |
| ... | @@ -31,7 +31,7 @@ pub fn main() !void { | ... | @@ -31,7 +31,7 @@ pub fn main() !void { |
| 31 | } | 31 | } |
| 32 | const a = @compileError("bad a"); | 32 | const a = @compileError("bad a"); |
| 33 | const b = "Hi there!\n"; | 33 | const b = "Hi there!\n"; |
| 34 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 34 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 35 | #expect_stdout="Hi there!\n" | 35 | #expect_stdout="Hi there!\n" |
| 36 | 36 | ||
| 37 | #update=introduce and remove reference to error | 37 | #update=introduce and remove reference to error |
| ... | @@ -42,5 +42,5 @@ pub fn main() !void { | ... | @@ -42,5 +42,5 @@ pub fn main() !void { |
| 42 | } | 42 | } |
| 43 | const a = "Back to a\n"; | 43 | const a = "Back to a\n"; |
| 44 | const b = @compileError("bad b"); | 44 | const b = @compileError("bad b"); |
| 45 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 45 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 46 | #expect_stdout="Back to a\n" | 46 | #expect_stdout="Back to a\n" |
test/standalone/coff_dwarf/build.zig+3| ... | @@ -46,6 +46,9 @@ pub fn build(b: *std.Build) void { | ... | @@ -46,6 +46,9 @@ pub fn build(b: *std.Build) void { |
| 46 | lib.root_module.addCSourceFile(.{ .file = b.path("shared_lib.c"), .flags = &.{"-gdwarf"} }); | 46 | lib.root_module.addCSourceFile(.{ .file = b.path("shared_lib.c"), .flags = &.{"-gdwarf"} }); |
| 47 | exe.root_module.linkLibrary(lib); | 47 | exe.root_module.linkLibrary(lib); |
| 48 | 48 | ||
| 49 | if (target.result.os.tag == .windows) | ||
| 50 | exe.root_module.linkSystemLibrary("ws2_32", .{}); | ||
| 51 | |||
| 49 | const run = b.addRunArtifact(exe); | 52 | const run = b.addRunArtifact(exe); |
| 50 | run.expectExitCode(0); | 53 | run.expectExitCode(0); |
| 51 | run.skip_foreign_checks = true; | 54 | run.skip_foreign_checks = true; |
test/standalone/dirname/exists_in.zig+1-1| ... | @@ -26,7 +26,7 @@ pub fn main(init: std.process.Init) !void { | ... | @@ -26,7 +26,7 @@ pub fn main(init: std.process.Init) !void { |
| 26 | return error.BadUsage; | 26 | return error.BadUsage; |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| 29 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 29 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 30 | 30 | ||
| 31 | var dir = try std.Io.Dir.cwd().openDir(io, dir_path, .{}); | 31 | var dir = try std.Io.Dir.cwd().openDir(io, dir_path, .{}); |
| 32 | defer dir.close(io); | 32 | defer dir.close(io); |
test/standalone/dirname/touch.zig+1-1| ... | @@ -21,7 +21,7 @@ pub fn main(init: std.process.Init) !void { | ... | @@ -21,7 +21,7 @@ pub fn main(init: std.process.Init) !void { |
| 21 | const dir_path = std.Io.Dir.path.dirname(path) orelse unreachable; | 21 | const dir_path = std.Io.Dir.path.dirname(path) orelse unreachable; |
| 22 | const basename = std.Io.Dir.path.basename(path); | 22 | const basename = std.Io.Dir.path.basename(path); |
| 23 | 23 | ||
| 24 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 24 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 25 | 25 | ||
| 26 | var dir = try std.Io.Dir.cwd().openDir(io, dir_path, .{}); | 26 | var dir = try std.Io.Dir.cwd().openDir(io, dir_path, .{}); |
| 27 | defer dir.close(io); | 27 | defer dir.close(io); |
test/standalone/issue_5825/build.zig+1| ... | @@ -34,6 +34,7 @@ pub fn build(b: *std.Build) void { | ... | @@ -34,6 +34,7 @@ pub fn build(b: *std.Build) void { |
| 34 | exe.subsystem = .console; | 34 | exe.subsystem = .console; |
| 35 | exe.root_module.linkSystemLibrary("kernel32", .{}); | 35 | exe.root_module.linkSystemLibrary("kernel32", .{}); |
| 36 | exe.root_module.linkSystemLibrary("ntdll", .{}); | 36 | exe.root_module.linkSystemLibrary("ntdll", .{}); |
| 37 | exe.root_module.linkSystemLibrary("ws2_32", .{}); | ||
| 37 | exe.root_module.addObject(obj); | 38 | exe.root_module.addObject(obj); |
| 38 | 39 | ||
| 39 | // TODO: actually check the output | 40 | // TODO: actually check the output |
test/standalone/mix_o_files/build.zig+3| ... | @@ -16,6 +16,9 @@ pub fn build(b: *std.Build) void { | ... | @@ -16,6 +16,9 @@ pub fn build(b: *std.Build) void { |
| 16 | }), | 16 | }), |
| 17 | }); | 17 | }); |
| 18 | 18 | ||
| 19 | if (target.result.os.tag == .windows) | ||
| 20 | obj.root_module.linkSystemLibrary("ws2_32", .{}); | ||
| 21 | |||
| 19 | const exe = b.addExecutable(.{ | 22 | const exe = b.addExecutable(.{ |
| 20 | .name = "test", | 23 | .name = "test", |
| 21 | .root_module = b.createModule(.{ | 24 | .root_module = b.createModule(.{ |
test/standalone/run_cwd/check_file_exists.zig+1-1| ... | @@ -5,7 +5,7 @@ pub fn main(init: std.process.Init) !void { | ... | @@ -5,7 +5,7 @@ pub fn main(init: std.process.Init) !void { |
| 5 | if (args.len != 2) return error.BadUsage; | 5 | if (args.len != 2) return error.BadUsage; |
| 6 | const path = args[1]; | 6 | const path = args[1]; |
| 7 | 7 | ||
| 8 | const io = std.Io.Threaded.global_single_threaded.ioBasic(); | 8 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 9 | 9 | ||
| 10 | std.Io.Dir.cwd().access(io, path, .{}) catch return error.AccessFailed; | 10 | std.Io.Dir.cwd().access(io, path, .{}) catch return error.AccessFailed; |
| 11 | } | 11 | } |
test/standalone/shared_library/build.zig+4-1| ... | @@ -5,7 +5,7 @@ pub fn build(b: *std.Build) void { | ... | @@ -5,7 +5,7 @@ pub fn build(b: *std.Build) void { |
| 5 | b.default_step = test_step; | 5 | b.default_step = test_step; |
| 6 | 6 | ||
| 7 | const optimize: std.builtin.OptimizeMode = .Debug; | 7 | const optimize: std.builtin.OptimizeMode = .Debug; |
| 8 | const target = b.graph.host; | 8 | const target = b.standardTargetOptions(.{}); |
| 9 | 9 | ||
| 10 | const exe_names: []const []const u8 = &.{ "test", "test-dync" }; | 10 | const exe_names: []const []const u8 = &.{ "test", "test-dync" }; |
| 11 | const lib_names: []const []const u8 = &.{ "mathtest", "mathtest-dync" }; | 11 | const lib_names: []const []const u8 = &.{ "mathtest", "mathtest-dync" }; |
| ... | @@ -24,6 +24,9 @@ pub fn build(b: *std.Build) void { | ... | @@ -24,6 +24,9 @@ pub fn build(b: *std.Build) void { |
| 24 | }), | 24 | }), |
| 25 | }); | 25 | }); |
| 26 | 26 | ||
| 27 | if (target.result.os.tag == .windows) | ||
| 28 | lib.root_module.linkSystemLibrary("ws2_32", .{}); | ||
| 29 | |||
| 27 | const exe = b.addExecutable(.{ | 30 | const exe = b.addExecutable(.{ |
| 28 | .name = exe_name, | 31 | .name = exe_name, |
| 29 | .root_module = b.createModule(.{ | 32 | .root_module = b.createModule(.{ |
test/standalone/windows_argv/build.zig+3| ... | @@ -20,6 +20,8 @@ pub fn build(b: *std.Build) !void { | ... | @@ -20,6 +20,8 @@ pub fn build(b: *std.Build) !void { |
| 20 | .optimize = optimize, | 20 | .optimize = optimize, |
| 21 | }), | 21 | }), |
| 22 | }); | 22 | }); |
| 23 | lib_gnu.root_module.linkSystemLibrary("ws2_32", .{}); | ||
| 24 | |||
| 23 | const verify_gnu = b.addExecutable(.{ | 25 | const verify_gnu = b.addExecutable(.{ |
| 24 | .name = "verify-gnu", | 26 | .name = "verify-gnu", |
| 25 | .root_module = b.createModule(.{ | 27 | .root_module = b.createModule(.{ |
| ... | @@ -101,6 +103,7 @@ pub fn build(b: *std.Build) !void { | ... | @@ -101,6 +103,7 @@ pub fn build(b: *std.Build) !void { |
| 101 | .flags = &.{ "-DUNICODE", "-D_UNICODE" }, | 103 | .flags = &.{ "-DUNICODE", "-D_UNICODE" }, |
| 102 | }); | 104 | }); |
| 103 | verify_msvc.root_module.linkLibrary(lib_msvc); | 105 | verify_msvc.root_module.linkLibrary(lib_msvc); |
| 106 | verify_msvc.root_module.linkSystemLibrary("ws2_32", .{}); | ||
| 104 | verify_msvc.root_module.link_libc = true; | 107 | verify_msvc.root_module.link_libc = true; |
| 105 | 108 | ||
| 106 | const run_msvc = b.addRunArtifact(fuzz); | 109 | const run_msvc = b.addRunArtifact(fuzz); |