Repository: apple/swift-nio
File: Sources/NIOPosix/HappyEyeballs.swift (Swift)

Code before:

    fileprivate init(host: String, port: Int) {
        self.host = host
        self.port = port
    }
}

extension NIOConnectionError: CustomStringConvertible {
    public var description: String {
        if let dnsError = (dnsAError ?? dnsAAAAError) {
             return "DNS error: \(dnsError.localizedDescription)"
         }

         if !connectionErrors.isEmpty {
             let descriptions = connectionErrors.map {
                 if let channelError = $0.error as? ChannelError {
                     channelError.description
                 } else {
                     $0.error.localizedDescription
                 }
             }

             return "Connection errors: \(descriptions.joined(separator: ", "))"
         }

         return "Unknown error"
     }
}

/// A simple iterator that manages iterating over the possible targets.
///
/// This iterator knows how to merge together the A and AAAA records in a sensible way:
/// specifically, it keeps track of what the last address family it emitted was, and emits the
/// address of the opposite family next.
private struct TargetIterator: IteratorProtocol {
    typealias Element = SocketAddress

    private enum AddressFamily {
        case v4
        case v6
    }

    private var previousAddressFamily: AddressFamily = .v4
    private var aQueryResults: [SocketAddress] = []
    private var aaaaQueryResults: [SocketAddress] = []

    mutating func aResultsAvailable(_ results: [SocketAddress]) {
        aQueryResults.append(contentsOf: results)
    }

    mutating func aaaaResultsAvailable(_ results: [SocketAddress]) {

Review comment (suggestion):
I think this can still hint that it's a connection error: e.g. `"NIOConnectionError: unknown"`

Code after:

    fileprivate init(host: String, port: Int) {
        self.host = host
        self.port = port
    }
}

extension NIOConnectionError: CustomStringConvertible {
    public var description: String {
        if let dnsError = (self.dnsAError ?? self.dnsAAAAError) {
            return "DNS error: \(dnsError)"
        }

        if !self.connectionErrors.isEmpty {
            let descriptions = self.connectionErrors.map {
                String(describing: $0)
            }

            return "Connection errors: \(descriptions.joined(separator: ", "))"
        }

        return "NIOConnectionError: unknown"
    }
}

/// A simple iterator that manages iterating over the possible targets.
///
/// This iterator knows how to merge together the A and AAAA records in a sensible way:
/// specifically, it keeps track of what the last address family it emitted was, and emits the
/// address of the opposite family next.
private struct TargetIterator: IteratorProtocol {
    typealias Element = SocketAddress

    private enum AddressFamily {
        case v4
        case v6
    }

    private var previousAddressFamily: AddressFamily = .v4
    private var aQueryResults: [SocketAddress] = []
    private var aaaaQueryResults: [SocketAddress] = []

    mutating func aResultsAvailable(_ results: [SocketAddress]) {
        aQueryResults.append(contentsOf: results)
    }

    mutating func aaaaResultsAvailable(_ results: [SocketAddress]) {
        aaaaQueryResults.append(contentsOf: results)
    }

    mutating func next() -> Element? {