Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make ChannelOptions Equatable #598

Closed
weissi opened this issue Aug 28, 2018 · 0 comments · Fixed by #823
Closed

make ChannelOptions Equatable #598

weissi opened this issue Aug 28, 2018 · 0 comments · Fixed by #823
Labels
kind/bug Feature doesn't work as expected.
Milestone

Comments

@weissi
Copy link
Member

weissi commented Aug 28, 2018

ChannelOptions should be equatable, we should do this for 1.10.0. This patch should do it

diff --git a/Sources/NIO/Bootstrap.swift b/Sources/NIO/Bootstrap.swift
index 43eefac..4adef67 100644
--- a/Sources/NIO/Bootstrap.swift
+++ b/Sources/NIO/Bootstrap.swift
@@ -119,21 +119,45 @@ public final class ServerBootstrap {
     /// - parameters:
     ///     - option: The option to be applied.
     ///     - value: The value for the option.
+    @available(*, deprecated, message: "non-Equatable ChannelOptions are deprecated")
     public func serverChannelOption<T: ChannelOption>(_ option: T, value: T.OptionType) -> Self {
         serverChannelOptions.put(key: option, value: value)
         return self
     }
 
+    /// Specifies a `ChannelOption` to be applied to the `ServerSocketChannel`.
+    ///
+    /// - note: To specify options for the accepted `SocketChannel`s, look at `ServerBootstrap.childChannelOption`.
+    ///
+    /// - parameters:
+    ///     - option: The option to be applied.
+    ///     - value: The value for the option.
+    public func serverChannelOption<T: ChannelOption & Equatable>(_ option: T, value: T.OptionType) -> Self {
+        serverChannelOptions.put(key: option, value: value)
+        return self
+    }
+
     /// Specifies a `ChannelOption` to be applied to the accepted `SocketChannel`s.
     ///
     /// - parameters:
     ///     - option: The option to be applied.
     ///     - value: The value for the option.
+    @available(*, deprecated, message: "non-Equatable ChannelOptions are deprecated")
     public func childChannelOption<T: ChannelOption>(_ option: T, value: T.OptionType) -> Self {
         childChannelOptions.put(key: option, value: value)
         return self
     }
 
+    /// Specifies a `ChannelOption` to be applied to the accepted `SocketChannel`s.
+    ///
+    /// - parameters:
+    ///     - option: The option to be applied.
+    ///     - value: The value for the option.
+    public func childChannelOption<T: ChannelOption & Equatable>(_ option: T, value: T.OptionType) -> Self {
+        childChannelOptions.put(key: option, value: value)
+        return self
+    }
+
     /// Bind the `ServerSocketChannel` to `host` and `port`.
     ///
     /// - parameters:
@@ -385,11 +409,22 @@ public final class ClientBootstrap {
     /// - parameters:
     ///     - option: The option to be applied.
     ///     - value: The value for the option.
+    @available(*, deprecated, message: "non-Equatable ChannelOptions are deprecated")
     public func channelOption<T: ChannelOption>(_ option: T, value: T.OptionType) -> Self {
         channelOptions.put(key: option, value: value)
         return self
     }
 
+    /// Specifies a `ChannelOption` to be applied to the `SocketChannel`.
+    ///
+    /// - parameters:
+    ///     - option: The option to be applied.
+    ///     - value: The value for the option.
+    public func channelOption<T: ChannelOption & Equatable>(_ option: T, value: T.OptionType) -> Self {
+        channelOptions.put(key: option, value: value)
+        return self
+    }
+
     /// Specifies a timeout to apply to a connection attempt.
     //
     /// - parameters:
@@ -581,11 +616,22 @@ public final class DatagramBootstrap {
     /// - parameters:
     ///     - option: The option to be applied.
     ///     - value: The value for the option.
+    @available(*, deprecated, message: "non-Equatable ChannelOptions are deprecated")
     public func channelOption<T: ChannelOption>(_ option: T, value: T.OptionType) -> Self {
         channelOptions.put(key: option, value: value)
         return self
     }
 
+    /// Specifies a `ChannelOption` to be applied to the `DatagramChannel`.
+    ///
+    /// - parameters:
+    ///     - option: The option to be applied.
+    ///     - value: The value for the option.
+    public func channelOption<T: ChannelOption & Equatable>(_ option: T, value: T.OptionType) -> Self {
+        channelOptions.put(key: option, value: value)
+        return self
+    }
+
     /// Use the existing bound socket file descriptor.
     ///
     /// - parameters:
diff --git a/Sources/NIO/ChannelOption.swift b/Sources/NIO/ChannelOption.swift
index 1b6bdc5..64b98b3 100644
--- a/Sources/NIO/ChannelOption.swift
+++ b/Sources/NIO/ChannelOption.swift
@@ -48,7 +48,7 @@ public typealias SocketOptionName = Int32
 /// `SocketOption` allows to specify configuration settings that are directly applied to the underlying socket file descriptor.
 ///
 /// Valid options are typically found in the various man pages like `man 4 tcp`.
-public enum SocketOption: ChannelOption {
+public enum SocketOption: ChannelOption, Equatable {
     public typealias AssociatedValueType = (SocketOptionLevel, SocketOptionName)
 
     public typealias OptionType = (SocketOptionValue)
@@ -70,58 +70,107 @@ public enum SocketOption: ChannelOption {
             return (level, name)
         }
     }
+
+    public static func == (lhs: SocketOption, rhs: SocketOption) -> Bool {
+        switch (lhs, rhs) {
+        case (.const(let lLevel, let lName), .const(let rLevel, let rName)):
+            return lLevel == rLevel && lName == rName
+        }
+    }
 }
 
 /// `AllocatorOption` allows to specify the `ByteBufferAllocator` to use.
-public enum AllocatorOption: ChannelOption {
+public enum AllocatorOption: ChannelOption, Equatable {
     public typealias AssociatedValueType = ()
     public typealias OptionType = ByteBufferAllocator
 
     case const(())
+
+    public static func == (lhs: AllocatorOption, rhs: AllocatorOption) -> Bool {
+        switch (lhs, rhs) {
+        case (.const(()), .const(())):
+            return true
+        }
+    }
 }
 
 /// `RecvAllocatorOption` allows to specify the `RecvByteBufferAllocator` to use.
-public enum RecvAllocatorOption: ChannelOption {
+public enum RecvAllocatorOption: ChannelOption, Equatable {
     public typealias AssociatedValueType = ()
     public typealias OptionType = RecvByteBufferAllocator
 
     case const(())
+
+    public static func == (lhs: RecvAllocatorOption, rhs: RecvAllocatorOption) -> Bool {
+        switch (lhs, rhs) {
+        case (.const(()), .const(())):
+            return true
+        }
+    }
 }
 
 /// `AutoReadOption` allows to configure if a `Channel` should automatically call `Channel.read` again once all data was read from the transport or
 /// if the user is responsible to call `Channel.read` manually.
-public enum AutoReadOption: ChannelOption {
+public enum AutoReadOption: ChannelOption, Equatable {
     public typealias AssociatedValueType = ()
     public typealias OptionType = Bool
 
     case const(())
+
+    public static func == (lhs: AutoReadOption, rhs: AutoReadOption) -> Bool {
+        switch (lhs, rhs) {
+        case (.const(()), .const(())):
+            return true
+        }
+    }
 }
 
 /// `WriteSpinOption` allows users to configure the number of repetitions of a only partially successful write call before considering the `Channel` not writable.
 /// Setting this option to `0` means that we only issue one write call and if that call does not write all the bytes,
 /// we consider the `Channel` not writable.
-public enum WriteSpinOption: ChannelOption {
+public enum WriteSpinOption: ChannelOption, Equatable {
     public typealias AssociatedValueType = ()
     public typealias OptionType = UInt
 
     case const(())
+
+    public static func == (lhs: WriteSpinOption, rhs: WriteSpinOption) -> Bool {
+        switch (lhs, rhs) {
+        case (.const(()), .const(())):
+            return true
+        }
+    }
 }
 
 /// `MaxMessagesPerReadOption` allows to configure the maximum number of read calls to the underlying transport are performed before wait again until
 /// there is more to read and be notified.
-public enum MaxMessagesPerReadOption: ChannelOption {
+public enum MaxMessagesPerReadOption: ChannelOption, Equatable {
     public typealias AssociatedValueType = ()
     public typealias OptionType = UInt
 
     case const(())
+
+    public static func == (lhs: MaxMessagesPerReadOption, rhs: MaxMessagesPerReadOption) -> Bool {
+        switch (lhs, rhs) {
+        case (.const(()), .const(())):
+            return true
+        }
+    }
 }
 
 /// `BacklogOption` allows to configure the `backlog` value as specified in `man 2 listen`. This is only useful for `ServerSocketChannel`s.
-public enum BacklogOption: ChannelOption {
+public enum BacklogOption: ChannelOption, Equatable {
     public typealias AssociatedValueType = ()
     public typealias OptionType = Int32
 
     case const(())
+
+    public static func == (lhs: BacklogOption, rhs: BacklogOption) -> Bool {
+        switch (lhs, rhs) {
+        case (.const(()), .const(())):
+            return true
+        }
+    }
 }
 
 /// The watermark used to detect when `Channel.isWritable` returns `true` or `false`.
@@ -158,20 +207,34 @@ public struct WriteBufferWaterMark {
 /// `Channel.isWritable` will return `false`. Once we were able to write some data out of the outbound buffer and the amount of bytes queued
 /// falls below `WriteBufferWaterMark.low` the `Channel` will become writable again. Once this happens `Channel.writable` will return
 /// `true` again. These writability changes are also propagated through the `ChannelPipeline` and so can be intercepted via `ChannelInboundHandler.channelWritabilityChanged`.
-public enum WriteBufferWaterMarkOption: ChannelOption {
+public enum WriteBufferWaterMarkOption: ChannelOption, Equatable {
     public typealias AssociatedValueType = ()
     public typealias OptionType = WriteBufferWaterMark
 
     case const(())
+
+    public static func == (lhs: WriteBufferWaterMarkOption, rhs: WriteBufferWaterMarkOption) -> Bool {
+        switch (lhs, rhs) {
+        case (.const(()), .const(())):
+            return true
+        }
+    }
 }
 
 /// `ConnectTimeoutOption` allows to configure the `TimeAmount` after which a connect will fail if it was not established in the meantime. May be
 /// `nil`, in which case the connection attempt will never time out.
-public enum ConnectTimeoutOption: ChannelOption {
+public enum ConnectTimeoutOption: ChannelOption, Equatable {
     public typealias AssociatedValueType = ()
     public typealias OptionType = TimeAmount?
 
     case const(())
+
+    public static func == (lhs: ConnectTimeoutOption, rhs: ConnectTimeoutOption) -> Bool {
+        switch (lhs, rhs) {
+        case (.const(()), .const(())):
+            return true
+        }
+    }
 }
 
 /// `AllowRemoteHalfClosureOption` allows users to configure whether the `Channel` will close itself when its remote
@@ -179,11 +242,18 @@ public enum ConnectTimeoutOption: ChannelOption {
 /// will be closed automatically if the remote peer shuts down its send stream. If set to true, the `Channel` will
 /// not be closed: instead, a `ChannelEvent.inboundClosed` user event will be sent on the `ChannelPipeline`,
 /// and no more data will be received.
-public enum AllowRemoteHalfClosureOption: ChannelOption {
+public enum AllowRemoteHalfClosureOption: ChannelOption, Equatable {
     public typealias AssociatedValueType = ()
     public typealias OptionType = Bool
 
     case const(())
+
+    public static func == (lhs: AllowRemoteHalfClosureOption, rhs: AllowRemoteHalfClosureOption) -> Bool {
+        switch (lhs, rhs) {
+        case (.const(()), .const(())):
+            return true
+        }
+    }
 }
 
 /// Provides `ChannelOption`s to be used with a `Channel`, `Bootstrap` or `ServerBootstrap`.
@@ -2697,12 +2705,3 @@ fileprivate class VerifyConnectionFailureHandler: ChannelInboundHandler {
         ctx.fireChannelUnregistered()
     }
 }
-
-extension SocketOption: Equatable {
-    public static func == (lhs: SocketOption, rhs: SocketOption) -> Bool {
-        switch (lhs, rhs) {
-        case (.const(let lLevel, let lName), .const(let rLevel, let rName)):
-            return lLevel == rLevel && lName == rName
-        }
-    }
-}
@weissi weissi added this to the 1.10.0 milestone Aug 28, 2018
@Lukasa Lukasa modified the milestones: 1.10.0, 1.11.0 Oct 29, 2018
@weissi weissi modified the milestones: 1.11.0, 1.12.0 Nov 6, 2018
@weissi weissi modified the milestones: 1.12.0, 2.0.0 Nov 27, 2018
@weissi weissi added the kind/bug Feature doesn't work as expected. label Nov 28, 2018
weissi added a commit to weissi/swift-nio that referenced this issue Feb 13, 2019
Motivation:

ChannelOptions should've always been Equatable and so far we've hacked
around them not being Equatable when we wanted to compare them.

Modifications:

make all ChannelOptions Equtable

Result:

- ChannelOption comparison actually works
- fixes apple#598
weissi added a commit to weissi/swift-nio that referenced this issue Feb 14, 2019
Motivation:

ChannelOptions should've always been Equatable and so far we've hacked
around them not being Equatable when we wanted to compare them.

Modifications:

- make all ChannelOptions Equtable
- make ChannelOptions.Storage public

Result:

- ChannelOption comparison actually works
- fixes apple#598
weissi added a commit to weissi/swift-nio that referenced this issue Feb 14, 2019
Motivation:

ChannelOptions should've always been Equatable and so far we've hacked
around them not being Equatable when we wanted to compare them.

Modifications:

- make all ChannelOptions Equtable
- make ChannelOptions.Storage public

Result:

- ChannelOption comparison actually works
- fixes apple#598
weissi added a commit to weissi/swift-nio that referenced this issue Feb 14, 2019
Motivation:

ChannelOptions should've always been Equatable and so far we've hacked
around them not being Equatable when we wanted to compare them.

Modifications:

- make all ChannelOptions Equtable
- make ChannelOptions.Storage public

Result:

- ChannelOption comparison actually works
- fixes apple#598
weissi added a commit to weissi/swift-nio that referenced this issue Feb 14, 2019
Motivation:

ChannelOptions should've always been Equatable and so far we've hacked
around them not being Equatable when we wanted to compare them.

Modifications:

make all ChannelOptions Equtable

Result:

- ChannelOption comparison actually works
- fixes apple#598
weissi added a commit to weissi/swift-nio that referenced this issue Feb 14, 2019
Motivation:

ChannelOptions should've always been Equatable and so far we've hacked
around them not being Equatable when we wanted to compare them.

Modifications:

make all ChannelOptions Equtable

Result:

- ChannelOption comparison actually works
- fixes apple#598
weissi added a commit to weissi/swift-nio that referenced this issue Feb 14, 2019
Motivation:

ChannelOptions should've always been Equatable and so far we've hacked
around them not being Equatable when we wanted to compare them.

Modifications:

make all ChannelOptions Equtable

Result:

- ChannelOption comparison actually works
- fixes apple#598
- make more ChannelOptions stuff inlinable to not regress allocations
weissi added a commit to weissi/swift-nio that referenced this issue Feb 14, 2019
Motivation:

ChannelOptions should've always been Equatable and so far we've hacked
around them not being Equatable when we wanted to compare them.

Modifications:

make all ChannelOptions Equtable

Result:

- ChannelOption comparison actually works
- fixes apple#598
- make more ChannelOptions stuff inlinable to not regress allocations
weissi added a commit to weissi/swift-nio that referenced this issue Feb 14, 2019
Motivation:

ChannelOptions should've always been Equatable and so far we've hacked
around them not being Equatable when we wanted to compare them.

Modifications:

make all ChannelOptions Equtable

Result:

- ChannelOption comparison actually works
- fixes apple#598
- make more ChannelOptions stuff inlinable to not regress allocations
weissi added a commit to weissi/swift-nio that referenced this issue Feb 19, 2019
Motivation:

ChannelOptions should've always been Equatable and so far we've hacked
around them not being Equatable when we wanted to compare them.

Modifications:

make all ChannelOptions Equtable

Result:

- ChannelOption comparison actually works
- fixes apple#598
- make more ChannelOptions stuff inlinable to not regress allocations
weissi added a commit that referenced this issue Feb 19, 2019
Motivation:

ChannelOptions should've always been Equatable and so far we've hacked
around them not being Equatable when we wanted to compare them.

Modifications:

make all ChannelOptions Equtable

Result:

- ChannelOption comparison actually works
- fixes #598
- make more ChannelOptions stuff inlinable to not regress allocations
weissi added a commit to weissi/swift-nio that referenced this issue Feb 21, 2019
Motivation:

ChannelOptions should've always been Equatable and so far we've hacked
around them not being Equatable when we wanted to compare them.

Modifications:

make all ChannelOptions Equtable

Result:

- ChannelOption comparison actually works
- fixes apple#598
- make more ChannelOptions stuff inlinable to not regress allocations
weissi added a commit to weissi/swift-nio that referenced this issue Feb 21, 2019
Motivation:

ChannelOptions should've always been Equatable and so far we've hacked
around them not being Equatable when we wanted to compare them.

Modifications:

make all ChannelOptions Equtable

Result:

- ChannelOption comparison actually works
- fixes apple#598
- make more ChannelOptions stuff inlinable to not regress allocations
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Feature doesn't work as expected.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants