Skip to content

Commit

Permalink
Merge pull request #48 from Vinz1911/release/12.0
Browse files Browse the repository at this point in the history
Release/12.0
  • Loading branch information
Vinz1911 authored Dec 14, 2024
2 parents bd217ca + 2975755 commit 2d900a1
Show file tree
Hide file tree
Showing 11 changed files with 48 additions and 52 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/swift.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ on:
- main
jobs:
build-and-test:
runs-on: macos-14
runs-on: macos-15
steps:
- name: 🛒 Checkout Code
uses: actions/checkout@v3
- name: 📦 Set Xcode Version
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: '15.4'
xcode-version: '16.1'
- name: 🛠️ Build and Test with Code Coverage
run: |
swift test --enable-code-coverage
Expand Down
10 changes: 4 additions & 6 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// swift-tools-version: 5.10
// swift-tools-version: 6.0
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "FusionKit",
platforms: [
.iOS(.v16), .macOS(.v14),
.iOS(.v18), .macOS(.v15),
],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
Expand All @@ -23,10 +23,8 @@ let package = Package(
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "FusionKit",
dependencies: [],
swiftSettings: [
.enableExperimentalFeature("StrictConcurrency")
]),
dependencies: []
),
.testTarget(
name: "FusionKitTests",
dependencies: ["FusionKit"]),
Expand Down
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ The `Fusion Framing Protocol (FFP)` is proprietary networking protocol which use
# Overview
| Swift Version | License | Coverage |
|--------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|
| [![Swift 5.10](https://img.shields.io/badge/Swift-5.10-orange.svg?logo=swift&style=flat)](https://swift.org) | [![License](https://img.shields.io/badge/license-GPLv3-blue.svg?longCache=true&style=flat)](https://github.com/Vinz1911/FusionKit/blob/main/LICENSE) | [![codecov](https://codecov.io/github/Vinz1911/FusionKit/branch/main/graph/badge.svg?token=EE3S0BOINS)](https://codecov.io/github/Vinz1911/FusionKit) |
| [![Swift 5.10](https://img.shields.io/badge/SPM-Support-orange.svg?logo=swift&style=flat)](https://swift.org) | | |
| [![Swift 6.0](https://img.shields.io/badge/Swift-6.0-orange.svg?logo=swift&style=flat)](https://swift.org) | [![License](https://img.shields.io/badge/license-GPLv3-blue.svg?longCache=true&style=flat)](https://github.com/Vinz1911/FusionKit/blob/main/LICENSE) | [![codecov](https://codecov.io/github/Vinz1911/FusionKit/branch/main/graph/badge.svg?token=EE3S0BOINS)](https://codecov.io/github/Vinz1911/FusionKit) |
| [![Swift 6.0](https://img.shields.io/badge/SPM-Support-orange.svg?logo=swift&style=flat)](https://swift.org) | | |

## Installation:
### Swift Packages
Expand All @@ -17,7 +17,7 @@ The `Fusion Framing Protocol (FFP)` is proprietary networking protocol which use
// ...
dependencies: [
// Dependencies declare other packages that this package depends on.
.package(url: "https://github.com/Vinz1911/FusionKit.git", from: .init(stringLiteral: "8.0.0")),
.package(url: "https://github.com/Vinz1911/FusionKit.git", from: .init(stringLiteral: "12.0.0")),
],
// ...
```
Expand All @@ -28,10 +28,10 @@ dependencies: [
import FusionKit

// create a new connection
let connection = FKConnection(host: "example.com", port: 8080)
let connection = FKConnection(host: "example.com", port: 7878)

// support for NWParameters, tls example:
let connection = FKConnection(host: "example.com", port: 8080, parameters: .tls)
let connection = FKConnection(host: "example.com", port: 7878, parameters: .tls)

// ...
```
Expand All @@ -42,7 +42,7 @@ let connection = FKConnection(host: "example.com", port: 8080, parameters: .tls)
import FusionKit

// create a new connection
let connection = FKConnection(host: "example.com", port: 8080)
let connection = FKConnection(host: "example.com", port: 7878)

// state update handler
connection.stateUpdateHandler = { state in
Expand All @@ -66,7 +66,7 @@ connection.start()
import FusionKit

// create a new connection
let connection = FKConnection(host: "example.com", port: 8080)
let connection = FKConnection(host: "example.com", port: 7878)

// the framework accepts generic data types
// send strings
Expand All @@ -85,7 +85,7 @@ connection.send(message: UInt16.max)
import FusionKit

// create a new connection
let connection = FKConnection(host: "example.com", port: 8080)
let connection = FKConnection(host: "example.com", port: 7878)

// read incoming messages and transmitted bytes count
connection.receive { message, bytes in
Expand Down
1 change: 0 additions & 1 deletion Sources/FusionKit/Error/FKError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import Foundation

/// The `FKConnection` specific errors
@frozen
public enum FKError: Error, Sendable {
case missingHost
case missingPort
Expand Down
3 changes: 1 addition & 2 deletions Sources/FusionKit/Extensions/Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ internal extension Timer {
let dispatchTimer = DispatchSource.makeTimerSource(flags: .strict, queue: queue)
dispatchTimer.setEventHandler(handler: completion)
dispatchTimer.schedule(deadline: .now() + after, repeating: .never, leeway: .nanoseconds(.zero))
dispatchTimer.resume()
return dispatchTimer
dispatchTimer.resume(); return dispatchTimer
}
}

Expand Down
4 changes: 2 additions & 2 deletions Sources/FusionKit/Model/FKConnection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ public final class FKConnection: FKConnectionProtocol, @unchecked Sendable {
/// - port: the host port as `UInt16`
/// - parameters: network framework `NWParameters`
/// - qos: quality of service class `DispatchQoS`
public required init(host: String, port: UInt16, parameters: NWParameters = .tcp, qos: DispatchQoS = .userInteractive) {
if host.isEmpty { fatalError(FKError.missingHost.description) }; if port == .zero { fatalError(FKError.missingPort.description) }
public required init(host: String, port: UInt16, parameters: NWParameters = .tcp, qos: DispatchQoS = .userInteractive) throws {
if host.isEmpty { throw(FKError.missingHost) }; if port == .zero { throw(FKError.missingPort) }
self.connection = NWConnection(host: NWEndpoint.Host(host), port: NWEndpoint.Port(integerLiteral: port), using: parameters)
self.queue = DispatchQueue(label: .identifier, qos: qos)
}
Expand Down
2 changes: 0 additions & 2 deletions Sources/FusionKit/Model/FKOpcodes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import Foundation

/// Opcodes for framing
@frozen
internal enum FKOpcodes: UInt8, Sendable {
case none = 0x0
case text = 0x1
Expand All @@ -18,7 +17,6 @@ internal enum FKOpcodes: UInt8, Sendable {
}

/// Protocol byte constants
@frozen
internal enum FKConstants: Int, Sendable {
case opcode = 0x1
case control = 0x5
Expand Down
2 changes: 0 additions & 2 deletions Sources/FusionKit/Model/FKState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,13 @@ public struct FKBytes: Sendable {
// MARK: - State Types -

/// The `FKState` state handler
@frozen
public enum FKState: Sendable {
case ready
case cancelled
case failed(Error?)
}

/// The `FKResult` internal message transmitter
@frozen
internal enum FKResult: Sendable {
case message(FKMessage)
case bytes(FKBytes)
Expand Down
2 changes: 1 addition & 1 deletion Sources/FusionKit/Protocols/FKConnectionProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public protocol FKConnectionProtocol: Sendable {
/// - port: the host port as `UInt16`
/// - parameters: network framework `NWParameters`
/// - qos: quality of service class `DispatchQoS`
init(host: String, port: UInt16, parameters: NWParameters, qos: DispatchQoS)
init(host: String, port: UInt16, parameters: NWParameters, qos: DispatchQoS) throws

/// Start a connection
func start() -> Void
Expand Down
2 changes: 1 addition & 1 deletion Sources/FusionKit/Protocols/FKFramerProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import Foundation

internal protocol FKFramerProtocol {
internal protocol FKFramerProtocol: Sendable {
/// The `FKFramer` represents the fusion framing protocol.
/// This is a very fast and lightweight message framing protocol that supports `String` and `Data` based messages.
/// It also supports `UInt16` for ping based transfer responses.
Expand Down
54 changes: 29 additions & 25 deletions Tests/FusionKitTests/FusionKitTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ private enum TestCase {
case ping
}

class FusionKitTests: XCTestCase {
private var connection = FKConnection(host: "de0.weist.org", port: 7878)
class FusionKitTests: XCTestCase, @unchecked Sendable {
private var connection = try? FKConnection(host: "de0.weist.org", port: 7878)
private var buffer = "50000"
private let timeout = 10.0
private let uuid = UUID().uuidString
Expand Down Expand Up @@ -61,14 +61,21 @@ class FusionKitTests: XCTestCase {

/// Start test error description mapping
func testErrorDescription() {
XCTAssertEqual(FKError.missingHost.description, "missing host")
XCTAssertEqual(FKError.missingPort.description, "missing port")
XCTAssertEqual(FKError.connectionTimeout.description, "connection timeout")
XCTAssertEqual(FKError.parsingFailed.description, "message parsing failed")
XCTAssertEqual(FKError.readBufferOverflow.description, "read buffer overflow")
XCTAssertEqual(FKError.writeBufferOverflow.description, "write buffer overflow")
XCTAssertEqual(FKError.unexpectedOpcode.description, "unexpected opcode")

do { _ = try FKConnection(host: "", port: 7878) } catch {
guard let error = error as? FKError else { return }
XCTAssert(error.description == "missing host")
}
do { _ = try FKConnection(host: "de0.weist.org", port: 0) } catch {
guard let error = error as? FKError else { return }
XCTAssert(error.description == "missing port")
}

exp.fulfill()
wait(for: [exp], timeout: timeout)
}
Expand All @@ -80,11 +87,12 @@ private extension FusionKitTests {
/// Create a connection and start
/// - Parameter test: test case
private func start(test: TestCase, cancel: Bool = false) {
guard let connection else { return }
stateUpdateHandler(connection: connection, test: test)
connection.receive { [weak self] message, bytes in
guard let self else { return }
if cancel { connection.cancel() }
if let message { handleMessages(message: message) }
if let message { assertion(message: message) }
}
connection.start()
wait(for: [exp], timeout: timeout)
Expand All @@ -94,38 +102,36 @@ private extension FusionKitTests {
private func framer<T: FKMessage>(message: T) {
let framer = FKFramer()
let message = framer.create(message: message)
switch message {
case .success(let data):

if case let .success(data) = message {
let dispatch = data.withUnsafeBytes { DispatchData(bytes: $0) }
framer.parse(data: dispatch) { result in
switch result {
case .success(let message):
if case let .success(message) = result {
if case let message as String = message { XCTAssertEqual(message, uuid); exp.fulfill() }
if case let message as Data = message { XCTAssertEqual(message, uuid.data(using: .utf8)); exp.fulfill() }
case .failure(let error): XCTFail("failed with error: \(error)") }
}
if case let .failure(error) = result { XCTFail("failed with error: \(error)") }
}
case .failure(let error): XCTFail("failed with error: \(error)") }
}
if case let .failure(error) = message { XCTFail("failed with error: \(error)") }
wait(for: [exp], timeout: timeout)
}

/// Handles test routes for messages
/// - Parameter message: generic `FKMessage`
private func handleMessages(message: FKMessage) {
private func assertion(message: FKMessage) {
guard let connection else { return }
if case let message as UInt16 = message {
XCTAssertEqual(message, UInt16(buffer))
connection.cancel()
exp.fulfill()
connection.cancel(); exp.fulfill()
}
if case let message as Data = message {
XCTAssertEqual(message.count, Int(buffer))
connection.cancel()
exp.fulfill()
connection.cancel(); exp.fulfill()
}
if case let message as String = message {
XCTAssertEqual(message, buffer)
connection.cancel()
exp.fulfill()
connection.cancel(); exp.fulfill()
}
}

Expand All @@ -134,15 +140,13 @@ private extension FusionKitTests {
private func stateUpdateHandler(connection: FKConnection, test: TestCase) {
connection.stateUpdateHandler = { [weak self] state in
guard let self else { return }
switch state {
case .ready:
if case .ready = state {
if test == .string { connection.send(message: buffer) }
if test == .data { connection.send(message: Data(count: Int(buffer)!)) }
if test == .ping { connection.send(message: UInt16(buffer)!) }
case .cancelled: exp.fulfill()
case .failed(let error):
guard let error else { return }
XCTFail("failed with error: \(error)") }
}
if case .cancelled = state { exp.fulfill() }
if case let .failed(error) = state { guard let error else { return }; XCTFail("failed with error: \(error)") }
}
}
}

0 comments on commit 2d900a1

Please sign in to comment.