From c1d8a155f7655010219edd8938249ec4e7cedff8 Mon Sep 17 00:00:00 2001 From: Adam Fowler Date: Tue, 19 Apr 2022 14:05:00 +0100 Subject: [PATCH] Sendable conformance (#104) * Setup Sendable conformance * swift format * Don't need _MQTTSendableProtocol * Revert var -> let so we don't make breaking change * Remove unnecessary @preconcurrency * swift format * comment --- .../MQTTNIO/AsyncAwaitSupport/Sendable.swift | 18 ++++++++++++++++++ Sources/MQTTNIO/MQTTClient.swift | 6 ++++++ Sources/MQTTNIO/MQTTCoreTypes.swift | 18 +++++++++++------- Sources/MQTTNIO/MQTTCoreTypesV5.swift | 14 ++++++-------- Sources/MQTTNIO/MQTTError.swift | 2 +- Sources/MQTTNIO/MQTTPacket.swift | 8 ++++++-- Sources/MQTTNIO/MQTTProperties.swift | 10 +++++++--- Sources/MQTTNIO/MQTTReason.swift | 2 +- Tests/MQTTNIOTests/MQTTNIOTests+async.swift | 1 - 9 files changed, 56 insertions(+), 23 deletions(-) create mode 100644 Sources/MQTTNIO/AsyncAwaitSupport/Sendable.swift diff --git a/Sources/MQTTNIO/AsyncAwaitSupport/Sendable.swift b/Sources/MQTTNIO/AsyncAwaitSupport/Sendable.swift new file mode 100644 index 00000000..df70af0a --- /dev/null +++ b/Sources/MQTTNIO/AsyncAwaitSupport/Sendable.swift @@ -0,0 +1,18 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the MQTTNIO project +// +// Copyright (c) 2020-2021 Adam Fowler +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +#if compiler(>=5.6) +public typealias _MQTTSendable = Sendable +#else +public typealias _MQTTSendable = Any +#endif diff --git a/Sources/MQTTNIO/MQTTClient.swift b/Sources/MQTTNIO/MQTTClient.swift index 1fbf42d7..a62b0608 100644 --- a/Sources/MQTTNIO/MQTTClient.swift +++ b/Sources/MQTTNIO/MQTTClient.swift @@ -739,3 +739,9 @@ extension Logger { return logger } } + +#if compiler(>=5.6) +// All public members of the class are immutable and the class manages access to the +// internal mutable state via Locks +extension MQTTClient: @unchecked Sendable {} +#endif diff --git a/Sources/MQTTNIO/MQTTCoreTypes.swift b/Sources/MQTTNIO/MQTTCoreTypes.swift index e2d6b1e9..2f2cc074 100644 --- a/Sources/MQTTNIO/MQTTCoreTypes.swift +++ b/Sources/MQTTNIO/MQTTCoreTypes.swift @@ -11,9 +11,13 @@ // //===----------------------------------------------------------------------===// -import NIO +#if compiler(>=5.6) +@preconcurrency import NIOCore +#else +import NIOCore +#endif -public enum MQTTQoS: UInt8 { +public enum MQTTQoS: UInt8, _MQTTSendable { /// fire and forget case atMostOnce = 0 /// wait for PUBACK, if you don't receive it after a period of time retry sending @@ -22,7 +26,7 @@ public enum MQTTQoS: UInt8 { case exactlyOnce = 2 } -public enum MQTTPacketType: UInt8 { +public enum MQTTPacketType: UInt8, _MQTTSendable { case CONNECT = 0x10 case CONNACK = 0x20 case PUBLISH = 0x30 @@ -41,7 +45,7 @@ public enum MQTTPacketType: UInt8 { } /// MQTT PUBLISH packet parameters. -public struct MQTTPublishInfo { +public struct MQTTPublishInfo: _MQTTSendable { /// Quality of Service for message. public let qos: MQTTQoS @@ -73,7 +77,7 @@ public struct MQTTPublishInfo { } /// MQTT SUBSCRIBE packet parameters. -public struct MQTTSubscribeInfo { +public struct MQTTSubscribeInfo: _MQTTSendable { /// Topic filter to subscribe to. public let topicFilter: String @@ -89,8 +93,8 @@ public struct MQTTSubscribeInfo { /// MQTT Sub ACK /// /// Contains data returned in subscribe ack packets -public struct MQTTSuback { - public enum ReturnCode: UInt8 { +public struct MQTTSuback: _MQTTSendable { + public enum ReturnCode: UInt8, _MQTTSendable { case grantedQoS0 = 0 case grantedQoS1 = 1 case grantedQoS2 = 2 diff --git a/Sources/MQTTNIO/MQTTCoreTypesV5.swift b/Sources/MQTTNIO/MQTTCoreTypesV5.swift index 11aba3f5..e1a75019 100644 --- a/Sources/MQTTNIO/MQTTCoreTypesV5.swift +++ b/Sources/MQTTNIO/MQTTCoreTypesV5.swift @@ -11,10 +11,8 @@ // //===----------------------------------------------------------------------===// -import NIO - /// MQTT V5 Connack -public struct MQTTConnackV5 { +public struct MQTTConnackV5: _MQTTSendable { /// is using session state from previous session public let sessionPresent: Bool /// connect reason code @@ -24,7 +22,7 @@ public struct MQTTConnackV5 { } /// MQTT V5 ACK information. Returned with PUBACK, PUBREL -public struct MQTTAckV5 { +public struct MQTTAckV5: _MQTTSendable { /// MQTT v5 reason code public let reason: MQTTReasonCode /// MQTT v5 properties @@ -37,9 +35,9 @@ public struct MQTTAckV5 { } /// MQTT SUBSCRIBE packet parameters. -public struct MQTTSubscribeInfoV5 { +public struct MQTTSubscribeInfoV5: _MQTTSendable { /// Retain handling options - public enum RetainHandling: UInt8 { + public enum RetainHandling: UInt8, _MQTTSendable { /// always send retain message case sendAlways = 0 /// send retain if new @@ -81,7 +79,7 @@ public struct MQTTSubscribeInfoV5 { /// MQTT V5 Sub ACK /// /// Contains data returned in subscribe/unsubscribe ack packets -public struct MQTTSubackV5 { +public struct MQTTSubackV5: _MQTTSendable { /// MQTT v5 subscription reason code public let reasons: [MQTTReasonCode] /// MQTT v5 properties @@ -96,7 +94,7 @@ public struct MQTTSubackV5 { /// MQTT V5 Sub ACK /// /// Contains data returned in subscribe/unsubscribe ack packets -public struct MQTTAuthV5 { +public struct MQTTAuthV5: _MQTTSendable { /// MQTT v5 authentication reason code public let reason: MQTTReasonCode /// MQTT v5 properties diff --git a/Sources/MQTTNIO/MQTTError.swift b/Sources/MQTTNIO/MQTTError.swift index 21d18e4a..bd481fa7 100644 --- a/Sources/MQTTNIO/MQTTError.swift +++ b/Sources/MQTTNIO/MQTTError.swift @@ -14,7 +14,7 @@ /// MQTTClient errors public enum MQTTError: Error { /// Value returned in connection error - public enum ConnectionReturnValue: UInt8 { + public enum ConnectionReturnValue: UInt8, _MQTTSendable { /// connection was accepted case accepted = 0 /// The Server does not support the version of the MQTT protocol requested by the Client. diff --git a/Sources/MQTTNIO/MQTTPacket.swift b/Sources/MQTTNIO/MQTTPacket.swift index 78b3743f..6626b7ea 100644 --- a/Sources/MQTTNIO/MQTTPacket.swift +++ b/Sources/MQTTNIO/MQTTPacket.swift @@ -11,7 +11,11 @@ // //===----------------------------------------------------------------------===// -import NIO +#if compiler(>=5.6) +@preconcurrency import NIOCore +#else +import NIOCore +#endif internal enum InternalError: Swift.Error { case incompletePacket @@ -19,7 +23,7 @@ internal enum InternalError: Swift.Error { } /// Protocol for all MQTT packet types -protocol MQTTPacket: CustomStringConvertible { +protocol MQTTPacket: CustomStringConvertible, _MQTTSendable { /// packet type var type: MQTTPacketType { get } /// packet id (default to zero if not used) diff --git a/Sources/MQTTNIO/MQTTProperties.swift b/Sources/MQTTNIO/MQTTProperties.swift index 5965d673..344850a8 100644 --- a/Sources/MQTTNIO/MQTTProperties.swift +++ b/Sources/MQTTNIO/MQTTProperties.swift @@ -11,12 +11,16 @@ // //===----------------------------------------------------------------------===// -import NIO +#if compiler(>=5.6) +@preconcurrency import NIOCore +#else +import NIOCore +#endif /// MQTT v5.0 properties. A property consists of a identifier and a value -public struct MQTTProperties { +public struct MQTTProperties: _MQTTSendable { /// MQTT Property - public enum Property: Equatable { + public enum Property: Equatable, _MQTTSendable { /// Payload format: 0 = bytes, 1 = UTF8 string (available for PUBLISH) case payloadFormat(UInt8) /// Message expiry indicates the lifetime of the message (available for PUBLISH) diff --git a/Sources/MQTTNIO/MQTTReason.swift b/Sources/MQTTNIO/MQTTReason.swift index e4636672..5bfc1b57 100644 --- a/Sources/MQTTNIO/MQTTReason.swift +++ b/Sources/MQTTNIO/MQTTReason.swift @@ -15,7 +15,7 @@ /// Reason codes less than 128 are considered successful. Codes greater than or equal to 128 are considered /// a failure. These are returned by CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, DISCONNECT and /// AUTH packets -public enum MQTTReasonCode: UInt8 { +public enum MQTTReasonCode: UInt8, _MQTTSendable { /// Success (available for all). For SUBACK mean QoS0 is available case success = 0 /// The subscription is accepted and the maximum QoS sent will be QoS 1. This might be a lower QoS than was requested. diff --git a/Tests/MQTTNIOTests/MQTTNIOTests+async.swift b/Tests/MQTTNIOTests/MQTTNIOTests+async.swift index 2ce28b78..4a7f93ad 100644 --- a/Tests/MQTTNIOTests/MQTTNIOTests+async.swift +++ b/Tests/MQTTNIOTests/MQTTNIOTests+async.swift @@ -13,7 +13,6 @@ #if compiler(>=5.5) && canImport(_Concurrency) -import Foundation import Logging import NIO import NIOConcurrencyHelpers