Repository: apple/swift-nio
File: Sources/NIOCore/ChannelHandler.swift (Swift)

Code before:
    /// Intializes a new ``NIOProtocolNegotiationResult`` with a final result.
    ///
    /// - Parameter result: The final result of protocol negotiation.
    public init(result: NegotiationResult) {
        self._result = .finished(result)
    }

    /// Intializes a new ``NIOProtocolNegotiationResult`` with a deferred result.
    ///
    /// - Parameter deferredResult: The deferred result.
    public init(deferredResult: EventLoopFuture<NIOProtocolNegotiationResult<NegotiationResult>>) {
        self._result = .deferredResult(deferredResult)
    }
}

extension EventLoopFuture {
    /// Get the result/error from the protocol negotiation.
    @available(macOS 10.15, *)
    @_spi(AsyncChannel)
    public func getResult<NegotiationResult: Sendable>() async throws -> NegotiationResult where Value == NIOProtocolNegotiationResult<NegotiationResult> {
        try await self.get().result
    }
}

@_spi(AsyncChannel)
extension NIOProtocolNegotiationResult.Result {
    fileprivate func resolve(on eventLoop: EventLoop) -> EventLoopFuture<NegotiationResult> {
        Self.resolve(on: eventLoop, result: self)
    }

    fileprivate static func resolve(on eventLoop: EventLoop, result: Self) -> EventLoopFuture<NegotiationResult> {
        switch result {
        case .finished(let negotiationResult):
            return eventLoop.makeSucceededFuture(negotiationResult)

        case .deferredResult(let future):
            return future.flatMap { result in
                return resolve(on: eventLoop, result: result._result)
            }
        }
    }
}

@_spi(AsyncChannel)
extension NIOProtocolNegotiationResult: Equatable where NegotiationResult: Equatable {}

@_spi(AsyncChannel)
extension NIOProtocolNegotiationResult: Sendable where NegotiationResult: Sendable {}

@_spi(AsyncChannel)
extension NIOProtocolNegotiationResult.Result: Equatable where NegotiationResult: Equatable {}

Review comment (suggestion):
Why not also make this:

```swift
public var result: NegotiationResult {
    get async throws { ... }
}
```

Code after:
    /// Intializes a new ``NIOProtocolNegotiationResult`` with a final result.
    ///
    /// - Parameter result: The final result of protocol negotiation.
    public init(result: NegotiationResult) {
        self._result = .finished(result)
    }

    /// Intializes a new ``NIOProtocolNegotiationResult`` with a deferred result.
    ///
    /// - Parameter deferredResult: The deferred result.
    public init(deferredResult: EventLoopFuture<NIOProtocolNegotiationResult<NegotiationResult>>) {
        self._result = .deferredResult(deferredResult)
    }

    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
    @available(*, deprecated, renamed: "getResult")
    public func waitForFinalResult() async throws -> NegotiationResult {
        try await self.result
    }
}

extension EventLoopFuture {
    /// Get the result/error from the protocol negotiation.
    @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
    @_spi(AsyncChannel)
    public func getResult<NegotiationResult: Sendable>() async throws -> NegotiationResult where Value == NIOProtocolNegotiationResult<NegotiationResult> {
        try await self.get().result
    }
}

@_spi(AsyncChannel)
extension NIOProtocolNegotiationResult.Result {
    fileprivate func resolve(on eventLoop: EventLoop) -> EventLoopFuture<NegotiationResult> {
        Self.resolve(on: eventLoop, result: self)
    }

    fileprivate static func resolve(on eventLoop: EventLoop, result: Self) -> EventLoopFuture<NegotiationResult> {
        switch result {
        case .finished(let negotiationResult):
            return eventLoop.makeSucceededFuture(negotiationResult)

        case .deferredResult(let future):
            return future.flatMap { result in
                return resolve(on: eventLoop, result: result._result)
            }
        }
    }
}

@_spi(AsyncChannel)
extension NIOProtocolNegotiationResult: Equatable where NegotiationResult: Equatable {}