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

Code before:
@available(*, unavailable)
extension ChannelPipeline.SynchronousOperations: Sendable {}

extension ChannelPipeline {
    /// A `Position` within the `ChannelPipeline` used to insert handlers into the `ChannelPipeline`.
    @preconcurrency
    public enum Position: Sendable {
        /// The first `ChannelHandler` -- the front of the `ChannelPipeline`.
        case first

        /// The last `ChannelHandler` -- the back of the `ChannelPipeline`.
        case last

        /// Before the given `ChannelHandler`.
        case before(ChannelHandler & Sendable)

        /// After the given `ChannelHandler`.
        case after(ChannelHandler & Sendable)
    }
}

extension ChannelPipeline.SynchronousOperations {
    /// A `Position` within the `ChannelPipeline`'s `SynchronousOperations` used to insert non-sendable handlers
    /// into the `ChannelPipeline` at a certain position.
    public enum Position {
        /// The first `ChannelHandler` -- the front of the `ChannelPipeline`.
        case first

        /// The last `ChannelHandler` -- the back of the `ChannelPipeline`.
        case last

        /// Before the given `ChannelHandler`.
        case before(ChannelHandler)

        /// After the given `ChannelHandler`.
        case after(ChannelHandler)

        public init(_ position: ChannelPipeline.Position) {
            switch position {
            case .first:
                self = .first
            case .last:
                self = .last
            case .before(let handler):
                self = .before(handler)
            case .after(let handler):
                self = .after(handler)
            }
        }
    }
}

Review comment (suggestion):
Note: this is here because you can only runtime-check against protocols with primary associated types starting from these versions.

Given the change of direction this API has taken, we might end up removing the associated type and just end up with this API taking a closure that works on an `Any`, in which case we could provide a different implementation without this platform requirement.

Code after:
        ///     // This closure is called.
        ///     return
        /// }
        ///
        /// try channel.pipeline.syncOperations.withUnsafeTransportIfAvailable {
        ///     // This closure is NOT called.
        ///     return
        /// }
        ///
        /// try channel.pipeline.syncOperations.withUnsafeTransportIfAvailable { (_: Any.self) in
        ///     // This closure is NOT called.
        ///     return
        /// }
        ///
        /// try channel.pipeline.syncOperations.withUnsafeTransportIfAvailable(of: Any.self) { _ in
        ///     // This closure is NOT called.
        ///     return
        /// }
        /// ```
        ///
        /// - Parameters:
        ///   - type: The expected transport type the channel makes available.
        ///   - body: /// A closure that takes the underlying transport, if the channel supports this operation.
        /// - Returns: The value returned by the closure, or `nil` if the channel does not expose its transport.
        /// - Throws: If there was an error accessing the underlying transport, or an error was thrown by the closure.
        @available(macOS 13, iOS 16, tvOS 16, watchOS 9, *)
        @inlinable
        public func withUnsafeTransportIfAvailable<Transport, Result>(
            of type: Transport.Type = Transport.self,
            _ body: (_ transport: Transport) throws -> Result
        ) throws -> Result? {
            self.eventLoop.assertInEventLoop()
            guard let core = self._pipeline.channel._channelCore as? any NIOTransportAccessibleChannelCore<Transport>
            else {
                return nil
            }
            return try core.withUnsafeTransport(body)
        }
    }

    /// Returns a view of operations which can be performed synchronously on this pipeline. All
    /// operations **must** be called on the event loop.
    public var syncOperations: SynchronousOperations {
        SynchronousOperations(pipeline: self)
    }
}

@available(*, unavailable)
extension ChannelPipeline.SynchronousOperations: Sendable {}

extension ChannelPipeline {