Commit 00f26cb0a4

Andrew Kelley <andrew@ziglang.org>
2025-10-03 06:39:32
WIP land the std.Io interface
fix std lib compilation errors caused by introducing std.Io
1 parent 85a6fea
lib/std/Build/WebServer.zig
@@ -2,12 +2,12 @@ gpa: Allocator,
 thread_pool: *std.Thread.Pool,
 graph: *const Build.Graph,
 all_steps: []const *Build.Step,
-listen_address: std.net.Address,
+listen_address: net.IpAddress,
 ttyconf: std.Io.tty.Config,
 root_prog_node: std.Progress.Node,
 watch: bool,
 
-tcp_server: ?std.net.Server,
+tcp_server: ?net.Server,
 serve_thread: ?std.Thread,
 
 base_timestamp: i128,
@@ -56,7 +56,7 @@ pub const Options = struct {
     ttyconf: std.Io.tty.Config,
     root_prog_node: std.Progress.Node,
     watch: bool,
-    listen_address: std.net.Address,
+    listen_address: net.IpAddress,
 };
 pub fn init(opts: Options) WebServer {
     // The upcoming `std.Io` interface should allow us to use `Io.async` and `Io.concurrent`
@@ -244,7 +244,7 @@ pub fn now(s: *const WebServer) i64 {
     return @intCast(std.time.nanoTimestamp() - s.base_timestamp);
 }
 
-fn accept(ws: *WebServer, connection: std.net.Server.Connection) void {
+fn accept(ws: *WebServer, connection: net.Server.Connection) void {
     defer connection.stream.close();
 
     var send_buffer: [4096]u8 = undefined;
@@ -851,5 +851,6 @@ const Cache = Build.Cache;
 const Fuzz = Build.Fuzz;
 const abi = Build.abi;
 const http = std.http;
+const net = std.Io.net;
 
 const WebServer = @This();
lib/std/fs/File.zig
@@ -698,17 +698,6 @@ pub fn read(self: File, buffer: []u8) ReadError!usize {
     return posix.read(self.handle, buffer);
 }
 
-/// Deprecated in favor of `Reader`.
-pub fn readAll(self: File, buffer: []u8) ReadError!usize {
-    var index: usize = 0;
-    while (index != buffer.len) {
-        const amt = try self.read(buffer[index..]);
-        if (amt == 0) break;
-        index += amt;
-    }
-    return index;
-}
-
 /// On Windows, this function currently does alter the file pointer.
 /// https://github.com/ziglang/zig/issues/12783
 pub fn pread(self: File, buffer: []u8, offset: u64) PReadError!usize {
@@ -719,17 +708,6 @@ pub fn pread(self: File, buffer: []u8, offset: u64) PReadError!usize {
     return posix.pread(self.handle, buffer, offset);
 }
 
-/// Deprecated in favor of `Reader`.
-pub fn preadAll(self: File, buffer: []u8, offset: u64) PReadError!usize {
-    var index: usize = 0;
-    while (index != buffer.len) {
-        const amt = try self.pread(buffer[index..], offset + index);
-        if (amt == 0) break;
-        index += amt;
-    }
-    return index;
-}
-
 /// See https://github.com/ziglang/zig/issues/7699
 pub fn readv(self: File, iovecs: []const posix.iovec) ReadError!usize {
     if (is_windows) {
@@ -741,36 +719,6 @@ pub fn readv(self: File, iovecs: []const posix.iovec) ReadError!usize {
     return posix.readv(self.handle, iovecs);
 }
 
-/// Deprecated in favor of `Reader`.
-pub fn readvAll(self: File, iovecs: []posix.iovec) ReadError!usize {
-    if (iovecs.len == 0) return 0;
-
-    // We use the address of this local variable for all zero-length
-    // vectors so that the OS does not complain that we are giving it
-    // addresses outside the application's address space.
-    var garbage: [1]u8 = undefined;
-    for (iovecs) |*v| {
-        if (v.len == 0) v.base = &garbage;
-    }
-
-    var i: usize = 0;
-    var off: usize = 0;
-    while (true) {
-        var amt = try self.readv(iovecs[i..]);
-        var eof = amt == 0;
-        off += amt;
-        while (amt >= iovecs[i].len) {
-            amt -= iovecs[i].len;
-            i += 1;
-            if (i >= iovecs.len) return off;
-            eof = false;
-        }
-        if (eof) return off;
-        iovecs[i].base += amt;
-        iovecs[i].len -= amt;
-    }
-}
-
 /// See https://github.com/ziglang/zig/issues/7699
 /// On Windows, this function currently does alter the file pointer.
 /// https://github.com/ziglang/zig/issues/12783
@@ -784,28 +732,6 @@ pub fn preadv(self: File, iovecs: []const posix.iovec, offset: u64) PReadError!u
     return posix.preadv(self.handle, iovecs, offset);
 }
 
-/// Deprecated in favor of `Reader`.
-pub fn preadvAll(self: File, iovecs: []posix.iovec, offset: u64) PReadError!usize {
-    if (iovecs.len == 0) return 0;
-
-    var i: usize = 0;
-    var off: usize = 0;
-    while (true) {
-        var amt = try self.preadv(iovecs[i..], offset + off);
-        var eof = amt == 0;
-        off += amt;
-        while (amt >= iovecs[i].len) {
-            amt -= iovecs[i].len;
-            i += 1;
-            if (i >= iovecs.len) return off;
-            eof = false;
-        }
-        if (eof) return off;
-        iovecs[i].base += amt;
-        iovecs[i].len -= amt;
-    }
-}
-
 pub const WriteError = posix.WriteError;
 pub const PWriteError = posix.PWriteError;
 
@@ -817,7 +743,6 @@ pub fn write(self: File, bytes: []const u8) WriteError!usize {
     return posix.write(self.handle, bytes);
 }
 
-/// Deprecated in favor of `Writer`.
 pub fn writeAll(self: File, bytes: []const u8) WriteError!void {
     var index: usize = 0;
     while (index < bytes.len) {
@@ -835,14 +760,6 @@ pub fn pwrite(self: File, bytes: []const u8, offset: u64) PWriteError!usize {
     return posix.pwrite(self.handle, bytes, offset);
 }
 
-/// Deprecated in favor of `Writer`.
-pub fn pwriteAll(self: File, bytes: []const u8, offset: u64) PWriteError!void {
-    var index: usize = 0;
-    while (index < bytes.len) {
-        index += try self.pwrite(bytes[index..], offset + index);
-    }
-}
-
 /// See https://github.com/ziglang/zig/issues/7699
 pub fn writev(self: File, iovecs: []const posix.iovec_const) WriteError!usize {
     if (is_windows) {
@@ -855,31 +772,6 @@ pub fn writev(self: File, iovecs: []const posix.iovec_const) WriteError!usize {
     return posix.writev(self.handle, iovecs);
 }
 
-/// Deprecated in favor of `Writer`.
-pub fn writevAll(self: File, iovecs: []posix.iovec_const) WriteError!void {
-    if (iovecs.len == 0) return;
-
-    // We use the address of this local variable for all zero-length
-    // vectors so that the OS does not complain that we are giving it
-    // addresses outside the application's address space.
-    var garbage: [1]u8 = undefined;
-    for (iovecs) |*v| {
-        if (v.len == 0) v.base = &garbage;
-    }
-
-    var i: usize = 0;
-    while (true) {
-        var amt = try self.writev(iovecs[i..]);
-        while (amt >= iovecs[i].len) {
-            amt -= iovecs[i].len;
-            i += 1;
-            if (i >= iovecs.len) return;
-        }
-        iovecs[i].base += amt;
-        iovecs[i].len -= amt;
-    }
-}
-
 /// See https://github.com/ziglang/zig/issues/7699
 /// On Windows, this function currently does alter the file pointer.
 /// https://github.com/ziglang/zig/issues/12783
@@ -893,485 +785,8 @@ pub fn pwritev(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteError
     return posix.pwritev(self.handle, iovecs, offset);
 }
 
-/// Deprecated in favor of `Writer`.
-pub fn pwritevAll(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteError!void {
-    if (iovecs.len == 0) return;
-    var i: usize = 0;
-    var off: u64 = 0;
-    while (true) {
-        var amt = try self.pwritev(iovecs[i..], offset + off);
-        off += amt;
-        while (amt >= iovecs[i].len) {
-            amt -= iovecs[i].len;
-            i += 1;
-            if (i >= iovecs.len) return;
-        }
-        iovecs[i].base += amt;
-        iovecs[i].len -= amt;
-    }
-}
-
-pub const CopyRangeError = posix.CopyFileRangeError;
-
-/// Deprecated in favor of `Writer`.
-pub fn copyRange(in: File, in_offset: u64, out: File, out_offset: u64, len: u64) CopyRangeError!u64 {
-    const adjusted_len = math.cast(usize, len) orelse maxInt(usize);
-    const result = try posix.copy_file_range(in.handle, in_offset, out.handle, out_offset, adjusted_len, 0);
-    return result;
-}
-
-/// Deprecated in favor of `Writer`.
-pub fn copyRangeAll(in: File, in_offset: u64, out: File, out_offset: u64, len: u64) CopyRangeError!u64 {
-    var total_bytes_copied: u64 = 0;
-    var in_off = in_offset;
-    var out_off = out_offset;
-    while (total_bytes_copied < len) {
-        const amt_copied = try copyRange(in, in_off, out, out_off, len - total_bytes_copied);
-        if (amt_copied == 0) return total_bytes_copied;
-        total_bytes_copied += amt_copied;
-        in_off += amt_copied;
-        out_off += amt_copied;
-    }
-    return total_bytes_copied;
-}
-
-/// Memoizes key information about a file handle such as:
-/// * The size from calling stat, or the error that occurred therein.
-/// * The current seek position.
-/// * The error that occurred when trying to seek.
-/// * Whether reading should be done positionally or streaming.
-/// * Whether reading should be done via fd-to-fd syscalls (e.g. `sendfile`)
-///   versus plain variants (e.g. `read`).
-///
-/// Fulfills the `std.Io.Reader` interface.
-pub const Reader = struct {
-    file: File,
-    err: ?ReadError = null,
-    mode: Reader.Mode = .positional,
-    /// Tracks the true seek position in the file. To obtain the logical
-    /// position, use `logicalPos`.
-    pos: u64 = 0,
-    size: ?u64 = null,
-    size_err: ?SizeError = null,
-    seek_err: ?Reader.SeekError = null,
-    interface: std.Io.Reader,
-
-    pub const SizeError = std.os.windows.GetFileSizeError || StatError || error{
-        /// Occurs if, for example, the file handle is a network socket and therefore does not have a size.
-        Streaming,
-    };
-
-    pub const SeekError = File.SeekError || error{
-        /// Seeking fell back to reading, and reached the end before the requested seek position.
-        /// `pos` remains at the end of the file.
-        EndOfStream,
-        /// Seeking fell back to reading, which failed.
-        ReadFailed,
-    };
-
-    pub const Mode = enum {
-        streaming,
-        positional,
-        /// Avoid syscalls other than `read` and `readv`.
-        streaming_reading,
-        /// Avoid syscalls other than `pread` and `preadv`.
-        positional_reading,
-        /// Indicates reading cannot continue because of a seek failure.
-        failure,
-
-        pub fn toStreaming(m: @This()) @This() {
-            return switch (m) {
-                .positional, .streaming => .streaming,
-                .positional_reading, .streaming_reading => .streaming_reading,
-                .failure => .failure,
-            };
-        }
-
-        pub fn toReading(m: @This()) @This() {
-            return switch (m) {
-                .positional, .positional_reading => .positional_reading,
-                .streaming, .streaming_reading => .streaming_reading,
-                .failure => .failure,
-            };
-        }
-    };
-
-    pub fn initInterface(buffer: []u8) std.Io.Reader {
-        return .{
-            .vtable = &.{
-                .stream = Reader.stream,
-                .discard = Reader.discard,
-                .readVec = Reader.readVec,
-            },
-            .buffer = buffer,
-            .seek = 0,
-            .end = 0,
-        };
-    }
-
-    pub fn init(file: File, buffer: []u8) Reader {
-        return .{
-            .file = file,
-            .interface = initInterface(buffer),
-        };
-    }
-
-    pub fn initSize(file: File, buffer: []u8, size: ?u64) Reader {
-        return .{
-            .file = file,
-            .interface = initInterface(buffer),
-            .size = size,
-        };
-    }
-
-    /// Positional is more threadsafe, since the global seek position is not
-    /// affected, but when such syscalls are not available, preemptively
-    /// initializing in streaming mode skips a failed syscall.
-    pub fn initStreaming(file: File, buffer: []u8) Reader {
-        return .{
-            .file = file,
-            .interface = Reader.initInterface(buffer),
-            .mode = .streaming,
-            .seek_err = error.Unseekable,
-            .size_err = error.Streaming,
-        };
-    }
-
-    pub fn getSize(r: *Reader) SizeError!u64 {
-        return r.size orelse {
-            if (r.size_err) |err| return err;
-            if (is_windows) {
-                if (windows.GetFileSizeEx(r.file.handle)) |size| {
-                    r.size = size;
-                    return size;
-                } else |err| {
-                    r.size_err = err;
-                    return err;
-                }
-            }
-            if (posix.Stat == void) {
-                r.size_err = error.Streaming;
-                return error.Streaming;
-            }
-            if (stat(r.file)) |st| {
-                if (st.kind == .file) {
-                    r.size = st.size;
-                    return st.size;
-                } else {
-                    r.mode = r.mode.toStreaming();
-                    r.size_err = error.Streaming;
-                    return error.Streaming;
-                }
-            } else |err| {
-                r.size_err = err;
-                return err;
-            }
-        };
-    }
-
-    pub fn seekBy(r: *Reader, offset: i64) Reader.SeekError!void {
-        switch (r.mode) {
-            .positional, .positional_reading => {
-                setLogicalPos(r, @intCast(@as(i64, @intCast(logicalPos(r))) + offset));
-            },
-            .streaming, .streaming_reading => {
-                if (posix.SEEK == void) {
-                    r.seek_err = error.Unseekable;
-                    return error.Unseekable;
-                }
-                const seek_err = r.seek_err orelse e: {
-                    if (posix.lseek_CUR(r.file.handle, offset)) |_| {
-                        setLogicalPos(r, @intCast(@as(i64, @intCast(logicalPos(r))) + offset));
-                        return;
-                    } else |err| {
-                        r.seek_err = err;
-                        break :e err;
-                    }
-                };
-                var remaining = std.math.cast(u64, offset) orelse return seek_err;
-                while (remaining > 0) {
-                    remaining -= discard(&r.interface, .limited64(remaining)) catch |err| {
-                        r.seek_err = err;
-                        return err;
-                    };
-                }
-                r.interface.seek = 0;
-                r.interface.end = 0;
-            },
-            .failure => return r.seek_err.?,
-        }
-    }
-
-    pub fn seekTo(r: *Reader, offset: u64) Reader.SeekError!void {
-        switch (r.mode) {
-            .positional, .positional_reading => {
-                setLogicalPos(r, offset);
-            },
-            .streaming, .streaming_reading => {
-                const logical_pos = logicalPos(r);
-                if (offset >= logical_pos) return Reader.seekBy(r, @intCast(offset - logical_pos));
-                if (r.seek_err) |err| return err;
-                posix.lseek_SET(r.file.handle, offset) catch |err| {
-                    r.seek_err = err;
-                    return err;
-                };
-                setLogicalPos(r, offset);
-            },
-            .failure => return r.seek_err.?,
-        }
-    }
-
-    pub fn logicalPos(r: *const Reader) u64 {
-        return r.pos - r.interface.bufferedLen();
-    }
-
-    fn setLogicalPos(r: *Reader, offset: u64) void {
-        const logical_pos = logicalPos(r);
-        if (offset < logical_pos or offset >= r.pos) {
-            r.interface.seek = 0;
-            r.interface.end = 0;
-            r.pos = offset;
-        } else {
-            const logical_delta: usize = @intCast(offset - logical_pos);
-            r.interface.seek += logical_delta;
-        }
-    }
-
-    /// Number of slices to store on the stack, when trying to send as many byte
-    /// vectors through the underlying read calls as possible.
-    const max_buffers_len = 16;
-
-    fn stream(io_reader: *std.Io.Reader, w: *std.Io.Writer, limit: std.Io.Limit) std.Io.Reader.StreamError!usize {
-        const r: *Reader = @alignCast(@fieldParentPtr("interface", io_reader));
-        switch (r.mode) {
-            .positional, .streaming => @panic("TODO"),
-            .positional_reading => {
-                const dest = limit.slice(try w.writableSliceGreedy(1));
-                var data: [1][]u8 = .{dest};
-                const n = try readVecPositional(r, &data);
-                w.advance(n);
-                return n;
-            },
-            .streaming_reading => {
-                const dest = limit.slice(try w.writableSliceGreedy(1));
-                var data: [1][]u8 = .{dest};
-                const n = try readVecStreaming(r, &data);
-                w.advance(n);
-                return n;
-            },
-            .failure => return error.ReadFailed,
-        }
-    }
-
-    fn readVec(io_reader: *std.Io.Reader, data: [][]u8) std.Io.Reader.Error!usize {
-        const r: *Reader = @alignCast(@fieldParentPtr("interface", io_reader));
-        switch (r.mode) {
-            .positional, .positional_reading => return readVecPositional(r, data),
-            .streaming, .streaming_reading => return readVecStreaming(r, data),
-            .failure => return error.ReadFailed,
-        }
-    }
-
-    fn readVecPositional(r: *Reader, data: [][]u8) std.Io.Reader.Error!usize {
-        const io_reader = &r.interface;
-        if (is_windows) {
-            // Unfortunately, `ReadFileScatter` cannot be used since it
-            // requires page alignment.
-            if (io_reader.seek == io_reader.end) {
-                io_reader.seek = 0;
-                io_reader.end = 0;
-            }
-            const first = data[0];
-            if (first.len >= io_reader.buffer.len - io_reader.end) {
-                return readPositional(r, first);
-            } else {
-                io_reader.end += try readPositional(r, io_reader.buffer[io_reader.end..]);
-                return 0;
-            }
-        }
-        var iovecs_buffer: [max_buffers_len]posix.iovec = undefined;
-        const dest_n, const data_size = try io_reader.writableVectorPosix(&iovecs_buffer, data);
-        const dest = iovecs_buffer[0..dest_n];
-        assert(dest[0].len > 0);
-        const n = posix.preadv(r.file.handle, dest, r.pos) catch |err| switch (err) {
-            error.Unseekable => {
-                r.mode = r.mode.toStreaming();
-                const pos = r.pos;
-                if (pos != 0) {
-                    r.pos = 0;
-                    r.seekBy(@intCast(pos)) catch {
-                        r.mode = .failure;
-                        return error.ReadFailed;
-                    };
-                }
-                return 0;
-            },
-            else => |e| {
-                r.err = e;
-                return error.ReadFailed;
-            },
-        };
-        if (n == 0) {
-            r.size = r.pos;
-            return error.EndOfStream;
-        }
-        r.pos += n;
-        if (n > data_size) {
-            io_reader.end += n - data_size;
-            return data_size;
-        }
-        return n;
-    }
-
-    fn readVecStreaming(r: *Reader, data: [][]u8) std.Io.Reader.Error!usize {
-        const io_reader = &r.interface;
-        if (is_windows) {
-            // Unfortunately, `ReadFileScatter` cannot be used since it
-            // requires page alignment.
-            if (io_reader.seek == io_reader.end) {
-                io_reader.seek = 0;
-                io_reader.end = 0;
-            }
-            const first = data[0];
-            if (first.len >= io_reader.buffer.len - io_reader.end) {
-                return readStreaming(r, first);
-            } else {
-                io_reader.end += try readStreaming(r, io_reader.buffer[io_reader.end..]);
-                return 0;
-            }
-        }
-        var iovecs_buffer: [max_buffers_len]posix.iovec = undefined;
-        const dest_n, const data_size = try io_reader.writableVectorPosix(&iovecs_buffer, data);
-        const dest = iovecs_buffer[0..dest_n];
-        assert(dest[0].len > 0);
-        const n = posix.readv(r.file.handle, dest) catch |err| {
-            r.err = err;
-            return error.ReadFailed;
-        };
-        if (n == 0) {
-            r.size = r.pos;
-            return error.EndOfStream;
-        }
-        r.pos += n;
-        if (n > data_size) {
-            io_reader.end += n - data_size;
-            return data_size;
-        }
-        return n;
-    }
-
-    fn discard(io_reader: *std.Io.Reader, limit: std.Io.Limit) std.Io.Reader.Error!usize {
-        const r: *Reader = @alignCast(@fieldParentPtr("interface", io_reader));
-        const file = r.file;
-        const pos = r.pos;
-        switch (r.mode) {
-            .positional, .positional_reading => {
-                const size = r.getSize() catch {
-                    r.mode = r.mode.toStreaming();
-                    return 0;
-                };
-                const delta = @min(@intFromEnum(limit), size - pos);
-                r.pos = pos + delta;
-                return delta;
-            },
-            .streaming, .streaming_reading => {
-                // Unfortunately we can't seek forward without knowing the
-                // size because the seek syscalls provided to us will not
-                // return the true end position if a seek would exceed the
-                // end.
-                fallback: {
-                    if (r.size_err == null and r.seek_err == null) break :fallback;
-                    var trash_buffer: [128]u8 = undefined;
-                    if (is_windows) {
-                        const n = windows.ReadFile(file.handle, limit.slice(&trash_buffer), null) catch |err| {
-                            r.err = err;
-                            return error.ReadFailed;
-                        };
-                        if (n == 0) {
-                            r.size = pos;
-                            return error.EndOfStream;
-                        }
-                        r.pos = pos + n;
-                        return n;
-                    }
-                    var iovecs: [max_buffers_len]std.posix.iovec = undefined;
-                    var iovecs_i: usize = 0;
-                    var remaining = @intFromEnum(limit);
-                    while (remaining > 0 and iovecs_i < iovecs.len) {
-                        iovecs[iovecs_i] = .{ .base = &trash_buffer, .len = @min(trash_buffer.len, remaining) };
-                        remaining -= iovecs[iovecs_i].len;
-                        iovecs_i += 1;
-                    }
-                    const n = posix.readv(file.handle, iovecs[0..iovecs_i]) catch |err| {
-                        r.err = err;
-                        return error.ReadFailed;
-                    };
-                    if (n == 0) {
-                        r.size = pos;
-                        return error.EndOfStream;
-                    }
-                    r.pos = pos + n;
-                    return n;
-                }
-                const size = r.getSize() catch return 0;
-                const n = @min(size - pos, maxInt(i64), @intFromEnum(limit));
-                file.seekBy(n) catch |err| {
-                    r.seek_err = err;
-                    return 0;
-                };
-                r.pos = pos + n;
-                return n;
-            },
-            .failure => return error.ReadFailed,
-        }
-    }
-
-    fn readPositional(r: *Reader, dest: []u8) std.Io.Reader.Error!usize {
-        const n = r.file.pread(dest, r.pos) catch |err| switch (err) {
-            error.Unseekable => {
-                r.mode = r.mode.toStreaming();
-                const pos = r.pos;
-                if (pos != 0) {
-                    r.pos = 0;
-                    r.seekBy(@intCast(pos)) catch {
-                        r.mode = .failure;
-                        return error.ReadFailed;
-                    };
-                }
-                return 0;
-            },
-            else => |e| {
-                r.err = e;
-                return error.ReadFailed;
-            },
-        };
-        if (n == 0) {
-            r.size = r.pos;
-            return error.EndOfStream;
-        }
-        r.pos += n;
-        return n;
-    }
-
-    fn readStreaming(r: *Reader, dest: []u8) std.Io.Reader.Error!usize {
-        const n = r.file.read(dest) catch |err| {
-            r.err = err;
-            return error.ReadFailed;
-        };
-        if (n == 0) {
-            r.size = r.pos;
-            return error.EndOfStream;
-        }
-        r.pos += n;
-        return n;
-    }
-
-    pub fn atEnd(r: *Reader) bool {
-        // Even if stat fails, size is set when end is encountered.
-        const size = r.size orelse return false;
-        return size - r.pos == 0;
-    }
-};
+/// Deprecated in favor of `std.Io.File.Reader`.
+pub const Reader = std.Io.File.Reader;
 
 pub const Writer = struct {
     file: File,
lib/std/net/test.zig โ†’ lib/std/Io/net/test.zig
@@ -1,38 +1,38 @@
 const std = @import("std");
 const builtin = @import("builtin");
-const net = std.net;
+const net = std.Io.net;
 const mem = std.mem;
 const testing = std.testing;
 
 test "parse and render IP addresses at comptime" {
     comptime {
-        const ipv6addr = net.Address.parseIp("::1", 0) catch unreachable;
+        const ipv6addr = net.IpAddress.parseIp("::1", 0) catch unreachable;
         try std.testing.expectFmt("[::1]:0", "{f}", .{ipv6addr});
 
-        const ipv4addr = net.Address.parseIp("127.0.0.1", 0) catch unreachable;
+        const ipv4addr = net.IpAddress.parseIp("127.0.0.1", 0) catch unreachable;
         try std.testing.expectFmt("127.0.0.1:0", "{f}", .{ipv4addr});
 
-        try testing.expectError(error.InvalidIpAddressFormat, net.Address.parseIp("::123.123.123.123", 0));
-        try testing.expectError(error.InvalidIpAddressFormat, net.Address.parseIp("127.01.0.1", 0));
-        try testing.expectError(error.InvalidIpAddressFormat, net.Address.resolveIp("::123.123.123.123", 0));
-        try testing.expectError(error.InvalidIpAddressFormat, net.Address.resolveIp("127.01.0.1", 0));
+        try testing.expectError(error.InvalidIpAddressFormat, net.IpAddress.parseIp("::123.123.123.123", 0));
+        try testing.expectError(error.InvalidIpAddressFormat, net.IpAddress.parseIp("127.01.0.1", 0));
+        try testing.expectError(error.InvalidIpAddressFormat, net.IpAddress.resolveIp("::123.123.123.123", 0));
+        try testing.expectError(error.InvalidIpAddressFormat, net.IpAddress.resolveIp("127.01.0.1", 0));
     }
 }
 
 test "format IPv6 address with no zero runs" {
-    const addr = try std.net.Address.parseIp6("2001:db8:1:2:3:4:5:6", 0);
+    const addr = try std.net.IpAddress.parseIp6("2001:db8:1:2:3:4:5:6", 0);
     try std.testing.expectFmt("[2001:db8:1:2:3:4:5:6]:0", "{f}", .{addr});
 }
 
 test "parse IPv6 addresses and check compressed form" {
     try std.testing.expectFmt("[2001:db8::1:0:0:2]:0", "{f}", .{
-        try std.net.Address.parseIp6("2001:0db8:0000:0000:0001:0000:0000:0002", 0),
+        try std.net.IpAddress.parseIp6("2001:0db8:0000:0000:0001:0000:0000:0002", 0),
     });
     try std.testing.expectFmt("[2001:db8::1:2]:0", "{f}", .{
-        try std.net.Address.parseIp6("2001:0db8:0000:0000:0000:0000:0001:0002", 0),
+        try std.net.IpAddress.parseIp6("2001:0db8:0000:0000:0000:0000:0001:0002", 0),
     });
     try std.testing.expectFmt("[2001:db8:1:0:1::2]:0", "{f}", .{
-        try std.net.Address.parseIp6("2001:0db8:0001:0000:0001:0000:0000:0002", 0),
+        try std.net.IpAddress.parseIp6("2001:0db8:0001:0000:0001:0000:0000:0002", 0),
     });
 }
 
@@ -44,7 +44,7 @@ test "parse IPv6 address, check raw bytes" {
         0x00, 0x00, 0x00, 0x02, // :0000:0002
     };
 
-    const addr = try std.net.Address.parseIp6("2001:db8:0000:0000:0001:0000:0000:0002", 0);
+    const addr = try std.net.IpAddress.parseIp6("2001:db8:0000:0000:0001:0000:0000:0002", 0);
 
     const actual_raw = addr.in6.sa.addr[0..];
     try std.testing.expectEqualSlices(u8, expected_raw[0..], actual_raw);
@@ -77,30 +77,30 @@ test "parse and render IPv6 addresses" {
         "::ffff:123.5.123.5",
     };
     for (ips, 0..) |ip, i| {
-        const addr = net.Address.parseIp6(ip, 0) catch unreachable;
+        const addr = net.IpAddress.parseIp6(ip, 0) catch unreachable;
         var newIp = std.fmt.bufPrint(buffer[0..], "{f}", .{addr}) catch unreachable;
         try std.testing.expect(std.mem.eql(u8, printed[i], newIp[1 .. newIp.len - 3]));
 
         if (builtin.os.tag == .linux) {
-            const addr_via_resolve = net.Address.resolveIp6(ip, 0) catch unreachable;
+            const addr_via_resolve = net.IpAddress.resolveIp6(ip, 0) catch unreachable;
             var newResolvedIp = std.fmt.bufPrint(buffer[0..], "{f}", .{addr_via_resolve}) catch unreachable;
             try std.testing.expect(std.mem.eql(u8, printed[i], newResolvedIp[1 .. newResolvedIp.len - 3]));
         }
     }
 
-    try testing.expectError(error.InvalidCharacter, net.Address.parseIp6(":::", 0));
-    try testing.expectError(error.Overflow, net.Address.parseIp6("FF001::FB", 0));
-    try testing.expectError(error.InvalidCharacter, net.Address.parseIp6("FF01::Fb:zig", 0));
-    try testing.expectError(error.InvalidEnd, net.Address.parseIp6("FF01:0:0:0:0:0:0:FB:", 0));
-    try testing.expectError(error.Incomplete, net.Address.parseIp6("FF01:", 0));
-    try testing.expectError(error.InvalidIpv4Mapping, net.Address.parseIp6("::123.123.123.123", 0));
-    try testing.expectError(error.Incomplete, net.Address.parseIp6("1", 0));
+    try testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp6(":::", 0));
+    try testing.expectError(error.Overflow, net.IpAddress.parseIp6("FF001::FB", 0));
+    try testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp6("FF01::Fb:zig", 0));
+    try testing.expectError(error.InvalidEnd, net.IpAddress.parseIp6("FF01:0:0:0:0:0:0:FB:", 0));
+    try testing.expectError(error.Incomplete, net.IpAddress.parseIp6("FF01:", 0));
+    try testing.expectError(error.InvalidIpv4Mapping, net.IpAddress.parseIp6("::123.123.123.123", 0));
+    try testing.expectError(error.Incomplete, net.IpAddress.parseIp6("1", 0));
     // TODO Make this test pass on other operating systems.
     if (builtin.os.tag == .linux or comptime builtin.os.tag.isDarwin() or builtin.os.tag == .windows) {
-        try testing.expectError(error.Incomplete, net.Address.resolveIp6("ff01::fb%", 0));
+        try testing.expectError(error.Incomplete, net.IpAddress.resolveIp6("ff01::fb%", 0));
         // Assumes IFNAMESIZE will always be a multiple of 2
-        try testing.expectError(error.Overflow, net.Address.resolveIp6("ff01::fb%wlp3" ++ "s0" ** @divExact(std.posix.IFNAMESIZE - 4, 2), 0));
-        try testing.expectError(error.Overflow, net.Address.resolveIp6("ff01::fb%12345678901234", 0));
+        try testing.expectError(error.Overflow, net.IpAddress.resolveIp6("ff01::fb%wlp3" ++ "s0" ** @divExact(std.posix.IFNAMESIZE - 4, 2), 0));
+        try testing.expectError(error.Overflow, net.IpAddress.resolveIp6("ff01::fb%12345678901234", 0));
     }
 }
 
@@ -111,7 +111,7 @@ test "invalid but parseable IPv6 scope ids" {
         return error.SkipZigTest;
     }
 
-    try testing.expectError(error.InterfaceNotFound, net.Address.resolveIp6("ff01::fb%123s45678901234", 0));
+    try testing.expectError(error.InterfaceNotFound, net.IpAddress.resolveIp6("ff01::fb%123s45678901234", 0));
 }
 
 test "parse and render IPv4 addresses" {
@@ -123,17 +123,17 @@ test "parse and render IPv4 addresses" {
         "123.255.0.91",
         "127.0.0.1",
     }) |ip| {
-        const addr = net.Address.parseIp4(ip, 0) catch unreachable;
+        const addr = net.IpAddress.parseIp4(ip, 0) catch unreachable;
         var newIp = std.fmt.bufPrint(buffer[0..], "{f}", .{addr}) catch unreachable;
         try std.testing.expect(std.mem.eql(u8, ip, newIp[0 .. newIp.len - 2]));
     }
 
-    try testing.expectError(error.Overflow, net.Address.parseIp4("256.0.0.1", 0));
-    try testing.expectError(error.InvalidCharacter, net.Address.parseIp4("x.0.0.1", 0));
-    try testing.expectError(error.InvalidEnd, net.Address.parseIp4("127.0.0.1.1", 0));
-    try testing.expectError(error.Incomplete, net.Address.parseIp4("127.0.0.", 0));
-    try testing.expectError(error.InvalidCharacter, net.Address.parseIp4("100..0.1", 0));
-    try testing.expectError(error.NonCanonical, net.Address.parseIp4("127.01.0.1", 0));
+    try testing.expectError(error.Overflow, net.IpAddress.parseIp4("256.0.0.1", 0));
+    try testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp4("x.0.0.1", 0));
+    try testing.expectError(error.InvalidEnd, net.IpAddress.parseIp4("127.0.0.1.1", 0));
+    try testing.expectError(error.Incomplete, net.IpAddress.parseIp4("127.0.0.", 0));
+    try testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp4("100..0.1", 0));
+    try testing.expectError(error.NonCanonical, net.IpAddress.parseIp4("127.01.0.1", 0));
 }
 
 test "parse and render UNIX addresses" {
@@ -161,8 +161,8 @@ test "resolve DNS" {
 
     // Resolve localhost, this should not fail.
     {
-        const localhost_v4 = try net.Address.parseIp("127.0.0.1", 80);
-        const localhost_v6 = try net.Address.parseIp("::2", 80);
+        const localhost_v4 = try net.IpAddress.parseIp("127.0.0.1", 80);
+        const localhost_v6 = try net.IpAddress.parseIp("::2", 80);
 
         const result = try net.getAddressList(testing.allocator, "localhost", 80);
         defer result.deinit();
@@ -198,13 +198,13 @@ test "listen on a port, send bytes, receive bytes" {
 
     // Try only the IPv4 variant as some CI builders have no IPv6 localhost
     // configured.
-    const localhost = try net.Address.parseIp("127.0.0.1", 0);
+    const localhost = try net.IpAddress.parseIp("127.0.0.1", 0);
 
     var server = try localhost.listen(.{});
     defer server.deinit();
 
     const S = struct {
-        fn clientFn(server_address: net.Address) !void {
+        fn clientFn(server_address: net.IpAddress) !void {
             const socket = try net.tcpConnectToAddress(server_address);
             defer socket.close();
 
@@ -232,7 +232,7 @@ test "listen on an in use port" {
         return error.SkipZigTest;
     }
 
-    const localhost = try net.Address.parseIp("127.0.0.1", 0);
+    const localhost = try net.IpAddress.parseIp("127.0.0.1", 0);
 
     var server1 = try localhost.listen(.{ .reuse_address = true });
     defer server1.deinit();
@@ -253,7 +253,7 @@ fn testClientToHost(allocator: mem.Allocator, name: []const u8, port: u16) anyer
     try testing.expect(mem.eql(u8, msg, "hello from server\n"));
 }
 
-fn testClient(addr: net.Address) anyerror!void {
+fn testClient(addr: net.IpAddress) anyerror!void {
     if (builtin.os.tag == .wasi) return error.SkipZigTest;
 
     const socket_file = try net.tcpConnectToAddress(addr);
@@ -290,7 +290,7 @@ test "listen on a unix socket, send bytes, receive bytes" {
     const socket_path = try generateFileName("socket.unix");
     defer testing.allocator.free(socket_path);
 
-    const socket_addr = try net.Address.initUnix(socket_path);
+    const socket_addr = try net.IpAddress.initUnix(socket_path);
     defer std.fs.cwd().deleteFile(socket_path) catch {};
 
     var server = try socket_addr.listen(.{});
@@ -351,7 +351,7 @@ test "non-blocking tcp server" {
         return error.SkipZigTest;
     }
 
-    const localhost = try net.Address.parseIp("127.0.0.1", 0);
+    const localhost = try net.IpAddress.parseIp("127.0.0.1", 0);
     var server = localhost.listen(.{ .force_nonblocking = true });
     defer server.deinit();
 
lib/std/Io/File.zig
@@ -1,6 +1,8 @@
 const File = @This();
 
 const builtin = @import("builtin");
+const native_os = builtin.os.tag;
+const is_windows = native_os == .windows;
 
 const std = @import("../std.zig");
 const Io = std.Io;
@@ -131,6 +133,18 @@ pub const Stat = struct {
     }
 };
 
+pub fn stdout() File {
+    return .{ .handle = if (is_windows) std.os.windows.peb().ProcessParameters.hStdOutput else std.posix.STDOUT_FILENO };
+}
+
+pub fn stderr() File {
+    return .{ .handle = if (is_windows) std.os.windows.peb().ProcessParameters.hStdError else std.posix.STDERR_FILENO };
+}
+
+pub fn stdin() File {
+    return .{ .handle = if (is_windows) std.os.windows.peb().ProcessParameters.hStdInput else std.posix.STDIN_FILENO };
+}
+
 pub const StatError = std.posix.FStatError || Io.Cancelable;
 
 /// Returns `Stat` containing basic information about the `File`.
@@ -183,6 +197,11 @@ pub fn write(file: File, io: Io, buffer: []const u8) WriteError!usize {
     return @errorCast(file.pwrite(io, buffer, -1));
 }
 
+pub fn writeAll(file: File, io: Io, bytes: []const u8) WriteError!void {
+    var index: usize = 0;
+    while (index < bytes.len) index += try file.write(io, bytes[index..]);
+}
+
 pub const PWriteError = std.fs.File.PWriteError || Io.Cancelable;
 
 pub fn pwrite(file: File, io: Io, buffer: []const u8, offset: std.posix.off_t) PWriteError!usize {
@@ -350,7 +369,7 @@ pub const Reader = struct {
         const io = r.io;
         switch (r.mode) {
             .positional, .positional_reading => {
-                setPosAdjustingBuffer(r, @intCast(@as(i64, @intCast(r.pos)) + offset));
+                setLogicalPos(r, @intCast(@as(i64, @intCast(logicalPos(r))) + offset));
             },
             .streaming, .streaming_reading => {
                 if (std.posix.SEEK == void) {
@@ -359,7 +378,7 @@ pub const Reader = struct {
                 }
                 const seek_err = r.seek_err orelse e: {
                     if (io.vtable.fileSeekBy(io.userdata, r.file, offset)) |_| {
-                        setPosAdjustingBuffer(r, @intCast(@as(i64, @intCast(r.pos)) + offset));
+                        setLogicalPos(r, @intCast(@as(i64, @intCast(logicalPos(r))) + offset));
                         return;
                     } else |err| {
                         r.seek_err = err;
@@ -384,16 +403,17 @@ pub const Reader = struct {
         const io = r.io;
         switch (r.mode) {
             .positional, .positional_reading => {
-                setPosAdjustingBuffer(r, offset);
+                setLogicalPos(r, offset);
             },
             .streaming, .streaming_reading => {
-                if (offset >= r.pos) return Reader.seekBy(r, @intCast(offset - r.pos));
+                const logical_pos = logicalPos(r);
+                if (offset >= logical_pos) return Reader.seekBy(r, @intCast(offset - logical_pos));
                 if (r.seek_err) |err| return err;
                 io.vtable.fileSeekTo(io.userdata, r.file, offset) catch |err| {
                     r.seek_err = err;
                     return err;
                 };
-                setPosAdjustingBuffer(r, offset);
+                setLogicalPos(r, offset);
             },
             .failure => return r.seek_err.?,
         }
@@ -403,7 +423,7 @@ pub const Reader = struct {
         return r.pos - r.interface.bufferedLen();
     }
 
-    fn setPosAdjustingBuffer(r: *Reader, offset: u64) void {
+    fn setLogicalPos(r: *Reader, offset: u64) void {
         const logical_pos = logicalPos(r);
         if (offset < logical_pos or offset >= r.pos) {
             r.interface.seek = 0;
@@ -544,9 +564,10 @@ pub const Reader = struct {
         }
     }
 
+    /// Returns whether the stream is at the logical end.
     pub fn atEnd(r: *Reader) bool {
         // Even if stat fails, size is set when end is encountered.
         const size = r.size orelse return false;
-        return size - r.pos == 0;
+        return size - logicalPos(r) == 0;
     }
 };
lib/std/Io/net.zig
@@ -43,6 +43,14 @@ pub const Protocol = enum(u32) {
     mptcp = 262,
 };
 
+/// Windows 10 added support for unix sockets in build 17063, redstone 4 is the
+/// first release to support them.
+pub const has_unix_sockets = switch (native_os) {
+    .windows => builtin.os.version_range.windows.isAtLeast(.win10_rs4) orelse false,
+    .wasi => false,
+    else => true,
+};
+
 pub const IpAddress = union(enum) {
     ip4: Ip4Address,
     ip6: Ip6Address,
@@ -980,7 +988,13 @@ pub const Stream = struct {
         stream: Stream,
         err: ?Error,
 
-        pub const Error = std.net.Stream.ReadError || Io.Cancelable || Io.Writer.Error || error{EndOfStream};
+        pub const Error = std.posix.ReadError || error{
+            SocketNotBound,
+            MessageTooBig,
+            NetworkSubsystemFailed,
+            ConnectionResetByPeer,
+            SocketUnconnected,
+        } || Io.Cancelable || Io.Writer.Error || error{EndOfStream};
 
         pub fn init(stream: Stream, buffer: []u8) Reader {
             return .{
@@ -1019,7 +1033,15 @@ pub const Stream = struct {
         stream: Stream,
         err: ?Error = null,
 
-        pub const Error = std.net.Stream.WriteError || Io.Cancelable;
+        pub const Error = std.posix.SendMsgError || error{
+            ConnectionResetByPeer,
+            SocketNotBound,
+            MessageTooBig,
+            NetworkSubsystemFailed,
+            SystemResources,
+            SocketUnconnected,
+            Unexpected,
+        } || Io.Cancelable;
 
         pub fn init(stream: Stream, buffer: []u8) Writer {
             return .{
@@ -1096,4 +1118,5 @@ fn testIp6ParseTransform(expected: []const u8, input: []const u8) !void {
 
 test {
     _ = HostName;
+    _ = @import("net/test.zig");
 }
lib/std/fs.zig
@@ -97,25 +97,6 @@ pub const base64_encoder = base64.Base64Encoder.init(base64_alphabet, null);
 /// Base64 decoder, replacing the standard `+/` with `-_` so that it can be used in a file name on any filesystem.
 pub const base64_decoder = base64.Base64Decoder.init(base64_alphabet, null);
 
-/// Same as `Dir.updateFile`, except asserts that both `source_path` and `dest_path`
-/// are absolute. See `Dir.updateFile` for a function that operates on both
-/// absolute and relative paths.
-/// On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
-/// On WASI, both paths should be encoded as valid UTF-8.
-/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding.
-pub fn updateFileAbsolute(
-    source_path: []const u8,
-    dest_path: []const u8,
-    args: Dir.CopyFileOptions,
-) !std.Io.Dir.PrevStatus {
-    assert(path.isAbsolute(source_path));
-    assert(path.isAbsolute(dest_path));
-    const my_cwd = cwd();
-    return Dir.updateFile(my_cwd, source_path, my_cwd, dest_path, args);
-}
-
-test updateFileAbsolute {}
-
 /// Same as `Dir.copyFile`, except asserts that both `source_path` and `dest_path`
 /// are absolute. See `Dir.copyFile` for a function that operates on both
 /// absolute and relative paths.
lib/std/net.zig
@@ -1,2424 +0,0 @@
-//! Cross-platform networking abstractions.
-
-const std = @import("std.zig");
-const builtin = @import("builtin");
-const assert = std.debug.assert;
-const net = @This();
-const mem = std.mem;
-const posix = std.posix;
-const fs = std.fs;
-const Io = std.Io;
-const native_endian = builtin.target.cpu.arch.endian();
-const native_os = builtin.os.tag;
-const windows = std.os.windows;
-const Allocator = std.mem.Allocator;
-const ArrayList = std.ArrayListUnmanaged;
-const File = std.fs.File;
-
-// Windows 10 added support for unix sockets in build 17063, redstone 4 is the
-// first release to support them.
-pub const has_unix_sockets = switch (native_os) {
-    .windows => builtin.os.version_range.windows.isAtLeast(.win10_rs4) orelse false,
-    .wasi => false,
-    else => true,
-};
-
-pub const IPParseError = error{
-    Overflow,
-    InvalidEnd,
-    InvalidCharacter,
-    Incomplete,
-};
-
-pub const IPv4ParseError = IPParseError || error{NonCanonical};
-
-pub const IPv6ParseError = IPParseError || error{InvalidIpv4Mapping};
-pub const IPv6InterfaceError = posix.SocketError || posix.IoCtl_SIOCGIFINDEX_Error || error{NameTooLong};
-pub const IPv6ResolveError = IPv6ParseError || IPv6InterfaceError;
-
-pub const Address = extern union {
-    any: posix.sockaddr,
-    in: Ip4Address,
-    in6: Ip6Address,
-    un: if (has_unix_sockets) posix.sockaddr.un else void,
-
-    /// Parse an IP address which may include a port. For IPv4, this is just written `address:port`.
-    /// For IPv6, RFC 3986 defines this as an "IP literal", and the port is differentiated from the
-    /// address by surrounding the address part in brackets '[addr]:port'. Even if the port is not
-    /// given, the brackets are mandatory.
-    pub fn parseIpAndPort(str: []const u8) error{ InvalidAddress, InvalidPort }!Address {
-        if (str.len == 0) return error.InvalidAddress;
-        if (str[0] == '[') {
-            const addr_end = std.mem.indexOfScalar(u8, str, ']') orelse
-                return error.InvalidAddress;
-            const addr_str = str[1..addr_end];
-            const port: u16 = p: {
-                if (addr_end == str.len - 1) break :p 0;
-                if (str[addr_end + 1] != ':') return error.InvalidAddress;
-                break :p parsePort(str[addr_end + 2 ..]) orelse return error.InvalidPort;
-            };
-            return parseIp6(addr_str, port) catch error.InvalidAddress;
-        } else {
-            if (std.mem.indexOfScalar(u8, str, ':')) |idx| {
-                // hold off on `error.InvalidPort` since `error.InvalidAddress` might make more sense
-                const port: ?u16 = parsePort(str[idx + 1 ..]);
-                const addr = parseIp4(str[0..idx], port orelse 0) catch return error.InvalidAddress;
-                if (port == null) return error.InvalidPort;
-                return addr;
-            } else {
-                return parseIp4(str, 0) catch error.InvalidAddress;
-            }
-        }
-    }
-    fn parsePort(str: []const u8) ?u16 {
-        var p: u16 = 0;
-        for (str) |c| switch (c) {
-            '0'...'9' => {
-                const shifted = std.math.mul(u16, p, 10) catch return null;
-                p = std.math.add(u16, shifted, c - '0') catch return null;
-            },
-            else => return null,
-        };
-        if (p == 0) return null;
-        return p;
-    }
-
-    /// Parse the given IP address string into an Address value.
-    /// It is recommended to use `resolveIp` instead, to handle
-    /// IPv6 link-local unix addresses.
-    pub fn parseIp(name: []const u8, port: u16) !Address {
-        if (parseIp4(name, port)) |ip4| return ip4 else |err| switch (err) {
-            error.Overflow,
-            error.InvalidEnd,
-            error.InvalidCharacter,
-            error.Incomplete,
-            error.NonCanonical,
-            => {},
-        }
-
-        if (parseIp6(name, port)) |ip6| return ip6 else |err| switch (err) {
-            error.Overflow,
-            error.InvalidEnd,
-            error.InvalidCharacter,
-            error.Incomplete,
-            error.InvalidIpv4Mapping,
-            => {},
-        }
-
-        return error.InvalidIpAddressFormat;
-    }
-
-    pub fn resolveIp(name: []const u8, port: u16) !Address {
-        if (parseIp4(name, port)) |ip4| return ip4 else |err| switch (err) {
-            error.Overflow,
-            error.InvalidEnd,
-            error.InvalidCharacter,
-            error.Incomplete,
-            error.NonCanonical,
-            => {},
-        }
-
-        if (resolveIp6(name, port)) |ip6| return ip6 else |err| switch (err) {
-            error.Overflow,
-            error.InvalidEnd,
-            error.InvalidCharacter,
-            error.Incomplete,
-            error.InvalidIpv4Mapping,
-            => {},
-            else => return err,
-        }
-
-        return error.InvalidIpAddressFormat;
-    }
-
-    pub fn parseExpectingFamily(name: []const u8, family: posix.sa_family_t, port: u16) !Address {
-        switch (family) {
-            posix.AF.INET => return parseIp4(name, port),
-            posix.AF.INET6 => return parseIp6(name, port),
-            posix.AF.UNSPEC => return parseIp(name, port),
-            else => unreachable,
-        }
-    }
-
-    pub fn parseIp6(buf: []const u8, port: u16) IPv6ParseError!Address {
-        return .{ .in6 = try Ip6Address.parse(buf, port) };
-    }
-
-    pub fn resolveIp6(buf: []const u8, port: u16) IPv6ResolveError!Address {
-        return .{ .in6 = try Ip6Address.resolve(buf, port) };
-    }
-
-    pub fn parseIp4(buf: []const u8, port: u16) IPv4ParseError!Address {
-        return .{ .in = try Ip4Address.parse(buf, port) };
-    }
-
-    pub fn initIp4(addr: [4]u8, port: u16) Address {
-        return .{ .in = Ip4Address.init(addr, port) };
-    }
-
-    pub fn initIp6(addr: [16]u8, port: u16, flowinfo: u32, scope_id: u32) Address {
-        return .{ .in6 = Ip6Address.init(addr, port, flowinfo, scope_id) };
-    }
-
-    pub fn initUnix(path: []const u8) !Address {
-        var sock_addr = posix.sockaddr.un{
-            .family = posix.AF.UNIX,
-            .path = undefined,
-        };
-
-        // Add 1 to ensure a terminating 0 is present in the path array for maximum portability.
-        if (path.len + 1 > sock_addr.path.len) return error.NameTooLong;
-
-        @memset(&sock_addr.path, 0);
-        @memcpy(sock_addr.path[0..path.len], path);
-
-        return .{ .un = sock_addr };
-    }
-
-    /// Returns the port in native endian.
-    /// Asserts that the address is ip4 or ip6.
-    pub fn getPort(self: Address) u16 {
-        return switch (self.any.family) {
-            posix.AF.INET => self.in.getPort(),
-            posix.AF.INET6 => self.in6.getPort(),
-            else => unreachable,
-        };
-    }
-
-    /// `port` is native-endian.
-    /// Asserts that the address is ip4 or ip6.
-    pub fn setPort(self: *Address, port: u16) void {
-        switch (self.any.family) {
-            posix.AF.INET => self.in.setPort(port),
-            posix.AF.INET6 => self.in6.setPort(port),
-            else => unreachable,
-        }
-    }
-
-    /// Asserts that `addr` is an IP address.
-    /// This function will read past the end of the pointer, with a size depending
-    /// on the address family.
-    pub fn initPosix(addr: *align(4) const posix.sockaddr) Address {
-        switch (addr.family) {
-            posix.AF.INET => return Address{ .in = Ip4Address{ .sa = @as(*const posix.sockaddr.in, @ptrCast(addr)).* } },
-            posix.AF.INET6 => return Address{ .in6 = Ip6Address{ .sa = @as(*const posix.sockaddr.in6, @ptrCast(addr)).* } },
-            else => unreachable,
-        }
-    }
-
-    pub fn format(self: Address, w: *Io.Writer) Io.Writer.Error!void {
-        switch (self.any.family) {
-            posix.AF.INET => try self.in.format(w),
-            posix.AF.INET6 => try self.in6.format(w),
-            posix.AF.UNIX => {
-                if (!has_unix_sockets) unreachable;
-                try w.writeAll(std.mem.sliceTo(&self.un.path, 0));
-            },
-            else => unreachable,
-        }
-    }
-
-    pub fn eql(a: Address, b: Address) bool {
-        const a_bytes = @as([*]const u8, @ptrCast(&a.any))[0..a.getOsSockLen()];
-        const b_bytes = @as([*]const u8, @ptrCast(&b.any))[0..b.getOsSockLen()];
-        return mem.eql(u8, a_bytes, b_bytes);
-    }
-
-    pub fn getOsSockLen(self: Address) posix.socklen_t {
-        switch (self.any.family) {
-            posix.AF.INET => return self.in.getOsSockLen(),
-            posix.AF.INET6 => return self.in6.getOsSockLen(),
-            posix.AF.UNIX => {
-                if (!has_unix_sockets) {
-                    unreachable;
-                }
-
-                // Using the full length of the structure here is more portable than returning
-                // the number of bytes actually used by the currently stored path.
-                // This also is correct regardless if we are passing a socket address to the kernel
-                // (e.g. in bind, connect, sendto) since we ensure the path is 0 terminated in
-                // initUnix() or if we are receiving a socket address from the kernel and must
-                // provide the full buffer size (e.g. getsockname, getpeername, recvfrom, accept).
-                //
-                // To access the path, std.mem.sliceTo(&address.un.path, 0) should be used.
-                return @as(posix.socklen_t, @intCast(@sizeOf(posix.sockaddr.un)));
-            },
-
-            else => unreachable,
-        }
-    }
-
-    pub const ListenError = posix.SocketError || posix.BindError || posix.ListenError ||
-        posix.SetSockOptError || posix.GetSockNameError;
-
-    pub const ListenOptions = struct {
-        /// How many connections the kernel will accept on the application's behalf.
-        /// If more than this many connections pool in the kernel, clients will start
-        /// seeing "Connection refused".
-        kernel_backlog: u31 = 128,
-        /// Sets SO_REUSEADDR and SO_REUSEPORT on POSIX.
-        /// Sets SO_REUSEADDR on Windows, which is roughly equivalent.
-        reuse_address: bool = false,
-        /// Sets O_NONBLOCK.
-        force_nonblocking: bool = false,
-    };
-
-    /// The returned `Server` has an open `stream`.
-    pub fn listen(address: Address, options: ListenOptions) ListenError!Server {
-        const nonblock: u32 = if (options.force_nonblocking) posix.SOCK.NONBLOCK else 0;
-        const sock_flags = posix.SOCK.STREAM | posix.SOCK.CLOEXEC | nonblock;
-        const proto: u32 = if (address.any.family == posix.AF.UNIX) 0 else posix.IPPROTO.TCP;
-
-        const sockfd = try posix.socket(address.any.family, sock_flags, proto);
-        var s: Server = .{
-            .listen_address = undefined,
-            .stream = .{ .handle = sockfd },
-        };
-        errdefer s.stream.close();
-
-        if (options.reuse_address) {
-            try posix.setsockopt(
-                sockfd,
-                posix.SOL.SOCKET,
-                posix.SO.REUSEADDR,
-                &mem.toBytes(@as(c_int, 1)),
-            );
-            if (@hasDecl(posix.SO, "REUSEPORT") and address.any.family != posix.AF.UNIX) {
-                try posix.setsockopt(
-                    sockfd,
-                    posix.SOL.SOCKET,
-                    posix.SO.REUSEPORT,
-                    &mem.toBytes(@as(c_int, 1)),
-                );
-            }
-        }
-
-        var socklen = address.getOsSockLen();
-        try posix.bind(sockfd, &address.any, socklen);
-        try posix.listen(sockfd, options.kernel_backlog);
-        try posix.getsockname(sockfd, &s.listen_address.any, &socklen);
-        return s;
-    }
-};
-
-pub const Ip4Address = extern struct {
-    sa: posix.sockaddr.in,
-
-    pub fn parse(buf: []const u8, port: u16) IPv4ParseError!Ip4Address {
-        var result: Ip4Address = .{
-            .sa = .{
-                .port = mem.nativeToBig(u16, port),
-                .addr = undefined,
-            },
-        };
-        const out_ptr = mem.asBytes(&result.sa.addr);
-
-        var x: u8 = 0;
-        var index: u8 = 0;
-        var saw_any_digits = false;
-        var has_zero_prefix = false;
-        for (buf) |c| {
-            if (c == '.') {
-                if (!saw_any_digits) {
-                    return error.InvalidCharacter;
-                }
-                if (index == 3) {
-                    return error.InvalidEnd;
-                }
-                out_ptr[index] = x;
-                index += 1;
-                x = 0;
-                saw_any_digits = false;
-                has_zero_prefix = false;
-            } else if (c >= '0' and c <= '9') {
-                if (c == '0' and !saw_any_digits) {
-                    has_zero_prefix = true;
-                } else if (has_zero_prefix) {
-                    return error.NonCanonical;
-                }
-                saw_any_digits = true;
-                x = try std.math.mul(u8, x, 10);
-                x = try std.math.add(u8, x, c - '0');
-            } else {
-                return error.InvalidCharacter;
-            }
-        }
-        if (index == 3 and saw_any_digits) {
-            out_ptr[index] = x;
-            return result;
-        }
-
-        return error.Incomplete;
-    }
-
-    pub fn resolveIp(name: []const u8, port: u16) !Ip4Address {
-        if (parse(name, port)) |ip4| return ip4 else |err| switch (err) {
-            error.Overflow,
-            error.InvalidEnd,
-            error.InvalidCharacter,
-            error.Incomplete,
-            error.NonCanonical,
-            => {},
-        }
-        return error.InvalidIpAddressFormat;
-    }
-
-    pub fn init(addr: [4]u8, port: u16) Ip4Address {
-        return Ip4Address{
-            .sa = posix.sockaddr.in{
-                .port = mem.nativeToBig(u16, port),
-                .addr = @as(*align(1) const u32, @ptrCast(&addr)).*,
-            },
-        };
-    }
-
-    /// Returns the port in native endian.
-    /// Asserts that the address is ip4 or ip6.
-    pub fn getPort(self: Ip4Address) u16 {
-        return mem.bigToNative(u16, self.sa.port);
-    }
-
-    /// `port` is native-endian.
-    /// Asserts that the address is ip4 or ip6.
-    pub fn setPort(self: *Ip4Address, port: u16) void {
-        self.sa.port = mem.nativeToBig(u16, port);
-    }
-
-    pub fn format(self: Ip4Address, w: *Io.Writer) Io.Writer.Error!void {
-        const bytes: *const [4]u8 = @ptrCast(&self.sa.addr);
-        try w.print("{d}.{d}.{d}.{d}:{d}", .{ bytes[0], bytes[1], bytes[2], bytes[3], self.getPort() });
-    }
-
-    pub fn getOsSockLen(self: Ip4Address) posix.socklen_t {
-        _ = self;
-        return @sizeOf(posix.sockaddr.in);
-    }
-};
-
-pub const Ip6Address = extern struct {
-    sa: posix.sockaddr.in6,
-
-    /// Parse a given IPv6 address string into an Address.
-    /// Assumes the Scope ID of the address is fully numeric.
-    /// For non-numeric addresses, see `resolveIp6`.
-    pub fn parse(buf: []const u8, port: u16) IPv6ParseError!Ip6Address {
-        var result = Ip6Address{
-            .sa = posix.sockaddr.in6{
-                .scope_id = 0,
-                .port = mem.nativeToBig(u16, port),
-                .flowinfo = 0,
-                .addr = undefined,
-            },
-        };
-        var ip_slice: *[16]u8 = result.sa.addr[0..];
-
-        var tail: [16]u8 = undefined;
-
-        var x: u16 = 0;
-        var saw_any_digits = false;
-        var index: u8 = 0;
-        var scope_id = false;
-        var abbrv = false;
-        for (buf, 0..) |c, i| {
-            if (scope_id) {
-                if (c >= '0' and c <= '9') {
-                    const digit = c - '0';
-                    {
-                        const ov = @mulWithOverflow(result.sa.scope_id, 10);
-                        if (ov[1] != 0) return error.Overflow;
-                        result.sa.scope_id = ov[0];
-                    }
-                    {
-                        const ov = @addWithOverflow(result.sa.scope_id, digit);
-                        if (ov[1] != 0) return error.Overflow;
-                        result.sa.scope_id = ov[0];
-                    }
-                } else {
-                    return error.InvalidCharacter;
-                }
-            } else if (c == ':') {
-                if (!saw_any_digits) {
-                    if (abbrv) return error.InvalidCharacter; // ':::'
-                    if (i != 0) abbrv = true;
-                    @memset(ip_slice[index..], 0);
-                    ip_slice = tail[0..];
-                    index = 0;
-                    continue;
-                }
-                if (index == 14) {
-                    return error.InvalidEnd;
-                }
-                ip_slice[index] = @as(u8, @truncate(x >> 8));
-                index += 1;
-                ip_slice[index] = @as(u8, @truncate(x));
-                index += 1;
-
-                x = 0;
-                saw_any_digits = false;
-            } else if (c == '%') {
-                if (!saw_any_digits) {
-                    return error.InvalidCharacter;
-                }
-                scope_id = true;
-                saw_any_digits = false;
-            } else if (c == '.') {
-                if (!abbrv or ip_slice[0] != 0xff or ip_slice[1] != 0xff) {
-                    // must start with '::ffff:'
-                    return error.InvalidIpv4Mapping;
-                }
-                const start_index = mem.lastIndexOfScalar(u8, buf[0..i], ':').? + 1;
-                const addr = (Ip4Address.parse(buf[start_index..], 0) catch {
-                    return error.InvalidIpv4Mapping;
-                }).sa.addr;
-                ip_slice = result.sa.addr[0..];
-                ip_slice[10] = 0xff;
-                ip_slice[11] = 0xff;
-
-                const ptr = mem.sliceAsBytes(@as(*const [1]u32, &addr)[0..]);
-
-                ip_slice[12] = ptr[0];
-                ip_slice[13] = ptr[1];
-                ip_slice[14] = ptr[2];
-                ip_slice[15] = ptr[3];
-                return result;
-            } else {
-                const digit = try std.fmt.charToDigit(c, 16);
-                {
-                    const ov = @mulWithOverflow(x, 16);
-                    if (ov[1] != 0) return error.Overflow;
-                    x = ov[0];
-                }
-                {
-                    const ov = @addWithOverflow(x, digit);
-                    if (ov[1] != 0) return error.Overflow;
-                    x = ov[0];
-                }
-                saw_any_digits = true;
-            }
-        }
-
-        if (!saw_any_digits and !abbrv) {
-            return error.Incomplete;
-        }
-        if (!abbrv and index < 14) {
-            return error.Incomplete;
-        }
-
-        if (index == 14) {
-            ip_slice[14] = @as(u8, @truncate(x >> 8));
-            ip_slice[15] = @as(u8, @truncate(x));
-            return result;
-        } else {
-            ip_slice[index] = @as(u8, @truncate(x >> 8));
-            index += 1;
-            ip_slice[index] = @as(u8, @truncate(x));
-            index += 1;
-            @memcpy(result.sa.addr[16 - index ..][0..index], ip_slice[0..index]);
-            return result;
-        }
-    }
-
-    pub fn resolve(buf: []const u8, port: u16) IPv6ResolveError!Ip6Address {
-        // TODO: Unify the implementations of resolveIp6 and parseIp6.
-        var result = Ip6Address{
-            .sa = posix.sockaddr.in6{
-                .scope_id = 0,
-                .port = mem.nativeToBig(u16, port),
-                .flowinfo = 0,
-                .addr = undefined,
-            },
-        };
-        var ip_slice: *[16]u8 = result.sa.addr[0..];
-
-        var tail: [16]u8 = undefined;
-
-        var x: u16 = 0;
-        var saw_any_digits = false;
-        var index: u8 = 0;
-        var abbrv = false;
-
-        var scope_id = false;
-        var scope_id_value: [posix.IFNAMESIZE - 1]u8 = undefined;
-        var scope_id_index: usize = 0;
-
-        for (buf, 0..) |c, i| {
-            if (scope_id) {
-                // Handling of percent-encoding should be for an URI library.
-                if ((c >= '0' and c <= '9') or
-                    (c >= 'A' and c <= 'Z') or
-                    (c >= 'a' and c <= 'z') or
-                    (c == '-') or (c == '.') or (c == '_') or (c == '~'))
-                {
-                    if (scope_id_index >= scope_id_value.len) {
-                        return error.Overflow;
-                    }
-
-                    scope_id_value[scope_id_index] = c;
-                    scope_id_index += 1;
-                } else {
-                    return error.InvalidCharacter;
-                }
-            } else if (c == ':') {
-                if (!saw_any_digits) {
-                    if (abbrv) return error.InvalidCharacter; // ':::'
-                    if (i != 0) abbrv = true;
-                    @memset(ip_slice[index..], 0);
-                    ip_slice = tail[0..];
-                    index = 0;
-                    continue;
-                }
-                if (index == 14) {
-                    return error.InvalidEnd;
-                }
-                ip_slice[index] = @as(u8, @truncate(x >> 8));
-                index += 1;
-                ip_slice[index] = @as(u8, @truncate(x));
-                index += 1;
-
-                x = 0;
-                saw_any_digits = false;
-            } else if (c == '%') {
-                if (!saw_any_digits) {
-                    return error.InvalidCharacter;
-                }
-                scope_id = true;
-                saw_any_digits = false;
-            } else if (c == '.') {
-                if (!abbrv or ip_slice[0] != 0xff or ip_slice[1] != 0xff) {
-                    // must start with '::ffff:'
-                    return error.InvalidIpv4Mapping;
-                }
-                const start_index = mem.lastIndexOfScalar(u8, buf[0..i], ':').? + 1;
-                const addr = (Ip4Address.parse(buf[start_index..], 0) catch {
-                    return error.InvalidIpv4Mapping;
-                }).sa.addr;
-                ip_slice = result.sa.addr[0..];
-                ip_slice[10] = 0xff;
-                ip_slice[11] = 0xff;
-
-                const ptr = mem.sliceAsBytes(@as(*const [1]u32, &addr)[0..]);
-
-                ip_slice[12] = ptr[0];
-                ip_slice[13] = ptr[1];
-                ip_slice[14] = ptr[2];
-                ip_slice[15] = ptr[3];
-                return result;
-            } else {
-                const digit = try std.fmt.charToDigit(c, 16);
-                {
-                    const ov = @mulWithOverflow(x, 16);
-                    if (ov[1] != 0) return error.Overflow;
-                    x = ov[0];
-                }
-                {
-                    const ov = @addWithOverflow(x, digit);
-                    if (ov[1] != 0) return error.Overflow;
-                    x = ov[0];
-                }
-                saw_any_digits = true;
-            }
-        }
-
-        if (!saw_any_digits and !abbrv) {
-            return error.Incomplete;
-        }
-
-        if (scope_id and scope_id_index == 0) {
-            return error.Incomplete;
-        }
-
-        var resolved_scope_id: u32 = 0;
-        if (scope_id_index > 0) {
-            const scope_id_str = scope_id_value[0..scope_id_index];
-            resolved_scope_id = std.fmt.parseInt(u32, scope_id_str, 10) catch |err| blk: {
-                if (err != error.InvalidCharacter) return err;
-                break :blk try if_nametoindex(scope_id_str);
-            };
-        }
-
-        result.sa.scope_id = resolved_scope_id;
-
-        if (index == 14) {
-            ip_slice[14] = @as(u8, @truncate(x >> 8));
-            ip_slice[15] = @as(u8, @truncate(x));
-            return result;
-        } else {
-            ip_slice[index] = @as(u8, @truncate(x >> 8));
-            index += 1;
-            ip_slice[index] = @as(u8, @truncate(x));
-            index += 1;
-            @memcpy(result.sa.addr[16 - index ..][0..index], ip_slice[0..index]);
-            return result;
-        }
-    }
-
-    pub fn init(addr: [16]u8, port: u16, flowinfo: u32, scope_id: u32) Ip6Address {
-        return Ip6Address{
-            .sa = posix.sockaddr.in6{
-                .addr = addr,
-                .port = mem.nativeToBig(u16, port),
-                .flowinfo = flowinfo,
-                .scope_id = scope_id,
-            },
-        };
-    }
-
-    /// Returns the port in native endian.
-    /// Asserts that the address is ip4 or ip6.
-    pub fn getPort(self: Ip6Address) u16 {
-        return mem.bigToNative(u16, self.sa.port);
-    }
-
-    /// `port` is native-endian.
-    /// Asserts that the address is ip4 or ip6.
-    pub fn setPort(self: *Ip6Address, port: u16) void {
-        self.sa.port = mem.nativeToBig(u16, port);
-    }
-
-    pub fn format(self: Ip6Address, w: *Io.Writer) Io.Writer.Error!void {
-        const port = mem.bigToNative(u16, self.sa.port);
-        if (mem.eql(u8, self.sa.addr[0..12], &[_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff })) {
-            try w.print("[::ffff:{d}.{d}.{d}.{d}]:{d}", .{
-                self.sa.addr[12],
-                self.sa.addr[13],
-                self.sa.addr[14],
-                self.sa.addr[15],
-                port,
-            });
-            return;
-        }
-        const big_endian_parts = @as(*align(1) const [8]u16, @ptrCast(&self.sa.addr));
-        const native_endian_parts = switch (native_endian) {
-            .big => big_endian_parts.*,
-            .little => blk: {
-                var buf: [8]u16 = undefined;
-                for (big_endian_parts, 0..) |part, i| {
-                    buf[i] = mem.bigToNative(u16, part);
-                }
-                break :blk buf;
-            },
-        };
-
-        // Find the longest zero run
-        var longest_start: usize = 8;
-        var longest_len: usize = 0;
-        var current_start: usize = 0;
-        var current_len: usize = 0;
-
-        for (native_endian_parts, 0..) |part, i| {
-            if (part == 0) {
-                if (current_len == 0) {
-                    current_start = i;
-                }
-                current_len += 1;
-                if (current_len > longest_len) {
-                    longest_start = current_start;
-                    longest_len = current_len;
-                }
-            } else {
-                current_len = 0;
-            }
-        }
-
-        // Only compress if the longest zero run is 2 or more
-        if (longest_len < 2) {
-            longest_start = 8;
-            longest_len = 0;
-        }
-
-        try w.writeAll("[");
-        var i: usize = 0;
-        var abbrv = false;
-        while (i < native_endian_parts.len) : (i += 1) {
-            if (i == longest_start) {
-                // Emit "::" for the longest zero run
-                if (!abbrv) {
-                    try w.writeAll(if (i == 0) "::" else ":");
-                    abbrv = true;
-                }
-                i += longest_len - 1; // Skip the compressed range
-                continue;
-            }
-            if (abbrv) {
-                abbrv = false;
-            }
-            try w.print("{x}", .{native_endian_parts[i]});
-            if (i != native_endian_parts.len - 1) {
-                try w.writeAll(":");
-            }
-        }
-        if (self.sa.scope_id != 0) {
-            try w.print("%{}", .{self.sa.scope_id});
-        }
-        try w.print("]:{}", .{port});
-    }
-
-    pub fn getOsSockLen(self: Ip6Address) posix.socklen_t {
-        _ = self;
-        return @sizeOf(posix.sockaddr.in6);
-    }
-};
-
-pub fn connectUnixSocket(path: []const u8) !Stream {
-    const opt_non_block = 0;
-    const sockfd = try posix.socket(
-        posix.AF.UNIX,
-        posix.SOCK.STREAM | posix.SOCK.CLOEXEC | opt_non_block,
-        0,
-    );
-    errdefer Stream.close(.{ .handle = sockfd });
-
-    var addr = try Address.initUnix(path);
-    try posix.connect(sockfd, &addr.any, addr.getOsSockLen());
-
-    return .{ .handle = sockfd };
-}
-
-fn if_nametoindex(name: []const u8) IPv6InterfaceError!u32 {
-    if (native_os == .linux) {
-        var ifr: posix.ifreq = undefined;
-        const sockfd = try posix.socket(posix.AF.UNIX, posix.SOCK.DGRAM | posix.SOCK.CLOEXEC, 0);
-        defer Stream.close(.{ .handle = sockfd });
-
-        @memcpy(ifr.ifrn.name[0..name.len], name);
-        ifr.ifrn.name[name.len] = 0;
-
-        // TODO investigate if this needs to be integrated with evented I/O.
-        try posix.ioctl_SIOCGIFINDEX(sockfd, &ifr);
-
-        return @bitCast(ifr.ifru.ivalue);
-    }
-
-    if (native_os.isDarwin()) {
-        if (name.len >= posix.IFNAMESIZE)
-            return error.NameTooLong;
-
-        var if_name: [posix.IFNAMESIZE:0]u8 = undefined;
-        @memcpy(if_name[0..name.len], name);
-        if_name[name.len] = 0;
-        const if_slice = if_name[0..name.len :0];
-        const index = std.c.if_nametoindex(if_slice);
-        if (index == 0)
-            return error.InterfaceNotFound;
-        return @as(u32, @bitCast(index));
-    }
-
-    if (native_os == .windows) {
-        if (name.len >= posix.IFNAMESIZE)
-            return error.NameTooLong;
-
-        var interface_name: [posix.IFNAMESIZE:0]u8 = undefined;
-        @memcpy(interface_name[0..name.len], name);
-        interface_name[name.len] = 0;
-        const index = std.os.windows.ws2_32.if_nametoindex(@as([*:0]const u8, &interface_name));
-        if (index == 0)
-            return error.InterfaceNotFound;
-        return index;
-    }
-
-    @compileError("std.net.if_nametoindex unimplemented for this OS");
-}
-
-pub const AddressList = struct {
-    arena: std.heap.ArenaAllocator,
-    addrs: []Address,
-    canon_name: ?[]u8,
-
-    pub fn deinit(self: *AddressList) void {
-        // Here we copy the arena allocator into stack memory, because
-        // otherwise it would destroy itself while it was still working.
-        var arena = self.arena;
-        arena.deinit();
-        // self is destroyed
-    }
-};
-
-pub const TcpConnectToHostError = GetAddressListError || TcpConnectToAddressError;
-
-/// All memory allocated with `allocator` will be freed before this function returns.
-pub fn tcpConnectToHost(allocator: Allocator, name: []const u8, port: u16) TcpConnectToHostError!Stream {
-    const list = try getAddressList(allocator, name, port);
-    defer list.deinit();
-
-    if (list.addrs.len == 0) return error.UnknownHostName;
-
-    for (list.addrs) |addr| {
-        return tcpConnectToAddress(addr) catch |err| switch (err) {
-            error.ConnectionRefused => {
-                continue;
-            },
-            else => return err,
-        };
-    }
-    return posix.ConnectError.ConnectionRefused;
-}
-
-pub const TcpConnectToAddressError = posix.SocketError || posix.ConnectError;
-
-pub fn tcpConnectToAddress(address: Address) TcpConnectToAddressError!Stream {
-    const nonblock = 0;
-    const sock_flags = posix.SOCK.STREAM | nonblock |
-        (if (native_os == .windows) 0 else posix.SOCK.CLOEXEC);
-    const sockfd = try posix.socket(address.any.family, sock_flags, posix.IPPROTO.TCP);
-    errdefer Stream.close(.{ .handle = sockfd });
-
-    try posix.connect(sockfd, &address.any, address.getOsSockLen());
-
-    return Stream{ .handle = sockfd };
-}
-
-// TODO: Instead of having a massive error set, make the error set have categories, and then
-// store the sub-error as a diagnostic value.
-const GetAddressListError = Allocator.Error || File.OpenError || File.ReadError || posix.SocketError || posix.BindError || posix.SetSockOptError || error{
-    TemporaryNameServerFailure,
-    NameServerFailure,
-    AddressFamilyNotSupported,
-    UnknownHostName,
-    ServiceUnavailable,
-    Unexpected,
-
-    HostLacksNetworkAddresses,
-
-    InvalidCharacter,
-    InvalidEnd,
-    NonCanonical,
-    Overflow,
-    Incomplete,
-    InvalidIpv4Mapping,
-    InvalidIpAddressFormat,
-
-    InterfaceNotFound,
-    FileSystem,
-    ResolveConfParseFailed,
-};
-
-/// Call `AddressList.deinit` on the result.
-pub fn getAddressList(gpa: Allocator, name: []const u8, port: u16) GetAddressListError!*AddressList {
-    const result = blk: {
-        var arena = std.heap.ArenaAllocator.init(gpa);
-        errdefer arena.deinit();
-
-        const result = try arena.allocator().create(AddressList);
-        result.* = AddressList{
-            .arena = arena,
-            .addrs = undefined,
-            .canon_name = null,
-        };
-        break :blk result;
-    };
-    const arena = result.arena.allocator();
-    errdefer result.deinit();
-
-    if (native_os == .windows) {
-        const name_c = try gpa.dupeZ(u8, name);
-        defer gpa.free(name_c);
-
-        const port_c = try std.fmt.allocPrintSentinel(gpa, "{d}", .{port}, 0);
-        defer gpa.free(port_c);
-
-        const ws2_32 = windows.ws2_32;
-        const hints: posix.addrinfo = .{
-            .flags = .{ .NUMERICSERV = true },
-            .family = posix.AF.UNSPEC,
-            .socktype = posix.SOCK.STREAM,
-            .protocol = posix.IPPROTO.TCP,
-            .canonname = null,
-            .addr = null,
-            .addrlen = 0,
-            .next = null,
-        };
-        var res: ?*posix.addrinfo = null;
-        var first = true;
-        while (true) {
-            const rc = ws2_32.getaddrinfo(name_c.ptr, port_c.ptr, &hints, &res);
-            switch (@as(windows.ws2_32.WinsockError, @enumFromInt(@as(u16, @intCast(rc))))) {
-                @as(windows.ws2_32.WinsockError, @enumFromInt(0)) => break,
-                .WSATRY_AGAIN => return error.TemporaryNameServerFailure,
-                .WSANO_RECOVERY => return error.NameServerFailure,
-                .WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported,
-                .WSA_NOT_ENOUGH_MEMORY => return error.OutOfMemory,
-                .WSAHOST_NOT_FOUND => return error.UnknownHostName,
-                .WSATYPE_NOT_FOUND => return error.ServiceUnavailable,
-                .WSAEINVAL => unreachable,
-                .WSAESOCKTNOSUPPORT => unreachable,
-                .WSANOTINITIALISED => {
-                    if (!first) return error.Unexpected;
-                    first = false;
-                    try windows.callWSAStartup();
-                    continue;
-                },
-                else => |err| return windows.unexpectedWSAError(err),
-            }
-        }
-        defer ws2_32.freeaddrinfo(res);
-
-        const addr_count = blk: {
-            var count: usize = 0;
-            var it = res;
-            while (it) |info| : (it = info.next) {
-                if (info.addr != null) {
-                    count += 1;
-                }
-            }
-            break :blk count;
-        };
-        result.addrs = try arena.alloc(Address, addr_count);
-
-        var it = res;
-        var i: usize = 0;
-        while (it) |info| : (it = info.next) {
-            const addr = info.addr orelse continue;
-            result.addrs[i] = Address.initPosix(@alignCast(addr));
-
-            if (info.canonname) |n| {
-                if (result.canon_name == null) {
-                    result.canon_name = try arena.dupe(u8, mem.sliceTo(n, 0));
-                }
-            }
-            i += 1;
-        }
-
-        return result;
-    }
-
-    if (builtin.link_libc) {
-        const name_c = try gpa.dupeZ(u8, name);
-        defer gpa.free(name_c);
-
-        const port_c = try std.fmt.allocPrintSentinel(gpa, "{d}", .{port}, 0);
-        defer gpa.free(port_c);
-
-        const hints: posix.addrinfo = .{
-            .flags = .{ .NUMERICSERV = true },
-            .family = posix.AF.UNSPEC,
-            .socktype = posix.SOCK.STREAM,
-            .protocol = posix.IPPROTO.TCP,
-            .canonname = null,
-            .addr = null,
-            .addrlen = 0,
-            .next = null,
-        };
-        var res: ?*posix.addrinfo = null;
-        switch (posix.system.getaddrinfo(name_c.ptr, port_c.ptr, &hints, &res)) {
-            @as(posix.system.EAI, @enumFromInt(0)) => {},
-            .ADDRFAMILY => return error.HostLacksNetworkAddresses,
-            .AGAIN => return error.TemporaryNameServerFailure,
-            .BADFLAGS => unreachable, // Invalid hints
-            .FAIL => return error.NameServerFailure,
-            .FAMILY => return error.AddressFamilyNotSupported,
-            .MEMORY => return error.OutOfMemory,
-            .NODATA => return error.HostLacksNetworkAddresses,
-            .NONAME => return error.UnknownHostName,
-            .SERVICE => return error.ServiceUnavailable,
-            .SOCKTYPE => unreachable, // Invalid socket type requested in hints
-            .SYSTEM => switch (posix.errno(-1)) {
-                else => |e| return posix.unexpectedErrno(e),
-            },
-            else => unreachable,
-        }
-        defer if (res) |some| posix.system.freeaddrinfo(some);
-
-        const addr_count = blk: {
-            var count: usize = 0;
-            var it = res;
-            while (it) |info| : (it = info.next) {
-                if (info.addr != null) {
-                    count += 1;
-                }
-            }
-            break :blk count;
-        };
-        result.addrs = try arena.alloc(Address, addr_count);
-
-        var it = res;
-        var i: usize = 0;
-        while (it) |info| : (it = info.next) {
-            const addr = info.addr orelse continue;
-            result.addrs[i] = Address.initPosix(@alignCast(addr));
-
-            if (info.canonname) |n| {
-                if (result.canon_name == null) {
-                    result.canon_name = try arena.dupe(u8, mem.sliceTo(n, 0));
-                }
-            }
-            i += 1;
-        }
-
-        return result;
-    }
-
-    if (native_os == .linux) {
-        const family = posix.AF.UNSPEC;
-        var lookup_addrs: ArrayList(LookupAddr) = .empty;
-        defer lookup_addrs.deinit(gpa);
-
-        var canon: ArrayList(u8) = .empty;
-        defer canon.deinit(gpa);
-
-        try linuxLookupName(gpa, &lookup_addrs, &canon, name, family, .{ .NUMERICSERV = true }, port);
-
-        result.addrs = try arena.alloc(Address, lookup_addrs.items.len);
-        if (canon.items.len != 0) {
-            result.canon_name = try arena.dupe(u8, canon.items);
-        }
-
-        for (lookup_addrs.items, 0..) |lookup_addr, i| {
-            result.addrs[i] = lookup_addr.addr;
-            assert(result.addrs[i].getPort() == port);
-        }
-
-        return result;
-    }
-    @compileError("std.net.getAddressList unimplemented for this OS");
-}
-
-const LookupAddr = struct {
-    addr: Address,
-    sortkey: i32 = 0,
-};
-
-const DAS_USABLE = 0x40000000;
-const DAS_MATCHINGSCOPE = 0x20000000;
-const DAS_MATCHINGLABEL = 0x10000000;
-const DAS_PREC_SHIFT = 20;
-const DAS_SCOPE_SHIFT = 16;
-const DAS_PREFIX_SHIFT = 8;
-const DAS_ORDER_SHIFT = 0;
-
-fn linuxLookupName(
-    gpa: Allocator,
-    addrs: *ArrayList(LookupAddr),
-    canon: *ArrayList(u8),
-    opt_name: ?[]const u8,
-    family: posix.sa_family_t,
-    flags: posix.AI,
-    port: u16,
-) !void {
-    if (opt_name) |name| {
-        // reject empty name and check len so it fits into temp bufs
-        canon.items.len = 0;
-        try canon.appendSlice(gpa, name);
-        if (Address.parseExpectingFamily(name, family, port)) |addr| {
-            try addrs.append(gpa, .{ .addr = addr });
-        } else |name_err| if (flags.NUMERICHOST) {
-            return name_err;
-        } else {
-            try linuxLookupNameFromHosts(gpa, addrs, canon, name, family, port);
-            if (addrs.items.len == 0) {
-                // RFC 6761 Section 6.3.3
-                // Name resolution APIs and libraries SHOULD recognize localhost
-                // names as special and SHOULD always return the IP loopback address
-                // for address queries and negative responses for all other query
-                // types.
-
-                // Check for equal to "localhost(.)" or ends in ".localhost(.)"
-                const localhost = if (name[name.len - 1] == '.') "localhost." else "localhost";
-                if (mem.endsWith(u8, name, localhost) and (name.len == localhost.len or name[name.len - localhost.len] == '.')) {
-                    try addrs.append(gpa, .{ .addr = .{ .in = Ip4Address.parse("127.0.0.1", port) catch unreachable } });
-                    try addrs.append(gpa, .{ .addr = .{ .in6 = Ip6Address.parse("::1", port) catch unreachable } });
-                    return;
-                }
-
-                try linuxLookupNameFromDnsSearch(gpa, addrs, canon, name, family, port);
-            }
-        }
-    } else {
-        try canon.resize(gpa, 0);
-        try addrs.ensureUnusedCapacity(gpa, 2);
-        linuxLookupNameFromNull(addrs, family, flags, port);
-    }
-    if (addrs.items.len == 0) return error.UnknownHostName;
-
-    // No further processing is needed if there are fewer than 2
-    // results or if there are only IPv4 results.
-    if (addrs.items.len == 1 or family == posix.AF.INET) return;
-    const all_ip4 = for (addrs.items) |addr| {
-        if (addr.addr.any.family != posix.AF.INET) break false;
-    } else true;
-    if (all_ip4) return;
-
-    // The following implements a subset of RFC 3484/6724 destination
-    // address selection by generating a single 31-bit sort key for
-    // each address. Rules 3, 4, and 7 are omitted for having
-    // excessive runtime and code size cost and dubious benefit.
-    // So far the label/precedence table cannot be customized.
-    // This implementation is ported from musl libc.
-    // A more idiomatic "ziggy" implementation would be welcome.
-    for (addrs.items, 0..) |*addr, i| {
-        var key: i32 = 0;
-        var sa6: posix.sockaddr.in6 = undefined;
-        @memset(@as([*]u8, @ptrCast(&sa6))[0..@sizeOf(posix.sockaddr.in6)], 0);
-        var da6 = posix.sockaddr.in6{
-            .family = posix.AF.INET6,
-            .scope_id = addr.addr.in6.sa.scope_id,
-            .port = 65535,
-            .flowinfo = 0,
-            .addr = [1]u8{0} ** 16,
-        };
-        var sa4: posix.sockaddr.in = undefined;
-        @memset(@as([*]u8, @ptrCast(&sa4))[0..@sizeOf(posix.sockaddr.in)], 0);
-        var da4 = posix.sockaddr.in{
-            .family = posix.AF.INET,
-            .port = 65535,
-            .addr = 0,
-            .zero = [1]u8{0} ** 8,
-        };
-        var sa: *align(4) posix.sockaddr = undefined;
-        var da: *align(4) posix.sockaddr = undefined;
-        var salen: posix.socklen_t = undefined;
-        var dalen: posix.socklen_t = undefined;
-        if (addr.addr.any.family == posix.AF.INET6) {
-            da6.addr = addr.addr.in6.sa.addr;
-            da = @ptrCast(&da6);
-            dalen = @sizeOf(posix.sockaddr.in6);
-            sa = @ptrCast(&sa6);
-            salen = @sizeOf(posix.sockaddr.in6);
-        } else {
-            sa6.addr[0..12].* = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff".*;
-            da6.addr[0..12].* = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff".*;
-            mem.writeInt(u32, da6.addr[12..], addr.addr.in.sa.addr, native_endian);
-            da4.addr = addr.addr.in.sa.addr;
-            da = @ptrCast(&da4);
-            dalen = @sizeOf(posix.sockaddr.in);
-            sa = @ptrCast(&sa4);
-            salen = @sizeOf(posix.sockaddr.in);
-        }
-        const dpolicy = policyOf(da6.addr);
-        const dscope: i32 = scopeOf(da6.addr);
-        const dlabel = dpolicy.label;
-        const dprec: i32 = dpolicy.prec;
-        const MAXADDRS = 3;
-        var prefixlen: i32 = 0;
-        const sock_flags = posix.SOCK.DGRAM | posix.SOCK.CLOEXEC;
-        if (posix.socket(addr.addr.any.family, sock_flags, posix.IPPROTO.UDP)) |fd| syscalls: {
-            defer Stream.close(.{ .handle = fd });
-            posix.connect(fd, da, dalen) catch break :syscalls;
-            key |= DAS_USABLE;
-            posix.getsockname(fd, sa, &salen) catch break :syscalls;
-            if (addr.addr.any.family == posix.AF.INET) {
-                mem.writeInt(u32, sa6.addr[12..16], sa4.addr, native_endian);
-            }
-            if (dscope == @as(i32, scopeOf(sa6.addr))) key |= DAS_MATCHINGSCOPE;
-            if (dlabel == labelOf(sa6.addr)) key |= DAS_MATCHINGLABEL;
-            prefixlen = prefixMatch(sa6.addr, da6.addr);
-        } else |_| {}
-        key |= dprec << DAS_PREC_SHIFT;
-        key |= (15 - dscope) << DAS_SCOPE_SHIFT;
-        key |= prefixlen << DAS_PREFIX_SHIFT;
-        key |= (MAXADDRS - @as(i32, @intCast(i))) << DAS_ORDER_SHIFT;
-        addr.sortkey = key;
-    }
-    mem.sort(LookupAddr, addrs.items, {}, addrCmpLessThan);
-}
-
-const Policy = struct {
-    addr: [16]u8,
-    len: u8,
-    mask: u8,
-    prec: u8,
-    label: u8,
-};
-
-const defined_policies = [_]Policy{
-    Policy{
-        .addr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01".*,
-        .len = 15,
-        .mask = 0xff,
-        .prec = 50,
-        .label = 0,
-    },
-    Policy{
-        .addr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00".*,
-        .len = 11,
-        .mask = 0xff,
-        .prec = 35,
-        .label = 4,
-    },
-    Policy{
-        .addr = "\x20\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".*,
-        .len = 1,
-        .mask = 0xff,
-        .prec = 30,
-        .label = 2,
-    },
-    Policy{
-        .addr = "\x20\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".*,
-        .len = 3,
-        .mask = 0xff,
-        .prec = 5,
-        .label = 5,
-    },
-    Policy{
-        .addr = "\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".*,
-        .len = 0,
-        .mask = 0xfe,
-        .prec = 3,
-        .label = 13,
-    },
-    //  These are deprecated and/or returned to the address
-    //  pool, so despite the RFC, treating them as special
-    //  is probably wrong.
-    // { "", 11, 0xff, 1, 3 },
-    // { "\xfe\xc0", 1, 0xc0, 1, 11 },
-    // { "\x3f\xfe", 1, 0xff, 1, 12 },
-    // Last rule must match all addresses to stop loop.
-    Policy{
-        .addr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".*,
-        .len = 0,
-        .mask = 0,
-        .prec = 40,
-        .label = 1,
-    },
-};
-
-fn policyOf(a: [16]u8) *const Policy {
-    for (&defined_policies) |*policy| {
-        if (!mem.eql(u8, a[0..policy.len], policy.addr[0..policy.len])) continue;
-        if ((a[policy.len] & policy.mask) != policy.addr[policy.len]) continue;
-        return policy;
-    }
-    unreachable;
-}
-
-fn scopeOf(a: [16]u8) u8 {
-    if (IN6_IS_ADDR_MULTICAST(a)) return a[1] & 15;
-    if (IN6_IS_ADDR_LINKLOCAL(a)) return 2;
-    if (IN6_IS_ADDR_LOOPBACK(a)) return 2;
-    if (IN6_IS_ADDR_SITELOCAL(a)) return 5;
-    return 14;
-}
-
-fn prefixMatch(s: [16]u8, d: [16]u8) u8 {
-    // TODO: This FIXME inherited from porting from musl libc.
-    // I don't want this to go into zig std lib 1.0.0.
-
-    // FIXME: The common prefix length should be limited to no greater
-    // than the nominal length of the prefix portion of the source
-    // address. However the definition of the source prefix length is
-    // not clear and thus this limiting is not yet implemented.
-    var i: u8 = 0;
-    while (i < 128 and ((s[i / 8] ^ d[i / 8]) & (@as(u8, 128) >> @as(u3, @intCast(i % 8)))) == 0) : (i += 1) {}
-    return i;
-}
-
-fn labelOf(a: [16]u8) u8 {
-    return policyOf(a).label;
-}
-
-fn IN6_IS_ADDR_MULTICAST(a: [16]u8) bool {
-    return a[0] == 0xff;
-}
-
-fn IN6_IS_ADDR_LINKLOCAL(a: [16]u8) bool {
-    return a[0] == 0xfe and (a[1] & 0xc0) == 0x80;
-}
-
-fn IN6_IS_ADDR_LOOPBACK(a: [16]u8) bool {
-    return a[0] == 0 and a[1] == 0 and
-        a[2] == 0 and
-        a[12] == 0 and a[13] == 0 and
-        a[14] == 0 and a[15] == 1;
-}
-
-fn IN6_IS_ADDR_SITELOCAL(a: [16]u8) bool {
-    return a[0] == 0xfe and (a[1] & 0xc0) == 0xc0;
-}
-
-// Parameters `b` and `a` swapped to make this descending.
-fn addrCmpLessThan(context: void, b: LookupAddr, a: LookupAddr) bool {
-    _ = context;
-    return a.sortkey < b.sortkey;
-}
-
-fn linuxLookupNameFromNull(
-    addrs: *ArrayList(LookupAddr),
-    family: posix.sa_family_t,
-    flags: posix.AI,
-    port: u16,
-) void {
-    if (flags.PASSIVE) {
-        if (family != posix.AF.INET6) {
-            addrs.appendAssumeCapacity(.{
-                .addr = Address.initIp4([1]u8{0} ** 4, port),
-            });
-        }
-        if (family != posix.AF.INET) {
-            addrs.appendAssumeCapacity(.{
-                .addr = Address.initIp6([1]u8{0} ** 16, port, 0, 0),
-            });
-        }
-    } else {
-        if (family != posix.AF.INET6) {
-            addrs.appendAssumeCapacity(.{
-                .addr = Address.initIp4([4]u8{ 127, 0, 0, 1 }, port),
-            });
-        }
-        if (family != posix.AF.INET) {
-            addrs.appendAssumeCapacity(.{
-                .addr = Address.initIp6(([1]u8{0} ** 15) ++ [1]u8{1}, port, 0, 0),
-            });
-        }
-    }
-}
-
-fn linuxLookupNameFromHosts(
-    gpa: Allocator,
-    addrs: *ArrayList(LookupAddr),
-    canon: *ArrayList(u8),
-    name: []const u8,
-    family: posix.sa_family_t,
-    port: u16,
-) !void {
-    const file = fs.openFileAbsoluteZ("/etc/hosts", .{}) catch |err| switch (err) {
-        error.FileNotFound,
-        error.NotDir,
-        error.AccessDenied,
-        => return,
-        else => |e| return e,
-    };
-    defer file.close();
-
-    var line_buf: [512]u8 = undefined;
-    var file_reader = file.reader(&line_buf);
-    return parseHosts(gpa, addrs, canon, name, family, port, &file_reader.interface) catch |err| switch (err) {
-        error.OutOfMemory => return error.OutOfMemory,
-        error.ReadFailed => return file_reader.err.?,
-    };
-}
-
-fn parseHosts(
-    gpa: Allocator,
-    addrs: *ArrayList(LookupAddr),
-    canon: *ArrayList(u8),
-    name: []const u8,
-    family: posix.sa_family_t,
-    port: u16,
-    br: *Io.Reader,
-) error{ OutOfMemory, ReadFailed }!void {
-    while (true) {
-        const line = br.takeDelimiter('\n') catch |err| switch (err) {
-            error.StreamTooLong => {
-                // Skip lines that are too long.
-                _ = br.discardDelimiterInclusive('\n') catch |e| switch (e) {
-                    error.EndOfStream => break,
-                    error.ReadFailed => return error.ReadFailed,
-                };
-                continue;
-            },
-            error.ReadFailed => return error.ReadFailed,
-        } orelse {
-            break; // end of stream
-        };
-        var split_it = mem.splitScalar(u8, line, '#');
-        const no_comment_line = split_it.first();
-
-        var line_it = mem.tokenizeAny(u8, no_comment_line, " \t");
-        const ip_text = line_it.next() orelse continue;
-        var first_name_text: ?[]const u8 = null;
-        while (line_it.next()) |name_text| {
-            if (first_name_text == null) first_name_text = name_text;
-            if (mem.eql(u8, name_text, name)) {
-                break;
-            }
-        } else continue;
-
-        const addr = Address.parseExpectingFamily(ip_text, family, port) catch |err| switch (err) {
-            error.Overflow,
-            error.InvalidEnd,
-            error.InvalidCharacter,
-            error.Incomplete,
-            error.InvalidIpAddressFormat,
-            error.InvalidIpv4Mapping,
-            error.NonCanonical,
-            => continue,
-        };
-        try addrs.append(gpa, .{ .addr = addr });
-
-        // first name is canonical name
-        const name_text = first_name_text.?;
-        if (isValidHostName(name_text)) {
-            canon.items.len = 0;
-            try canon.appendSlice(gpa, name_text);
-        }
-    }
-}
-
-test parseHosts {
-    if (builtin.os.tag == .wasi) {
-        // TODO parsing addresses should not have OS dependencies
-        return error.SkipZigTest;
-    }
-    var reader: Io.Reader = .fixed(
-        \\127.0.0.1 localhost
-        \\::1 localhost
-        \\127.0.0.2 abcd
-    );
-    var addrs: ArrayList(LookupAddr) = .empty;
-    defer addrs.deinit(std.testing.allocator);
-    var canon: ArrayList(u8) = .empty;
-    defer canon.deinit(std.testing.allocator);
-    try parseHosts(std.testing.allocator, &addrs, &canon, "abcd", posix.AF.UNSPEC, 1234, &reader);
-    try std.testing.expectEqual(1, addrs.items.len);
-    try std.testing.expectFmt("127.0.0.2:1234", "{f}", .{addrs.items[0].addr});
-}
-
-pub fn isValidHostName(bytes: []const u8) bool {
-    _ = std.Io.net.HostName.init(bytes) catch return false;
-    return true;
-}
-
-fn linuxLookupNameFromDnsSearch(
-    gpa: Allocator,
-    addrs: *ArrayList(LookupAddr),
-    canon: *ArrayList(u8),
-    name: []const u8,
-    family: posix.sa_family_t,
-    port: u16,
-) !void {
-    var rc: ResolvConf = undefined;
-    rc.init(gpa) catch return error.ResolveConfParseFailed;
-    defer rc.deinit();
-
-    // Count dots, suppress search when >=ndots or name ends in
-    // a dot, which is an explicit request for global scope.
-    var dots: usize = 0;
-    for (name) |byte| {
-        if (byte == '.') dots += 1;
-    }
-
-    const search = if (dots >= rc.ndots or mem.endsWith(u8, name, "."))
-        ""
-    else
-        rc.search.items;
-
-    var canon_name = name;
-
-    // Strip final dot for canon, fail if multiple trailing dots.
-    if (mem.endsWith(u8, canon_name, ".")) canon_name.len -= 1;
-    if (mem.endsWith(u8, canon_name, ".")) return error.UnknownHostName;
-
-    // Name with search domain appended is setup in canon[]. This both
-    // provides the desired default canonical name (if the requested
-    // name is not a CNAME record) and serves as a buffer for passing
-    // the full requested name to name_from_dns.
-    try canon.resize(gpa, canon_name.len);
-    @memcpy(canon.items, canon_name);
-    try canon.append(gpa, '.');
-
-    var tok_it = mem.tokenizeAny(u8, search, " \t");
-    while (tok_it.next()) |tok| {
-        canon.shrinkRetainingCapacity(canon_name.len + 1);
-        try canon.appendSlice(gpa, tok);
-        try linuxLookupNameFromDns(gpa, addrs, canon, canon.items, family, rc, port);
-        if (addrs.items.len != 0) return;
-    }
-
-    canon.shrinkRetainingCapacity(canon_name.len);
-    return linuxLookupNameFromDns(gpa, addrs, canon, name, family, rc, port);
-}
-
-const dpc_ctx = struct {
-    gpa: Allocator,
-    addrs: *ArrayList(LookupAddr),
-    canon: *ArrayList(u8),
-    port: u16,
-};
-
-fn linuxLookupNameFromDns(
-    gpa: Allocator,
-    addrs: *ArrayList(LookupAddr),
-    canon: *ArrayList(u8),
-    name: []const u8,
-    family: posix.sa_family_t,
-    rc: ResolvConf,
-    port: u16,
-) !void {
-    const ctx: dpc_ctx = .{
-        .gpa = gpa,
-        .addrs = addrs,
-        .canon = canon,
-        .port = port,
-    };
-    const AfRr = struct {
-        af: posix.sa_family_t,
-        rr: u8,
-    };
-    const afrrs = [_]AfRr{
-        .{ .af = posix.AF.INET6, .rr = posix.RR.A },
-        .{ .af = posix.AF.INET, .rr = posix.RR.AAAA },
-    };
-    var qbuf: [2][280]u8 = undefined;
-    var abuf: [2][512]u8 = undefined;
-    var qp: [2][]const u8 = undefined;
-    const apbuf = [2][]u8{ &abuf[0], &abuf[1] };
-    var nq: usize = 0;
-
-    for (afrrs) |afrr| {
-        if (family != afrr.af) {
-            const len = posix.res_mkquery(0, name, 1, afrr.rr, &[_]u8{}, null, &qbuf[nq]);
-            qp[nq] = qbuf[nq][0..len];
-            nq += 1;
-        }
-    }
-
-    var ap = [2][]u8{ apbuf[0], apbuf[1] };
-    ap[0].len = 0;
-    ap[1].len = 0;
-
-    try rc.resMSendRc(qp[0..nq], ap[0..nq], apbuf[0..nq]);
-
-    var i: usize = 0;
-    while (i < nq) : (i += 1) {
-        dnsParse(ap[i], ctx, dnsParseCallback) catch {};
-    }
-
-    if (addrs.items.len != 0) return;
-    if (ap[0].len < 4 or (ap[0][3] & 15) == 2) return error.TemporaryNameServerFailure;
-    if ((ap[0][3] & 15) == 0) return error.UnknownHostName;
-    if ((ap[0][3] & 15) == 3) return;
-    return error.NameServerFailure;
-}
-
-const ResolvConf = struct {
-    gpa: Allocator,
-    attempts: u32,
-    ndots: u32,
-    timeout: u32,
-    search: ArrayList(u8),
-    /// TODO there are actually only allowed to be maximum 3 nameservers, no need
-    /// for an array list.
-    ns: ArrayList(LookupAddr),
-
-    /// Returns `error.StreamTooLong` if a line is longer than 512 bytes.
-    /// TODO: https://github.com/ziglang/zig/issues/2765 and https://github.com/ziglang/zig/issues/2761
-    fn init(rc: *ResolvConf, gpa: Allocator) !void {
-        rc.* = .{
-            .gpa = gpa,
-            .ns = .empty,
-            .search = .empty,
-            .ndots = 1,
-            .timeout = 5,
-            .attempts = 2,
-        };
-        errdefer rc.deinit();
-
-        const file = fs.openFileAbsoluteZ("/etc/resolv.conf", .{}) catch |err| switch (err) {
-            error.FileNotFound,
-            error.NotDir,
-            error.AccessDenied,
-            => return linuxLookupNameFromNumericUnspec(gpa, &rc.ns, "127.0.0.1", 53),
-            else => |e| return e,
-        };
-        defer file.close();
-
-        var line_buf: [512]u8 = undefined;
-        var file_reader = file.reader(&line_buf);
-        return parse(rc, &file_reader.interface) catch |err| switch (err) {
-            error.ReadFailed => return file_reader.err.?,
-            else => |e| return e,
-        };
-    }
-
-    const Directive = enum { options, nameserver, domain, search };
-    const Option = enum { ndots, attempts, timeout };
-
-    fn parse(rc: *ResolvConf, reader: *Io.Reader) !void {
-        const gpa = rc.gpa;
-        while (reader.takeSentinel('\n')) |line_with_comment| {
-            const line = line: {
-                var split = mem.splitScalar(u8, line_with_comment, '#');
-                break :line split.first();
-            };
-            var line_it = mem.tokenizeAny(u8, line, " \t");
-
-            const token = line_it.next() orelse continue;
-            switch (std.meta.stringToEnum(Directive, token) orelse continue) {
-                .options => while (line_it.next()) |sub_tok| {
-                    var colon_it = mem.splitScalar(u8, sub_tok, ':');
-                    const name = colon_it.first();
-                    const value_txt = colon_it.next() orelse continue;
-                    const value = std.fmt.parseInt(u8, value_txt, 10) catch |err| switch (err) {
-                        error.Overflow => 255,
-                        error.InvalidCharacter => continue,
-                    };
-                    switch (std.meta.stringToEnum(Option, name) orelse continue) {
-                        .ndots => rc.ndots = @min(value, 15),
-                        .attempts => rc.attempts = @min(value, 10),
-                        .timeout => rc.timeout = @min(value, 60),
-                    }
-                },
-                .nameserver => {
-                    const ip_txt = line_it.next() orelse continue;
-                    try linuxLookupNameFromNumericUnspec(gpa, &rc.ns, ip_txt, 53);
-                },
-                .domain, .search => {
-                    rc.search.items.len = 0;
-                    try rc.search.appendSlice(gpa, line_it.rest());
-                },
-            }
-        } else |err| switch (err) {
-            error.EndOfStream => if (reader.bufferedLen() != 0) return error.EndOfStream,
-            else => |e| return e,
-        }
-
-        if (rc.ns.items.len == 0) {
-            return linuxLookupNameFromNumericUnspec(gpa, &rc.ns, "127.0.0.1", 53);
-        }
-    }
-
-    fn resMSendRc(
-        rc: ResolvConf,
-        queries: []const []const u8,
-        answers: [][]u8,
-        answer_bufs: []const []u8,
-    ) !void {
-        const gpa = rc.gpa;
-        const timeout = 1000 * rc.timeout;
-        const attempts = rc.attempts;
-
-        var sl: posix.socklen_t = @sizeOf(posix.sockaddr.in);
-        var family: posix.sa_family_t = posix.AF.INET;
-
-        var ns_list: ArrayList(Address) = .empty;
-        defer ns_list.deinit(gpa);
-
-        try ns_list.resize(gpa, rc.ns.items.len);
-
-        for (ns_list.items, rc.ns.items) |*ns, iplit| {
-            ns.* = iplit.addr;
-            assert(ns.getPort() == 53);
-            if (iplit.addr.any.family != posix.AF.INET) {
-                family = posix.AF.INET6;
-            }
-        }
-
-        const flags = posix.SOCK.DGRAM | posix.SOCK.CLOEXEC | posix.SOCK.NONBLOCK;
-        const fd = posix.socket(family, flags, 0) catch |err| switch (err) {
-            error.AddressFamilyNotSupported => blk: {
-                // Handle case where system lacks IPv6 support
-                if (family == posix.AF.INET6) {
-                    family = posix.AF.INET;
-                    break :blk try posix.socket(posix.AF.INET, flags, 0);
-                }
-                return err;
-            },
-            else => |e| return e,
-        };
-        defer Stream.close(.{ .handle = fd });
-
-        // Past this point, there are no errors. Each individual query will
-        // yield either no reply (indicated by zero length) or an answer
-        // packet which is up to the caller to interpret.
-
-        // Convert any IPv4 addresses in a mixed environment to v4-mapped
-        if (family == posix.AF.INET6) {
-            try posix.setsockopt(
-                fd,
-                posix.SOL.IPV6,
-                std.os.linux.IPV6.V6ONLY,
-                &mem.toBytes(@as(c_int, 0)),
-            );
-            for (ns_list.items) |*ns| {
-                if (ns.any.family != posix.AF.INET) continue;
-                mem.writeInt(u32, ns.in6.sa.addr[12..], ns.in.sa.addr, native_endian);
-                ns.in6.sa.addr[0..12].* = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff".*;
-                ns.any.family = posix.AF.INET6;
-                ns.in6.sa.flowinfo = 0;
-                ns.in6.sa.scope_id = 0;
-            }
-            sl = @sizeOf(posix.sockaddr.in6);
-        }
-
-        // Get local address and open/bind a socket
-        var sa: Address = undefined;
-        @memset(@as([*]u8, @ptrCast(&sa))[0..@sizeOf(Address)], 0);
-        sa.any.family = family;
-        try posix.bind(fd, &sa.any, sl);
-
-        var pfd = [1]posix.pollfd{posix.pollfd{
-            .fd = fd,
-            .events = posix.POLL.IN,
-            .revents = undefined,
-        }};
-        const retry_interval = timeout / attempts;
-        var next: u32 = 0;
-        var t2: u64 = @bitCast(std.time.milliTimestamp());
-        const t0 = t2;
-        var t1 = t2 - retry_interval;
-
-        var servfail_retry: usize = undefined;
-
-        outer: while (t2 - t0 < timeout) : (t2 = @as(u64, @bitCast(std.time.milliTimestamp()))) {
-            if (t2 - t1 >= retry_interval) {
-                // Query all configured nameservers in parallel
-                var i: usize = 0;
-                while (i < queries.len) : (i += 1) {
-                    if (answers[i].len == 0) {
-                        for (ns_list.items) |*ns| {
-                            _ = posix.sendto(fd, queries[i], posix.MSG.NOSIGNAL, &ns.any, sl) catch undefined;
-                        }
-                    }
-                }
-                t1 = t2;
-                servfail_retry = 2 * queries.len;
-            }
-
-            // Wait for a response, or until time to retry
-            const clamped_timeout = @min(@as(u31, std.math.maxInt(u31)), t1 + retry_interval - t2);
-            const nevents = posix.poll(&pfd, clamped_timeout) catch 0;
-            if (nevents == 0) continue;
-
-            while (true) {
-                var sl_copy = sl;
-                const rlen = posix.recvfrom(fd, answer_bufs[next], 0, &sa.any, &sl_copy) catch break;
-
-                // Ignore non-identifiable packets
-                if (rlen < 4) continue;
-
-                // Ignore replies from addresses we didn't send to
-                const ns = for (ns_list.items) |*ns| {
-                    if (ns.eql(sa)) break ns;
-                } else continue;
-
-                // Find which query this answer goes with, if any
-                var i: usize = next;
-                while (i < queries.len and (answer_bufs[next][0] != queries[i][0] or
-                    answer_bufs[next][1] != queries[i][1])) : (i += 1)
-                {}
-
-                if (i == queries.len) continue;
-                if (answers[i].len != 0) continue;
-
-                // Only accept positive or negative responses;
-                // retry immediately on server failure, and ignore
-                // all other codes such as refusal.
-                switch (answer_bufs[next][3] & 15) {
-                    0, 3 => {},
-                    2 => if (servfail_retry != 0) {
-                        servfail_retry -= 1;
-                        _ = posix.sendto(fd, queries[i], posix.MSG.NOSIGNAL, &ns.any, sl) catch undefined;
-                    },
-                    else => continue,
-                }
-
-                // Store answer in the right slot, or update next
-                // available temp slot if it's already in place.
-                answers[i].len = rlen;
-                if (i == next) {
-                    while (next < queries.len and answers[next].len != 0) : (next += 1) {}
-                } else {
-                    @memcpy(answer_bufs[i][0..rlen], answer_bufs[next][0..rlen]);
-                }
-
-                if (next == queries.len) break :outer;
-            }
-        }
-    }
-
-    fn deinit(rc: *ResolvConf) void {
-        const gpa = rc.gpa;
-        rc.ns.deinit(gpa);
-        rc.search.deinit(gpa);
-        rc.* = undefined;
-    }
-};
-
-fn linuxLookupNameFromNumericUnspec(
-    gpa: Allocator,
-    addrs: *ArrayList(LookupAddr),
-    name: []const u8,
-    port: u16,
-) !void {
-    const addr = try Address.resolveIp(name, port);
-    try addrs.append(gpa, .{ .addr = addr });
-}
-
-fn dnsParse(
-    r: []const u8,
-    ctx: anytype,
-    comptime callback: anytype,
-) !void {
-    // This implementation is ported from musl libc.
-    // A more idiomatic "ziggy" implementation would be welcome.
-    if (r.len < 12) return error.InvalidDnsPacket;
-    if ((r[3] & 15) != 0) return;
-    var p = r.ptr + 12;
-    var qdcount = r[4] * @as(usize, 256) + r[5];
-    var ancount = r[6] * @as(usize, 256) + r[7];
-    if (qdcount + ancount > 64) return error.InvalidDnsPacket;
-    while (qdcount != 0) {
-        qdcount -= 1;
-        while (@intFromPtr(p) - @intFromPtr(r.ptr) < r.len and p[0] -% 1 < 127) p += 1;
-        if (p[0] > 193 or (p[0] == 193 and p[1] > 254) or @intFromPtr(p) > @intFromPtr(r.ptr) + r.len - 6)
-            return error.InvalidDnsPacket;
-        p += @as(usize, 5) + @intFromBool(p[0] != 0);
-    }
-    while (ancount != 0) {
-        ancount -= 1;
-        while (@intFromPtr(p) - @intFromPtr(r.ptr) < r.len and p[0] -% 1 < 127) p += 1;
-        if (p[0] > 193 or (p[0] == 193 and p[1] > 254) or @intFromPtr(p) > @intFromPtr(r.ptr) + r.len - 6)
-            return error.InvalidDnsPacket;
-        p += @as(usize, 1) + @intFromBool(p[0] != 0);
-        const len = p[8] * @as(usize, 256) + p[9];
-        if (@intFromPtr(p) + len > @intFromPtr(r.ptr) + r.len) return error.InvalidDnsPacket;
-        try callback(ctx, p[1], p[10..][0..len], r);
-        p += 10 + len;
-    }
-}
-
-fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8) !void {
-    const gpa = ctx.gpa;
-    switch (rr) {
-        posix.RR.A => {
-            if (data.len != 4) return error.InvalidDnsARecord;
-            try ctx.addrs.append(gpa, .{
-                .addr = Address.initIp4(data[0..4].*, ctx.port),
-            });
-        },
-        posix.RR.AAAA => {
-            if (data.len != 16) return error.InvalidDnsAAAARecord;
-            try ctx.addrs.append(gpa, .{
-                .addr = Address.initIp6(data[0..16].*, ctx.port, 0, 0),
-            });
-        },
-        posix.RR.CNAME => {
-            var tmp: [256]u8 = undefined;
-            // Returns len of compressed name. strlen to get canon name.
-            _ = try posix.dn_expand(packet, data, &tmp);
-            const canon_name = mem.sliceTo(&tmp, 0);
-            if (isValidHostName(canon_name)) {
-                ctx.canon.items.len = 0;
-                try ctx.canon.appendSlice(gpa, canon_name);
-            }
-        },
-        else => return,
-    }
-}
-
-pub const Stream = struct {
-    /// Underlying platform-defined type which may or may not be
-    /// interchangeable with a file system file descriptor.
-    handle: Handle,
-
-    pub const Handle = switch (native_os) {
-        .windows => windows.ws2_32.SOCKET,
-        else => posix.fd_t,
-    };
-
-    pub fn close(s: Stream) void {
-        switch (native_os) {
-            .windows => windows.closesocket(s.handle) catch unreachable,
-            else => posix.close(s.handle),
-        }
-    }
-
-    pub const ReadError = posix.ReadError || error{
-        SocketNotBound,
-        MessageTooBig,
-        NetworkSubsystemFailed,
-        ConnectionResetByPeer,
-        SocketUnconnected,
-    };
-
-    pub const WriteError = posix.SendMsgError || error{
-        ConnectionResetByPeer,
-        SocketNotBound,
-        MessageTooBig,
-        NetworkSubsystemFailed,
-        SystemResources,
-        SocketUnconnected,
-        Unexpected,
-    };
-
-    pub const Reader = switch (native_os) {
-        .windows => struct {
-            /// Use `interface` for portable code.
-            interface_state: Io.Reader,
-            /// Use `getStream` for portable code.
-            net_stream: Stream,
-            /// Use `getError` for portable code.
-            error_state: ?Error,
-
-            pub const Error = ReadError;
-
-            pub fn getStream(r: *const Reader) Stream {
-                return r.net_stream;
-            }
-
-            pub fn getError(r: *const Reader) ?Error {
-                return r.error_state;
-            }
-
-            pub fn interface(r: *Reader) *Io.Reader {
-                return &r.interface_state;
-            }
-
-            pub fn init(net_stream: Stream, buffer: []u8) Reader {
-                return .{
-                    .interface_state = .{
-                        .vtable = &.{
-                            .stream = stream,
-                            .readVec = readVec,
-                        },
-                        .buffer = buffer,
-                        .seek = 0,
-                        .end = 0,
-                    },
-                    .net_stream = net_stream,
-                    .error_state = null,
-                };
-            }
-
-            fn stream(io_r: *Io.Reader, io_w: *Io.Writer, limit: Io.Limit) Io.Reader.StreamError!usize {
-                const dest = limit.slice(try io_w.writableSliceGreedy(1));
-                var bufs: [1][]u8 = .{dest};
-                const n = try readVec(io_r, &bufs);
-                io_w.advance(n);
-                return n;
-            }
-
-            fn readVec(io_r: *std.Io.Reader, data: [][]u8) Io.Reader.Error!usize {
-                const r: *Reader = @alignCast(@fieldParentPtr("interface_state", io_r));
-                var iovecs: [max_buffers_len]windows.ws2_32.WSABUF = undefined;
-                const bufs_n, const data_size = try io_r.writableVectorWsa(&iovecs, data);
-                const bufs = iovecs[0..bufs_n];
-                assert(bufs[0].len != 0);
-                const n = streamBufs(r, bufs) catch |err| {
-                    r.error_state = err;
-                    return error.ReadFailed;
-                };
-                if (n == 0) return error.EndOfStream;
-                if (n > data_size) {
-                    io_r.end += n - data_size;
-                    return data_size;
-                }
-                return n;
-            }
-
-            fn handleRecvError(winsock_error: windows.ws2_32.WinsockError) Error!void {
-                switch (winsock_error) {
-                    .WSAECONNRESET => return error.ConnectionResetByPeer,
-                    .WSAEFAULT => unreachable, // a pointer is not completely contained in user address space.
-                    .WSAEINPROGRESS, .WSAEINTR => unreachable, // deprecated and removed in WSA 2.2
-                    .WSAEINVAL => return error.SocketNotBound,
-                    .WSAEMSGSIZE => return error.MessageTooBig,
-                    .WSAENETDOWN => return error.NetworkSubsystemFailed,
-                    .WSAENETRESET => return error.ConnectionResetByPeer,
-                    .WSAENOTCONN => return error.SocketUnconnected,
-                    .WSAEWOULDBLOCK => return error.WouldBlock,
-                    .WSANOTINITIALISED => unreachable, // WSAStartup must be called before this function
-                    .WSA_IO_PENDING => unreachable,
-                    .WSA_OPERATION_ABORTED => unreachable, // not using overlapped I/O
-                    else => |err| return windows.unexpectedWSAError(err),
-                }
-            }
-
-            fn streamBufs(r: *Reader, bufs: []windows.ws2_32.WSABUF) Error!u32 {
-                var flags: u32 = 0;
-                var overlapped: windows.OVERLAPPED = std.mem.zeroes(windows.OVERLAPPED);
-
-                var n: u32 = undefined;
-                if (windows.ws2_32.WSARecv(
-                    r.net_stream.handle,
-                    bufs.ptr,
-                    @intCast(bufs.len),
-                    &n,
-                    &flags,
-                    &overlapped,
-                    null,
-                ) == windows.ws2_32.SOCKET_ERROR) switch (windows.ws2_32.WSAGetLastError()) {
-                    .WSA_IO_PENDING => {
-                        var result_flags: u32 = undefined;
-                        if (windows.ws2_32.WSAGetOverlappedResult(
-                            r.net_stream.handle,
-                            &overlapped,
-                            &n,
-                            windows.TRUE,
-                            &result_flags,
-                        ) == windows.FALSE) try handleRecvError(windows.ws2_32.WSAGetLastError());
-                    },
-                    else => |winsock_error| try handleRecvError(winsock_error),
-                };
-
-                return n;
-            }
-        },
-        else => struct {
-            /// Use `getStream`, `interface`, and `getError` for portable code.
-            file_reader: File.Reader,
-
-            pub const Error = ReadError;
-
-            pub fn interface(r: *Reader) *Io.Reader {
-                return &r.file_reader.interface;
-            }
-
-            pub fn init(net_stream: Stream, buffer: []u8) Reader {
-                return .{
-                    .file_reader = .{
-                        .interface = File.Reader.initInterface(buffer),
-                        .file = .{ .handle = net_stream.handle },
-                        .mode = .streaming,
-                        .seek_err = error.Unseekable,
-                        .size_err = error.Streaming,
-                    },
-                };
-            }
-
-            pub fn getStream(r: *const Reader) Stream {
-                return .{ .handle = r.file_reader.file.handle };
-            }
-
-            pub fn getError(r: *const Reader) ?Error {
-                return r.file_reader.err;
-            }
-        },
-    };
-
-    pub const Writer = switch (native_os) {
-        .windows => struct {
-            /// This field is present on all systems.
-            interface: Io.Writer,
-            /// Use `getStream` for cross-platform support.
-            stream: Stream,
-            /// This field is present on all systems.
-            err: ?Error = null,
-
-            pub const Error = WriteError;
-
-            pub fn init(stream: Stream, buffer: []u8) Writer {
-                return .{
-                    .stream = stream,
-                    .interface = .{
-                        .vtable = &.{ .drain = drain },
-                        .buffer = buffer,
-                    },
-                };
-            }
-
-            pub fn getStream(w: *const Writer) Stream {
-                return w.stream;
-            }
-
-            fn addWsaBuf(v: []windows.ws2_32.WSABUF, i: *u32, bytes: []const u8) void {
-                const cap = std.math.maxInt(u32);
-                var remaining = bytes;
-                while (remaining.len > cap) {
-                    if (v.len - i.* == 0) return;
-                    v[i.*] = .{ .buf = @constCast(remaining.ptr), .len = cap };
-                    i.* += 1;
-                    remaining = remaining[cap..];
-                } else {
-                    @branchHint(.likely);
-                    if (v.len - i.* == 0) return;
-                    v[i.*] = .{ .buf = @constCast(remaining.ptr), .len = @intCast(remaining.len) };
-                    i.* += 1;
-                }
-            }
-
-            fn drain(io_w: *Io.Writer, data: []const []const u8, splat: usize) Io.Writer.Error!usize {
-                const w: *Writer = @alignCast(@fieldParentPtr("interface", io_w));
-                const buffered = io_w.buffered();
-                comptime assert(native_os == .windows);
-                var iovecs: [max_buffers_len]windows.ws2_32.WSABUF = undefined;
-                var len: u32 = 0;
-                addWsaBuf(&iovecs, &len, buffered);
-                for (data[0 .. data.len - 1]) |bytes| addWsaBuf(&iovecs, &len, bytes);
-                const pattern = data[data.len - 1];
-                if (iovecs.len - len != 0) switch (splat) {
-                    0 => {},
-                    1 => addWsaBuf(&iovecs, &len, pattern),
-                    else => switch (pattern.len) {
-                        0 => {},
-                        1 => {
-                            const splat_buffer_candidate = io_w.buffer[io_w.end..];
-                            var backup_buffer: [64]u8 = undefined;
-                            const splat_buffer = if (splat_buffer_candidate.len >= backup_buffer.len)
-                                splat_buffer_candidate
-                            else
-                                &backup_buffer;
-                            const memset_len = @min(splat_buffer.len, splat);
-                            const buf = splat_buffer[0..memset_len];
-                            @memset(buf, pattern[0]);
-                            addWsaBuf(&iovecs, &len, buf);
-                            var remaining_splat = splat - buf.len;
-                            while (remaining_splat > splat_buffer.len and len < iovecs.len) {
-                                addWsaBuf(&iovecs, &len, splat_buffer);
-                                remaining_splat -= splat_buffer.len;
-                            }
-                            addWsaBuf(&iovecs, &len, splat_buffer[0..remaining_splat]);
-                        },
-                        else => for (0..@min(splat, iovecs.len - len)) |_| {
-                            addWsaBuf(&iovecs, &len, pattern);
-                        },
-                    },
-                };
-                const n = sendBufs(w.stream.handle, iovecs[0..len]) catch |err| {
-                    w.err = err;
-                    return error.WriteFailed;
-                };
-                return io_w.consume(n);
-            }
-
-            fn handleSendError(winsock_error: windows.ws2_32.WinsockError) Error!void {
-                switch (winsock_error) {
-                    .WSAECONNABORTED => return error.ConnectionResetByPeer,
-                    .WSAECONNRESET => return error.ConnectionResetByPeer,
-                    .WSAEFAULT => unreachable, // a pointer is not completely contained in user address space.
-                    .WSAEINPROGRESS, .WSAEINTR => unreachable, // deprecated and removed in WSA 2.2
-                    .WSAEINVAL => return error.SocketNotBound,
-                    .WSAEMSGSIZE => return error.MessageTooBig,
-                    .WSAENETDOWN => return error.NetworkSubsystemFailed,
-                    .WSAENETRESET => return error.ConnectionResetByPeer,
-                    .WSAENOBUFS => return error.SystemResources,
-                    .WSAENOTCONN => return error.SocketUnconnected,
-                    .WSAENOTSOCK => unreachable, // not a socket
-                    .WSAEOPNOTSUPP => unreachable, // only for message-oriented sockets
-                    .WSAESHUTDOWN => unreachable, // cannot send on a socket after write shutdown
-                    .WSAEWOULDBLOCK => return error.WouldBlock,
-                    .WSANOTINITIALISED => unreachable, // WSAStartup must be called before this function
-                    .WSA_IO_PENDING => unreachable,
-                    .WSA_OPERATION_ABORTED => unreachable, // not using overlapped I/O
-                    else => |err| return windows.unexpectedWSAError(err),
-                }
-            }
-
-            fn sendBufs(handle: Stream.Handle, bufs: []windows.ws2_32.WSABUF) Error!u32 {
-                var n: u32 = undefined;
-                var overlapped: windows.OVERLAPPED = std.mem.zeroes(windows.OVERLAPPED);
-                if (windows.ws2_32.WSASend(
-                    handle,
-                    bufs.ptr,
-                    @intCast(bufs.len),
-                    &n,
-                    0,
-                    &overlapped,
-                    null,
-                ) == windows.ws2_32.SOCKET_ERROR) switch (windows.ws2_32.WSAGetLastError()) {
-                    .WSA_IO_PENDING => {
-                        var result_flags: u32 = undefined;
-                        if (windows.ws2_32.WSAGetOverlappedResult(
-                            handle,
-                            &overlapped,
-                            &n,
-                            windows.TRUE,
-                            &result_flags,
-                        ) == windows.FALSE) try handleSendError(windows.ws2_32.WSAGetLastError());
-                    },
-                    else => |winsock_error| try handleSendError(winsock_error),
-                };
-
-                return n;
-            }
-        },
-        else => struct {
-            /// This field is present on all systems.
-            interface: Io.Writer,
-
-            err: ?Error = null,
-            file_writer: File.Writer,
-
-            pub const Error = WriteError;
-
-            pub fn init(stream: Stream, buffer: []u8) Writer {
-                return .{
-                    .interface = .{
-                        .vtable = &.{
-                            .drain = drain,
-                            .sendFile = sendFile,
-                        },
-                        .buffer = buffer,
-                    },
-                    .file_writer = .initStreaming(.{ .handle = stream.handle }, &.{}),
-                };
-            }
-
-            pub fn getStream(w: *const Writer) Stream {
-                return .{ .handle = w.file_writer.file.handle };
-            }
-
-            fn addBuf(v: []posix.iovec_const, i: *@FieldType(posix.msghdr_const, "iovlen"), bytes: []const u8) void {
-                // OS checks ptr addr before length so zero length vectors must be omitted.
-                if (bytes.len == 0) return;
-                if (v.len - i.* == 0) return;
-                v[i.*] = .{ .base = bytes.ptr, .len = bytes.len };
-                i.* += 1;
-            }
-
-            fn drain(io_w: *Io.Writer, data: []const []const u8, splat: usize) Io.Writer.Error!usize {
-                const w: *Writer = @alignCast(@fieldParentPtr("interface", io_w));
-                const buffered = io_w.buffered();
-                var iovecs: [max_buffers_len]posix.iovec_const = undefined;
-                var msg: posix.msghdr_const = .{
-                    .name = null,
-                    .namelen = 0,
-                    .iov = &iovecs,
-                    .iovlen = 0,
-                    .control = null,
-                    .controllen = 0,
-                    .flags = 0,
-                };
-                addBuf(&iovecs, &msg.iovlen, buffered);
-                for (data[0 .. data.len - 1]) |bytes| addBuf(&iovecs, &msg.iovlen, bytes);
-                const pattern = data[data.len - 1];
-                if (iovecs.len - msg.iovlen != 0) switch (splat) {
-                    0 => {},
-                    1 => addBuf(&iovecs, &msg.iovlen, pattern),
-                    else => switch (pattern.len) {
-                        0 => {},
-                        1 => {
-                            const splat_buffer_candidate = io_w.buffer[io_w.end..];
-                            var backup_buffer: [64]u8 = undefined;
-                            const splat_buffer = if (splat_buffer_candidate.len >= backup_buffer.len)
-                                splat_buffer_candidate
-                            else
-                                &backup_buffer;
-                            const memset_len = @min(splat_buffer.len, splat);
-                            const buf = splat_buffer[0..memset_len];
-                            @memset(buf, pattern[0]);
-                            addBuf(&iovecs, &msg.iovlen, buf);
-                            var remaining_splat = splat - buf.len;
-                            while (remaining_splat > splat_buffer.len and iovecs.len - msg.iovlen != 0) {
-                                assert(buf.len == splat_buffer.len);
-                                addBuf(&iovecs, &msg.iovlen, splat_buffer);
-                                remaining_splat -= splat_buffer.len;
-                            }
-                            addBuf(&iovecs, &msg.iovlen, splat_buffer[0..remaining_splat]);
-                        },
-                        else => for (0..@min(splat, iovecs.len - msg.iovlen)) |_| {
-                            addBuf(&iovecs, &msg.iovlen, pattern);
-                        },
-                    },
-                };
-                const flags = posix.MSG.NOSIGNAL;
-                return io_w.consume(posix.sendmsg(w.file_writer.file.handle, &msg, flags) catch |err| {
-                    w.err = err;
-                    return error.WriteFailed;
-                });
-            }
-
-            fn sendFile(io_w: *Io.Writer, file_reader: *File.Reader, limit: Io.Limit) Io.Writer.FileError!usize {
-                const w: *Writer = @alignCast(@fieldParentPtr("interface", io_w));
-                const n = try w.file_writer.interface.sendFileHeader(io_w.buffered(), file_reader, limit);
-                return io_w.consume(n);
-            }
-        },
-    };
-
-    pub fn reader(stream: Stream, buffer: []u8) Reader {
-        return .init(stream, buffer);
-    }
-
-    pub fn writer(stream: Stream, buffer: []u8) Writer {
-        return .init(stream, buffer);
-    }
-
-    const max_buffers_len = 8;
-
-    /// Deprecated in favor of `Reader`.
-    pub fn read(self: Stream, buffer: []u8) ReadError!usize {
-        if (native_os == .windows) {
-            return windows.ReadFile(self.handle, buffer, null);
-        }
-
-        return posix.read(self.handle, buffer);
-    }
-
-    /// Deprecated in favor of `Reader`.
-    pub fn readv(s: Stream, iovecs: []const posix.iovec) ReadError!usize {
-        if (native_os == .windows) {
-            if (iovecs.len == 0) return 0;
-            const first = iovecs[0];
-            return windows.ReadFile(s.handle, first.base[0..first.len], null);
-        }
-
-        return posix.readv(s.handle, iovecs);
-    }
-
-    /// Deprecated in favor of `Reader`.
-    pub fn readAtLeast(s: Stream, buffer: []u8, len: usize) ReadError!usize {
-        assert(len <= buffer.len);
-        var index: usize = 0;
-        while (index < len) {
-            const amt = try s.read(buffer[index..]);
-            if (amt == 0) break;
-            index += amt;
-        }
-        return index;
-    }
-
-    /// Deprecated in favor of `Writer`.
-    pub fn write(self: Stream, buffer: []const u8) WriteError!usize {
-        var stream_writer = self.writer(&.{});
-        return stream_writer.interface.writeVec(&.{buffer}) catch return stream_writer.err.?;
-    }
-
-    /// Deprecated in favor of `Writer`.
-    pub fn writeAll(self: Stream, bytes: []const u8) WriteError!void {
-        var index: usize = 0;
-        while (index < bytes.len) {
-            index += try self.write(bytes[index..]);
-        }
-    }
-
-    /// Deprecated in favor of `Writer`.
-    pub fn writev(self: Stream, iovecs: []const posix.iovec_const) WriteError!usize {
-        return @errorCast(posix.writev(self.handle, iovecs));
-    }
-
-    /// Deprecated in favor of `Writer`.
-    pub fn writevAll(self: Stream, iovecs: []posix.iovec_const) WriteError!void {
-        if (iovecs.len == 0) return;
-
-        var i: usize = 0;
-        while (true) {
-            var amt = try self.writev(iovecs[i..]);
-            while (amt >= iovecs[i].len) {
-                amt -= iovecs[i].len;
-                i += 1;
-                if (i >= iovecs.len) return;
-            }
-            iovecs[i].base += amt;
-            iovecs[i].len -= amt;
-        }
-    }
-};
-
-/// A bound, listening TCP socket, ready to accept new connections.
-pub const Server = struct {
-    listen_address: Address,
-    stream: Stream,
-
-    pub const Connection = struct {
-        stream: Stream,
-        address: Address,
-    };
-
-    pub fn deinit(s: *Server) void {
-        s.stream.close();
-        s.* = undefined;
-    }
-
-    pub const AcceptError = posix.AcceptError;
-
-    /// Blocks until a client connects to the server. The returned `Connection` has
-    /// an open stream.
-    pub fn accept(s: *Server) AcceptError!Connection {
-        var accepted_addr: Address = undefined;
-        var addr_len: posix.socklen_t = @sizeOf(Address);
-        const fd = try posix.accept(s.stream.handle, &accepted_addr.any, &addr_len, posix.SOCK.CLOEXEC);
-        return .{
-            .stream = .{ .handle = fd },
-            .address = accepted_addr,
-        };
-    }
-};
-
-test {
-    if (builtin.os.tag != .wasi) {
-        _ = Server;
-        _ = Stream;
-        _ = Address;
-        _ = @import("net/test.zig");
-    }
-}
lib/std/Progress.zig
@@ -523,9 +523,7 @@ pub fn setStatus(new_status: Status) void {
 
 /// Returns whether a resize is needed to learn the terminal size.
 fn wait(timeout_ns: u64) bool {
-    const resize_flag = if (global_progress.redraw_event.timedWait(timeout_ns)) |_|
-        true
-    else |err| switch (err) {
+    const resize_flag = if (global_progress.redraw_event.timedWait(timeout_ns)) |_| true else |err| switch (err) {
         error.Timeout => false,
     };
     global_progress.redraw_event.reset();
lib/std/std.zig
@@ -85,7 +85,6 @@ pub const macho = @import("macho.zig");
 pub const math = @import("math.zig");
 pub const mem = @import("mem.zig");
 pub const meta = @import("meta.zig");
-pub const net = @import("net.zig");
 pub const os = @import("os.zig");
 pub const once = @import("once.zig").once;
 pub const pdb = @import("pdb.zig");
lib/std/Thread.zig
@@ -71,7 +71,7 @@ pub const ResetEvent = enum(u32) {
     ///
     /// The memory accesses before the set() can be said to happen before
     /// timedWait() returns without error.
-    pub fn timedWait(re: *ResetEvent, timeout_ns: u64) void {
+    pub fn timedWait(re: *ResetEvent, timeout_ns: u64) error{Timeout}!void {
         if (builtin.single_threaded) switch (re.*) {
             .unset => {
                 sleep(timeout_ns);
@@ -1774,9 +1774,9 @@ test "setName, getName" {
     if (builtin.single_threaded) return error.SkipZigTest;
 
     const Context = struct {
-        start_wait_event: ResetEvent = .{},
-        test_done_event: ResetEvent = .{},
-        thread_done_event: ResetEvent = .{},
+        start_wait_event: ResetEvent = .unset,
+        test_done_event: ResetEvent = .unset,
+        thread_done_event: ResetEvent = .unset,
 
         done: std.atomic.Value(bool) = std.atomic.Value(bool).init(false),
         thread: Thread = undefined,
@@ -1843,7 +1843,7 @@ test join {
     if (builtin.single_threaded) return error.SkipZigTest;
 
     var value: usize = 0;
-    var event = ResetEvent{};
+    var event: ResetEvent = .unset;
 
     const thread = try Thread.spawn(.{}, testIncrementNotify, .{ &value, &event });
     thread.join();
@@ -1855,7 +1855,7 @@ test detach {
     if (builtin.single_threaded) return error.SkipZigTest;
 
     var value: usize = 0;
-    var event = ResetEvent{};
+    var event: ResetEvent = .unset;
 
     const thread = try Thread.spawn(.{}, testIncrementNotify, .{ &value, &event });
     thread.detach();
@@ -1902,8 +1902,7 @@ fn testTls() !void {
 }
 
 test "ResetEvent smoke test" {
-    // make sure the event is unset
-    var event = ResetEvent{};
+    var event: ResetEvent = .unset;
     try testing.expectEqual(false, event.isSet());
 
     // make sure the event gets set
@@ -1932,8 +1931,8 @@ test "ResetEvent signaling" {
     }
 
     const Context = struct {
-        in: ResetEvent = .{},
-        out: ResetEvent = .{},
+        in: ResetEvent = .unset,
+        out: ResetEvent = .unset,
         value: usize = 0,
 
         fn input(self: *@This()) !void {
@@ -1994,7 +1993,7 @@ test "ResetEvent broadcast" {
 
     const num_threads = 10;
     const Barrier = struct {
-        event: ResetEvent = .{},
+        event: ResetEvent = .unset,
         counter: std.atomic.Value(usize) = std.atomic.Value(usize).init(num_threads),
 
         fn wait(self: *@This()) void {