Skip to content

Commit

Permalink
Turn Network{Implementation,Preference} enums into structs
Browse files Browse the repository at this point in the history
Motivation:

Public enums are a pain for API evolution and there's no need for users to
be able to exhaustively switch over `NetworkImplementation` and
`NetworkPreference`.

Modifications:

- Turn both into structs backed by enums

Result:

More evolvable API.
  • Loading branch information
glbrntt committed Jun 30, 2020
1 parent 2732990 commit 4e250b0
Showing 1 changed file with 35 additions and 10 deletions.
45 changes: 35 additions & 10 deletions Sources/GRPC/PlatformSupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -134,17 +157,19 @@ 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.
fatalError(".networkFramework is being used on an unsupported platform")
}
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)
Expand Down

0 comments on commit 4e250b0

Please sign in to comment.