From 87c532383a149264561a85824222004af6262ccb Mon Sep 17 00:00:00 2001 From: Johannes Weiss Date: Tue, 13 Jul 2021 12:36:28 +0100 Subject: [PATCH] remove NIO1 API shims (#1897) Motivation: The lastest NIO versions require Swift 5.2+ to compile. Given that hopefully nobody ever created a NIO1 application for Swift 5.2+, I'd say it's about time to remove the NIO1 API shims (and related docs). Modification: - remove the NIO1 API shims - remove the migration docs Result: Less code. --- Package.swift | 3 - Sources/_NIO1APIShims/NIO1APIShims.swift | 542 ----------------------- docs/migration-guide-NIO1-to-NIO2.md | 73 +-- docs/public-api-changes-NIO1-to-NIO2.md | 90 ---- scripts/build_podspecs.sh | 4 - 5 files changed, 1 insertion(+), 711 deletions(-) delete mode 100644 Sources/_NIO1APIShims/NIO1APIShims.swift delete mode 100644 docs/public-api-changes-NIO1-to-NIO2.md diff --git a/Package.swift b/Package.swift index 6a025cbe0c..39c6fb4b2f 100644 --- a/Package.swift +++ b/Package.swift @@ -16,8 +16,6 @@ import PackageDescription var targets: [PackageDescription.Target] = [ - .target(name: "_NIO1APIShims", - dependencies: ["NIO", "NIOHTTP1", "NIOTLS", "NIOFoundationCompat", "NIOWebSocket"]), .target(name: "NIO", dependencies: ["CNIOLinux", "CNIODarwin", @@ -89,7 +87,6 @@ let package = Package( name: "swift-nio", products: [ .library(name: "NIO", targets: ["NIO"]), - .library(name: "_NIO1APIShims", targets: ["_NIO1APIShims"]), .library(name: "_NIOConcurrency", targets: ["_NIOConcurrency"]), .library(name: "NIOTLS", targets: ["NIOTLS"]), .library(name: "NIOHTTP1", targets: ["NIOHTTP1"]), diff --git a/Sources/_NIO1APIShims/NIO1APIShims.swift b/Sources/_NIO1APIShims/NIO1APIShims.swift deleted file mode 100644 index 19696ec39e..0000000000 --- a/Sources/_NIO1APIShims/NIO1APIShims.swift +++ /dev/null @@ -1,542 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the SwiftNIO open source project -// -// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of SwiftNIO project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import Dispatch -import Foundation -import NIO -import NIOFoundationCompat -import NIOHTTP1 -import NIOTLS -import NIOWebSocket - -// This is NIO 2's 'NIO1 API Shims' module. -// -// Please note that _NIO1APIShimsHelpers is a transitional module that is untested and -// is not part of the public API. Before NIO 2.0.0 gets released it's still very useful -// to `import _NIO1APIShimsHelpers` because it will make it easier for you to keep up -// with NIO2 API changes until the API will stabilise and we will start tagging versions. -// -// Please do not depend on this module in tagged versions. -// -// 💜 the SwiftNIO team. - -@available(*, deprecated, message: "ContiguousCollection does not exist in NIO2") -public protocol ContiguousCollection: Collection { - func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R -} - -@available(*, deprecated, renamed: "SNIResult") -public typealias SniResult = SNIResult - -@available(*, deprecated, renamed: "SNIHandler") -public typealias SniHandler = SNIHandler - -@available(*, deprecated, renamed: "NIOFileHandle") -public typealias FileHandle = NIOFileHandle - -@available(*, deprecated, message: "don't use the StaticString: Collection extension please") -extension StaticString: Collection { - @available(*, deprecated, message: "don't use the StaticString: Collection extension please") - public typealias Element = UInt8 - @available(*, deprecated, message: "don't use the StaticString: Collection extension please") - public typealias SubSequence = ArraySlice - - @available(*, deprecated, message: "don't use the StaticString: Collection extension please") - public typealias _Index = Int - - @available(*, deprecated, message: "don't use the StaticString: Collection extension please") - public var startIndex: _Index { return 0 } - @available(*, deprecated, message: "don't use the StaticString: Collection extension please") - public var endIndex: _Index { return self.utf8CodeUnitCount } - @available(*, deprecated, message: "don't use the StaticString: Collection extension please") - public func index(after i: _Index) -> _Index { return i + 1 } - - @available(*, deprecated, message: "don't use the StaticString: Collection extension please") - public subscript(position: Int) -> UInt8 { - precondition(position < self.utf8CodeUnitCount, "index \(position) out of bounds") - return self.utf8Start.advanced(by: position).pointee - } - - @available(*, deprecated, message: "don't use the StaticString: Collection extension please") - public subscript(bounds: Range) -> SubSequence { - precondition(startIndex <= bounds.lowerBound && - bounds.lowerBound <= bounds.upperBound && - bounds.upperBound <= endIndex, - "indices out of bounds") - return withUTF8Buffer { return ArraySlice($0[bounds]) } - } -} - -extension ChannelPipeline { - @available(*, deprecated, message: "please use addHandler(ByteToMessageHandler(myByteToMessageDecoder))") - public func add(handler decoder: Decoder) -> EventLoopFuture { - return self.addHandler(ByteToMessageHandler(decoder)) - } - - @available(*, deprecated, message: "please use addHandler(MessageToByteHandler(myMessageToByteEncoder))") - public func add(handler encoder: Encoder) -> EventLoopFuture { - return self.addHandler(MessageToByteHandler(encoder)) - } - - @available(*, deprecated, renamed: "addHandler(_:position:)") - public func add(handler: ChannelHandler, first: Bool = false) -> EventLoopFuture { - return self.addHandler(handler, position: first ? .first : .last) - } - - @available(*, deprecated, renamed: "addHandler(_:name:position:)") - public func add(name: String, handler: ChannelHandler, first: Bool = false) -> EventLoopFuture { - return self.addHandler(handler, name: name, position: first ? .first : .last) - } - - @available(*, deprecated, renamed: "addHandler(_:name:position:)") - public func add(name: String? = nil, handler: ChannelHandler, after: ChannelHandler) -> EventLoopFuture { - return self.addHandler(handler, name: name, position: .after(after)) - } - - @available(*, deprecated, renamed: "addHandler(_:name:position:)") - public func add(name: String? = nil, handler: ChannelHandler, before: ChannelHandler) -> EventLoopFuture { - return self.addHandler(handler, name: name, position: .before(before)) - } - - @available(*, deprecated, renamed: "removeHandler(_:)") - public func remove(handler: RemovableChannelHandler) -> EventLoopFuture { - return self.removeHandler(handler) - } - - @available(*, deprecated, renamed: "removeHandler(name:)") - public func remove(name: String) -> EventLoopFuture { - return self.removeHandler(name: name) - } - - @available(*, deprecated, renamed: "removeHandler(context:)") - public func remove(context: ChannelHandlerContext) -> EventLoopFuture { - return self.removeHandler(context: context) - } - - @available(*, deprecated, renamed: "removeHandler(_:promise:)") - public func remove(handler: RemovableChannelHandler, promise: EventLoopPromise?) { - return self.removeHandler(handler, promise: promise) - } - - @available(*, deprecated, renamed: "removeHandler(name:promise:)") - public func remove(name: String, promise: EventLoopPromise?) { - return self.removeHandler(name: name, promise: promise) - } - - @available(*, deprecated, renamed: "removeHandler(context:promise:)") - public func remove(context: ChannelHandlerContext, promise: EventLoopPromise?) { - return self.removeHandler(context: context, promise: promise) - } -} - -extension EventLoop { - @available(*, deprecated, renamed: "makePromise") - public func newPromise(of type: T.Type = T.self, file: StaticString = #file, line: UInt = #line) -> EventLoopPromise { - return self.makePromise(of: type, file: file, line: line) - } - - @available(*, deprecated, renamed: "makeSucceededFuture(_:)") - public func newSucceededFuture(result: T) -> EventLoopFuture { - return self.makeSucceededFuture(result) - } - - @available(*, deprecated, renamed: "makeFailedFuture(_:)") - public func newFailedFuture(error: Error) -> EventLoopFuture { - return self.makeFailedFuture(error) - } - - @available(*, deprecated, renamed: "scheduleRepeatedAsyncTask") - public func scheduleRepeatedTask(initialDelay: TimeAmount, - delay: TimeAmount, - notifying promise: EventLoopPromise? = nil, - _ task: @escaping (RepeatedTask) -> EventLoopFuture) -> RepeatedTask { - return self.scheduleRepeatedAsyncTask(initialDelay: initialDelay, delay: delay, task) - } -} - -extension EventLoopFuture { - @available(*, deprecated, renamed: "Value") - public typealias T = Value - - @available(*, deprecated, message: "whenComplete now gets Result") - public func whenComplete(_ body: @escaping () -> Void) { - self.whenComplete { (_: Result) in - body() - } - } - - @available(*, deprecated, renamed: "flatMap") - public func then(file: StaticString = #file, line: UInt = #line, _ callback: @escaping (Value) -> EventLoopFuture) -> EventLoopFuture { - return self.flatMap(file: file, line: line, callback) - } - - @available(*, deprecated, renamed: "flatMapThrowing") - public func thenThrowing(file: StaticString = #file, line: UInt = #line, _ callback: @escaping (Value) throws -> U) -> EventLoopFuture { - return self.flatMapThrowing(file: file, line: line, callback) - } - - @available(*, deprecated, renamed: "flatMapError") - public func thenIfError(file: StaticString = #file, line: UInt = #line, _ callback: @escaping (Error) -> EventLoopFuture) -> EventLoopFuture { - return self.flatMapError(file: file, line: line, callback) - } - - @available(*, deprecated, renamed: "flatMapErrorThrowing") - public func thenIfErrorThrowing(file: StaticString = #file, line: UInt = #line, _ callback: @escaping (Error) throws -> Value) -> EventLoopFuture { - return self.flatMapErrorThrowing(file: file, line: line, callback) - } - - @available(*, deprecated, renamed: "recover") - public func mapIfError(file: StaticString = #file, line: UInt = #line, _ callback: @escaping (Error) -> Value) -> EventLoopFuture { - return self.recover(file: file, line: line, callback) - } - - @available(*, deprecated, renamed: "and(value:file:line:)") - public func and(result: OtherValue, - file: StaticString = #file, - line: UInt = #line) -> EventLoopFuture<(Value, OtherValue)> { - return self.and(value: result, file: file, line: line) - } - - @available(*, deprecated, renamed: "cascade(to:)") - public func cascade(promise: EventLoopPromise?) { - self.cascade(to: promise) - } - - @available(*, deprecated, renamed: "cascadeFailure(to:)") - public func cascadeFailure(promise: EventLoopPromise?) { - self.cascadeFailure(to: promise) - } - - @available(*, deprecated, renamed: "andAllSucceed(_:on:)") - public static func andAll(_ futures: [EventLoopFuture], eventLoop: EventLoop) -> EventLoopFuture { - return .andAllSucceed(futures, on: eventLoop) - } - - @available(*, deprecated, renamed: "hop(to:)") - public func hopTo(eventLoop: EventLoop) -> EventLoopFuture { - return self.hop(to: eventLoop) - } - - @available(*, deprecated, renamed: "reduce(_:_:on:_:)") - public static func reduce(_ initialResult: Value, - _ futures: [EventLoopFuture], - eventLoop: EventLoop, - _ nextPartialResult: @escaping (Value, InputValue) -> Value) -> EventLoopFuture { - return .reduce(initialResult, futures, on: eventLoop, nextPartialResult) - } - - @available(*, deprecated, renamed: "reduce(into:_:on:_:)") - public static func reduce(into initialResult: Value, - _ futures: [EventLoopFuture], - eventLoop: EventLoop, - _ updateAccumulatingResult: @escaping (inout Value, InputValue) -> Void) -> EventLoopFuture { - return .reduce(into: initialResult, futures, on: eventLoop, updateAccumulatingResult) - } -} - -extension EventLoopPromise { - @available(*, deprecated, renamed: "succeed(_:)") - public func succeed(result: Value) { - self.succeed(result) - } - - @available(*, deprecated, renamed: "fail(_:)") - public func fail(error: Error) { - self.fail(error) - } -} - -extension EventLoopGroup { - @available(*, deprecated, message: "makeIterator is now required") - public func makeIterator() -> NIO.EventLoopIterator { - return .init([]) - } -} - -extension MarkedCircularBuffer { - @available(*, deprecated, renamed: "Element") - public typealias E = Element - - func _makeIndex(value: Int) -> Index { - return self.index(self.startIndex, offsetBy: value) - } - - @available(*, deprecated, renamed: "init(initialCapacity:)") - public init(initialRingCapacity: Int) { - self = .init(initialCapacity: initialRingCapacity) - } - - @available(*, deprecated, message: "please use MarkedCircularBuffer.Index instead of Int") - public func index(after i: Int) -> Int { - return i + 1 - } - - @available(*, deprecated, message: "please use MarkedCircularBuffer.Index instead of Int") - public func index(before: Int) -> Int { - return before - 1 - } - - @available(*, deprecated, message: "please use MarkedCircularBuffer.Index instead of Int") - public func isMarked(index: Int) -> Bool { - return self.isMarked(index: self._makeIndex(value: index)) - } - - @available(*, deprecated, message: "hasMark is now a property, remove `()`") - public func hasMark() -> Bool { - return self.hasMark - } - - @available(*, deprecated, message: "markedElement is now a property, remove `()`") - public func markedElement() -> E? { - return self.markedElement - } - - @available(*, deprecated, message: "markedElementIndex is now a property, remove `()`") - public func markedElementIndex() -> Index? { - return self.markedElementIndex - } -} - -extension HTTPVersion { - @available(*, deprecated, message: "type of major and minor is now Int") - public init(major: UInt16, minor: UInt16) { - self = .init(major: Int(major), minor: Int(minor)) - } - - @available(*, deprecated, message: "type of major is now Int") - public var majorLegacy: UInt16 { - return UInt16(self.major) - } - - @available(*, deprecated, message: "type of minor is now Int") - public var minorLegacy: UInt16 { - return UInt16(self.minor) - } -} - -extension HTTPHeaders { - @available(*, deprecated, message: "don't pass ByteBufferAllocator anymore") - public init(_ headers: [(String, String)] = [], allocator: ByteBufferAllocator) { - self.init(headers) - } -} - -@available(*, deprecated, renamed: "ChannelError") -public enum ChannelLifecycleError { - @available(*, deprecated, message: "ChannelLifecycleError values are now available on ChannelError") - public static var inappropriateOperationForState: ChannelError { - return ChannelError.inappropriateOperationForState - } - -} - -@available(*, deprecated, renamed: "ChannelError") -public enum MulticastError { - @available(*, deprecated, message: "MulticastError values are now available on ChannelError") - public static var unknownLocalAddress: ChannelError { - return .unknownLocalAddress - } - - @available(*, deprecated, message: "MulticastError values are now available on ChannelError") - public static var badMulticastGroupAddressFamily: ChannelError { - return .badMulticastGroupAddressFamily - } - - @available(*, deprecated, message: "MulticastError values are now available on ChannelError") - public static var badInterfaceAddressFamily: ChannelError { - return .badInterfaceAddressFamily - } - - @available(*, deprecated, message: "MulticastError values are now available on ChannelError") - public static func illegalMulticastAddress(_ address: SocketAddress) -> ChannelError { - return .illegalMulticastAddress(address) - } -} - -extension ChannelError { - @available(*, deprecated, message: "ChannelError.connectFailed has been removed") - public static var connectFailed: NIOConnectionError { - fatalError("ChannelError.connectFailed has been removed in NIO2") - } -} - - -extension SocketAddress { - @available(*, deprecated, message: "type of port is now Int?") - public var portLegacy: UInt16? { - return self.port.map(UInt16.init) - } - - @available(*, deprecated, renamed: "makeAddressResolvingHost") - public static func newAddressResolving(host: String, port: Int) throws -> SocketAddress { - return try self.makeAddressResolvingHost(host, port: port) - } -} - -extension CircularBuffer { - func _makeIndex(value: Int) -> Index { - return self.index(self.startIndex, offsetBy: value) - } - - @available(*, deprecated, renamed: "Element") - public typealias E = Element - - @available(*, deprecated, renamed: "init(initialCapacity:)") - public init(initialRingCapacity: Int) { - self = .init(initialCapacity: initialRingCapacity) - } - - @available(*, deprecated, message: "please use CircularBuffer.Index instead of Int") - public subscript(index: Int) -> E { - return self[_makeIndex(value: index)] - } - - @available(*, deprecated, message: "please use CircularBuffer.Index instead of Int") - public func index(after: Int) -> Int { - return after + 1 - } - - @available(*, deprecated, message: "please use CircularBuffer.Index instead of Int") - public func index(before: Int) -> Int { - return before - 1 - } - - @available(*, deprecated, message: "please use CircularBuffer.Index instead of Int") - public mutating func removeSubrange(_ bounds: Range) { - return self.removeSubrange(_makeIndex(value: bounds.lowerBound) ..< _makeIndex(value: bounds.upperBound)) - } - - @available(*, deprecated, message: "please use CircularBuffer.Index instead of Int") - public mutating func remove(at position: Int) -> E { - return self.remove(at: _makeIndex(value: position)) - } -} - -extension ByteBuffer { - @available(*, deprecated, renamed: "writeStaticString(_:)") - public mutating func write(staticString: StaticString) -> Int { - return self.writeStaticString(staticString) - } - - @available(*, deprecated, renamed: "setStaticString(_:at:)") - public mutating func set(staticString: StaticString, at index: Int) -> Int { - return self.setStaticString(staticString, at: index) - } - - @available(*, deprecated, renamed: "writeString(_:)") - public mutating func write(string: String) -> Int { - return self.writeString(string) - } - - @available(*, deprecated, renamed: "setString(_:at:)") - public mutating func set(string: String, at index: Int) -> Int { - return self.setString(string, at: index) - } - - @available(*, deprecated, renamed: "writeDispatchData(_:)") - public mutating func write(dispatchData: DispatchData) -> Int { - return self.writeDispatchData(dispatchData) - } - - @available(*, deprecated, renamed: "setDispatchData(_:)") - public mutating func set(dispatchData: DispatchData, at index: Int) -> Int { - return self.setDispatchData(dispatchData, at: index) - } - - @available(*, deprecated, renamed: "writeBuffer(_:)") - public mutating func write(buffer: inout ByteBuffer) -> Int { - return self.writeBuffer(&buffer) - } - - @available(*, deprecated, renamed: "writeBytes(_:)") - public mutating func write(bytes: Bytes) -> Int where Bytes.Element == UInt8 { - return self.writeBytes(bytes) - } - - @available(*, deprecated, renamed: "writeBytes(_:)") - public mutating func write(bytes: UnsafeRawBufferPointer) -> Int { - return self.writeBytes(bytes) - } - - @available(*, deprecated, renamed: "setBytes(at:)") - public mutating func set(bytes: Bytes, at index: Int) -> Int where Bytes.Element == UInt8 { - return self.setBytes(bytes, at: index) - } - - @available(*, deprecated, renamed: "setBytes(at:)") - public mutating func set(bytes: UnsafeRawBufferPointer, at index: Int) -> Int { - return self.setBytes(bytes, at: index) - } - - @available(*, deprecated, renamed: "writeInteger(_:endianness:as:)") - public mutating func write(integer: T, endianness: Endianness = .big, as type: T.Type = T.self) -> Int { - return self.writeInteger(integer, endianness: endianness, as: type) - } - - @available(*, deprecated, renamed: "setInteger(_:at:endianness:as:)") - public mutating func set(integer: T, at index: Int, endianness: Endianness = .big, as type: T.Type = T.self) -> Int { - return self.setInteger(integer, at: index, endianness: endianness, as: type) - } - - @available(*, deprecated, renamed: "writeString(_:encoding:)") - public mutating func write(string: String, encoding: String.Encoding) throws -> Int { - return try self.writeString(string, encoding: encoding) - } - - @available(*, deprecated, renamed: "setString(_:encoding:at:)") - public mutating func set(string: String, encoding: String.Encoding, at index: Int) throws -> Int { - return try self.setString(string, encoding: encoding, at: index) - } -} - -extension Channel { - @available(*, deprecated, renamed: "_channelCore") - public var _unsafe: ChannelCore { - return self._channelCore - } - - @available(*, deprecated, renamed: "setOption(_:value:)") - public func setOption(option: Option, value: Option.Value) -> EventLoopFuture { - return self.setOption(option, value: value) - } - - @available(*, deprecated, renamed: "getOption(_:)") - public func getOption(option: Option) -> EventLoopFuture { - return self.getOption(option) - } -} - -extension ChannelOption { - @available(*, deprecated, renamed: "Value") - public typealias OptionType = Value -} - -@available(*, deprecated, renamed: "HTTPServerProtocolUpgrader") -public typealias HTTPProtocolUpgrader = HTTPServerProtocolUpgrader - -@available(*, deprecated, renamed: "HTTPServerUpgradeEvents") -public typealias HTTPUpgradeEvents = HTTPServerUpgradeEvents - -@available(*, deprecated, renamed: "HTTPServerUpgradeErrors") -public typealias HTTPUpgradeErrors = HTTPServerUpgradeErrors - -@available(*, deprecated, renamed: "NIOThreadPool") -public typealias BlockingIOThreadPool = NIOThreadPool - -extension WebSocketFrameDecoder { - @available(*, deprecated, message: "automaticErrorHandling deprecated, use WebSocketProtocolErrorHandler instead") - public convenience init(maxFrameSize: Int = 1 << 14, automaticErrorHandling: Bool) { - self.init(maxFrameSize: maxFrameSize) - } -} diff --git a/docs/migration-guide-NIO1-to-NIO2.md b/docs/migration-guide-NIO1-to-NIO2.md index a233402fcd..7345efde44 100644 --- a/docs/migration-guide-NIO1-to-NIO2.md +++ b/docs/migration-guide-NIO1-to-NIO2.md @@ -1,74 +1,3 @@ # NIO 1 to NIO 2 migration guide -This migration guide is our recommendation to migrate from NIO 1 to NIO 2. None of the steps apart from changing your `Package.swift` and fixing the errors is actually required but this might help you complete the migration as fast as possible. For the NIO repositories and some example projects, we had really good success in migrating them fairly pain-free. - -This repository also contains a fairly complete list of public [API changes](https://github.com/apple/swift-nio/blob/main/docs/public-api-changes-NIO1-to-NIO2.md) from NIO 1 to NIO 2. - -### Note: As of NIO 2.30.0 the minimum version of Swift required is 5.2. - -## Step 1: A warning-free compile on NIO 1 with Swift 5 - -To start with, we highly recommend to first get your project to compile warning-free with NIO 1 on Swift 5. The reason is that some of the warnings you might get are the result of deprecation in NIO 1 and deprecated NIO 1 API has been fully removed in NIO 2. - -For macOS, download Xcode 10, beta 3 or better and you're good to go. On Linux, use a very recent Swift 5.0 snapshot. - -## Step 2: Update your NIO dependencies - -Update the NIO packages you use to include the following versions. - -- `swift-nio`: `.package(url: "https://github.com/apple/swift-nio.git", from: "2.0.0")` -- `swift-nio-ssl`: `.package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.0.0")` -- `swift-nio-extras`: `.package(url: "https://github.com/apple/swift-nio-extras.git", from: "1.0.0")` -- `swift-nio-http2`: `.package(url: "https://github.com/apple/swift-nio-http2.git", from: "1.0.0")` -- `swift-nio-transport-services`: `.package(url: "https://github.com/apple/swift-nio-transport-services.git", from: "1.0.0")` - -After you changes your `Package.swift`, run `swift package update`. - -## Step 3: `ctx` to `context` - -The NIO community has [correctly](https://swift.org/documentation/api-design-guidelines/#avoid-abbreviations) [pointed](https://github.com/apple/swift-nio/issues/663#issuecomment-442013880) [out](https://github.com/apple/swift-nio/issues/483) that the use of `ctx` for the `ChannelHandlerContext` variables feels alien in Swift. We agree with this and have decided that despite the breakage it will cause, we shall rename all mentions of `ctx` to `context`. Unfortunately, that means that every `ChannelHandler` in existence needs a change. To make it worse, `ChannelHandler`s have default implementations for all events which means if you have a `ChannelHandler` method that still uses `ctx`, your code will still compile but the method will never be called because its first parameter is now named `context`. - -Therefore, do yourself a favour and start the conversion from NIO 1 to NIO 2 by running the following command in the root of your package: - -```bash -# if you're developing on macOS / BSD -find . -name '*.swift' -type f | while read line; do sed -E -i '' 's/([^"])[[:<:]]ctx[[:>:]]([^"])/\1context\2/g' "$line"; done -``` - -```bash -# if you're developing on Linux -find . -name '*.swift' -type f | while read line; do sed -E -i 's/([^"])\([^"])/\1context\2/g' "$line"; done -``` - -What these unwieldy commands do is replace `ctx` if it appears as its own word with `context` in all `.swift` files under the current directory. For the NIO packages themselves that was all that was needed for this huge change. - -## Step 4: Use `_NIO1APIShims` - -The goal of the `_NIO1APIShims` module (which is _not_ public API and is also untested) is to help you with all the small renames we have done for NIO 2. We recommend to follow these steps to make as much use of automation as possible as possible: - -1. in your `Package.swift`, add `_NIO1APIShims` to your target's `dependencies:` list in all places that use any of the NIO modules. So for example `dependencies: ["NIO", "SomethingElse"]` should become `dependencies: ["NIO", "_NIO1APIShims", "SomethingElse"]` -2. add `import _NIO1APIShims` to all files where you `import NIO` or any of the other NIO modules like `import NIOHTTP1`. The following command will list all such files: - `find . -name '*.swift' -type f | while read line; do if grep -q "import NIO" "$line"; then echo "$line"; fi; done` -3. fix all remaining compile errors, if there are any -4. apply all the compiler-suggested fixits, in Xcode you can - 1. Press `⌘'` to Jump to Next Issue - 2. Press `^⎇⌘F` to Fix All Issues in the current file - 3. Go back to 4.1 (jump to next issue) until you've gone through all the files and applied all the fixits -5. fix remaining warnings manually -6. remove all `import _NIO1APIShims` imports and all `_NIO1APIShims` mentions in your `Package.swift` - -## Step 5: Require Swift 5 and NIO 2 - -NIO 2 only supports Swift 5 so after the migration you should change the first line of your `Package.swift` to read `// swift-tools-version:5.0`. That will also allow you to use all the great new features Swift Package Manager added in recent releases. - -## Step 6: Watch out for more subtle changes - -- Make sure you close your `Channel` if there's an unhandled error. Usually, the right thing to do is to invoke `context.close(promise: nil)` when `errorCaught` is invoked on your last `ChannelHandler`. Of course, handle all the errors you know you can handle but `close` on all others. This has always been true for NIO 1 too but in NIO 2 we have removed some of the automatic `Channel` closes in the `HTTPDecoder`s and `ByteToMessageDecoder`s have been removed. Why have they been removed? So a user can opt out of the automatic closure. -- If you have a `ByteToMessageDecoder` or a `MessageToByteEncoder`, you will now need to wrap them before adding them to the pipeline. For example: - -```swift - channel.pipeline.addHandler(ByteToMessageHandler(MyExampleDecoder())).flatMap { - channel.pipeline.addHandler(MessageToByteHandler(MyExampleEncoder())) - } -``` -- Apart from this, most `ByteToMessageDecoder`s should continue to work. There is however one more subtle change: In SwiftNIO 1, you could (illegally) intercept arbitrary `ChannelInboundHandler` or `ChannelOutboundHandler` events in `ByteToMessageHandler`s. This did never work correctly (because the `ByteToMessageDecoder` driver would then not receive those events anymore). In SwiftNIO 2 this is fixed and you won't receive any of the standard `ChannelHandler` events in `ByteToMessageDecoder`s anymore. +Please take a look at [SwiftNIO 2.29.0](https://github.com/apple/swift-nio/blob/2.29.0/docs/migration-guide-NIO1-to-NIO2.md), the last version with Swift 5.0 support. SwiftNIO 2.29.0 will also come with the `_NIO1APIShims` module which eases the migration. diff --git a/docs/public-api-changes-NIO1-to-NIO2.md b/docs/public-api-changes-NIO1-to-NIO2.md deleted file mode 100644 index e82399361a..0000000000 --- a/docs/public-api-changes-NIO1-to-NIO2.md +++ /dev/null @@ -1,90 +0,0 @@ -# Changes in the Public API from NIO 1 to NIO 2 - -- renamed all instances of `ctx` to `context`. Your `ChannelHandler` methods now - need to take a `context` parameter and no longer `ctx`. Example: `func channelRead(context: ChannelHandlerContext, data: NIOAny)` -- `HTTPResponseCompressor` moved to [`swift-nio-extras`](https://github.com/apple/swift-nio-extras). -- removed all previously deprecated functions, types and modules. -- renamed `SniResult` to `SNIResult` -- renamed `SniHandler` to `SNIHandler` -- made `EventLoopGroup.makeIterator()` a required method -- `Channel._unsafe` is now `Channel._channelCore` -- `TimeAmount.Value` is now `Int64` (from `Int` on 64 bit platforms, no change - for 32 bit platforms) -- `ByteToMessageDecoder`s now need to be wrapped in `ByteToMessageHandler` - before they can be added to the pipeline. - before: `pipeline.add(MyDecoder())`, after: `pipeline.add(ByteToMessageHandler(MyDecoder()))` -- `MessageToByteEncoder`s now need to be wrapped in `MessageToByteHandler` - before they can be added to the pipeline. - before: `pipeline.add(MyEncoder())`, after: `pipeline.add(MessageToByteHandler(MyEncoder()))` -- `BlockingIOThreadPool` has been renamed to `NIOThreadPool` -- `ByteToMessageDecoder` now requires the implementation of `decodeLast` -- `MessageToByteEncoder` now requires the implementation of `encode` -- `MessageToByteEncoder.allocateOutBuffer` was removed without replacement -- `MessageToByteEncoder.encode` no longer gets access to the `ChannelHandlerContext` -- `ByteToMessageDecoder.decodeLast` has a new parameter `seenEOF: Bool` -- `EventLoop.makePromise`/`makeSucceededFuture`/`makeFailedFuture` instead of `new*`, also `result:`/`error:` labels dropped -- `SocketAddress.makeAddressResolvingHost(:port:)` instead of - `SocketAddress.newAddressResolving(host:port:)` -- changed all ports to `Int` (from `UInt16`) -- changed `HTTPVersion`'s `major` and `minor` properties to `Int` (from `UInt16`) -- `NIOWebSocketUpgradeError` is now a `struct` rather than an `enum` -- renamed the generic parameter name to `Bytes` where we're talking about a - generic collection of bytes -- Moved error `ChannelLifecycleError.inappropriateOperationForState` to `ChannelError.inappropriateOperationForState`. -- Moved all errors in `MulticastError` enum into `ChannelError`. -- Removed `ChannelError.connectFailed`. All errors that triggered this now throw `NIOConnectError` directly. -- Made `WebSocketOpcode` a struct. Removed `WebSocketOpcode.unknownControl` and - `WebSocketOpcode.unknownNonControl` values: these should be replaced by - simply instantiating `WebSocketOpcode` with the value. -- `ThreadSpecificVariable` is now a `class` instead of a `struct` -- `Channel.setOption(option:value:)` has been renamed `Channel.setOption(_:value:)` -- `Channel.getOption(option:value:)` has been renamed `Channel.getOption(_:value:)` -- `ChannelOption.AssociatedValueType` has been removed -- `ChannelOption.OptionType` has been renamed `ChannelOption.Value` -- the default `ChannelOption`s have been switched changed from `case FooOption { case const }` to a `struct FooOption { public init() {} }` -- `markedElementIndex()`, `markedElement()` and `hasMark()` are now computed variables instead of functions. -- `ByteBuffer.setString(_:at:)` (used to be `set(string:at:)`) no longer returns an `Int?`, instead it - returns `Int` and has had its return value made discardable. -- `ByteBuffer.write(string:)` (now named `ByteBuffer.writeString(_:)`) no longer returns an `Int?`, instead it - returns `Int` and has had its return value made discardable. -- removed ContiguousCollection -- CircularBuffer(initialRingCapacity:) is now CircularBuffer(initialCapacity:) -- MarkedCircularBuffer(initialRingCapacity:) is now MarkedCircularBuffer(initialCapacity:) -- EventLoopFuture.whenComplete now provides Result -- renamed `EventLoopFuture.then` to `EventLoopFuture.flatMap` -- renamed `EventLoopFuture.thenIfError` to `EventLoopFuture.flatMapError` -- renamed `EventLoopFuture.mapIfError` to `EventLoopFuture.recover` -- renamed `EventLoopFuture.thenThrowing` to `EventLoopFuture.flatMapThrowing` -- renamed `EventLoopFuture`'s generic parameter from `T` to `Value` -- renamed `EventLoopFuture.and(result:)` to `EventLoopFuture.and(value:)` -- the asynchronous task version of `EventLoop.scheduleRepeatedTask` has been renamed to `scheduleRepeatedAsyncTask` -- `EventLoopPromise.succeed(result: Value)` lost its label so is now `EventLoopPromise.succeed(Value)` -- `EventLoopPromise.fail(error: Error)` lost its label so is now `EventLoopPromise.fail(Error)` -- renamed `HTTPProtocolUpgrader` to `HTTPServerProtocolUpgrader` -- `ByteToMessageDecoder`s no longer automatically close the connection on error. -- `EventLoopFuture.cascade(promise: EventLoopPromise)` had its label changed to `EventLoopFuture.cascade(to: EventLoopPromise)` -- `EventLoopFuture.cascadeFailure(promise: EventLoopPromise)` had its label changed to `EventLoopFuture.cascade(to: EventLoopPromise)` -- renamed `EventLoopFuture.andAll(_:eventLoop:)` to `EventLoopFuture.andAllSucceed(_:on:)` -- all `ChannelPipeline.remove(...)` now return `EventLoopFuture` instead of `EventLoopFuture` -- `ByteBuffer.set(, ...)` is now `ByteBuffer.set` -- `ByteBuffer.write(, ...)` is now `ByteBuffer.write` -- renamed `EventLoopFuture.hopTo(eventLoop:)` to `EventLoopFuture.hop(to:)` -- `EventLoopFuture.reduce(into:_:eventLoop:_:)` had its label signature changed to `EventLoopFuture.reduce(into:_:on:_:)` -- `EventLoopFuture.reduce(_:_:eventLoop:_:` had its label signature changed to `EventLoopFuture.reduce(_:_:on:_:)` -- `CircularBuffer` and `MarkedCircularBuffer`'s indices are now opaque and no longer `Strideable`, use `CircularBuffer.index(...)` for index calculations -- all `ChannelOption`s are now required to be `Equatable` -- `HTTPHeaderIndex` has been removed, without replacement -- `HTTPHeader` has been removed, without replacement -- `HTTPHeaders[canonicalForm:]` now returns `[Substring]` instead of `[String]` -- `HTTPListHeaderIterator` has been removed, without replacement -- `WebSocketFrameDecoder`'s `automaticErrorHandling:` parameter has been deprecated. Remove if `false`, add `WebSocketProtocolErrorHandler` to your pipeline instead if `true` -- rename `FileHandle` to `NIOFileHandle` -- rename all `ChannelPipeline.add(name:handler:...)`s to `ChannelPipeline.addHandler(_:name:...)` -- rename all `ChannelPipeline.remove(...)`s to `ChannelPipeline.removeHandler(...)` -- change `ChannelPipeline.addHandler[s](_:first:)` to `ChannelPipeline.addHandler(_:postion:)` where `position` can be `.first`, `.last`, `.before(ChannelHandler)`, and `.after(ChannelHandler)` -- change `ChannelPipeline.addHandler(_:before:)` to `ChannelPipeline.addHandler(_:postion:)` where `position` can be `.first`, `.last`, `.before(ChannelHandler)`, and `.after(ChannelHandler)` -- change `ChannelPipeline.addHandler(_:after:)` to `ChannelPipeline.addHandler(_:postion:)` where `position` can be `.first`, `.last`, `.before(ChannelHandler)`, and `.after(ChannelHandler)` -- Change `HTTPServerProtocolUpgrader` `protocol` to require `buildUpgradeResponse` to take a `channel` and return an `EventLoopFuture`. -- `EmbeddedChannel.writeInbound/Outbound` are now `throwing` -- `EmbeddedChannel.finish/writeInbound/writeOutbound` now return an `enum` representation of their effects rather than mystery bools. -- `HTTPMethod.hasRequestBody` and the `HTTPMethod.HasBody` type have been removed from the public API diff --git a/scripts/build_podspecs.sh b/scripts/build_podspecs.sh index 97814259d1..c11903ee8f 100755 --- a/scripts/build_podspecs.sh +++ b/scripts/build_podspecs.sh @@ -62,10 +62,6 @@ echo "Building podspecs in $tmpfile" targets=( $("${here}/list_topsorted_dependencies.sh" -l -r | grep -v "NIOPriorityQueue" | sed 's/^NIO/SwiftNIO/') ) for target in "${targets[@]}"; do - if [[ "$target" == "_NIO1APIShims" ]]; then - continue - fi - if [[ -n "$skip_until" && "$target" != "$skip_until" ]]; then echo "Skipping $target" continue