diff --git a/Sources/GRPC/PlatformSupport.swift b/Sources/GRPC/PlatformSupport.swift index 5b32b30b8..361482b39 100644 --- a/Sources/GRPC/PlatformSupport.swift +++ b/Sources/GRPC/PlatformSupport.swift @@ -18,27 +18,50 @@ import NIOTransportServices import Logging /// How a network implementation should be chosen. -public enum NetworkPreference { +public struct NetworkPreference { + private enum Wrapped { + case best + case userDefined(NetworkImplementation) + } + + private var wrapped: Wrapped + private init(_ wrapped: Wrapped) { + self.wrapped = wrapped + } + /// Use the best available, that is, Network.framework (and NIOTransportServices) when it is /// available on Darwin platforms (macOS 10.14+, iOS 12.0+, tvOS 12.0+, watchOS 6.0+), and /// falling back to the POSIX network model otherwise. - case best + public static let best = NetworkPreference(.best) /// Use the given implementation. Doing so may require additional availability checks depending /// on the implementation. - case userDefined(NetworkImplementation) + public static func userDefined(_ implementation: NetworkImplementation) -> NetworkPreference { + return NetworkPreference(.userDefined(implementation)) + } } /// The network implementation to use: POSIX sockets or Network.framework. This also determines /// which variant of NIO to use; NIO or NIOTransportServices, respectively. -public enum NetworkImplementation { +public struct NetworkImplementation { + fileprivate enum Wrapped { + case networkFramework + case posix + } + + fileprivate var wrapped: Wrapped + private init(_ wrapped: Wrapped) { + self.wrapped = wrapped + } + #if canImport(Network) /// Network.framework (NIOTransportServices). @available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *) - case networkFramework + public static let networkFramework = NetworkImplementation(.networkFramework) #endif + /// POSIX (NIO). - case posix + public static let posix = NetworkImplementation(.posix) } extension NetworkPreference { @@ -52,7 +75,7 @@ extension NetworkPreference { /// - `@available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *)`, or /// - `#available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *)`. public var implementation: NetworkImplementation { - switch self { + switch self.wrapped { case .best: #if canImport(Network) guard #available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *) else { @@ -134,9 +157,9 @@ public enum PlatformSupport { ) -> EventLoopGroup { let logger = logger ?? PlatformSupport.logger logger.debug("making EventLoopGroup for \(networkPreference) network preference") - switch networkPreference.implementation { - #if canImport(Network) + switch networkPreference.implementation.wrapped { case .networkFramework: + #if canImport(Network) guard #available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *) else { logger.critical("Network.framework can be imported but is not supported on this platform") // This is gated by the availability of `.networkFramework` so should never happen. @@ -144,7 +167,9 @@ public enum PlatformSupport { } logger.debug("created NIOTSEventLoopGroup for \(networkPreference) preference") return NIOTSEventLoopGroup(loopCount: loopCount) - #endif + #else + fatalError(".networkFramework is being used on an unsupported platform") + #endif case .posix: logger.debug("created MultiThreadedEventLoopGroup for \(networkPreference) preference") return MultiThreadedEventLoopGroup(numberOfThreads: loopCount)