diff --git a/Package.swift b/Package.swift index 39c6fb4b..a5b3316d 100644 --- a/Package.swift +++ b/Package.swift @@ -16,11 +16,14 @@ import PackageDescription var targets: [PackageDescription.Target] = [ + .target(name: "NIOCore", + dependencies: ["NIOConcurrencyHelpers"]), .target(name: "NIO", dependencies: ["CNIOLinux", "CNIODarwin", "CNIOWindows", - "NIOConcurrencyHelpers"]), + "NIOConcurrencyHelpers", + "NIOCore"]), .target(name: "_NIOConcurrency", dependencies: ["NIO"]), .target(name: "NIOFoundationCompat", dependencies: ["NIO"]), @@ -86,6 +89,7 @@ var targets: [PackageDescription.Target] = [ let package = Package( name: "swift-nio", products: [ + .library(name: "NIOCore", targets: ["NIOCore"]), .library(name: "NIO", targets: ["NIO"]), .library(name: "_NIOConcurrency", targets: ["_NIOConcurrency"]), .library(name: "NIOTLS", targets: ["NIOTLS"]), diff --git a/Sources/NIO/ExportCore.swift b/Sources/NIO/ExportCore.swift new file mode 100644 index 00000000..4ea9d599 --- /dev/null +++ b/Sources/NIO/ExportCore.swift @@ -0,0 +1,14 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftNIO open source project +// +// Copyright (c) 2021 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 +// +//===----------------------------------------------------------------------===// +@_exported import NIOCore diff --git a/Sources/NIO/ByteBuffer-aux.swift b/Sources/NIOCore/ByteBuffer-aux.swift similarity index 100% rename from Sources/NIO/ByteBuffer-aux.swift rename to Sources/NIOCore/ByteBuffer-aux.swift diff --git a/Sources/NIO/ByteBuffer-conversions.swift b/Sources/NIOCore/ByteBuffer-conversions.swift similarity index 100% rename from Sources/NIO/ByteBuffer-conversions.swift rename to Sources/NIOCore/ByteBuffer-conversions.swift diff --git a/Sources/NIO/ByteBuffer-core.swift b/Sources/NIOCore/ByteBuffer-core.swift similarity index 99% rename from Sources/NIO/ByteBuffer-core.swift rename to Sources/NIOCore/ByteBuffer-core.swift index 8132aa2e..7890fd3b 100644 --- a/Sources/NIO/ByteBuffer-core.swift +++ b/Sources/NIOCore/ByteBuffer-core.swift @@ -14,6 +14,10 @@ #if os(Windows) import ucrt +#elseif os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +import Darwin +#else +import Glibc #endif let sysMalloc: @convention(c) (size_t) -> UnsafeMutableRawPointer? = malloc diff --git a/Sources/NIO/ByteBuffer-int.swift b/Sources/NIOCore/ByteBuffer-int.swift similarity index 100% rename from Sources/NIO/ByteBuffer-int.swift rename to Sources/NIOCore/ByteBuffer-int.swift diff --git a/Sources/NIO/ByteBuffer-views.swift b/Sources/NIOCore/ByteBuffer-views.swift similarity index 100% rename from Sources/NIO/ByteBuffer-views.swift rename to Sources/NIOCore/ByteBuffer-views.swift diff --git a/Sources/NIO/CircularBuffer.swift b/Sources/NIOCore/CircularBuffer.swift similarity index 100% rename from Sources/NIO/CircularBuffer.swift rename to Sources/NIOCore/CircularBuffer.swift diff --git a/Sources/NIOCore/IntegerBitPacking.swift b/Sources/NIOCore/IntegerBitPacking.swift new file mode 100644 index 00000000..6eff57f9 --- /dev/null +++ b/Sources/NIOCore/IntegerBitPacking.swift @@ -0,0 +1,103 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftNIO open source project +// +// Copyright (c) 2021 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 +// +//===----------------------------------------------------------------------===// + +// FIXME: Duplicated in NIO. + +@usableFromInline +enum _IntegerBitPacking {} + +extension _IntegerBitPacking { + @inlinable + static func packUU(_ left: Left, + _ right: Right, + type: Result.Type = Result.self) -> Result { + assert(MemoryLayout.size + MemoryLayout.size <= MemoryLayout.size) + + let resultLeft = Result(left) + let resultRight = Result(right) + let result = (resultLeft << Right.bitWidth) | resultRight + assert(result.nonzeroBitCount == left.nonzeroBitCount + right.nonzeroBitCount) + return result + } + + @inlinable + static func unpackUU(_ input: Input, + leftType: Left.Type = Left.self, + rightType: Right.Type = Right.self) -> (Left, Right) { + assert(MemoryLayout.size + MemoryLayout.size <= MemoryLayout.size) + + let leftMask = Input(Left.max) + let rightMask = Input(Right.max) + let right = input & rightMask + let left = (input >> Right.bitWidth) & leftMask + + assert(input.nonzeroBitCount == left.nonzeroBitCount + right.nonzeroBitCount) + return (Left(left), Right(right)) + } +} + +@usableFromInline +enum IntegerBitPacking {} + +extension IntegerBitPacking { + @inlinable + static func packUInt32UInt16UInt8(_ left: UInt32, _ middle: UInt16, _ right: UInt8) -> UInt64 { + return _IntegerBitPacking.packUU( + _IntegerBitPacking.packUU(right, middle, type: UInt32.self), + left + ) + } + + @inlinable + static func unpackUInt32UInt16UInt8(_ value: UInt64) -> (UInt32, UInt16, UInt8) { + let leftRight = _IntegerBitPacking.unpackUU(value, leftType: UInt32.self, rightType: UInt32.self) + let left = _IntegerBitPacking.unpackUU(leftRight.0, leftType: UInt8.self, rightType: UInt16.self) + return (leftRight.1, left.1, left.0) + } + + @inlinable + static func packUInt8UInt8(_ left: UInt8, _ right: UInt8) -> UInt16 { + return _IntegerBitPacking.packUU(left, right) + } + + @inlinable + static func unpackUInt8UInt8(_ value: UInt16) -> (UInt8, UInt8) { + return _IntegerBitPacking.unpackUU(value) + } + + @inlinable + static func packUInt16UInt8(_ left: UInt16, _ right: UInt8) -> UInt32 { + return _IntegerBitPacking.packUU(left, right) + } + + @inlinable + static func unpackUInt16UInt8(_ value: UInt32) -> (UInt16, UInt8) { + return _IntegerBitPacking.unpackUU(value) + } + + @inlinable + static func packUInt32CInt(_ left: UInt32, _ right: CInt) -> UInt64 { + return _IntegerBitPacking.packUU(left, UInt32(truncatingIfNeeded: right)) + } + + @inlinable + static func unpackUInt32CInt(_ value: UInt64) -> (UInt32, CInt) { + let unpacked = _IntegerBitPacking.unpackUU(value, leftType: UInt32.self, rightType: UInt32.self) + return (unpacked.0, CInt(truncatingIfNeeded: unpacked.1)) + } +} diff --git a/Sources/NIOCore/IntegerTypes.swift b/Sources/NIOCore/IntegerTypes.swift new file mode 100644 index 00000000..88edccb4 --- /dev/null +++ b/Sources/NIOCore/IntegerTypes.swift @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// MARK: _UInt24 + +// FIXME: Duplicated in NIO. + +/// A 24-bit unsigned integer value type. +@usableFromInline +struct _UInt24 { + @usableFromInline var _backing: (UInt16, UInt8) + + @inlinable + init(_ value: UInt32) { + assert(value & 0xff_00_00_00 == 0, "value \(value) too large for _UInt24") + self._backing = IntegerBitPacking.unpackUInt16UInt8(value) + } + + static let bitWidth: Int = 24 + + @usableFromInline + static let max: _UInt24 = .init((UInt32(1) << 24) - 1) + + @usableFromInline + static let min: _UInt24 = .init(0) +} + +extension UInt32 { + @inlinable + init(_ value: _UInt24) { + self = IntegerBitPacking.packUInt16UInt8(value._backing.0, value._backing.1) + } +} + +extension Int { + @inlinable + init(_ value: _UInt24) { + self = Int(UInt32(value)) + } +} + + +extension _UInt24: Equatable { + @inlinable + public static func ==(lhs: _UInt24, rhs: _UInt24) -> Bool { + return lhs._backing == rhs._backing + } +} + +extension _UInt24: CustomStringConvertible { + @usableFromInline + var description: String { + return UInt32(self).description + } +} + +// MARK: _UInt56 + +/// A 56-bit unsigned integer value type. +struct _UInt56 { + @usableFromInline var _backing: (UInt32, UInt16, UInt8) + + @inlinable init(_ value: UInt64) { + self._backing = IntegerBitPacking.unpackUInt32UInt16UInt8(value) + } + + static let bitWidth: Int = 56 + + private static let initializeUInt64 : UInt64 = (1 << 56) - 1 + static let max: _UInt56 = .init(initializeUInt64) + static let min: _UInt56 = .init(0) +} + +extension _UInt56 { + init(_ value: Int) { + self.init(UInt64(value)) + } +} + +extension UInt64 { + init(_ value: _UInt56) { + self = IntegerBitPacking.packUInt32UInt16UInt8(value._backing.0, + value._backing.1, + value._backing.2) + } +} + +extension Int { + init(_ value: _UInt56) { + self = Int(UInt64(value)) + } +} + +extension _UInt56: Equatable { + @inlinable + public static func ==(lhs: _UInt56, rhs: _UInt56) -> Bool { + return lhs._backing == rhs._backing + } +} + +extension _UInt56: CustomStringConvertible { + var description: String { + return UInt64(self).description + } +} diff --git a/Sources/NIOCore/PointerHelpers.swift b/Sources/NIOCore/PointerHelpers.swift new file mode 100644 index 00000000..0acc2f2c --- /dev/null +++ b/Sources/NIOCore/PointerHelpers.swift @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// MARK: Rebasing shims + +// FIXME: Duplicated in NIO. + +// These methods are shimmed in to NIO until https://github.com/apple/swift/pull/34879 is resolved. +// They address the fact that the current rebasing initializers are surprisingly expensive and do excessive +// checked arithmetic. This expense forces them to often be outlined, reducing the ability to optimise out +// further preconditions and branches. +extension UnsafeRawBufferPointer { + @inlinable + init(fastRebase slice: Slice) { + let base = slice.base.baseAddress?.advanced(by: slice.startIndex) + self.init(start: base, count: slice.endIndex &- slice.startIndex) + } + + @inlinable + init(fastRebase slice: Slice) { + let base = slice.base.baseAddress?.advanced(by: slice.startIndex) + self.init(start: base, count: slice.endIndex &- slice.startIndex) + } +} + +extension UnsafeMutableRawBufferPointer { + @inlinable + init(fastRebase slice: Slice) { + let base = slice.base.baseAddress?.advanced(by: slice.startIndex) + self.init(start: base, count: slice.endIndex &- slice.startIndex) + } +} diff --git a/Sources/NIO/RecvByteBufferAllocator.swift b/Sources/NIOCore/RecvByteBufferAllocator.swift similarity index 100% rename from Sources/NIO/RecvByteBufferAllocator.swift rename to Sources/NIOCore/RecvByteBufferAllocator.swift diff --git a/Sources/NIOCore/Utilities.swift b/Sources/NIOCore/Utilities.swift new file mode 100644 index 00000000..fb860c2d --- /dev/null +++ b/Sources/NIOCore/Utilities.swift @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftNIO open source project +// +// Copyright (c) 2021 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 +// +//===----------------------------------------------------------------------===// + +/// A utility function that runs the body code only in debug builds, without +/// emitting compiler warnings. +/// +/// This is currently the only way to do this in Swift: see +/// https://forums.swift.org/t/support-debug-only-code/11037 for a discussion. +@inlinable +internal func debugOnly(_ body: () -> Void) { + // FIXME: duplicated with NIO. + assert({ body(); return true }()) +} diff --git a/Tests/NIOTests/ByteBufferTest.swift b/Tests/NIOTests/ByteBufferTest.swift index 954ed062..a9a1e1b1 100644 --- a/Tests/NIOTests/ByteBufferTest.swift +++ b/Tests/NIOTests/ByteBufferTest.swift @@ -14,7 +14,7 @@ import struct Foundation.Data import XCTest -@testable import NIO +@testable import NIOCore import NIOFoundationCompat class ByteBufferTest: XCTestCase { diff --git a/Tests/NIOTests/ChannelTests.swift b/Tests/NIOTests/ChannelTests.swift index 13d22a4d..3470f703 100644 --- a/Tests/NIOTests/ChannelTests.swift +++ b/Tests/NIOTests/ChannelTests.swift @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// import XCTest +@testable import NIOCore @testable import NIO import NIOConcurrencyHelpers import NIOTestUtils diff --git a/Tests/NIOTests/CircularBufferTests.swift b/Tests/NIOTests/CircularBufferTests.swift index 144c313b..aa3a6e74 100644 --- a/Tests/NIOTests/CircularBufferTests.swift +++ b/Tests/NIOTests/CircularBufferTests.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import XCTest -@testable import NIO +@testable import NIOCore class CircularBufferTests: XCTestCase { func testTrivial() { diff --git a/Tests/NIOTests/CodecTest.swift b/Tests/NIOTests/CodecTest.swift index a2bb38fe..0ce9e90f 100644 --- a/Tests/NIOTests/CodecTest.swift +++ b/Tests/NIOTests/CodecTest.swift @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -// import XCTest +@testable import NIOCore @testable import NIO private var testDecoderIsNotQuadratic_mallocs = 0 diff --git a/Tests/NIOTests/IntegerTypesTest.swift b/Tests/NIOTests/IntegerTypesTest.swift index 3c33505c..f1b4a988 100644 --- a/Tests/NIOTests/IntegerTypesTest.swift +++ b/Tests/NIOTests/IntegerTypesTest.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import XCTest -@testable import NIO +@testable import NIOCore public final class IntegerTypesTest: XCTestCase { func testNextPowerOfOfTwoZero() { diff --git a/Tests/NIOTests/PendingDatagramWritesManagerTests.swift b/Tests/NIOTests/PendingDatagramWritesManagerTests.swift index 80c6309a..a247fa66 100644 --- a/Tests/NIOTests/PendingDatagramWritesManagerTests.swift +++ b/Tests/NIOTests/PendingDatagramWritesManagerTests.swift @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +@testable import NIOCore @testable import NIO import XCTest