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

Code before:
///
/// A `Channel` owns its `ChannelPipeline` which handles all I/O events and requests associated with the `Channel`.
public protocol Channel: AnyObject, ChannelOutboundInvoker, _NIOPreconcurrencySendable {
    /// The `Channel`'s `ByteBuffer` allocator. This is _the only_ supported way of allocating `ByteBuffer`s to be used with this `Channel`.
    var allocator: ByteBufferAllocator { get }

    /// The `closeFuture` will fire when the `Channel` has been closed.
    ///
    /// - Important: This future should never be failed: it signals when the channel has been closed, and this action should not fail,
    ///              regardless of whether the close happenned cleanly or not.
    ///              If you are interested in any errors thrown during `close` to diagnose any unclean channel closures, you
    ///              should instead use the future returned from ``ChannelOutboundInvoker/close(mode:file:line:)-7hlgf``
    ///              or pass a promise via ``ChannelOutboundInvoker/close(mode:promise:)``.
    var closeFuture: EventLoopFuture<Void> { get }

    /// The `ChannelPipeline` which handles all I/O events and requests associated with this `Channel`.
    var pipeline: ChannelPipeline { get }

    /// The local `SocketAddress`.
    var localAddress: SocketAddress? { get }

    /// The remote peer's `SocketAddress`.
    ///
    /// If we end up accepting an already-closed connection, the kernel can end up in a place
    /// where it has no remote address to give us. In this situation, `remoteAddress` will be
    /// `nil`.
    var remoteAddress: SocketAddress? { get }

    /// `Channel`s are hierarchical and might have a parent `Channel`. `Channel` hierarchies are in use for certain
    /// protocols such as HTTP/2.
    var parent: Channel? { get }

    /// Set `option` to `value` on this `Channel`.
    func setOption<Option: ChannelOption>(_ option: Option, value: Option.Value) -> EventLoopFuture<Void>

    /// Get the value of `option` for this `Channel`.
    func getOption<Option: ChannelOption>(_ option: Option) -> EventLoopFuture<Option.Value>

    /// Returns if this `Channel` is currently writable.
    var isWritable: Bool { get }

    /// Returns if this `Channel` is currently active. Active is defined as the period of time after the
    /// `channelActive` and before `channelInactive` has fired. The main use for this is to know if `channelActive`
    /// or `channelInactive` can be expected next when `handlerAdded` was received.
    var isActive: Bool { get }

    /// Reach out to the `_ChannelCore`.
    ///
    /// - warning: Unsafe, this is for use in NIO's core only.
    var _channelCore: ChannelCore { get }


Review comment (suggestion):
The remote address can also be `nil` in cases where it isn't representable in `SocketAddress`, e.g. if we're talking over a vsock.

Code after:
///
/// A `Channel` owns its `ChannelPipeline` which handles all I/O events and requests associated with the `Channel`.
public protocol Channel: AnyObject, ChannelOutboundInvoker, _NIOPreconcurrencySendable {
    /// The `Channel`'s `ByteBuffer` allocator. This is _the only_ supported way of allocating `ByteBuffer`s to be used with this `Channel`.
    var allocator: ByteBufferAllocator { get }

    /// The `closeFuture` will fire when the `Channel` has been closed.
    ///
    /// - Important: This future should never be failed: it signals when the channel has been closed, and this action should not fail,
    ///              regardless of whether the close happenned cleanly or not.
    ///              If you are interested in any errors thrown during `close` to diagnose any unclean channel closures, you
    ///              should instead use the future returned from ``ChannelOutboundInvoker/close(mode:file:line:)-7hlgf``
    ///              or pass a promise via ``ChannelOutboundInvoker/close(mode:promise:)``.
    var closeFuture: EventLoopFuture<Void> { get }

    /// The `ChannelPipeline` which handles all I/O events and requests associated with this `Channel`.
    var pipeline: ChannelPipeline { get }

    /// The local `SocketAddress`.
    var localAddress: SocketAddress? { get }

    /// The remote peer's `SocketAddress`.
    ///
    /// If we end up accepting an already-closed connection, the kernel can end up in a place
    /// where it has no remote address to give us. In this situation, `remoteAddress` will be
    /// `nil`. It can also be `nil` in cases where it isn't representable in SocketAddress, e.g. if
    /// we're talking over a vsock.
    var remoteAddress: SocketAddress? { get }

    /// `Channel`s are hierarchical and might have a parent `Channel`. `Channel` hierarchies are in use for certain
    /// protocols such as HTTP/2.
    var parent: Channel? { get }

    /// Set `option` to `value` on this `Channel`.
    func setOption<Option: ChannelOption>(_ option: Option, value: Option.Value) -> EventLoopFuture<Void>

    /// Get the value of `option` for this `Channel`.
    func getOption<Option: ChannelOption>(_ option: Option) -> EventLoopFuture<Option.Value>

    /// Returns if this `Channel` is currently writable.
    var isWritable: Bool { get }

    /// Returns if this `Channel` is currently active. Active is defined as the period of time after the
    /// `channelActive` and before `channelInactive` has fired. The main use for this is to know if `channelActive`
    /// or `channelInactive` can be expected next when `handlerAdded` was received.
    var isActive: Bool { get }

    /// Reach out to the `_ChannelCore`.
    ///
    /// - warning: Unsafe, this is for use in NIO's core only.
    var _channelCore: ChannelCore { get }