From e076af323fb3ee567193180b649e687d9d88570e Mon Sep 17 00:00:00 2001 From: Adam Fowler Date: Wed, 29 Jan 2025 20:25:44 +0000 Subject: [PATCH 1/5] swift-format --- .github/workflows/ci.yml | 10 ++- .github/workflows/validate.yml | 7 +-- .swift-format | 63 +++++++++++++++++++ .swiftformat | 26 -------- Package.swift | 2 +- .../AsyncAwaitSupport/MQTTClient+async.swift | 28 +++++---- .../MQTTClientV5+async.swift | 21 ++++--- .../ChannelHandlers/MQTTMessageHandler.swift | 22 ++++--- .../ChannelHandlers/WebSocketHandler.swift | 4 +- Sources/MQTTNIO/MQTTClient.swift | 5 +- Sources/MQTTNIO/MQTTClientV5.swift | 8 +-- Sources/MQTTNIO/MQTTConfiguration.swift | 1 + Sources/MQTTNIO/MQTTConnection.swift | 6 +- Sources/MQTTNIO/MQTTPacket.swift | 20 +++--- Sources/MQTTNIO/MQTTProperties.swift | 11 ++-- Sources/MQTTNIO/TSTLSConfiguration.swift | 17 +++-- Tests/MQTTNIOTests/CoreMQTTTests.swift | 3 +- Tests/MQTTNIOTests/MQTTNIOv5Tests.swift | 7 ++- scripts/validate.sh | 11 +--- 19 files changed, 162 insertions(+), 110 deletions(-) create mode 100644 .swift-format delete mode 100644 .swiftformat diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 33a90797..c1a0c96e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,10 +31,9 @@ jobs: -instr-profile=.build/debug/codecov/default.profdata > info.lcov - name: Upload to codecov.io uses: codecov/codecov-action@v4 - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} with: - file: info.lcov + files: info.lcov + token: ${{ secrets.CODECOV_TOKEN }} ios: runs-on: macOS-latest @@ -94,7 +93,6 @@ jobs: -instr-profile .build/debug/codecov/default.profdata > info.lcov - name: Upload to codecov.io uses: codecov/codecov-action@v4 - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} with: - file: info.lcov + files: info.lcov + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 34047888..ba7b9d12 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -2,6 +2,9 @@ name: Validity Check on: pull_request: +concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-validate + cancel-in-progress: true jobs: validate: @@ -11,9 +14,5 @@ jobs: uses: actions/checkout@v1 with: fetch-depth: 1 - - name: Install Dependencies - run: | - brew install mint - mint install nicklockwood/swiftformat@0.52.10 --no-link - name: run script run: ./scripts/validate.sh diff --git a/.swift-format b/.swift-format new file mode 100644 index 00000000..bb3dcff3 --- /dev/null +++ b/.swift-format @@ -0,0 +1,63 @@ +{ + "version" : 1, + "indentation" : { + "spaces" : 4 + }, + "tabWidth" : 4, + "fileScopedDeclarationPrivacy" : { + "accessLevel" : "private" + }, + "spacesAroundRangeFormationOperators" : false, + "indentConditionalCompilationBlocks" : false, + "indentSwitchCaseLabels" : false, + "lineBreakAroundMultilineExpressionChainComponents" : false, + "lineBreakBeforeControlFlowKeywords" : false, + "lineBreakBeforeEachArgument" : true, + "lineBreakBeforeEachGenericRequirement" : true, + "lineLength" : 150, + "maximumBlankLines" : 1, + "respectsExistingLineBreaks" : true, + "prioritizeKeepingFunctionOutputTogether" : true, + "multiElementCollectionTrailingCommas" : true, + "rules" : { + "AllPublicDeclarationsHaveDocumentation" : false, + "AlwaysUseLiteralForEmptyCollectionInit" : false, + "AlwaysUseLowerCamelCase" : false, + "AmbiguousTrailingClosureOverload" : true, + "BeginDocumentationCommentWithOneLineSummary" : false, + "DoNotUseSemicolons" : true, + "DontRepeatTypeInStaticProperties" : true, + "FileScopedDeclarationPrivacy" : true, + "FullyIndirectEnum" : true, + "GroupNumericLiterals" : true, + "IdentifiersMustBeASCII" : true, + "NeverForceUnwrap" : false, + "NeverUseForceTry" : false, + "NeverUseImplicitlyUnwrappedOptionals" : false, + "NoAccessLevelOnExtensionDeclaration" : true, + "NoAssignmentInExpressions" : true, + "NoBlockComments" : true, + "NoCasesWithOnlyFallthrough" : true, + "NoEmptyTrailingClosureParentheses" : true, + "NoLabelsInCasePatterns" : true, + "NoLeadingUnderscores" : false, + "NoParensAroundConditions" : true, + "NoVoidReturnOnFunctionSignature" : true, + "OmitExplicitReturns" : true, + "OneCasePerLine" : true, + "OneVariableDeclarationPerLine" : true, + "OnlyOneTrailingClosureArgument" : true, + "OrderedImports" : true, + "ReplaceForEachWithForLoop" : true, + "ReturnVoidInsteadOfEmptyTuple" : true, + "UseEarlyExits" : false, + "UseExplicitNilCheckInConditions" : false, + "UseLetInEveryBoundCaseVariable" : false, + "UseShorthandTypeNames" : true, + "UseSingleLinePropertyGetter" : false, + "UseSynthesizedInitializer" : false, + "UseTripleSlashForDocumentationComments" : true, + "UseWhereClausesInForLoops" : false, + "ValidateDocumentationComments" : false + } +} diff --git a/.swiftformat b/.swiftformat deleted file mode 100644 index 04434d12..00000000 --- a/.swiftformat +++ /dev/null @@ -1,26 +0,0 @@ -# Minimum swiftformat version ---minversion 0.52.0 - -# Swift version ---swiftversion 5.7 - -# file options ---exclude .build - -# rules ---disable redundantReturn, extensionAccessControl - -# format options ---ifdef no-indent ---nospaceoperators ...,..< ---patternlet inline ---self insert ---stripunusedargs unnamed-only - -#--maxwidth 150 ---wraparguments before-first ---wrapparameters before-first ---wrapcollections before-first - -#file header -#--header "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the MQTTNIO project\n//\n// Copyright (c) 2020-{year} Adam Fowler\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//" diff --git a/Package.swift b/Package.swift index f7ec4bda..e68d90cf 100644 --- a/Package.swift +++ b/Package.swift @@ -6,7 +6,7 @@ let package = Package( name: "mqtt-nio", platforms: [.macOS(.v10_14), .iOS(.v12), .tvOS(.v12), .watchOS(.v6)], products: [ - .library(name: "MQTTNIO", targets: ["MQTTNIO"]), + .library(name: "MQTTNIO", targets: ["MQTTNIO"]) ], dependencies: [ .package(url: "https://github.com/apple/swift-atomics.git", from: "1.0.0"), diff --git a/Sources/MQTTNIO/AsyncAwaitSupport/MQTTClient+async.swift b/Sources/MQTTNIO/AsyncAwaitSupport/MQTTClient+async.swift index 29f33c81..dbfde92f 100644 --- a/Sources/MQTTNIO/AsyncAwaitSupport/MQTTClient+async.swift +++ b/Sources/MQTTNIO/AsyncAwaitSupport/MQTTClient+async.swift @@ -11,13 +11,14 @@ // //===----------------------------------------------------------------------===// +import NIOCore + #if canImport(FoundationEssentials) import Dispatch import FoundationEssentials #else import Foundation #endif -import NIOCore @available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *) extension MQTTClient { @@ -31,7 +32,7 @@ extension MQTTClient { /// - Parameters: /// - queue: Dispatch Queue to run shutdown on public func shutdown(queue: DispatchQueue = .global()) async throws { - return try await withUnsafeThrowingContinuation { cont in + try await withUnsafeThrowingContinuation { cont in self.shutdown(queue: queue) { error in if let error { cont.resume(throwing: error) @@ -59,7 +60,7 @@ extension MQTTClient { cleanSession: Bool = true, will: (topicName: String, payload: ByteBuffer, qos: MQTTQoS, retain: Bool)? = nil ) async throws -> Bool { - return try await self.connect(cleanSession: cleanSession, will: will).get() + try await self.connect(cleanSession: cleanSession, will: will).get() } /// Connect to MQTT server @@ -80,10 +81,11 @@ extension MQTTClient { will: (topicName: String, payload: ByteBuffer, qos: MQTTQoS, retain: Bool)? = nil, connectConfiguration: ConnectConfiguration ) async throws -> Bool { - return try await self.connect( + try await self.connect( cleanSession: cleanSession, - will: will, connectConfiguration: - connectConfiguration + will: will, + connectConfiguration: + connectConfiguration ).get() } @@ -101,7 +103,7 @@ extension MQTTClient { /// - qos: Quality of Service for message. /// - retain: Whether this is a retained message. public func publish(to topicName: String, payload: ByteBuffer, qos: MQTTQoS, retain: Bool = false) async throws { - return try await self.publish(to: topicName, payload: payload, qos: qos, retain: retain).get() + try await self.publish(to: topicName, payload: payload, qos: qos, retain: retain).get() } /// Subscribe to topic @@ -109,7 +111,7 @@ extension MQTTClient { /// Completes when SUBACK is received /// - Parameter subscriptions: Subscription infos public func subscribe(to subscriptions: [MQTTSubscribeInfo]) async throws -> MQTTSuback { - return try await self.subscribe(to: subscriptions).get() + try await self.subscribe(to: subscriptions).get() } /// Unsubscribe from topic @@ -117,7 +119,7 @@ extension MQTTClient { /// Completes when UNSUBACK is received /// - Parameter subscriptions: List of subscriptions to unsubscribe from public func unsubscribe(from subscriptions: [String]) async throws { - return try await self.unsubscribe(from: subscriptions).get() + try await self.unsubscribe(from: subscriptions).get() } /// Ping the server to test if it is still alive and to tell it you are alive. @@ -128,12 +130,12 @@ extension MQTTClient { /// the connection is still live. If you initialize the client with the configuration `disablePingReq: true` then these /// are disabled and it is up to you to send the PINGREQ messages yourself public func ping() async throws { - return try await self.ping().get() + try await self.ping().get() } /// Disconnect from server public func disconnect() async throws { - return try await self.disconnect().get() + try await self.disconnect().get() } /// Create a publish listener AsyncSequence that yields a result whenever a PUBLISH message is received from the server @@ -153,7 +155,7 @@ extension MQTTClient { /// } /// ``` public func createPublishListener() -> MQTTPublishListener { - return .init(self) + .init(self) } } @@ -187,6 +189,6 @@ public class MQTTPublishListener: AsyncSequence { } public __consuming func makeAsyncIterator() -> AsyncStream.AsyncIterator { - return self.stream.makeAsyncIterator() + self.stream.makeAsyncIterator() } } diff --git a/Sources/MQTTNIO/AsyncAwaitSupport/MQTTClientV5+async.swift b/Sources/MQTTNIO/AsyncAwaitSupport/MQTTClientV5+async.swift index 802d61d7..a9490aba 100644 --- a/Sources/MQTTNIO/AsyncAwaitSupport/MQTTClientV5+async.swift +++ b/Sources/MQTTNIO/AsyncAwaitSupport/MQTTClientV5+async.swift @@ -11,12 +11,13 @@ // //===----------------------------------------------------------------------===// +import NIOCore + #if canImport(FoundationEssentials) import FoundationEssentials #else import Foundation #endif -import NIOCore @available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *) extension MQTTClient.V5 { @@ -42,7 +43,7 @@ extension MQTTClient.V5 { will: (topicName: String, payload: ByteBuffer, qos: MQTTQoS, retain: Bool, properties: MQTTProperties)? = nil, authWorkflow: ((MQTTAuthV5, EventLoop) -> EventLoopFuture)? = nil ) async throws -> MQTTConnackV5 { - return try await self.connect(cleanStart: cleanStart, properties: properties, will: will, authWorkflow: authWorkflow).get() + try await self.connect(cleanStart: cleanStart, properties: properties, will: will, authWorkflow: authWorkflow).get() } /// Connect to MQTT server @@ -69,7 +70,7 @@ extension MQTTClient.V5 { authWorkflow: ((MQTTAuthV5, EventLoop) -> EventLoopFuture)? = nil, connectConfiguration: MQTTClient.ConnectConfiguration ) async throws -> MQTTConnackV5 { - return try await self.connect( + try await self.connect( cleanStart: cleanStart, properties: properties, will: will, @@ -95,7 +96,7 @@ extension MQTTClient.V5 { retain: Bool = false, properties: MQTTProperties = .init() ) async throws -> MQTTAckV5? { - return try await self.publish(to: topicName, payload: payload, qos: qos, retain: retain, properties: properties).get() + try await self.publish(to: topicName, payload: payload, qos: qos, retain: retain, properties: properties).get() } /// Subscribe to topic @@ -108,7 +109,7 @@ extension MQTTClient.V5 { to subscriptions: [MQTTSubscribeInfoV5], properties: MQTTProperties = .init() ) async throws -> MQTTSubackV5 { - return try await self.subscribe(to: subscriptions, properties: properties).get() + try await self.subscribe(to: subscriptions, properties: properties).get() } /// Unsubscribe from topic @@ -121,14 +122,14 @@ extension MQTTClient.V5 { from subscriptions: [String], properties: MQTTProperties = .init() ) async throws -> MQTTSubackV5 { - return try await self.unsubscribe(from: subscriptions, properties: properties).get() + try await self.unsubscribe(from: subscriptions, properties: properties).get() } /// Disconnect from server /// - Parameter properties: properties to attach to disconnect packet /// - Returns: Future waiting on disconnect message to be sent public func disconnect(properties: MQTTProperties = .init()) async throws { - return try await self.disconnect(properties: properties).get() + try await self.disconnect(properties: properties).get() } /// Re-authenticate with server @@ -141,13 +142,13 @@ extension MQTTClient.V5 { properties: MQTTProperties, authWorkflow: ((MQTTAuthV5, EventLoop) -> EventLoopFuture)? = nil ) async throws -> MQTTAuthV5 { - return try await self.auth(properties: properties, authWorkflow: authWorkflow).get() + try await self.auth(properties: properties, authWorkflow: authWorkflow).get() } /// Create a publish listener AsyncSequence that yields a value whenever a PUBLISH message is received from the server /// with the specified subscription id public func createPublishListener(subscriptionId: UInt) -> MQTTPublishIdListener { - return .init(self, subscriptionId: subscriptionId) + .init(self, subscriptionId: subscriptionId) } } @@ -181,6 +182,6 @@ public class MQTTPublishIdListener: AsyncSequence { } public __consuming func makeAsyncIterator() -> AsyncStream.AsyncIterator { - return self.stream.makeAsyncIterator() + self.stream.makeAsyncIterator() } } diff --git a/Sources/MQTTNIO/ChannelHandlers/MQTTMessageHandler.swift b/Sources/MQTTNIO/ChannelHandlers/MQTTMessageHandler.swift index efb2c9a9..30075c72 100644 --- a/Sources/MQTTNIO/ChannelHandlers/MQTTMessageHandler.swift +++ b/Sources/MQTTNIO/ChannelHandlers/MQTTMessageHandler.swift @@ -72,11 +72,14 @@ class MQTTMessageHandler: ChannelDuplexHandler { case .PUBLISH: let publishMessage = message as! MQTTPublishPacket // publish logging includes topic name - self.client.logger.trace("MQTT In", metadata: [ - "mqtt_message": .stringConvertible(publishMessage), - "mqtt_packet_id": .stringConvertible(publishMessage.packetId), - "mqtt_topicName": .string(publishMessage.publish.topicName), - ]) + self.client.logger.trace( + "MQTT In", + metadata: [ + "mqtt_message": .stringConvertible(publishMessage), + "mqtt_packet_id": .stringConvertible(publishMessage.packetId), + "mqtt_topicName": .string(publishMessage.publish.topicName), + ] + ) self.respondToPublish(publishMessage) return @@ -99,7 +102,10 @@ class MQTTMessageHandler: ChannelDuplexHandler { self.client.logger.error("Unexpected MQTT Message", metadata: ["mqtt_message": .string("\(message)")]) return } - self.client.logger.trace("MQTT In", metadata: ["mqtt_message": .stringConvertible(message), "mqtt_packet_id": .stringConvertible(message.packetId)]) + self.client.logger.trace( + "MQTT In", + metadata: ["mqtt_message": .stringConvertible(message), "mqtt_packet_id": .stringConvertible(message.packetId)] + ) } } catch { context.fireErrorCaught(error) @@ -124,7 +130,7 @@ class MQTTMessageHandler: ChannelDuplexHandler { case .atLeastOnce: connection.sendMessageNoWait(MQTTPubAckPacket(type: .PUBACK, packetId: message.packetId)) - .map { _ in return message.publish } + .map { _ in message.publish } .whenComplete { self.client.publishListeners.notify($0) } case .exactlyOnce: @@ -141,7 +147,7 @@ class MQTTMessageHandler: ChannelDuplexHandler { // now we have received the PUBREL we can process the published message. PUBCOMP is sent by `respondToPubrel` return true } - .map { _ in return publish } + .map { _ in publish } .whenComplete { result in // do not report retrySend error if case .failure(let error) = result, case MQTTError.retrySend = error { diff --git a/Sources/MQTTNIO/ChannelHandlers/WebSocketHandler.swift b/Sources/MQTTNIO/ChannelHandlers/WebSocketHandler.swift index af17a83d..205d2c29 100644 --- a/Sources/MQTTNIO/ChannelHandlers/WebSocketHandler.swift +++ b/Sources/MQTTNIO/ChannelHandlers/WebSocketHandler.swift @@ -134,7 +134,7 @@ final class WebSocketHandler: ChannelDuplexHandler { private func pong(context: ChannelHandlerContext, frame: WebSocketFrame) { var frameData = frame.unmaskedData guard let frameDataString = frameData.readString(length: Self.pingData.count), - frameDataString == Self.pingData + frameDataString == Self.pingData else { self.close(context: context, code: .goingAway, promise: nil) return @@ -234,7 +234,7 @@ extension WebSocketErrorCode { case .invalidFrameLength: self = .messageTooLarge case .fragmentedControlFrame, - .multiByteControlFrameLength: + .multiByteControlFrameLength: self = .protocolError } } diff --git a/Sources/MQTTNIO/MQTTClient.swift b/Sources/MQTTNIO/MQTTClient.swift index 1a5a3367..98a4f28b 100644 --- a/Sources/MQTTNIO/MQTTClient.swift +++ b/Sources/MQTTNIO/MQTTClient.swift @@ -480,7 +480,8 @@ extension MQTTClient { let connectFuture = MQTTConnection.create(client: self, pingInterval: pingInterval) let eventLoop = connectFuture.eventLoop - return connectFuture + return + connectFuture .flatMap { connection -> EventLoopFuture in self.connection = connection connection.closeFuture.whenComplete { result in @@ -716,7 +717,7 @@ extension MQTTClient { .flatMapErrorThrowing { error in // if publish caused server to close the connection then remove from inflight array if case MQTTError.serverDisconnection(let ack) = error, - ack.reason == .malformedPacket + ack.reason == .malformedPacket { self.inflight.remove(id: packet.packetId) } diff --git a/Sources/MQTTNIO/MQTTClientV5.swift b/Sources/MQTTNIO/MQTTClientV5.swift index b4eb0783..b9a3e98c 100644 --- a/Sources/MQTTNIO/MQTTClientV5.swift +++ b/Sources/MQTTNIO/MQTTClientV5.swift @@ -140,7 +140,7 @@ extension MQTTClient { let packet = MQTTSubscribePacket(subscriptions: subscriptions, properties: properties, packetId: packetId) return self.client.subscribe(packet: packet) .map { message in - return MQTTSubackV5(reasons: message.reasons, properties: message.properties) + MQTTSubackV5(reasons: message.reasons, properties: message.properties) } } @@ -158,7 +158,7 @@ extension MQTTClient { let packet = MQTTUnsubscribePacket(subscriptions: subscriptions, properties: properties, packetId: packetId) return self.client.unsubscribe(packet: packet) .map { message in - return MQTTSubackV5(reasons: message.reasons, properties: message.properties) + MQTTSubackV5(reasons: message.reasons, properties: message.properties) } } @@ -166,7 +166,7 @@ extension MQTTClient { /// - Parameter properties: properties to attach to disconnect packet /// - Returns: Future waiting on disconnect message to be sent public func disconnect(properties: MQTTProperties = .init()) -> EventLoopFuture { - return self.client.disconnect(packet: MQTTDisconnectPacket(reason: .success, properties: properties)) + self.client.disconnect(packet: MQTTDisconnectPacket(reason: .success, properties: properties)) } /// Re-authenticate with server @@ -208,7 +208,7 @@ extension MQTTClient { if case .success(let info) = result { for property in info.properties { if case .subscriptionIdentifier(let id) = property, - id == subscriptionId + id == subscriptionId { listener(info) break diff --git a/Sources/MQTTNIO/MQTTConfiguration.swift b/Sources/MQTTNIO/MQTTConfiguration.swift index 0826e240..00394be8 100644 --- a/Sources/MQTTNIO/MQTTConfiguration.swift +++ b/Sources/MQTTNIO/MQTTConfiguration.swift @@ -13,6 +13,7 @@ import NIO import NIOHTTP1 + #if os(macOS) || os(Linux) import NIOSSL #endif diff --git a/Sources/MQTTNIO/MQTTConnection.swift b/Sources/MQTTNIO/MQTTConnection.swift index a852e2c4..942d711f 100644 --- a/Sources/MQTTNIO/MQTTConnection.swift +++ b/Sources/MQTTNIO/MQTTConnection.swift @@ -107,7 +107,7 @@ final class MQTTConnection { #if canImport(Network) // if eventLoop is compatible with NIOTransportServices create a NIOTSConnectionBootstrap if #available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *), - let tsBootstrap = NIOTSConnectionBootstrap(validatingGroup: client.eventLoopGroup) + let tsBootstrap = NIOTSConnectionBootstrap(validatingGroup: client.eventLoopGroup) { // create NIOClientTCPBootstrap with NIOTS TLS provider let options: NWProtocolTLS.Options @@ -131,7 +131,7 @@ final class MQTTConnection { } #endif - #if os(macOS) || os(Linux) // canImport(Network) + #if os(macOS) || os(Linux) // canImport(Network) if let clientBootstrap = ClientBootstrap(validatingGroup: client.eventLoopGroup) { let tlsConfiguration: TLSConfiguration switch client.configuration.tlsConfiguration { @@ -196,7 +196,7 @@ final class MQTTConnection { } func sendMessageNoWait(_ message: MQTTPacket) -> EventLoopFuture { - return self.channel.writeAndFlush(message) + self.channel.writeAndFlush(message) } func close() -> EventLoopFuture { diff --git a/Sources/MQTTNIO/MQTTPacket.swift b/Sources/MQTTNIO/MQTTPacket.swift index c10a8e96..f5902340 100644 --- a/Sources/MQTTNIO/MQTTPacket.swift +++ b/Sources/MQTTNIO/MQTTPacket.swift @@ -315,7 +315,7 @@ struct MQTTSubscribePacket: MQTTPacket { } // payload return self.subscriptions.reduce(size) { - $0 + 2 + $1.topicFilter.utf8.count + 1 // topic filter length + topic filter + qos + $0 + 2 + $1.topicFilter.utf8.count + 1 // topic filter length + topic filter + qos } } } @@ -358,7 +358,7 @@ struct MQTTUnsubscribePacket: MQTTPacket { } // payload return self.subscriptions.reduce(size) { - $0 + 2 + $1.utf8.count // topic filter length + topic filter + $0 + 2 + $1.utf8.count // topic filter length + topic filter } } } @@ -386,7 +386,7 @@ struct MQTTPubAckPacket: MQTTPacket { writeFixedHeader(packetType: self.type, size: self.packetSize(version: version), to: &byteBuffer) byteBuffer.writeInteger(self.packetId) if version == .v5_0, - self.reason != .success || self.properties.count > 0 + self.reason != .success || self.properties.count > 0 { byteBuffer.writeInteger(self.reason.rawValue) try self.properties.write(to: &byteBuffer) @@ -404,7 +404,7 @@ struct MQTTPubAckPacket: MQTTPacket { return MQTTPubAckPacket(type: packet.type, packetId: packetId) } guard let reasonByte: UInt8 = remainingData.readInteger(), - let reason = MQTTReasonCode(rawValue: reasonByte) + let reason = MQTTReasonCode(rawValue: reasonByte) else { throw MQTTError.badResponse } @@ -415,7 +415,7 @@ struct MQTTPubAckPacket: MQTTPacket { func packetSize(version: MQTTClient.Version) -> Int { if version == .v5_0, - self.reason != .success || self.properties.count > 0 + self.reason != .success || self.properties.count > 0 { let propertiesPacketSize = self.properties.packetSize return 3 + MQTTSerializer.variableLengthIntegerPacketSize(propertiesPacketSize) + propertiesPacketSize @@ -495,7 +495,7 @@ struct MQTTPingrespPacket: MQTTPacket { } static func read(version: MQTTClient.Version, from packet: MQTTIncomingPacket) throws -> Self { - return MQTTPingrespPacket() + MQTTPingrespPacket() } var packetSize: Int { 0 } @@ -515,7 +515,7 @@ struct MQTTDisconnectPacket: MQTTPacket { func write(version: MQTTClient.Version, to byteBuffer: inout ByteBuffer) throws { writeFixedHeader(packetType: self.type, size: self.packetSize(version: version), to: &byteBuffer) if version == .v5_0, - self.reason != .success || self.properties.count > 0 + self.reason != .success || self.properties.count > 0 { byteBuffer.writeInteger(self.reason.rawValue) try self.properties.write(to: &byteBuffer) @@ -532,7 +532,7 @@ struct MQTTDisconnectPacket: MQTTPacket { return MQTTDisconnectPacket(reason: .success) } guard let reasonByte: UInt8 = buffer.readInteger(), - let reason = MQTTReasonCode(rawValue: reasonByte) + let reason = MQTTReasonCode(rawValue: reasonByte) else { throw MQTTError.badResponse } @@ -543,7 +543,7 @@ struct MQTTDisconnectPacket: MQTTPacket { func packetSize(version: MQTTClient.Version) -> Int { if version == .v5_0, - self.reason != .success || self.properties.count > 0 + self.reason != .success || self.properties.count > 0 { let propertiesPacketSize = self.properties.packetSize return 1 + MQTTSerializer.variableLengthIntegerPacketSize(propertiesPacketSize) + propertiesPacketSize @@ -604,7 +604,7 @@ struct MQTTAuthPacket: MQTTPacket { return MQTTAuthPacket(reason: .success, properties: .init()) } guard let reasonByte: UInt8 = remainingData.readInteger(), - let reason = MQTTReasonCode(rawValue: reasonByte) + let reason = MQTTReasonCode(rawValue: reasonByte) else { throw MQTTError.badResponse } diff --git a/Sources/MQTTNIO/MQTTProperties.swift b/Sources/MQTTNIO/MQTTProperties.swift index 12510599..acf3ad3c 100644 --- a/Sources/MQTTNIO/MQTTProperties.swift +++ b/Sources/MQTTNIO/MQTTProperties.swift @@ -104,11 +104,11 @@ extension MQTTProperties: Collection { public var endIndex: Index { self.properties.endIndex } public subscript(_ index: Index) -> Property { - return self.properties[index] + self.properties[index] } public func index(after index: Index) -> Index { - return self.properties.index(after: index) + self.properties.index(after: index) } } @@ -136,7 +136,7 @@ extension MQTTProperties { } var packetSize: Int { - return self.properties.reduce(0) { $0 + 1 + $1.value.packetSize } + self.properties.reduce(0) { $0 + 1 + $1.value.packetSize } } enum PropertyId: UInt8 { @@ -355,7 +355,8 @@ extension MQTTProperties.Property { return .topicAlias(value) case .maximumQoS: guard let value: UInt8 = byteBuffer.readInteger(), - let qos = MQTTQoS(rawValue: value) else { throw MQTTError.badResponse } + let qos = MQTTQoS(rawValue: value) + else { throw MQTTError.badResponse } return .maximumQoS(qos) case .retainAvailable: guard let value: UInt8 = byteBuffer.readInteger() else { throw MQTTError.badResponse } @@ -380,6 +381,6 @@ extension MQTTProperties.Property { } var packetSize: Int { - return self.value.packetSize + self.value.packetSize } } diff --git a/Sources/MQTTNIO/TSTLSConfiguration.swift b/Sources/MQTTNIO/TSTLSConfiguration.swift index 0a41a9e1..5334bfd0 100644 --- a/Sources/MQTTNIO/TSTLSConfiguration.swift +++ b/Sources/MQTTNIO/TSTLSConfiguration.swift @@ -103,7 +103,9 @@ public struct TSTLSConfiguration { public static func pem(_ filename: String) throws -> Self { let certificates = try NIOSSLCertificate.fromPEMFile(filename) let secCertificates = try certificates.map { certificate -> SecCertificate in - guard let certificate = try SecCertificateCreateWithData(nil, Data(certificate.toDERBytes()) as CFData) else { throw TSTLSConfiguration.Error.invalidData } + guard let certificate = try SecCertificateCreateWithData(nil, Data(certificate.toDERBytes()) as CFData) else { + throw TSTLSConfiguration.Error.invalidData + } return certificate } return .init(certificates: secCertificates) @@ -113,7 +115,9 @@ public struct TSTLSConfiguration { /// Create certificate array from DER file public static func der(_ filename: String) throws -> Self { let certificateData = try Data(contentsOf: URL(fileURLWithPath: filename)) - guard let secCertificate = SecCertificateCreateWithData(nil, certificateData as CFData) else { throw TSTLSConfiguration.Error.invalidData } + guard let secCertificate = SecCertificateCreateWithData(nil, certificateData as CFData) else { + throw TSTLSConfiguration.Error.invalidData + } return .init(certificates: [secCertificate]) } } @@ -130,10 +134,12 @@ public struct TSTLSConfiguration { let data = try Data(contentsOf: URL(fileURLWithPath: filename)) let options: [String: String] = [kSecImportExportPassphrase as String: password] var rawItems: CFArray? - guard SecPKCS12Import(data as CFData, options as CFDictionary, &rawItems) == errSecSuccess else { throw TSTLSConfiguration.Error.invalidData } + guard SecPKCS12Import(data as CFData, options as CFDictionary, &rawItems) == errSecSuccess else { + throw TSTLSConfiguration.Error.invalidData + } let items = rawItems! as! [[String: Any]] guard let firstItem = items.first, - let secIdentity = firstItem[kSecImportItemIdentity as String] as! SecIdentity? + let secIdentity = firstItem[kSecImportItemIdentity as String] as! SecIdentity? else { throw TSTLSConfiguration.Error.invalidData } @@ -268,7 +274,8 @@ extension TSTLSConfiguration { } } } - }, Self.tlsDispatchQueue + }, + Self.tlsDispatchQueue ) } return options diff --git a/Tests/MQTTNIOTests/CoreMQTTTests.swift b/Tests/MQTTNIOTests/CoreMQTTTests.swift index e8615a94..4180ca4d 100644 --- a/Tests/MQTTNIOTests/CoreMQTTTests.swift +++ b/Tests/MQTTNIOTests/CoreMQTTTests.swift @@ -11,10 +11,11 @@ // //===----------------------------------------------------------------------===// -@testable import MQTTNIO import NIO import XCTest +@testable import MQTTNIO + final class CoreMQTTTests: XCTestCase { func testConnect() throws { let publish = MQTTPublishInfo( diff --git a/Tests/MQTTNIOTests/MQTTNIOv5Tests.swift b/Tests/MQTTNIOTests/MQTTNIOv5Tests.swift index b9f4dddd..cb8b40da 100644 --- a/Tests/MQTTNIOTests/MQTTNIOv5Tests.swift +++ b/Tests/MQTTNIOTests/MQTTNIOv5Tests.swift @@ -17,10 +17,12 @@ import NIO import NIOFoundationCompat import NIOHTTP1 import XCTest + +@testable import MQTTNIO + #if os(macOS) || os(Linux) import NIOSSL #endif -@testable import MQTTNIO final class MQTTNIOv5Tests: XCTestCase { static let hostname = ProcessInfo.processInfo.environment["MOSQUITTO_SERVER"] ?? "localhost" @@ -288,7 +290,8 @@ final class MQTTNIOv5Tests: XCTestCase { expectation.expectedFulfillmentCount = 2 expectation.assertForOverFulfill = true - let payloadString = #"{"from":1000000,"to":1234567,"type":1,"content":"I am a beginner in swift and I am studying hard!!测试\n\n test, message","timestamp":1607243024,"nonce":"pAx2EsUuXrVuiIU3GGOGHNbUjzRRdT5b","sign":"ff902e31a6a5f5343d70a3a93ac9f946adf1caccab539c6f3a6"}"# + let payloadString = + #"{"from":1000000,"to":1234567,"type":1,"content":"I am a beginner in swift and I am studying hard!!测试\n\n test, message","timestamp":1607243024,"nonce":"pAx2EsUuXrVuiIU3GGOGHNbUjzRRdT5b","sign":"ff902e31a6a5f5343d70a3a93ac9f946adf1caccab539c6f3a6"}"# let payload = ByteBufferAllocator().buffer(string: payloadString) let client = self.createClient(identifier: "testPersistentSession_publisherV5") diff --git a/scripts/validate.sh b/scripts/validate.sh index 210f4cc0..10284167 100755 --- a/scripts/validate.sh +++ b/scripts/validate.sh @@ -24,13 +24,9 @@ command -v swiftformat >/dev/null || { printf "=> Checking format... " FIRST_OUT="$(git status --porcelain)" -if [[ -n "${CI-""}" ]]; then - printf "(using v%s) " "$(mint run NickLockwood/SwiftFormat@$SWIFT_FORMAT_VERSION --version)" - mint run NickLockwood/SwiftFormat@$SWIFT_FORMAT_VERSION . > /dev/null 2>&1 -else - printf "(using v%s) " "$(swiftformat --version)" - swiftformat . > /dev/null 2>&1 -fi +git ls-files -z '*.swift' | xargs -0 swift format format --parallel --in-place +git diff --exit-code '*.swift' + SECOND_OUT="$(git status --porcelain)" if [[ "$FIRST_OUT" != "$SECOND_OUT" ]]; then printf "\033[0;31mformatting issues!\033[0m\n" @@ -39,4 +35,3 @@ if [[ "$FIRST_OUT" != "$SECOND_OUT" ]]; then else printf "\033[0;32mokay.\033[0m\n" fi - From 873a85174325b0d708c0e480956360ed73d8d3a4 Mon Sep 17 00:00:00 2001 From: Adam Fowler Date: Wed, 29 Jan 2025 20:26:20 +0000 Subject: [PATCH 2/5] checkout v4 --- .github/workflows/validate.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index ba7b9d12..434025a9 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -8,10 +8,11 @@ concurrency: jobs: validate: - runs-on: macOS-latest + runs-on: ubuntu-latest + timeout-minutes: 15 steps: - name: Checkout - uses: actions/checkout@v1 + uses: actions/checkout@v4 with: fetch-depth: 1 - name: run script From 6881de9c275dd059eb2d3ef21af4d5ca951d2261 Mon Sep 17 00:00:00 2001 From: Adam Fowler Date: Wed, 29 Jan 2025 20:27:20 +0000 Subject: [PATCH 3/5] Add dependabot --- .github/dependabot.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..b1752285 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,24 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + ignore: + - dependency-name: "codecov/codecov-action" + update-types: ["version-update:semver-major"] + groups: + dependencies: + patterns: + - "*" + - package-ecosystem: "swift" + directory: "/" + schedule: + interval: "daily" + open-pull-requests-limit: 5 + allow: + - dependency-type: all + groups: + all-dependencies: + patterns: + - "*" From 5c7f67714ee674b50ce4d3238ffbf1f0ab3ff74a Mon Sep 17 00:00:00 2001 From: Adam Fowler Date: Wed, 29 Jan 2025 20:29:29 +0000 Subject: [PATCH 4/5] Update validate.sh --- scripts/validate.sh | 7 ------- 1 file changed, 7 deletions(-) diff --git a/scripts/validate.sh b/scripts/validate.sh index 10284167..6ad4df2c 100755 --- a/scripts/validate.sh +++ b/scripts/validate.sh @@ -13,15 +13,8 @@ ## ##===----------------------------------------------------------------------===## -SWIFT_FORMAT_VERSION=0.52.10 - set -eu -command -v swiftformat >/dev/null || { - echo "swiftformat not installed. You can install it using 'mint install nicklockwood/swiftformat'" - exit 1 -} - printf "=> Checking format... " FIRST_OUT="$(git status --porcelain)" git ls-files -z '*.swift' | xargs -0 swift format format --parallel --in-place From ef16b8d3f5bcdc39aaac191b7938060ab70e72cb Mon Sep 17 00:00:00 2001 From: Adam Fowler Date: Wed, 29 Jan 2025 20:35:38 +0000 Subject: [PATCH 5/5] Fix generic parameter 'T' could not be inferred --- Sources/MQTTNIO/AsyncAwaitSupport/MQTTClient+async.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/MQTTNIO/AsyncAwaitSupport/MQTTClient+async.swift b/Sources/MQTTNIO/AsyncAwaitSupport/MQTTClient+async.swift index dbfde92f..67dd4c0c 100644 --- a/Sources/MQTTNIO/AsyncAwaitSupport/MQTTClient+async.swift +++ b/Sources/MQTTNIO/AsyncAwaitSupport/MQTTClient+async.swift @@ -32,7 +32,7 @@ extension MQTTClient { /// - Parameters: /// - queue: Dispatch Queue to run shutdown on public func shutdown(queue: DispatchQueue = .global()) async throws { - try await withUnsafeThrowingContinuation { cont in + try await withUnsafeThrowingContinuation { (cont: UnsafeContinuation) in self.shutdown(queue: queue) { error in if let error { cont.resume(throwing: error)