| ... | ... | @@ -0,0 +1,659 @@ |
| 1 | const Debug = @This(); |
| 2 | |
| 3 | impl: Io, |
| 4 | |
| 5 | /// It is safe for this to be a `std.Thread.Mutex` because it does not guard any |
| 6 | /// `Io` operations, only data structure accesses. Using an `Io.Mutex` would be |
| 7 | /// undesirable as it may significantly change the scheduling behavior of the |
| 8 | /// application. |
| 9 | mutex: std.Thread.Mutex, |
| 10 | |
| 11 | gpa: Allocator, |
| 12 | oom_count: u32, |
| 13 | open_files: std.AutoArrayHashMapUnmanaged(Io.File.Handle, StackTrace) = .empty, |
| 14 | open_dirs: std.AutoArrayHashMapUnmanaged(Io.Dir.Handle, StackTrace) = .empty, |
| 15 | |
| 16 | const StackTrace = struct { index: usize, buf: [6]usize }; |
| 17 | |
| 18 | pub fn init(impl: Io, gpa: Allocator) Debug { |
| 19 | return .{ |
| 20 | .impl = impl, |
| 21 | .mutex = .{}, |
| 22 | .gpa = gpa, |
| 23 | .oom_count = 0, |
| 24 | .open_files = .empty, |
| 25 | .open_dirs = .empty, |
| 26 | }; |
| 27 | } |
| 28 | |
| 29 | pub fn deinit(dbg: *Debug) void { |
| 30 | if (dbg.oom_count > 0) { |
| 31 | std.log.warn("ran out of memory to track {d} handles; some leaks may not be detected", .{dbg.oom_count}); |
| 32 | } |
| 33 | for (dbg.open_files.keys(), dbg.open_files.values()) |handle, *st| { |
| 34 | std.log.err("file handle '{any}' leaked: {f}", .{ |
| 35 | handle, |
| 36 | @as(std.debug.FormatStackTrace, .{ |
| 37 | .stack_trace = .{ .instruction_addresses = &st.buf, .index = st.index }, |
| 38 | .terminal_mode = std.log.terminalMode(), |
| 39 | }), |
| 40 | }); |
| 41 | } |
| 42 | for (dbg.open_dirs.keys(), dbg.open_dirs.values()) |handle, *st| { |
| 43 | std.log.err("dir handle '{any}' leaked: {f}", .{ |
| 44 | handle, |
| 45 | @as(std.debug.FormatStackTrace, .{ |
| 46 | .stack_trace = .{ .instruction_addresses = &st.buf, .index = st.index }, |
| 47 | .terminal_mode = std.log.terminalMode(), |
| 48 | }), |
| 49 | }); |
| 50 | } |
| 51 | dbg.open_files.deinit(dbg.gpa); |
| 52 | dbg.open_dirs.deinit(dbg.gpa); |
| 53 | } |
| 54 | |
| 55 | pub fn io(dbg: *Debug) Io { |
| 56 | return .{ |
| 57 | .userdata = dbg, |
| 58 | .vtable = &.{ |
| 59 | .async = &async, |
| 60 | .concurrent = &concurrent, |
| 61 | .await = &await, |
| 62 | .cancel = &cancel, |
| 63 | .select = &select, |
| 64 | |
| 65 | .groupAsync = &groupAsync, |
| 66 | .groupConcurrent = &groupConcurrent, |
| 67 | .groupAwait = &groupAwait, |
| 68 | .groupCancel = &groupCancel, |
| 69 | |
| 70 | .recancel = &recancel, |
| 71 | .swapCancelProtection = &swapCancelProtection, |
| 72 | .checkCancel = &checkCancel, |
| 73 | |
| 74 | .futexWait = &futexWait, |
| 75 | .futexWaitUncancelable = &futexWaitUncancelable, |
| 76 | .futexWake = &futexWake, |
| 77 | |
| 78 | .dirCreateDir = &dirCreateDir, |
| 79 | .dirCreateDirPath = &dirCreateDirPath, |
| 80 | .dirCreateDirPathOpen = &dirCreateDirPathOpen, |
| 81 | .dirOpenDir = &dirOpenDir, |
| 82 | .dirStat = &dirStat, |
| 83 | .dirStatFile = &dirStatFile, |
| 84 | .dirAccess = &dirAccess, |
| 85 | .dirCreateFile = &dirCreateFile, |
| 86 | .dirCreateFileAtomic = &dirCreateFileAtomic, |
| 87 | .dirOpenFile = &dirOpenFile, |
| 88 | .dirClose = &dirClose, |
| 89 | .dirRead = &dirRead, |
| 90 | .dirRealPath = &dirRealPath, |
| 91 | .dirRealPathFile = &dirRealPathFile, |
| 92 | .dirDeleteFile = &dirDeleteFile, |
| 93 | .dirDeleteDir = &dirDeleteDir, |
| 94 | .dirRename = &dirRename, |
| 95 | .dirRenamePreserve = &dirRenamePreserve, |
| 96 | .dirSymLink = &dirSymLink, |
| 97 | .dirReadLink = &dirReadLink, |
| 98 | .dirSetOwner = &dirSetOwner, |
| 99 | .dirSetFileOwner = &dirSetFileOwner, |
| 100 | .dirSetPermissions = &dirSetPermissions, |
| 101 | .dirSetFilePermissions = &dirSetFilePermissions, |
| 102 | .dirSetTimestamps = &dirSetTimestamps, |
| 103 | .dirHardLink = &dirHardLink, |
| 104 | |
| 105 | .fileStat = &fileStat, |
| 106 | .fileLength = &fileLength, |
| 107 | .fileClose = &fileClose, |
| 108 | .fileWriteStreaming = &fileWriteStreaming, |
| 109 | .fileWritePositional = &fileWritePositional, |
| 110 | .fileWriteFileStreaming = &fileWriteFileStreaming, |
| 111 | .fileWriteFilePositional = &fileWriteFilePositional, |
| 112 | .fileReadStreaming = &fileReadStreaming, |
| 113 | .fileReadPositional = &fileReadPositional, |
| 114 | .fileSeekBy = &fileSeekBy, |
| 115 | .fileSeekTo = &fileSeekTo, |
| 116 | .fileSync = &fileSync, |
| 117 | .fileIsTty = &fileIsTty, |
| 118 | .fileEnableAnsiEscapeCodes = &fileEnableAnsiEscapeCodes, |
| 119 | .fileSupportsAnsiEscapeCodes = &fileSupportsAnsiEscapeCodes, |
| 120 | .fileSetLength = &fileSetLength, |
| 121 | .fileSetOwner = &fileSetOwner, |
| 122 | .fileSetPermissions = &fileSetPermissions, |
| 123 | .fileSetTimestamps = &fileSetTimestamps, |
| 124 | .fileLock = &fileLock, |
| 125 | .fileTryLock = &fileTryLock, |
| 126 | .fileUnlock = &fileUnlock, |
| 127 | .fileDowngradeLock = &fileDowngradeLock, |
| 128 | .fileRealPath = &fileRealPath, |
| 129 | .fileHardLink = &fileHardLink, |
| 130 | |
| 131 | .processExecutableOpen = &processExecutableOpen, |
| 132 | .processExecutablePath = &processExecutablePath, |
| 133 | .lockStderr = &lockStderr, |
| 134 | .tryLockStderr = &tryLockStderr, |
| 135 | .unlockStderr = &unlockStderr, |
| 136 | .processSetCurrentDir = &processSetCurrentDir, |
| 137 | .processReplace = &processReplace, |
| 138 | .processReplacePath = &processReplacePath, |
| 139 | .processSpawn = &processSpawn, |
| 140 | .processSpawnPath = &processSpawnPath, |
| 141 | .childWait = &childWait, |
| 142 | .childKill = &childKill, |
| 143 | |
| 144 | .progressParentFile = &progressParentFile, |
| 145 | |
| 146 | .now = &now, |
| 147 | .sleep = &sleep, |
| 148 | |
| 149 | .random = &random, |
| 150 | .randomSecure = &randomSecure, |
| 151 | |
| 152 | .netListenIp = &netListenIp, |
| 153 | .netAccept = &netAccept, |
| 154 | .netBindIp = &netBindIp, |
| 155 | .netConnectIp = &netConnectIp, |
| 156 | .netListenUnix = &netListenUnix, |
| 157 | .netConnectUnix = &netConnectUnix, |
| 158 | .netSend = &netSend, |
| 159 | .netReceive = &netReceive, |
| 160 | |
| 161 | .netRead = &netRead, |
| 162 | .netWrite = &netWrite, |
| 163 | .netWriteFile = &netWriteFile, |
| 164 | .netClose = &netClose, |
| 165 | .netShutdown = &netShutdown, |
| 166 | .netInterfaceNameResolve = &netInterfaceNameResolve, |
| 167 | .netInterfaceName = &netInterfaceName, |
| 168 | .netLookup = &netLookup, |
| 169 | }, |
| 170 | }; |
| 171 | } |
| 172 | |
| 173 | fn trackOpenFile(dbg: *Debug, file: Io.File, ra: usize) void { |
| 174 | dbg.mutex.lock(); |
| 175 | defer dbg.mutex.unlock(); |
| 176 | const gop = dbg.open_files.getOrPut(dbg.gpa, file.handle) catch |err| switch (err) { |
| 177 | error.OutOfMemory => { |
| 178 | dbg.oom_count += 1; |
| 179 | return; |
| 180 | }, |
| 181 | }; |
| 182 | assert(!gop.found_existing); // underlying implementation returned duplicate handle |
| 183 | const st = std.debug.captureCurrentStackTrace(.{ .first_address = ra }, &gop.value_ptr.buf); |
| 184 | gop.value_ptr.index = st.index; |
| 185 | } |
| 186 | |
| 187 | fn trackCloseFile(dbg: *Debug, file: Io.File, ra: usize) void { |
| 188 | dbg.mutex.lock(); |
| 189 | defer dbg.mutex.unlock(); |
| 190 | if (!dbg.open_files.swapRemove(file.handle)) { |
| 191 | // If there was an OOM we might have failed to track the handle, but otherwise this is |
| 192 | // definitely incorrect usage. |
| 193 | if (dbg.oom_count == 0) { |
| 194 | std.debug.panicExtra(ra, "attempted to close file handle '{any}' which is not open", .{file.handle}); |
| 195 | } |
| 196 | } |
| 197 | } |
| 198 | |
| 199 | fn trackOpenDir(dbg: *Debug, dir: Io.Dir, ra: usize) void { |
| 200 | dbg.mutex.lock(); |
| 201 | defer dbg.mutex.unlock(); |
| 202 | const gop = dbg.open_dirs.getOrPut(dbg.gpa, dir.handle) catch |err| switch (err) { |
| 203 | error.OutOfMemory => { |
| 204 | dbg.oom_count += 1; |
| 205 | return; |
| 206 | }, |
| 207 | }; |
| 208 | assert(!gop.found_existing); // underlying implementation returned duplicate handle |
| 209 | const st = std.debug.captureCurrentStackTrace(.{ .first_address = ra }, &gop.value_ptr.buf); |
| 210 | gop.value_ptr.index = st.index; |
| 211 | } |
| 212 | |
| 213 | fn trackCloseDir(dbg: *Debug, dir: Io.Dir, ra: usize) void { |
| 214 | dbg.mutex.lock(); |
| 215 | defer dbg.mutex.unlock(); |
| 216 | if (!dbg.open_dirs.swapRemove(dir.handle)) { |
| 217 | // If there was an OOM we might have failed to track the handle, but otherwise this is |
| 218 | // definitely incorrect usage. |
| 219 | if (dbg.oom_count == 0) { |
| 220 | std.debug.panicExtra(ra, "attempted to close dir handle '{any}' which is not open", .{dir.handle}); |
| 221 | } |
| 222 | } |
| 223 | } |
| 224 | |
| 225 | fn async(userdata: ?*anyopaque, result: []u8, result_alignment: std.mem.Alignment, context: []const u8, context_alignment: std.mem.Alignment, start: *const fn (context: *const anyopaque, result: *anyopaque) void) ?*Io.AnyFuture { |
| 226 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 227 | return dbg.impl.vtable.async(dbg.impl.userdata, result, result_alignment, context, context_alignment, start); |
| 228 | } |
| 229 | |
| 230 | fn concurrent(userdata: ?*anyopaque, result_len: usize, result_alignment: std.mem.Alignment, context: []const u8, context_alignment: std.mem.Alignment, start: *const fn (context: *const anyopaque, result: *anyopaque) void) Io.ConcurrentError!*Io.AnyFuture { |
| 231 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 232 | return dbg.impl.vtable.concurrent(dbg.impl.userdata, result_len, result_alignment, context, context_alignment, start); |
| 233 | } |
| 234 | |
| 235 | fn await(userdata: ?*anyopaque, any_future: *Io.AnyFuture, result: []u8, result_alignment: std.mem.Alignment) void { |
| 236 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 237 | return dbg.impl.vtable.await(dbg.impl.userdata, any_future, result, result_alignment); |
| 238 | } |
| 239 | |
| 240 | fn cancel(userdata: ?*anyopaque, any_future: *Io.AnyFuture, result: []u8, result_alignment: std.mem.Alignment) void { |
| 241 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 242 | return dbg.impl.vtable.cancel(dbg.impl.userdata, any_future, result, result_alignment); |
| 243 | } |
| 244 | |
| 245 | fn groupAsync(userdata: ?*anyopaque, group: *Io.Group, context: []const u8, context_alignment: std.mem.Alignment, start: *const fn (context: *const anyopaque) Cancelable!void) void { |
| 246 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 247 | return dbg.impl.vtable.groupAsync(dbg.impl.userdata, group, context, context_alignment, start); |
| 248 | } |
| 249 | |
| 250 | fn groupConcurrent(userdata: ?*anyopaque, group: *Io.Group, context: []const u8, context_alignment: std.mem.Alignment, start: *const fn (context: *const anyopaque) Cancelable!void) Io.ConcurrentError!void { |
| 251 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 252 | return dbg.impl.vtable.groupConcurrent(dbg.impl.userdata, group, context, context_alignment, start); |
| 253 | } |
| 254 | fn groupAwait(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) Cancelable!void { |
| 255 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 256 | return dbg.impl.vtable.groupAwait(dbg.impl.userdata, group, token); |
| 257 | } |
| 258 | fn groupCancel(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) void { |
| 259 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 260 | return dbg.impl.vtable.groupCancel(dbg.impl.userdata, group, token); |
| 261 | } |
| 262 | |
| 263 | fn recancel(userdata: ?*anyopaque) void { |
| 264 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 265 | return dbg.impl.vtable.recancel(dbg.impl.userdata); |
| 266 | } |
| 267 | fn swapCancelProtection(userdata: ?*anyopaque, new: Io.CancelProtection) Io.CancelProtection { |
| 268 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 269 | return dbg.impl.vtable.swapCancelProtection(dbg.impl.userdata, new); |
| 270 | } |
| 271 | fn checkCancel(userdata: ?*anyopaque) Cancelable!void { |
| 272 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 273 | return dbg.impl.vtable.checkCancel(dbg.impl.userdata); |
| 274 | } |
| 275 | |
| 276 | fn select(userdata: ?*anyopaque, futures: []const *Io.AnyFuture) Cancelable!usize { |
| 277 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 278 | return dbg.impl.vtable.select(dbg.impl.userdata, futures); |
| 279 | } |
| 280 | |
| 281 | fn futexWait(userdata: ?*anyopaque, ptr: *const u32, expected: u32, timeout: Io.Timeout) Cancelable!void { |
| 282 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 283 | return dbg.impl.vtable.futexWait(dbg.impl.userdata, ptr, expected, timeout); |
| 284 | } |
| 285 | fn futexWaitUncancelable(userdata: ?*anyopaque, ptr: *const u32, expected: u32) void { |
| 286 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 287 | return dbg.impl.vtable.futexWaitUncancelable(dbg.impl.userdata, ptr, expected); |
| 288 | } |
| 289 | fn futexWake(userdata: ?*anyopaque, ptr: *const u32, max_waiters: u32) void { |
| 290 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 291 | return dbg.impl.vtable.futexWake(dbg.impl.userdata, ptr, max_waiters); |
| 292 | } |
| 293 | |
| 294 | fn dirCreateDir(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, permissions: Io.Dir.Permissions) Io.Dir.CreateDirError!void { |
| 295 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 296 | return dbg.impl.vtable.dirCreateDir(dbg.impl.userdata, dir, sub_path, permissions); |
| 297 | } |
| 298 | fn dirCreateDirPath(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, permissions: Io.Dir.Permissions) Io.Dir.CreateDirPathError!Io.Dir.CreatePathStatus { |
| 299 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 300 | return dbg.impl.vtable.dirCreateDirPath(dbg.impl.userdata, dir, sub_path, permissions); |
| 301 | } |
| 302 | fn dirCreateDirPathOpen(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, permissions: Io.Dir.Permissions, options: Io.Dir.OpenOptions) Io.Dir.CreateDirPathOpenError!Io.Dir { |
| 303 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 304 | const new_dir = try dbg.impl.vtable.dirCreateDirPathOpen(dbg.impl.userdata, dir, sub_path, permissions, options); |
| 305 | dbg.trackOpenDir(new_dir, @returnAddress()); |
| 306 | return new_dir; |
| 307 | } |
| 308 | fn dirOpenDir(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, options: Io.Dir.OpenOptions) Io.Dir.OpenError!Io.Dir { |
| 309 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 310 | const new_dir = try dbg.impl.vtable.dirOpenDir(dbg.impl.userdata, dir, sub_path, options); |
| 311 | dbg.trackOpenDir(new_dir, @returnAddress()); |
| 312 | return new_dir; |
| 313 | } |
| 314 | fn dirStat(userdata: ?*anyopaque, dir: Io.Dir) Io.Dir.StatError!Io.Dir.Stat { |
| 315 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 316 | return dbg.impl.vtable.dirStat(dbg.impl.userdata, dir); |
| 317 | } |
| 318 | fn dirStatFile(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, options: Io.Dir.StatFileOptions) Io.Dir.StatFileError!Io.File.Stat { |
| 319 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 320 | return dbg.impl.vtable.dirStatFile(dbg.impl.userdata, dir, sub_path, options); |
| 321 | } |
| 322 | fn dirAccess(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, options: Io.Dir.AccessOptions) Io.Dir.AccessError!void { |
| 323 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 324 | return dbg.impl.vtable.dirAccess(dbg.impl.userdata, dir, sub_path, options); |
| 325 | } |
| 326 | fn dirCreateFile(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, flags: Io.File.CreateFlags) Io.File.OpenError!Io.File { |
| 327 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 328 | const file = try dbg.impl.vtable.dirCreateFile(dbg.impl.userdata, dir, sub_path, flags); |
| 329 | dbg.trackOpenFile(file, @returnAddress()); |
| 330 | return file; |
| 331 | } |
| 332 | fn dirCreateFileAtomic(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, options: Io.Dir.CreateFileAtomicOptions) Io.Dir.CreateFileAtomicError!Io.File.Atomic { |
| 333 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 334 | const af = try dbg.impl.vtable.dirCreateFileAtomic(dbg.impl.userdata, dir, sub_path, options); |
| 335 | if (af.file_open) dbg.trackOpenFile(af.file, @returnAddress()); |
| 336 | return af; |
| 337 | } |
| 338 | fn dirOpenFile(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, flags: Io.File.OpenFlags) Io.File.OpenError!Io.File { |
| 339 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 340 | const file = try dbg.impl.vtable.dirOpenFile(dbg.impl.userdata, dir, sub_path, flags); |
| 341 | dbg.trackOpenFile(file, @returnAddress()); |
| 342 | return file; |
| 343 | } |
| 344 | fn dirClose(userdata: ?*anyopaque, dirs: []const Io.Dir) void { |
| 345 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 346 | for (dirs) |dir| dbg.trackCloseDir(dir, @returnAddress()); |
| 347 | return dbg.impl.vtable.dirClose(dbg.impl.userdata, dirs); |
| 348 | } |
| 349 | fn dirRead(userdata: ?*anyopaque, dr: *Io.Dir.Reader, buffer: []Io.Dir.Entry) Io.Dir.Reader.Error!usize { |
| 350 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 351 | return dbg.impl.vtable.dirRead(dbg.impl.userdata, dr, buffer); |
| 352 | } |
| 353 | fn dirRealPath(userdata: ?*anyopaque, dir: Io.Dir, out_buffer: []u8) Io.Dir.RealPathError!usize { |
| 354 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 355 | return dbg.impl.vtable.dirRealPath(dbg.impl.userdata, dir, out_buffer); |
| 356 | } |
| 357 | fn dirRealPathFile(userdata: ?*anyopaque, dir: Io.Dir, path_name: []const u8, out_buffer: []u8) Io.Dir.RealPathFileError!usize { |
| 358 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 359 | return dbg.impl.vtable.dirRealPathFile(dbg.impl.userdata, dir, path_name, out_buffer); |
| 360 | } |
| 361 | fn dirDeleteFile(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8) Io.Dir.DeleteFileError!void { |
| 362 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 363 | return dbg.impl.vtable.dirDeleteFile(dbg.impl.userdata, dir, sub_path); |
| 364 | } |
| 365 | fn dirDeleteDir(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8) Io.Dir.DeleteDirError!void { |
| 366 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 367 | return dbg.impl.vtable.dirDeleteDir(dbg.impl.userdata, dir, sub_path); |
| 368 | } |
| 369 | fn dirRename(userdata: ?*anyopaque, old_dir: Io.Dir, old_sub_path: []const u8, new_dir: Io.Dir, new_sub_path: []const u8) Io.Dir.RenameError!void { |
| 370 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 371 | return dbg.impl.vtable.dirRename(dbg.impl.userdata, old_dir, old_sub_path, new_dir, new_sub_path); |
| 372 | } |
| 373 | fn dirRenamePreserve(userdata: ?*anyopaque, old_dir: Io.Dir, old_sub_path: []const u8, new_dir: Io.Dir, new_sub_path: []const u8) Io.Dir.RenamePreserveError!void { |
| 374 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 375 | return dbg.impl.vtable.dirRenamePreserve(dbg.impl.userdata, old_dir, old_sub_path, new_dir, new_sub_path); |
| 376 | } |
| 377 | fn dirSymLink(userdata: ?*anyopaque, dir: Io.Dir, target_path: []const u8, sym_link_path: []const u8, flags: Io.Dir.SymLinkFlags) Io.Dir.SymLinkError!void { |
| 378 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 379 | return dbg.impl.vtable.dirSymLink(dbg.impl.userdata, dir, target_path, sym_link_path, flags); |
| 380 | } |
| 381 | fn dirReadLink(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, buffer: []u8) Io.Dir.ReadLinkError!usize { |
| 382 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 383 | return dbg.impl.vtable.dirReadLink(dbg.impl.userdata, dir, sub_path, buffer); |
| 384 | } |
| 385 | fn dirSetOwner(userdata: ?*anyopaque, dir: Io.Dir, uid: ?Io.File.Uid, gid: ?Io.File.Gid) Io.Dir.SetOwnerError!void { |
| 386 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 387 | return dbg.impl.vtable.dirSetOwner(dbg.impl.userdata, dir, uid, gid); |
| 388 | } |
| 389 | fn dirSetFileOwner(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, uid: ?Io.File.Uid, gid: ?Io.File.Gid, options: Io.Dir.SetFileOwnerOptions) Io.Dir.SetFileOwnerError!void { |
| 390 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 391 | return dbg.impl.vtable.dirSetFileOwner(dbg.impl.userdata, dir, sub_path, uid, gid, options); |
| 392 | } |
| 393 | fn dirSetPermissions(userdata: ?*anyopaque, dir: Io.Dir, permissions: Io.Dir.Permissions) Io.Dir.SetPermissionsError!void { |
| 394 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 395 | return dbg.impl.vtable.dirSetPermissions(dbg.impl.userdata, dir, permissions); |
| 396 | } |
| 397 | fn dirSetFilePermissions(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, permissions: Io.File.Permissions, options: Io.Dir.SetFilePermissionsOptions) Io.Dir.SetFilePermissionsError!void { |
| 398 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 399 | return dbg.impl.vtable.dirSetFilePermissions(dbg.impl.userdata, dir, sub_path, permissions, options); |
| 400 | } |
| 401 | fn dirSetTimestamps(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, options: Io.Dir.SetTimestampsOptions) Io.Dir.SetTimestampsError!void { |
| 402 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 403 | return dbg.impl.vtable.dirSetTimestamps(dbg.impl.userdata, dir, sub_path, options); |
| 404 | } |
| 405 | fn dirHardLink(userdata: ?*anyopaque, old_dir: Io.Dir, old_sub_path: []const u8, new_dir: Io.Dir, new_sub_path: []const u8, options: Io.Dir.HardLinkOptions) Io.Dir.HardLinkError!void { |
| 406 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 407 | return dbg.impl.vtable.dirHardLink(dbg.impl.userdata, old_dir, old_sub_path, new_dir, new_sub_path, options); |
| 408 | } |
| 409 | |
| 410 | fn fileStat(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.Stat { |
| 411 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 412 | return dbg.impl.vtable.fileStat(dbg.impl.userdata, file); |
| 413 | } |
| 414 | fn fileLength(userdata: ?*anyopaque, file: Io.File) Io.File.LengthError!u64 { |
| 415 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 416 | return dbg.impl.vtable.fileLength(dbg.impl.userdata, file); |
| 417 | } |
| 418 | fn fileClose(userdata: ?*anyopaque, files: []const Io.File) void { |
| 419 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 420 | for (files) |file| dbg.trackCloseFile(file, @returnAddress()); |
| 421 | return dbg.impl.vtable.fileClose(dbg.impl.userdata, files); |
| 422 | } |
| 423 | fn fileWriteStreaming(userdata: ?*anyopaque, file: Io.File, header: []const u8, data: []const []const u8, splat: usize) Io.File.Writer.Error!usize { |
| 424 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 425 | return dbg.impl.vtable.fileWriteStreaming(dbg.impl.userdata, file, header, data, splat); |
| 426 | } |
| 427 | fn fileWritePositional(userdata: ?*anyopaque, file: Io.File, header: []const u8, data: []const []const u8, splat: usize, offset: u64) Io.File.WritePositionalError!usize { |
| 428 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 429 | return dbg.impl.vtable.fileWritePositional(dbg.impl.userdata, file, header, data, splat, offset); |
| 430 | } |
| 431 | fn fileWriteFileStreaming(userdata: ?*anyopaque, file: Io.File, header: []const u8, fr: *Io.File.Reader, limit: Io.Limit) Io.File.Writer.WriteFileError!usize { |
| 432 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 433 | return dbg.impl.vtable.fileWriteFileStreaming(dbg.impl.userdata, file, header, fr, limit); |
| 434 | } |
| 435 | fn fileWriteFilePositional(userdata: ?*anyopaque, file: Io.File, header: []const u8, fr: *Io.File.Reader, limit: Io.Limit, offset: u64) Io.File.WriteFilePositionalError!usize { |
| 436 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 437 | return dbg.impl.vtable.fileWriteFilePositional(dbg.impl.userdata, file, header, fr, limit, offset); |
| 438 | } |
| 439 | |
| 440 | fn fileReadStreaming(userdata: ?*anyopaque, file: Io.File, data: []const []u8) Io.File.Reader.Error!usize { |
| 441 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 442 | return dbg.impl.vtable.fileReadStreaming(dbg.impl.userdata, file, data); |
| 443 | } |
| 444 | |
| 445 | fn fileReadPositional(userdata: ?*anyopaque, file: Io.File, data: []const []u8, offset: u64) Io.File.ReadPositionalError!usize { |
| 446 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 447 | return dbg.impl.vtable.fileReadPositional(dbg.impl.userdata, file, data, offset); |
| 448 | } |
| 449 | fn fileSeekBy(userdata: ?*anyopaque, file: Io.File, relative_offset: i64) Io.File.SeekError!void { |
| 450 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 451 | return dbg.impl.vtable.fileSeekBy(dbg.impl.userdata, file, relative_offset); |
| 452 | } |
| 453 | fn fileSeekTo(userdata: ?*anyopaque, file: Io.File, absolute_offset: u64) Io.File.SeekError!void { |
| 454 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 455 | return dbg.impl.vtable.fileSeekTo(dbg.impl.userdata, file, absolute_offset); |
| 456 | } |
| 457 | fn fileSync(userdata: ?*anyopaque, file: Io.File) Io.File.SyncError!void { |
| 458 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 459 | return dbg.impl.vtable.fileSync(dbg.impl.userdata, file); |
| 460 | } |
| 461 | fn fileIsTty(userdata: ?*anyopaque, file: Io.File) Cancelable!bool { |
| 462 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 463 | return dbg.impl.vtable.fileIsTty(dbg.impl.userdata, file); |
| 464 | } |
| 465 | fn fileEnableAnsiEscapeCodes(userdata: ?*anyopaque, file: Io.File) Io.File.EnableAnsiEscapeCodesError!void { |
| 466 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 467 | return dbg.impl.vtable.fileEnableAnsiEscapeCodes(dbg.impl.userdata, file); |
| 468 | } |
| 469 | fn fileSupportsAnsiEscapeCodes(userdata: ?*anyopaque, file: Io.File) Cancelable!bool { |
| 470 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 471 | return dbg.impl.vtable.fileSupportsAnsiEscapeCodes(dbg.impl.userdata, file); |
| 472 | } |
| 473 | fn fileSetLength(userdata: ?*anyopaque, file: Io.File, length: u64) Io.File.SetLengthError!void { |
| 474 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 475 | return dbg.impl.vtable.fileSetLength(dbg.impl.userdata, file, length); |
| 476 | } |
| 477 | fn fileSetOwner(userdata: ?*anyopaque, file: Io.File, uid: ?Io.File.Uid, gid: ?Io.File.Gid) Io.File.SetOwnerError!void { |
| 478 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 479 | return dbg.impl.vtable.fileSetOwner(dbg.impl.userdata, file, uid, gid); |
| 480 | } |
| 481 | fn fileSetPermissions(userdata: ?*anyopaque, file: Io.File, permissions: Io.File.Permissions) Io.File.SetPermissionsError!void { |
| 482 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 483 | return dbg.impl.vtable.fileSetPermissions(dbg.impl.userdata, file, permissions); |
| 484 | } |
| 485 | fn fileSetTimestamps(userdata: ?*anyopaque, file: Io.File, options: Io.File.SetTimestampsOptions) Io.File.SetTimestampsError!void { |
| 486 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 487 | return dbg.impl.vtable.fileSetTimestamps(dbg.impl.userdata, file, options); |
| 488 | } |
| 489 | fn fileLock(userdata: ?*anyopaque, file: Io.File, lock: Io.File.Lock) Io.File.LockError!void { |
| 490 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 491 | return dbg.impl.vtable.fileLock(dbg.impl.userdata, file, lock); |
| 492 | } |
| 493 | fn fileTryLock(userdata: ?*anyopaque, file: Io.File, lock: Io.File.Lock) Io.File.LockError!bool { |
| 494 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 495 | return dbg.impl.vtable.fileTryLock(dbg.impl.userdata, file, lock); |
| 496 | } |
| 497 | fn fileUnlock(userdata: ?*anyopaque, file: Io.File) void { |
| 498 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 499 | return dbg.impl.vtable.fileUnlock(dbg.impl.userdata, file); |
| 500 | } |
| 501 | fn fileDowngradeLock(userdata: ?*anyopaque, file: Io.File) Io.File.DowngradeLockError!void { |
| 502 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 503 | return dbg.impl.vtable.fileDowngradeLock(dbg.impl.userdata, file); |
| 504 | } |
| 505 | fn fileRealPath(userdata: ?*anyopaque, file: Io.File, out_buffer: []u8) Io.File.RealPathError!usize { |
| 506 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 507 | return dbg.impl.vtable.fileRealPath(dbg.impl.userdata, file, out_buffer); |
| 508 | } |
| 509 | fn fileHardLink(userdata: ?*anyopaque, file: Io.File, dir: Io.Dir, sub_path: []const u8, options: Io.File.HardLinkOptions) Io.File.HardLinkError!void { |
| 510 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 511 | return dbg.impl.vtable.fileHardLink(dbg.impl.userdata, file, dir, sub_path, options); |
| 512 | } |
| 513 | |
| 514 | fn processExecutableOpen(userdata: ?*anyopaque, flags: Io.File.OpenFlags) std.process.OpenExecutableError!Io.File { |
| 515 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 516 | const file = try dbg.impl.vtable.processExecutableOpen(dbg.impl.userdata, flags); |
| 517 | dbg.trackOpenFile(file, @returnAddress()); |
| 518 | return file; |
| 519 | } |
| 520 | fn processExecutablePath(userdata: ?*anyopaque, buffer: []u8) std.process.ExecutablePathError!usize { |
| 521 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 522 | return dbg.impl.vtable.processExecutablePath(dbg.impl.userdata, buffer); |
| 523 | } |
| 524 | fn lockStderr(userdata: ?*anyopaque, mode: ?Io.Terminal.Mode) Cancelable!Io.LockedStderr { |
| 525 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 526 | return dbg.impl.vtable.lockStderr(dbg.impl.userdata, mode); |
| 527 | } |
| 528 | fn tryLockStderr(userdata: ?*anyopaque, mode: ?Io.Terminal.Mode) Cancelable!?Io.LockedStderr { |
| 529 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 530 | return dbg.impl.vtable.tryLockStderr(dbg.impl.userdata, mode); |
| 531 | } |
| 532 | fn unlockStderr(userdata: ?*anyopaque) void { |
| 533 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 534 | return dbg.impl.vtable.unlockStderr(dbg.impl.userdata); |
| 535 | } |
| 536 | fn processSetCurrentDir(userdata: ?*anyopaque, dir: Io.Dir) std.process.SetCurrentDirError!void { |
| 537 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 538 | return dbg.impl.vtable.processSetCurrentDir(dbg.impl.userdata, dir); |
| 539 | } |
| 540 | fn processReplace(userdata: ?*anyopaque, options: std.process.ReplaceOptions) std.process.ReplaceError { |
| 541 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 542 | return dbg.impl.vtable.processReplace(dbg.impl.userdata, options); |
| 543 | } |
| 544 | fn processReplacePath(userdata: ?*anyopaque, dir: Io.Dir, options: std.process.ReplaceOptions) std.process.ReplaceError { |
| 545 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 546 | return dbg.impl.vtable.processReplacePath(dbg.impl.userdata, dir, options); |
| 547 | } |
| 548 | fn processSpawn(userdata: ?*anyopaque, options: std.process.SpawnOptions) std.process.SpawnError!std.process.Child { |
| 549 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 550 | return dbg.impl.vtable.processSpawn(dbg.impl.userdata, options); |
| 551 | } |
| 552 | fn processSpawnPath(userdata: ?*anyopaque, dir: Io.Dir, options: std.process.SpawnOptions) std.process.SpawnError!std.process.Child { |
| 553 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 554 | return dbg.impl.vtable.processSpawnPath(dbg.impl.userdata, dir, options); |
| 555 | } |
| 556 | fn childWait(userdata: ?*anyopaque, child: *std.process.Child) std.process.Child.WaitError!std.process.Child.Term { |
| 557 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 558 | return dbg.impl.vtable.childWait(dbg.impl.userdata, child); |
| 559 | } |
| 560 | fn childKill(userdata: ?*anyopaque, child: *std.process.Child) void { |
| 561 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 562 | return dbg.impl.vtable.childKill(dbg.impl.userdata, child); |
| 563 | } |
| 564 | |
| 565 | fn progressParentFile(userdata: ?*anyopaque) std.Progress.ParentFileError!Io.File { |
| 566 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 567 | return dbg.impl.vtable.progressParentFile(dbg.impl.userdata); |
| 568 | } |
| 569 | |
| 570 | fn now(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp { |
| 571 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 572 | return dbg.impl.vtable.now(dbg.impl.userdata, clock); |
| 573 | } |
| 574 | fn sleep(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { |
| 575 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 576 | return dbg.impl.vtable.sleep(dbg.impl.userdata, timeout); |
| 577 | } |
| 578 | |
| 579 | fn random(userdata: ?*anyopaque, buffer: []u8) void { |
| 580 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 581 | return dbg.impl.vtable.random(dbg.impl.userdata, buffer); |
| 582 | } |
| 583 | fn randomSecure(userdata: ?*anyopaque, buffer: []u8) Io.RandomSecureError!void { |
| 584 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 585 | return dbg.impl.vtable.randomSecure(dbg.impl.userdata, buffer); |
| 586 | } |
| 587 | |
| 588 | fn netListenIp(userdata: ?*anyopaque, address: net.IpAddress, options: net.IpAddress.ListenOptions) net.IpAddress.ListenError!net.Server { |
| 589 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 590 | return dbg.impl.vtable.netListenIp(dbg.impl.userdata, address, options); |
| 591 | } |
| 592 | fn netAccept(userdata: ?*anyopaque, server: net.Socket.Handle) net.Server.AcceptError!net.Stream { |
| 593 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 594 | return dbg.impl.vtable.netAccept(dbg.impl.userdata, server); |
| 595 | } |
| 596 | fn netBindIp(userdata: ?*anyopaque, address: *const net.IpAddress, options: net.IpAddress.BindOptions) net.IpAddress.BindError!net.Socket { |
| 597 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 598 | return dbg.impl.vtable.netBindIp(dbg.impl.userdata, address, options); |
| 599 | } |
| 600 | fn netConnectIp(userdata: ?*anyopaque, address: *const net.IpAddress, options: net.IpAddress.ConnectOptions) net.IpAddress.ConnectError!net.Stream { |
| 601 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 602 | return dbg.impl.vtable.netConnectIp(dbg.impl.userdata, address, options); |
| 603 | } |
| 604 | fn netListenUnix(userdata: ?*anyopaque, address: *const net.UnixAddress, options: net.UnixAddress.ListenOptions) net.UnixAddress.ListenError!net.Socket.Handle { |
| 605 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 606 | return dbg.impl.vtable.netListenUnix(dbg.impl.userdata, address, options); |
| 607 | } |
| 608 | fn netConnectUnix(userdata: ?*anyopaque, address: *const net.UnixAddress) net.UnixAddress.ConnectError!net.Socket.Handle { |
| 609 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 610 | return dbg.impl.vtable.netConnectUnix(dbg.impl.userdata, address); |
| 611 | } |
| 612 | fn netSend(userdata: ?*anyopaque, handle: net.Socket.Handle, messages: []net.OutgoingMessage, flags: net.SendFlags) struct { ?net.Socket.SendError, usize } { |
| 613 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 614 | return dbg.impl.vtable.netSend(dbg.impl.userdata, handle, messages, flags); |
| 615 | } |
| 616 | fn netReceive(userdata: ?*anyopaque, handle: net.Socket.Handle, message_buffer: []net.IncomingMessage, data_buffer: []u8, flags: net.ReceiveFlags, timeout: Io.Timeout) struct { ?net.Socket.ReceiveTimeoutError, usize } { |
| 617 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 618 | return dbg.impl.vtable.netReceive(dbg.impl.userdata, handle, message_buffer, data_buffer, flags, timeout); |
| 619 | } |
| 620 | |
| 621 | fn netRead(userdata: ?*anyopaque, src: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize { |
| 622 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 623 | return dbg.impl.vtable.netRead(dbg.impl.userdata, src, data); |
| 624 | } |
| 625 | fn netWrite(userdata: ?*anyopaque, dest: net.Socket.Handle, header: []const u8, data: []const []const u8, splat: usize) net.Stream.Writer.Error!usize { |
| 626 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 627 | return dbg.impl.vtable.netWrite(dbg.impl.userdata, dest, header, data, splat); |
| 628 | } |
| 629 | fn netWriteFile(userdata: ?*anyopaque, dest: net.Socket.Handle, header: []const u8, fr: *Io.File.Reader, limit: Io.Limit) net.Stream.Writer.WriteFileError!usize { |
| 630 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 631 | return dbg.impl.vtable.netWriteFile(dbg.impl.userdata, dest, header, fr, limit); |
| 632 | } |
| 633 | fn netClose(userdata: ?*anyopaque, handle: []const net.Socket.Handle) void { |
| 634 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 635 | return dbg.impl.vtable.netClose(dbg.impl.userdata, handle); |
| 636 | } |
| 637 | fn netShutdown(userdata: ?*anyopaque, handle: net.Socket.Handle, how: net.ShutdownHow) net.ShutdownError!void { |
| 638 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 639 | return dbg.impl.vtable.netShutdown(dbg.impl.userdata, handle, how); |
| 640 | } |
| 641 | fn netInterfaceNameResolve(userdata: ?*anyopaque, name: *const net.Interface.Name) net.Interface.Name.ResolveError!net.Interface { |
| 642 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 643 | return dbg.impl.vtable.netInterfaceNameResolve(dbg.impl.userdata, name); |
| 644 | } |
| 645 | fn netInterfaceName(userdata: ?*anyopaque, interface: net.Interface) net.Interface.NameError!net.Interface.Name { |
| 646 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 647 | return dbg.impl.vtable.netInterfaceName(dbg.impl.userdata, interface); |
| 648 | } |
| 649 | fn netLookup(userdata: ?*anyopaque, host_name: net.HostName, resolved: *Io.Queue(net.HostName.LookupResult), options: net.HostName.LookupOptions) net.HostName.LookupError!void { |
| 650 | const dbg: *Debug = @ptrCast(@alignCast(userdata)); |
| 651 | return dbg.impl.vtable.netLookup(dbg.impl.userdata, host_name, resolved, options); |
| 652 | } |
| 653 | |
| 654 | const std = @import("../std.zig"); |
| 655 | const Allocator = std.mem.Allocator; |
| 656 | const Cancelable = Io.Cancelable; |
| 657 | const Io = std.Io; |
| 658 | const assert = std.debug.assert; |
| 659 | const net = Io.net; |