From 2dbf6ed3108c8d54613e13d57aa6b8bcd6dcfba3 Mon Sep 17 00:00:00 2001 From: Honza Dvorsky Date: Fri, 20 Feb 2026 17:30:01 +0100 Subject: [PATCH 1/5] Migrate to Swift 6.0+ and Swift 6 language mode --- .devcontainer/devcontainer.json | 39 ++++++++++ .github/workflows/main.yml | 7 +- .github/workflows/pull_request.yml | 7 +- .../OpenAPIRuntimeBenchmarks/Benchmarks.swift | 9 ++- Benchmarks/Package.swift | 2 +- Package.swift | 31 +++++--- Sources/OpenAPIRuntime/Base/Acceptable.swift | 2 + .../Base/Base64EncodedData.swift | 4 + .../Base/ContentDisposition.swift | 6 +- .../OpenAPIRuntime/Base/CopyOnWriteBox.swift | 3 + .../OpenAPIRuntime/Base/OpenAPIMIMEType.swift | 5 ++ .../OpenAPIRuntime/Base/OpenAPIValue.swift | 10 +-- .../Base/UndocumentedPayload.swift | 2 +- .../Conversion/Configuration.swift | 4 +- .../Conversion/Converter+Client.swift | 3 +- .../Conversion/Converter+Common.swift | 7 +- .../Conversion/Converter+Server.swift | 3 +- .../OpenAPIRuntime/Conversion/Converter.swift | 8 +- .../Conversion/CurrencyExtensions.swift | 1 + .../Conversion/ErrorExtensions.swift | 1 + .../Conversion/FoundationExtensions.swift | 1 + .../Conversion/ServerVariable.swift | 2 +- .../Conversion/URLExtensions.swift | 7 +- .../Deprecated/Deprecated.swift | 7 +- .../OpenAPIRuntime/Errors/ClientError.swift | 9 +-- .../OpenAPIRuntime/Errors/CodingErrors.swift | 5 ++ .../OpenAPIRuntime/Errors/RuntimeError.swift | 8 +- .../OpenAPIRuntime/Errors/ServerError.swift | 4 +- .../EventStreams/JSONLinesDecoding.swift | 12 +-- .../EventStreams/JSONLinesEncoding.swift | 9 ++- .../EventStreams/JSONSequenceDecoding.swift | 13 ++-- .../EventStreams/JSONSequenceEncoding.swift | 9 ++- .../ServerSentEventsDecoding.swift | 13 +++- .../ServerSentEventsEncoding.swift | 9 +-- .../Interface/AsyncSequenceCommon.swift | 9 +++ .../Interface/ClientTransport.swift | 8 +- .../Interface/CurrencyTypes.swift | 2 +- .../Interface/ErrorHandlingMiddleware.swift | 2 +- .../OpenAPIRuntime/Interface/HTTPBody.swift | 7 +- .../Interface/SendableMetatype.swift | 19 +++++ .../Interface/ServerTransport.swift | 2 +- .../Interface/UniversalClient.swift | 9 ++- .../Interface/UniversalServer.swift | 9 +-- .../MultipartBoundaryGenerator.swift | 1 + .../MultipartBytesToFramesSequence.swift | 6 +- .../MultipartFramesToBytesSequence.swift | 6 +- .../MultipartFramesToRawPartsSequence.swift | 14 +++- .../Multipart/MultipartPublicTypes.swift | 5 +- .../MultipartPublicTypesExtensions.swift | 6 +- .../MultipartRawPartsToFramesSequence.swift | 6 +- .../Multipart/MultipartValidation.swift | 6 +- .../URICoder/Common/URICodeCodingKey.swift | 4 + .../Common/URICoderConfiguration.swift | 4 + .../URICoder/Common/URIEncodedNode.swift | 4 + .../URICoder/Common/URIParsedTypes.swift | 4 + .../URICoder/Decoding/URIDecoder.swift | 4 + .../URIValueFromNodeDecoder+Keyed.swift | 4 + .../URIValueFromNodeDecoder+Single.swift | 4 + .../URIValueFromNodeDecoder+Unkeyed.swift | 4 + .../Decoding/URIValueFromNodeDecoder.swift | 4 + .../URICoder/Encoding/URIEncoder.swift | 4 + .../URIValueToNodeEncoder+Keyed.swift | 4 + .../URIValueToNodeEncoder+Single.swift | 4 + .../URIValueToNodeEncoder+Unkeyed.swift | 4 + .../Encoding/URIValueToNodeEncoder.swift | 4 + .../AsyncSyncSequence.swift | 76 +++++++++++++++++++ .../Conversion/Test_Configuration.swift | 7 +- .../Conversion/Test_Converter+Client.swift | 2 +- .../EventStreams/Test_JSONLinesDecoding.swift | 7 +- .../EventStreams/Test_JSONLinesEncoding.swift | 7 +- .../Test_JSONSequenceDecoding.swift | 7 +- .../Test_JSONSequenceEncoding.swift | 7 +- .../Test_ServerSentEventsDecoding.swift | 7 +- .../Test_ServerSentEventsEncoding.swift | 7 +- .../Interface/Test_HTTPBody.swift | 7 +- .../Interface/Test_MultipartBody.swift | 7 +- .../Interface/Test_UniversalClient.swift | 15 ++-- .../Interface/Test_UniversalServer.swift | 7 +- .../Test_MultipartBoundaryGenerator.swift | 7 +- .../Test_MultipartBytesToFramesSequence.swift | 10 ++- .../Test_MultipartFramesToBytesSequence.swift | 10 ++- ...st_MultipartFramesToRawPartsSequence.swift | 15 ++-- ...st_MultipartRawPartsToFramesSequence.swift | 29 ++++--- .../Test_MultipartValidationSequence.swift | 10 ++- Tests/OpenAPIRuntimeTests/Test_Runtime.swift | 6 +- .../URICoder/Decoder/Test_URIDecoder.swift | 2 +- .../URICoder/Test_URICodingRoundtrip.swift | 9 ++- 87 files changed, 536 insertions(+), 160 deletions(-) create mode 100644 .devcontainer/devcontainer.json create mode 100644 Sources/OpenAPIRuntime/Interface/SendableMetatype.swift create mode 100644 Tests/OpenAPIRuntimeTests/AsyncSyncSequence.swift diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..ec68805f --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,39 @@ +{ + "name": "Swift", + "image": "swift:6.2", + "features": { + "ghcr.io/devcontainers/features/common-utils:2": { + "installZsh": "false", + "username": "vscode", + "upgradePackages": "false" + }, + "ghcr.io/devcontainers/features/git:1": { + "version": "os-provided", + "ppa": "false" + } + }, + "runArgs": [ + "--cap-add=SYS_PTRACE", + "--security-opt", + "seccomp=unconfined" + ], + // Configure tool-specific properties. + "customizations": { + // Configure properties specific to VS Code. + "vscode": { + // Set *default* container specific settings.json values on container create. + "settings": { + "lldb.library": "/usr/lib/liblldb.so" + }, + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "swiftlang.swift-vscode" + ] + } + }, + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Set `remoteUser` to `root` to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. + "remoteUser": "vscode" +} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ed95591a..36f8c267 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,8 +14,7 @@ jobs: name: Unit tests uses: apple/swift-nio/.github/workflows/unit_tests.yml@main with: - linux_5_9_arguments_override: "--explicit-target-dependency-import-check error" - linux_5_10_arguments_override: "--explicit-target-dependency-import-check error" + linux_5_10_enabled: false linux_6_0_arguments_override: "--explicit-target-dependency-import-check error" linux_6_1_arguments_override: "--explicit-target-dependency-import-check error" linux_6_2_arguments_override: "--explicit-target-dependency-import-check error" @@ -24,12 +23,12 @@ jobs: windows_6_0_enabled: true windows_6_1_enabled: true windows_6_2_enabled: true - windows_nightly_6_1_enabled: true + windows_nightly_next_enabled: true windows_nightly_main_enabled: true windows_6_0_arguments_override: "--explicit-target-dependency-import-check error" windows_6_1_arguments_override: "--explicit-target-dependency-import-check error" windows_6_2_arguments_override: "--explicit-target-dependency-import-check error" - windows_nightly_6_1_arguments_override: "--explicit-target-dependency-import-check error" + windows_nightly_next_arguments_override: "--explicit-target-dependency-import-check error" windows_nightly_main_arguments_override: "--explicit-target-dependency-import-check error" construct-integration-test-matrix: diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index b988f24f..2fd20881 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -18,8 +18,7 @@ jobs: name: Unit tests uses: apple/swift-nio/.github/workflows/unit_tests.yml@main with: - linux_5_9_arguments_override: "--explicit-target-dependency-import-check error" - linux_5_10_arguments_override: "--explicit-target-dependency-import-check error" + linux_5_10_enabled: false linux_6_0_arguments_override: "--explicit-target-dependency-import-check error" linux_6_1_arguments_override: "--explicit-target-dependency-import-check error" linux_6_2_arguments_override: "--explicit-target-dependency-import-check error" @@ -28,12 +27,12 @@ jobs: windows_6_0_enabled: true windows_6_1_enabled: true windows_6_2_enabled: true - windows_nightly_6_1_enabled: true + windows_nightly_next_enabled: true windows_nightly_main_enabled: true windows_6_0_arguments_override: "--explicit-target-dependency-import-check error" windows_6_1_arguments_override: "--explicit-target-dependency-import-check error" windows_6_2_arguments_override: "--explicit-target-dependency-import-check error" - windows_nightly_6_1_arguments_override: "--explicit-target-dependency-import-check error" + windows_nightly_next_arguments_override: "--explicit-target-dependency-import-check error" windows_nightly_main_arguments_override: "--explicit-target-dependency-import-check error" construct-integration-test-matrix: diff --git a/Benchmarks/Benchmarks/OpenAPIRuntimeBenchmarks/Benchmarks.swift b/Benchmarks/Benchmarks/OpenAPIRuntimeBenchmarks/Benchmarks.swift index 634a0d65..7b921fdf 100644 --- a/Benchmarks/Benchmarks/OpenAPIRuntimeBenchmarks/Benchmarks.swift +++ b/Benchmarks/Benchmarks/OpenAPIRuntimeBenchmarks/Benchmarks.swift @@ -11,11 +11,16 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else +import Foundation +#endif import Benchmark import OpenAPIRuntime -import Foundation -let benchmarks = { +let benchmarks: @Sendable () -> Void = { let defaultMetrics: [BenchmarkMetric] = [.mallocCountTotal, .cpuTotal] Benchmark( diff --git a/Benchmarks/Package.swift b/Benchmarks/Package.swift index 1294475e..fd23dcf2 100644 --- a/Benchmarks/Package.swift +++ b/Benchmarks/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 5.9 +// swift-tools-version: 6.0 import PackageDescription let package = Package( diff --git a/Package.swift b/Package.swift index 58fc1d4d..ea6977e1 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 5.9 +// swift-tools-version: 6.0 //===----------------------------------------------------------------------===// // // This source file is part of the SwiftOpenAPIGenerator open source project @@ -51,16 +51,23 @@ let package = Package( ] ) -// --- STANDARD CROSS-REPO SETTINGS DO NOT EDIT --- // for target in package.targets { - switch target.type { - case .regular, .test, .executable: - var settings = target.swiftSettings ?? [] - // https://github.com/swiftlang/swift-evolution/blob/main/proposals/0444-member-import-visibility.md - settings.append(.enableUpcomingFeature("MemberImportVisibility")) - target.swiftSettings = settings - case .macro, .plugin, .system, .binary: () // not applicable - @unknown default: () // we don't know what to do here, do nothing - } + var settings = target.swiftSettings ?? [] + + // https://github.com/apple/swift-evolution/blob/main/proposals/0335-existential-any.md + // Require `any` for existential types. + settings.append(.enableUpcomingFeature("ExistentialAny")) + + // https://github.com/swiftlang/swift-evolution/blob/main/proposals/0444-member-import-visibility.md + settings.append(.enableUpcomingFeature("MemberImportVisibility")) + + // https://github.com/swiftlang/swift-evolution/blob/main/proposals/0409-access-level-on-imports.md + settings.append(.enableUpcomingFeature("InternalImportsByDefault")) + + #if compiler(>=6.2) + // Ensure all public types are explicitly annotated as Sendable or not Sendable. + settings.append(.unsafeFlags(["-Xfrontend", "-require-explicit-sendable"])) + #endif + + target.swiftSettings = settings } -// --- END: STANDARD CROSS-REPO SETTINGS DO NOT EDIT --- // diff --git a/Sources/OpenAPIRuntime/Base/Acceptable.swift b/Sources/OpenAPIRuntime/Base/Acceptable.swift index 2f1b5e21..51093017 100644 --- a/Sources/OpenAPIRuntime/Base/Acceptable.swift +++ b/Sources/OpenAPIRuntime/Base/Acceptable.swift @@ -11,6 +11,8 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +// Full Foundation needed for String(format:) import Foundation /// The protocol that all generated `AcceptableContentType` enums conform to. diff --git a/Sources/OpenAPIRuntime/Base/Base64EncodedData.swift b/Sources/OpenAPIRuntime/Base/Base64EncodedData.swift index ce3c43fa..e75e7255 100644 --- a/Sources/OpenAPIRuntime/Base/Base64EncodedData.swift +++ b/Sources/OpenAPIRuntime/Base/Base64EncodedData.swift @@ -12,7 +12,11 @@ // //===----------------------------------------------------------------------===// +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// A type for converting data as a base64 string. /// diff --git a/Sources/OpenAPIRuntime/Base/ContentDisposition.swift b/Sources/OpenAPIRuntime/Base/ContentDisposition.swift index 11a43dc0..09b501f3 100644 --- a/Sources/OpenAPIRuntime/Base/ContentDisposition.swift +++ b/Sources/OpenAPIRuntime/Base/ContentDisposition.swift @@ -11,6 +11,8 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +// Full Foundation needed for String.trimmingCharacters import Foundation /// A parsed representation of the `content-disposition` header described by RFC 6266 containing only @@ -105,9 +107,9 @@ extension ContentDisposition: RawRepresentable { var components = rawValue.split(separator: ";").map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } guard !components.isEmpty else { return nil } self.dispositionType = DispositionType(rawValue: components.removeFirst()) - let parameterTuples: [(ParameterName, String)] = components.compactMap { component in + let parameterTuples: [(ParameterName, String)] = components.compactMap { (component: String) -> (ParameterName, String)? in let parameterComponents = component.split(separator: "=", maxSplits: 1) - .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } + .map { $0.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) } guard parameterComponents.count == 2 else { return nil } let valueWithoutQuotes = parameterComponents[1].trimmingCharacters(in: ["\""]) return (.init(rawValue: parameterComponents[0]), valueWithoutQuotes) diff --git a/Sources/OpenAPIRuntime/Base/CopyOnWriteBox.swift b/Sources/OpenAPIRuntime/Base/CopyOnWriteBox.swift index f876666e..7e433960 100644 --- a/Sources/OpenAPIRuntime/Base/CopyOnWriteBox.swift +++ b/Sources/OpenAPIRuntime/Base/CopyOnWriteBox.swift @@ -46,6 +46,9 @@ } } +@available(*, unavailable) +extension CopyOnWriteBox.Storage: Sendable {} + extension CopyOnWriteBox: Encodable where Wrapped: Encodable { /// Encodes this value into the given encoder. diff --git a/Sources/OpenAPIRuntime/Base/OpenAPIMIMEType.swift b/Sources/OpenAPIRuntime/Base/OpenAPIMIMEType.swift index 3d7adef8..d47195d2 100644 --- a/Sources/OpenAPIRuntime/Base/OpenAPIMIMEType.swift +++ b/Sources/OpenAPIRuntime/Base/OpenAPIMIMEType.swift @@ -11,7 +11,12 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// A container for a parsed, valid MIME type. @_spi(Generated) public struct OpenAPIMIMEType: Equatable, Sendable { diff --git a/Sources/OpenAPIRuntime/Base/OpenAPIValue.swift b/Sources/OpenAPIRuntime/Base/OpenAPIValue.swift index 83da78c1..dcd55c23 100644 --- a/Sources/OpenAPIRuntime/Base/OpenAPIValue.swift +++ b/Sources/OpenAPIRuntime/Base/OpenAPIValue.swift @@ -12,17 +12,11 @@ // //===----------------------------------------------------------------------===// -#if canImport(Foundation) -#if canImport(Darwin) -import class Foundation.NSNull -#else -@preconcurrency import class Foundation.NSNull -#endif -import class Foundation.NSNumber +// Full Foundation needed for NSNull +import Foundation #if canImport(CoreFoundation) import CoreFoundation #endif -#endif /// A container for a value represented by JSON Schema. /// diff --git a/Sources/OpenAPIRuntime/Base/UndocumentedPayload.swift b/Sources/OpenAPIRuntime/Base/UndocumentedPayload.swift index 399256de..9b16bc03 100644 --- a/Sources/OpenAPIRuntime/Base/UndocumentedPayload.swift +++ b/Sources/OpenAPIRuntime/Base/UndocumentedPayload.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import HTTPTypes +public import HTTPTypes /// A payload value used by undocumented operation responses. /// diff --git a/Sources/OpenAPIRuntime/Conversion/Configuration.swift b/Sources/OpenAPIRuntime/Conversion/Configuration.swift index 2ee7ab00..40798379 100644 --- a/Sources/OpenAPIRuntime/Conversion/Configuration.swift +++ b/Sources/OpenAPIRuntime/Conversion/Configuration.swift @@ -11,7 +11,9 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// -import Foundation + +// Full Foundation needed for NSLock +public import Foundation /// A type that allows customization of Date encoding and decoding. /// diff --git a/Sources/OpenAPIRuntime/Conversion/Converter+Client.swift b/Sources/OpenAPIRuntime/Conversion/Converter+Client.swift index 28abbdb2..181d06d4 100644 --- a/Sources/OpenAPIRuntime/Conversion/Converter+Client.swift +++ b/Sources/OpenAPIRuntime/Conversion/Converter+Client.swift @@ -11,8 +11,9 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + import Foundation -import HTTPTypes +public import HTTPTypes extension Converter { diff --git a/Sources/OpenAPIRuntime/Conversion/Converter+Common.swift b/Sources/OpenAPIRuntime/Conversion/Converter+Common.swift index 73f8fecb..537146de 100644 --- a/Sources/OpenAPIRuntime/Conversion/Converter+Common.swift +++ b/Sources/OpenAPIRuntime/Conversion/Converter+Common.swift @@ -11,8 +11,13 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation -import HTTPTypes +#endif +public import HTTPTypes extension Converter { diff --git a/Sources/OpenAPIRuntime/Conversion/Converter+Server.swift b/Sources/OpenAPIRuntime/Conversion/Converter+Server.swift index a3088bd3..03746e30 100644 --- a/Sources/OpenAPIRuntime/Conversion/Converter+Server.swift +++ b/Sources/OpenAPIRuntime/Conversion/Converter+Server.swift @@ -11,8 +11,9 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + import Foundation -import HTTPTypes +public import HTTPTypes extension Converter { diff --git a/Sources/OpenAPIRuntime/Conversion/Converter.swift b/Sources/OpenAPIRuntime/Conversion/Converter.swift index 606790f7..e1e4f714 100644 --- a/Sources/OpenAPIRuntime/Conversion/Converter.swift +++ b/Sources/OpenAPIRuntime/Conversion/Converter.swift @@ -11,12 +11,12 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// -#if canImport(Darwin) -import class Foundation.JSONEncoder + +#if canImport(FoundationEssentials) +import FoundationEssentials #else -@preconcurrency import class Foundation.JSONEncoder +import Foundation #endif -import class Foundation.JSONDecoder /// Converter between generated and HTTP currency types. @_spi(Generated) public struct Converter: Sendable { diff --git a/Sources/OpenAPIRuntime/Conversion/CurrencyExtensions.swift b/Sources/OpenAPIRuntime/Conversion/CurrencyExtensions.swift index fc50b2a1..27663b33 100644 --- a/Sources/OpenAPIRuntime/Conversion/CurrencyExtensions.swift +++ b/Sources/OpenAPIRuntime/Conversion/CurrencyExtensions.swift @@ -11,6 +11,7 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + import Foundation import HTTPTypes diff --git a/Sources/OpenAPIRuntime/Conversion/ErrorExtensions.swift b/Sources/OpenAPIRuntime/Conversion/ErrorExtensions.swift index b8e32edc..bcf3fd34 100644 --- a/Sources/OpenAPIRuntime/Conversion/ErrorExtensions.swift +++ b/Sources/OpenAPIRuntime/Conversion/ErrorExtensions.swift @@ -11,6 +11,7 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + import Foundation extension DecodingError { diff --git a/Sources/OpenAPIRuntime/Conversion/FoundationExtensions.swift b/Sources/OpenAPIRuntime/Conversion/FoundationExtensions.swift index 8f0117b3..f58c24f9 100644 --- a/Sources/OpenAPIRuntime/Conversion/FoundationExtensions.swift +++ b/Sources/OpenAPIRuntime/Conversion/FoundationExtensions.swift @@ -11,6 +11,7 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + import Foundation extension String { diff --git a/Sources/OpenAPIRuntime/Conversion/ServerVariable.swift b/Sources/OpenAPIRuntime/Conversion/ServerVariable.swift index a9658afa..69bf219d 100644 --- a/Sources/OpenAPIRuntime/Conversion/ServerVariable.swift +++ b/Sources/OpenAPIRuntime/Conversion/ServerVariable.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import Foundation +public import Foundation extension URL { /// Returns a validated server URL created from the URL template, or diff --git a/Sources/OpenAPIRuntime/Conversion/URLExtensions.swift b/Sources/OpenAPIRuntime/Conversion/URLExtensions.swift index 432d78ae..b4658225 100644 --- a/Sources/OpenAPIRuntime/Conversion/URLExtensions.swift +++ b/Sources/OpenAPIRuntime/Conversion/URLExtensions.swift @@ -11,7 +11,12 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// -import Foundation + +#if canImport(FoundationEssentials) +public import FoundationEssentials +#else +public import Foundation +#endif extension URL { /// Returns the default server URL of "/". diff --git a/Sources/OpenAPIRuntime/Deprecated/Deprecated.swift b/Sources/OpenAPIRuntime/Deprecated/Deprecated.swift index 2ce41750..ee9d865e 100644 --- a/Sources/OpenAPIRuntime/Deprecated/Deprecated.swift +++ b/Sources/OpenAPIRuntime/Deprecated/Deprecated.swift @@ -11,7 +11,12 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// -import Foundation + +#if canImport(FoundationEssentials) +public import FoundationEssentials +#else +public import Foundation +#endif import HTTPTypes // MARK: - Functionality to be removed in the future diff --git a/Sources/OpenAPIRuntime/Errors/ClientError.swift b/Sources/OpenAPIRuntime/Errors/ClientError.swift index eb0c8005..89862063 100644 --- a/Sources/OpenAPIRuntime/Errors/ClientError.swift +++ b/Sources/OpenAPIRuntime/Errors/ClientError.swift @@ -12,13 +12,8 @@ // //===----------------------------------------------------------------------===// -import HTTPTypes -#if canImport(Darwin) -import struct Foundation.URL -#else -@preconcurrency import struct Foundation.URL -#endif -import protocol Foundation.LocalizedError +public import Foundation +public import HTTPTypes /// An error thrown by a client performing an OpenAPI operation. /// diff --git a/Sources/OpenAPIRuntime/Errors/CodingErrors.swift b/Sources/OpenAPIRuntime/Errors/CodingErrors.swift index 12bdb42c..50b66fec 100644 --- a/Sources/OpenAPIRuntime/Errors/CodingErrors.swift +++ b/Sources/OpenAPIRuntime/Errors/CodingErrors.swift @@ -11,7 +11,12 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif extension DecodingError: PrettyStringConvertible { var prettyDescription: String { diff --git a/Sources/OpenAPIRuntime/Errors/RuntimeError.swift b/Sources/OpenAPIRuntime/Errors/RuntimeError.swift index 95c29913..6ea5caf5 100644 --- a/Sources/OpenAPIRuntime/Errors/RuntimeError.swift +++ b/Sources/OpenAPIRuntime/Errors/RuntimeError.swift @@ -11,8 +11,12 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// -import protocol Foundation.LocalizedError -import struct Foundation.Data + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else +import Foundation +#endif import HTTPTypes /// Error thrown by generated code. diff --git a/Sources/OpenAPIRuntime/Errors/ServerError.swift b/Sources/OpenAPIRuntime/Errors/ServerError.swift index adcb2687..0fa5b2b8 100644 --- a/Sources/OpenAPIRuntime/Errors/ServerError.swift +++ b/Sources/OpenAPIRuntime/Errors/ServerError.swift @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -import HTTPTypes -import protocol Foundation.LocalizedError +public import Foundation +public import HTTPTypes /// An error thrown by a server handling an OpenAPI operation. public struct ServerError: Error, HTTPResponseConvertible { diff --git a/Sources/OpenAPIRuntime/EventStreams/JSONLinesDecoding.swift b/Sources/OpenAPIRuntime/EventStreams/JSONLinesDecoding.swift index eed9acdc..3209e4cb 100644 --- a/Sources/OpenAPIRuntime/EventStreams/JSONLinesDecoding.swift +++ b/Sources/OpenAPIRuntime/EventStreams/JSONLinesDecoding.swift @@ -12,12 +12,11 @@ // //===----------------------------------------------------------------------===// -#if canImport(Darwin) -import class Foundation.JSONDecoder +#if canImport(FoundationEssentials) +public import FoundationEssentials #else -@preconcurrency import class Foundation.JSONDecoder +public import Foundation #endif -import struct Foundation.Data /// A sequence that parses arbitrary byte chunks into lines using the JSON Lines format. public struct JSONLinesDeserializationSequence: Sendable @@ -72,6 +71,9 @@ extension JSONLinesDeserializationSequence: AsyncSequence { } } +@available(*, unavailable) +extension JSONLinesDeserializationSequence.Iterator: Sendable {} + extension AsyncSequence where Element == ArraySlice { /// Returns another sequence that decodes each JSON Lines event as the provided type using the provided decoder. @@ -79,7 +81,7 @@ extension AsyncSequence where Element == ArraySlice { /// - eventType: The type to decode the JSON event into. /// - decoder: The JSON decoder to use. /// - Returns: A sequence that provides the decoded JSON events. - public func asDecodedJSONLines( + public func asDecodedJSONLines( of eventType: Event.Type = Event.self, decoder: JSONDecoder = .init() ) -> AsyncThrowingMapSequence, Event> { diff --git a/Sources/OpenAPIRuntime/EventStreams/JSONLinesEncoding.swift b/Sources/OpenAPIRuntime/EventStreams/JSONLinesEncoding.swift index f1d9b9b8..e56e9f0d 100644 --- a/Sources/OpenAPIRuntime/EventStreams/JSONLinesEncoding.swift +++ b/Sources/OpenAPIRuntime/EventStreams/JSONLinesEncoding.swift @@ -12,10 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Darwin) -import class Foundation.JSONEncoder +#if canImport(FoundationEssentials) +public import FoundationEssentials #else -@preconcurrency import class Foundation.JSONEncoder +public import Foundation #endif /// A sequence that serializes lines by concatenating them using the JSON Lines format. @@ -69,6 +69,9 @@ extension JSONLinesSerializationSequence: AsyncSequence { } } +@available(*, unavailable) +extension JSONLinesSerializationSequence.Iterator: Sendable {} + extension AsyncSequence where Element: Encodable & Sendable, Self: Sendable { /// Returns another sequence that encodes the events using the provided encoder into JSON Lines. diff --git a/Sources/OpenAPIRuntime/EventStreams/JSONSequenceDecoding.swift b/Sources/OpenAPIRuntime/EventStreams/JSONSequenceDecoding.swift index 4b34658c..e61d2e4c 100644 --- a/Sources/OpenAPIRuntime/EventStreams/JSONSequenceDecoding.swift +++ b/Sources/OpenAPIRuntime/EventStreams/JSONSequenceDecoding.swift @@ -12,13 +12,11 @@ // //===----------------------------------------------------------------------===// -#if canImport(Darwin) -import class Foundation.JSONDecoder +#if canImport(FoundationEssentials) +public import FoundationEssentials #else -@preconcurrency import class Foundation.JSONDecoder +public import Foundation #endif -import protocol Foundation.LocalizedError -import struct Foundation.Data /// A sequence that parses arbitrary byte chunks into lines using the JSON Sequence format. public struct JSONSequenceDeserializationSequence: Sendable @@ -92,6 +90,9 @@ extension JSONSequenceDeserializationSequence: AsyncSequence { } } +@available(*, unavailable) +extension JSONSequenceDeserializationSequence.Iterator: Sendable {} + extension AsyncSequence where Element == ArraySlice { /// Returns another sequence that decodes each JSON Sequence event as the provided type using the provided decoder. @@ -99,7 +100,7 @@ extension AsyncSequence where Element == ArraySlice { /// - eventType: The type to decode the JSON event into. /// - decoder: The JSON decoder to use. /// - Returns: A sequence that provides the decoded JSON events. - public func asDecodedJSONSequence( + public func asDecodedJSONSequence( of eventType: Event.Type = Event.self, decoder: JSONDecoder = .init() ) -> AsyncThrowingMapSequence, Event> { diff --git a/Sources/OpenAPIRuntime/EventStreams/JSONSequenceEncoding.swift b/Sources/OpenAPIRuntime/EventStreams/JSONSequenceEncoding.swift index a6ffe940..a62acb31 100644 --- a/Sources/OpenAPIRuntime/EventStreams/JSONSequenceEncoding.swift +++ b/Sources/OpenAPIRuntime/EventStreams/JSONSequenceEncoding.swift @@ -12,10 +12,10 @@ // //===----------------------------------------------------------------------===// -#if canImport(Darwin) -import class Foundation.JSONEncoder +#if canImport(FoundationEssentials) +public import FoundationEssentials #else -@preconcurrency import class Foundation.JSONEncoder +public import Foundation #endif /// A sequence that serializes lines by concatenating them using the JSON Sequence format. @@ -69,6 +69,9 @@ extension JSONSequenceSerializationSequence: AsyncSequence { } } +@available(*, unavailable) +extension JSONSequenceSerializationSequence.Iterator: Sendable {} + extension AsyncSequence where Element: Encodable & Sendable, Self: Sendable { /// Returns another sequence that encodes the events using the provided encoder into a JSON Sequence. diff --git a/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsDecoding.swift b/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsDecoding.swift index 34f51b21..33a9964c 100644 --- a/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsDecoding.swift +++ b/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsDecoding.swift @@ -12,12 +12,11 @@ // //===----------------------------------------------------------------------===// -#if canImport(Darwin) -import class Foundation.JSONDecoder +#if canImport(FoundationEssentials) +public import FoundationEssentials #else -@preconcurrency import class Foundation.JSONDecoder +public import Foundation #endif -import struct Foundation.Data /// A sequence that parses arbitrary byte chunks into events using the Server-sent Events format. /// @@ -94,6 +93,9 @@ extension ServerSentEventsDeserializationSequence: AsyncSequence { } } +@available(*, unavailable) +extension ServerSentEventsDeserializationSequence.Iterator: Sendable {} + extension AsyncSequence where Element == ArraySlice, Self: Sendable { /// Returns another sequence that decodes each event's data as the provided type using the provided decoder. @@ -346,6 +348,9 @@ extension ServerSentEventsLineDeserializationSequence: AsyncSequence { } } +@available(*, unavailable) +extension ServerSentEventsLineDeserializationSequence.Iterator: Sendable {} + extension ServerSentEventsLineDeserializationSequence.Iterator { /// A state machine for parsing lines in Server-Sent Events. diff --git a/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift b/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift index 853d76d2..557d622f 100644 --- a/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift +++ b/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift @@ -12,11 +12,7 @@ // //===----------------------------------------------------------------------===// -#if canImport(Darwin) -import class Foundation.JSONEncoder -#else -@preconcurrency import class Foundation.JSONEncoder -#endif +public import Foundation /// A sequence that serializes Server-sent Events. public struct ServerSentEventsSerializationSequence: Sendable @@ -69,6 +65,9 @@ extension ServerSentEventsSerializationSequence: AsyncSequence { } } +@available(*, unavailable) +extension ServerSentEventsSerializationSequence.Iterator: Sendable {} + extension AsyncSequence { /// Returns another sequence that encodes Server-sent Events with generic data in the data field. diff --git a/Sources/OpenAPIRuntime/Interface/AsyncSequenceCommon.swift b/Sources/OpenAPIRuntime/Interface/AsyncSequenceCommon.swift index 392eead8..24917a8c 100644 --- a/Sources/OpenAPIRuntime/Interface/AsyncSequenceCommon.swift +++ b/Sources/OpenAPIRuntime/Interface/AsyncSequenceCommon.swift @@ -50,6 +50,9 @@ public enum IterationBehavior: Sendable { public mutating func next() async throws -> Element? { try await produceNext() } } +@available(*, unavailable) +extension AnyIterator: Sendable {} + /// A type-erased async sequence that wraps input sequences. @usableFromInline struct AnySequence: AsyncSequence, Sendable { @@ -101,6 +104,9 @@ where Upstream.Element: Sendable { @usableFromInline func makeAsyncIterator() -> AsyncIterator { Iterator(iterator: sequence.makeIterator()) } } +@available(*, unavailable) +extension WrappedSyncSequence.Iterator: Sendable {} + /// An empty async sequence. @usableFromInline struct EmptySequence: AsyncSequence, Sendable { @@ -118,3 +124,6 @@ where Upstream.Element: Sendable { @usableFromInline func makeAsyncIterator() -> AsyncIterator { EmptyIterator() } } + +@available(*, unavailable) +extension EmptySequence.EmptyIterator: Sendable {} diff --git a/Sources/OpenAPIRuntime/Interface/ClientTransport.swift b/Sources/OpenAPIRuntime/Interface/ClientTransport.swift index cb20c651..80737397 100644 --- a/Sources/OpenAPIRuntime/Interface/ClientTransport.swift +++ b/Sources/OpenAPIRuntime/Interface/ClientTransport.swift @@ -12,8 +12,12 @@ // //===----------------------------------------------------------------------===// -import HTTPTypes -import struct Foundation.URL +#if canImport(FoundationEssentials) +public import FoundationEssentials +#else +public import Foundation +#endif +public import HTTPTypes /// A type that performs HTTP operations. /// diff --git a/Sources/OpenAPIRuntime/Interface/CurrencyTypes.swift b/Sources/OpenAPIRuntime/Interface/CurrencyTypes.swift index 9e3e4542..d64a418f 100644 --- a/Sources/OpenAPIRuntime/Interface/CurrencyTypes.swift +++ b/Sources/OpenAPIRuntime/Interface/CurrencyTypes.swift @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -import HTTPTypes import Foundation +public import HTTPTypes /// A container for request metadata already parsed and validated /// by the server transport. diff --git a/Sources/OpenAPIRuntime/Interface/ErrorHandlingMiddleware.swift b/Sources/OpenAPIRuntime/Interface/ErrorHandlingMiddleware.swift index 1fb49409..d03fcb86 100644 --- a/Sources/OpenAPIRuntime/Interface/ErrorHandlingMiddleware.swift +++ b/Sources/OpenAPIRuntime/Interface/ErrorHandlingMiddleware.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import HTTPTypes +public import HTTPTypes /// An opt-in error handling middleware that converts an error to an HTTP response. /// diff --git a/Sources/OpenAPIRuntime/Interface/HTTPBody.swift b/Sources/OpenAPIRuntime/Interface/HTTPBody.swift index 59292ec9..114045df 100644 --- a/Sources/OpenAPIRuntime/Interface/HTTPBody.swift +++ b/Sources/OpenAPIRuntime/Interface/HTTPBody.swift @@ -12,9 +12,7 @@ // //===----------------------------------------------------------------------===// -import class Foundation.NSLock -import protocol Foundation.LocalizedError -import struct Foundation.Data // only for convenience initializers +public import Foundation /// A body of an HTTP request or HTTP response. /// @@ -562,3 +560,6 @@ extension HTTPBody { public mutating func next() async throws -> Element? { try await produceNext() } } } + +@available(*, unavailable) +extension HTTPBody.Iterator: Sendable {} diff --git a/Sources/OpenAPIRuntime/Interface/SendableMetatype.swift b/Sources/OpenAPIRuntime/Interface/SendableMetatype.swift new file mode 100644 index 00000000..cc86343e --- /dev/null +++ b/Sources/OpenAPIRuntime/Interface/SendableMetatype.swift @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftOpenAPIGenerator open source project +// +// Copyright (c) 2026 Apple Inc. and the SwiftOpenAPIGenerator project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftOpenAPIGenerator project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +#if compiler(>=6.2) +public typealias _OpenAPIRuntimeSendableMetatype = SendableMetatype +#else +public typealias _OpenAPIRuntimeSendableMetatype = Any +#endif \ No newline at end of file diff --git a/Sources/OpenAPIRuntime/Interface/ServerTransport.swift b/Sources/OpenAPIRuntime/Interface/ServerTransport.swift index 0984ed21..a1f35eaf 100644 --- a/Sources/OpenAPIRuntime/Interface/ServerTransport.swift +++ b/Sources/OpenAPIRuntime/Interface/ServerTransport.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import HTTPTypes +public import HTTPTypes /// A type that registers and handles HTTP operations. /// diff --git a/Sources/OpenAPIRuntime/Interface/UniversalClient.swift b/Sources/OpenAPIRuntime/Interface/UniversalClient.swift index 5afff2b1..991a208f 100644 --- a/Sources/OpenAPIRuntime/Interface/UniversalClient.swift +++ b/Sources/OpenAPIRuntime/Interface/UniversalClient.swift @@ -11,12 +11,13 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// -import HTTPTypes -#if canImport(Darwin) -import struct Foundation.URL + +#if canImport(FoundationEssentials) +public import FoundationEssentials #else -@preconcurrency import struct Foundation.URL +public import Foundation #endif +public import HTTPTypes /// OpenAPI document-agnostic HTTP client used by OpenAPI document-specific, /// generated clients to perform request serialization, middleware and transport diff --git a/Sources/OpenAPIRuntime/Interface/UniversalServer.swift b/Sources/OpenAPIRuntime/Interface/UniversalServer.swift index 2153ccea..d96915e5 100644 --- a/Sources/OpenAPIRuntime/Interface/UniversalServer.swift +++ b/Sources/OpenAPIRuntime/Interface/UniversalServer.swift @@ -12,13 +12,12 @@ // //===----------------------------------------------------------------------===// -import HTTPTypes -#if canImport(Darwin) -import struct Foundation.URL +#if canImport(FoundationEssentials) +public import FoundationEssentials #else -@preconcurrency import struct Foundation.URL +public import Foundation #endif -import struct Foundation.URLComponents +public import HTTPTypes /// OpenAPI document-agnostic HTTP server used by OpenAPI document-specific, /// generated servers to perform request deserialization, middleware and handler diff --git a/Sources/OpenAPIRuntime/Multipart/MultipartBoundaryGenerator.swift b/Sources/OpenAPIRuntime/Multipart/MultipartBoundaryGenerator.swift index c3397ba2..cdea9a3c 100644 --- a/Sources/OpenAPIRuntime/Multipart/MultipartBoundaryGenerator.swift +++ b/Sources/OpenAPIRuntime/Multipart/MultipartBoundaryGenerator.swift @@ -11,6 +11,7 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + import Foundation /// A generator of a new boundary string used by multipart messages to separate parts. diff --git a/Sources/OpenAPIRuntime/Multipart/MultipartBytesToFramesSequence.swift b/Sources/OpenAPIRuntime/Multipart/MultipartBytesToFramesSequence.swift index 1e03fc75..8155cffb 100644 --- a/Sources/OpenAPIRuntime/Multipart/MultipartBytesToFramesSequence.swift +++ b/Sources/OpenAPIRuntime/Multipart/MultipartBytesToFramesSequence.swift @@ -12,8 +12,12 @@ // //===----------------------------------------------------------------------===// -import HTTPTypes +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif +import HTTPTypes /// A sequence that parses multipart frames from bytes. struct MultipartBytesToFramesSequence: Sendable diff --git a/Sources/OpenAPIRuntime/Multipart/MultipartFramesToBytesSequence.swift b/Sources/OpenAPIRuntime/Multipart/MultipartFramesToBytesSequence.swift index 07538233..2d607116 100644 --- a/Sources/OpenAPIRuntime/Multipart/MultipartFramesToBytesSequence.swift +++ b/Sources/OpenAPIRuntime/Multipart/MultipartFramesToBytesSequence.swift @@ -12,8 +12,12 @@ // //===----------------------------------------------------------------------===// -import HTTPTypes +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif +import HTTPTypes /// A sequence that serializes multipart frames into bytes. struct MultipartFramesToBytesSequence: Sendable diff --git a/Sources/OpenAPIRuntime/Multipart/MultipartFramesToRawPartsSequence.swift b/Sources/OpenAPIRuntime/Multipart/MultipartFramesToRawPartsSequence.swift index 8734b6aa..2f426dc7 100644 --- a/Sources/OpenAPIRuntime/Multipart/MultipartFramesToRawPartsSequence.swift +++ b/Sources/OpenAPIRuntime/Multipart/MultipartFramesToRawPartsSequence.swift @@ -12,8 +12,12 @@ // //===----------------------------------------------------------------------===// -import HTTPTypes +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif +import HTTPTypes /// A sequence that parses raw multipart parts from multipart frames. struct MultipartFramesToRawPartsSequence: Sendable @@ -348,7 +352,9 @@ extension MultipartFramesToRawPartsSequence { if #available(macOS 15, iOS 18.0, tvOS 18.0, watchOS 11.0, macCatalyst 18.0, visionOS 2.0, *) { frame = try await upstream.next(isolation: self) } else { - frame = try await upstream.next() + nonisolated(unsafe) var unsafeUpstream = upstream + frame = try await unsafeUpstream.next() + upstream = unsafeUpstream } #else frame = try await upstream.next() @@ -380,7 +386,9 @@ extension MultipartFramesToRawPartsSequence { if #available(macOS 15, iOS 18.0, tvOS 18.0, watchOS 11.0, macCatalyst 18.0, visionOS 2.0, *) { frame = try await upstream.next(isolation: self) } else { - frame = try await upstream.next() + nonisolated(unsafe) var unsafeUpstream = upstream + frame = try await unsafeUpstream.next() + upstream = unsafeUpstream } #else frame = try await upstream.next() diff --git a/Sources/OpenAPIRuntime/Multipart/MultipartPublicTypes.swift b/Sources/OpenAPIRuntime/Multipart/MultipartPublicTypes.swift index 6db356c3..eccf0886 100644 --- a/Sources/OpenAPIRuntime/Multipart/MultipartPublicTypes.swift +++ b/Sources/OpenAPIRuntime/Multipart/MultipartPublicTypes.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import Foundation -import HTTPTypes +public import HTTPTypes /// A raw multipart part containing the header fields and the body stream. public struct MultipartRawPart: Sendable, Hashable { @@ -358,3 +358,6 @@ extension MultipartBody { public mutating func next() async throws -> Element? { try await produceNext() } } } + +@available(*, unavailable) +extension MultipartBody.Iterator: Sendable {} diff --git a/Sources/OpenAPIRuntime/Multipart/MultipartPublicTypesExtensions.swift b/Sources/OpenAPIRuntime/Multipart/MultipartPublicTypesExtensions.swift index ac9d9d5f..ff7cf631 100644 --- a/Sources/OpenAPIRuntime/Multipart/MultipartPublicTypesExtensions.swift +++ b/Sources/OpenAPIRuntime/Multipart/MultipartPublicTypesExtensions.swift @@ -12,8 +12,12 @@ // //===----------------------------------------------------------------------===// +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation -import HTTPTypes +#endif +public import HTTPTypes // MARK: - Extensions diff --git a/Sources/OpenAPIRuntime/Multipart/MultipartRawPartsToFramesSequence.swift b/Sources/OpenAPIRuntime/Multipart/MultipartRawPartsToFramesSequence.swift index 343eb0f2..71b9c82a 100644 --- a/Sources/OpenAPIRuntime/Multipart/MultipartRawPartsToFramesSequence.swift +++ b/Sources/OpenAPIRuntime/Multipart/MultipartRawPartsToFramesSequence.swift @@ -12,8 +12,12 @@ // //===----------------------------------------------------------------------===// -import HTTPTypes +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif +import HTTPTypes /// A sequence that serializes raw multipart parts into multipart frames. struct MultipartRawPartsToFramesSequence: Sendable diff --git a/Sources/OpenAPIRuntime/Multipart/MultipartValidation.swift b/Sources/OpenAPIRuntime/Multipart/MultipartValidation.swift index dbac2bc8..13c97e50 100644 --- a/Sources/OpenAPIRuntime/Multipart/MultipartValidation.swift +++ b/Sources/OpenAPIRuntime/Multipart/MultipartValidation.swift @@ -12,8 +12,12 @@ // //===----------------------------------------------------------------------===// -import HTTPTypes +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif +import HTTPTypes /// A container for multipart body requirements. struct MultipartBodyRequirements: Sendable, Hashable { diff --git a/Sources/OpenAPIRuntime/URICoder/Common/URICodeCodingKey.swift b/Sources/OpenAPIRuntime/URICoder/Common/URICodeCodingKey.swift index 48744267..5a86dc11 100644 --- a/Sources/OpenAPIRuntime/URICoder/Common/URICodeCodingKey.swift +++ b/Sources/OpenAPIRuntime/URICoder/Common/URICodeCodingKey.swift @@ -12,7 +12,11 @@ // //===----------------------------------------------------------------------===// +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// The coding key used by the URI encoder and decoder. struct URICoderCodingKey { diff --git a/Sources/OpenAPIRuntime/URICoder/Common/URICoderConfiguration.swift b/Sources/OpenAPIRuntime/URICoder/Common/URICoderConfiguration.swift index 3f7b380e..bbc4a0c2 100644 --- a/Sources/OpenAPIRuntime/URICoder/Common/URICoderConfiguration.swift +++ b/Sources/OpenAPIRuntime/URICoder/Common/URICoderConfiguration.swift @@ -12,7 +12,11 @@ // //===----------------------------------------------------------------------===// +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// A bag of configuration values used by the URI encoder and decoder. struct URICoderConfiguration { diff --git a/Sources/OpenAPIRuntime/URICoder/Common/URIEncodedNode.swift b/Sources/OpenAPIRuntime/URICoder/Common/URIEncodedNode.swift index d2f9edbb..196c419e 100644 --- a/Sources/OpenAPIRuntime/URICoder/Common/URIEncodedNode.swift +++ b/Sources/OpenAPIRuntime/URICoder/Common/URIEncodedNode.swift @@ -12,7 +12,11 @@ // //===----------------------------------------------------------------------===// +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// A node produced by `URIValueToNodeEncoder`. enum URIEncodedNode: Equatable { diff --git a/Sources/OpenAPIRuntime/URICoder/Common/URIParsedTypes.swift b/Sources/OpenAPIRuntime/URICoder/Common/URIParsedTypes.swift index 23d54e65..d4246634 100644 --- a/Sources/OpenAPIRuntime/URICoder/Common/URIParsedTypes.swift +++ b/Sources/OpenAPIRuntime/URICoder/Common/URIParsedTypes.swift @@ -12,7 +12,11 @@ // //===----------------------------------------------------------------------===// +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// A component of a `URIParsedKey`. typealias URIParsedKeyComponent = String.SubSequence diff --git a/Sources/OpenAPIRuntime/URICoder/Decoding/URIDecoder.swift b/Sources/OpenAPIRuntime/URICoder/Decoding/URIDecoder.swift index 3be1dce1..abd27044 100644 --- a/Sources/OpenAPIRuntime/URICoder/Decoding/URIDecoder.swift +++ b/Sources/OpenAPIRuntime/URICoder/Decoding/URIDecoder.swift @@ -12,7 +12,11 @@ // //===----------------------------------------------------------------------===// +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// A type that decodes a `Decodable` value from an URI-encoded string /// using the rules from RFC 6570, RFC 1866, and OpenAPI 3.0.4, depending on diff --git a/Sources/OpenAPIRuntime/URICoder/Decoding/URIValueFromNodeDecoder+Keyed.swift b/Sources/OpenAPIRuntime/URICoder/Decoding/URIValueFromNodeDecoder+Keyed.swift index 3e3990f6..c1ac27d7 100644 --- a/Sources/OpenAPIRuntime/URICoder/Decoding/URIValueFromNodeDecoder+Keyed.swift +++ b/Sources/OpenAPIRuntime/URICoder/Decoding/URIValueFromNodeDecoder+Keyed.swift @@ -12,7 +12,11 @@ // //===----------------------------------------------------------------------===// +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// A keyed container used by `URIValueFromNodeDecoder`. struct URIKeyedDecodingContainer { diff --git a/Sources/OpenAPIRuntime/URICoder/Decoding/URIValueFromNodeDecoder+Single.swift b/Sources/OpenAPIRuntime/URICoder/Decoding/URIValueFromNodeDecoder+Single.swift index 2207bd84..0830754e 100644 --- a/Sources/OpenAPIRuntime/URICoder/Decoding/URIValueFromNodeDecoder+Single.swift +++ b/Sources/OpenAPIRuntime/URICoder/Decoding/URIValueFromNodeDecoder+Single.swift @@ -12,7 +12,11 @@ // //===----------------------------------------------------------------------===// +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// A single value container used by `URIValueFromNodeDecoder`. struct URISingleValueDecodingContainer { diff --git a/Sources/OpenAPIRuntime/URICoder/Decoding/URIValueFromNodeDecoder+Unkeyed.swift b/Sources/OpenAPIRuntime/URICoder/Decoding/URIValueFromNodeDecoder+Unkeyed.swift index 72fe4739..569721ae 100644 --- a/Sources/OpenAPIRuntime/URICoder/Decoding/URIValueFromNodeDecoder+Unkeyed.swift +++ b/Sources/OpenAPIRuntime/URICoder/Decoding/URIValueFromNodeDecoder+Unkeyed.swift @@ -12,7 +12,11 @@ // //===----------------------------------------------------------------------===// +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// An unkeyed container used by `URIValueFromNodeDecoder`. struct URIUnkeyedDecodingContainer { diff --git a/Sources/OpenAPIRuntime/URICoder/Decoding/URIValueFromNodeDecoder.swift b/Sources/OpenAPIRuntime/URICoder/Decoding/URIValueFromNodeDecoder.swift index 83c77c90..3c1f812d 100644 --- a/Sources/OpenAPIRuntime/URICoder/Decoding/URIValueFromNodeDecoder.swift +++ b/Sources/OpenAPIRuntime/URICoder/Decoding/URIValueFromNodeDecoder.swift @@ -12,7 +12,11 @@ // //===----------------------------------------------------------------------===// +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// A type that allows decoding `Decodable` values from a URI-encoded string. final class URIValueFromNodeDecoder { diff --git a/Sources/OpenAPIRuntime/URICoder/Encoding/URIEncoder.swift b/Sources/OpenAPIRuntime/URICoder/Encoding/URIEncoder.swift index 06103408..fe42b5c8 100644 --- a/Sources/OpenAPIRuntime/URICoder/Encoding/URIEncoder.swift +++ b/Sources/OpenAPIRuntime/URICoder/Encoding/URIEncoder.swift @@ -12,7 +12,11 @@ // //===----------------------------------------------------------------------===// +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// A type that encodes an `Encodable` value to an URI-encoded string /// using the rules from RFC 6570, RFC 1866, and OpenAPI 3.0.4, depending on diff --git a/Sources/OpenAPIRuntime/URICoder/Encoding/URIValueToNodeEncoder+Keyed.swift b/Sources/OpenAPIRuntime/URICoder/Encoding/URIValueToNodeEncoder+Keyed.swift index 296ab578..dc4c572b 100644 --- a/Sources/OpenAPIRuntime/URICoder/Encoding/URIValueToNodeEncoder+Keyed.swift +++ b/Sources/OpenAPIRuntime/URICoder/Encoding/URIValueToNodeEncoder+Keyed.swift @@ -12,7 +12,11 @@ // //===----------------------------------------------------------------------===// +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// A keyed container used by `URIValueToNodeEncoder`. struct URIKeyedEncodingContainer { diff --git a/Sources/OpenAPIRuntime/URICoder/Encoding/URIValueToNodeEncoder+Single.swift b/Sources/OpenAPIRuntime/URICoder/Encoding/URIValueToNodeEncoder+Single.swift index 31a82f60..8266a0e8 100644 --- a/Sources/OpenAPIRuntime/URICoder/Encoding/URIValueToNodeEncoder+Single.swift +++ b/Sources/OpenAPIRuntime/URICoder/Encoding/URIValueToNodeEncoder+Single.swift @@ -12,7 +12,11 @@ // //===----------------------------------------------------------------------===// +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// A single value container used by `URIValueToNodeEncoder`. struct URISingleValueEncodingContainer { diff --git a/Sources/OpenAPIRuntime/URICoder/Encoding/URIValueToNodeEncoder+Unkeyed.swift b/Sources/OpenAPIRuntime/URICoder/Encoding/URIValueToNodeEncoder+Unkeyed.swift index 5d892151..c1c34683 100644 --- a/Sources/OpenAPIRuntime/URICoder/Encoding/URIValueToNodeEncoder+Unkeyed.swift +++ b/Sources/OpenAPIRuntime/URICoder/Encoding/URIValueToNodeEncoder+Unkeyed.swift @@ -12,7 +12,11 @@ // //===----------------------------------------------------------------------===// +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// An unkeyed container used by `URIValueToNodeEncoder`. struct URIUnkeyedEncodingContainer { diff --git a/Sources/OpenAPIRuntime/URICoder/Encoding/URIValueToNodeEncoder.swift b/Sources/OpenAPIRuntime/URICoder/Encoding/URIValueToNodeEncoder.swift index b48f2c2f..71903798 100644 --- a/Sources/OpenAPIRuntime/URICoder/Encoding/URIValueToNodeEncoder.swift +++ b/Sources/OpenAPIRuntime/URICoder/Encoding/URIValueToNodeEncoder.swift @@ -12,7 +12,11 @@ // //===----------------------------------------------------------------------===// +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif /// A type that converts an `Encodable` type into a `URIEncodableNode` value. final class URIValueToNodeEncoder { diff --git a/Tests/OpenAPIRuntimeTests/AsyncSyncSequence.swift b/Tests/OpenAPIRuntimeTests/AsyncSyncSequence.swift new file mode 100644 index 00000000..07099a39 --- /dev/null +++ b/Tests/OpenAPIRuntimeTests/AsyncSyncSequence.swift @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftOpenAPIGenerator open source project +// +// Copyright (c) 2026 Apple Inc. and the SwiftOpenAPIGenerator project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftOpenAPIGenerator project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift Async Algorithms open source project +// +// Copyright (c) 2022 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +extension Sequence { + /// An asynchronous sequence containing the same elements as this sequence, + /// but on which operations, such as `map` and `filter`, are + /// implemented asynchronously. + var async: AsyncSyncSequence { + AsyncSyncSequence(self) + } +} + +/// An asynchronous sequence composed from a synchronous sequence. +/// +/// Asynchronous lazy sequences can be used to interface existing or pre-calculated +/// data to interoperate with other asynchronous sequences and algorithms based on +/// asynchronous sequences. +/// +/// This functions similarly to `LazySequence` by accessing elements sequentially +/// in the iterator's `next()` method. +struct AsyncSyncSequence: AsyncSequence { + typealias Element = Base.Element + + struct Iterator: AsyncIteratorProtocol { + var iterator: Base.Iterator? + + init(_ iterator: Base.Iterator) { + self.iterator = iterator + } + + mutating func next() async -> Base.Element? { + guard !Task.isCancelled, let value = iterator?.next() else { + iterator = nil + return nil + } + return value + } + } + + let base: Base + + init(_ base: Base) { + self.base = base + } + + func makeAsyncIterator() -> Iterator { + Iterator(base.makeIterator()) + } +} + +extension AsyncSyncSequence: Sendable where Base: Sendable {} + +@available(*, unavailable) +extension AsyncSyncSequence.Iterator: Sendable {} diff --git a/Tests/OpenAPIRuntimeTests/Conversion/Test_Configuration.swift b/Tests/OpenAPIRuntimeTests/Conversion/Test_Configuration.swift index e4e3ff03..6c220989 100644 --- a/Tests/OpenAPIRuntimeTests/Conversion/Test_Configuration.swift +++ b/Tests/OpenAPIRuntimeTests/Conversion/Test_Configuration.swift @@ -11,9 +11,14 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else +import Foundation +#endif import XCTest import HTTPTypes -import Foundation @_spi(Generated) import OpenAPIRuntime final class Test_Configuration: Test_Runtime { diff --git a/Tests/OpenAPIRuntimeTests/Conversion/Test_Converter+Client.swift b/Tests/OpenAPIRuntimeTests/Conversion/Test_Converter+Client.swift index e223ea53..060d7461 100644 --- a/Tests/OpenAPIRuntimeTests/Conversion/Test_Converter+Client.swift +++ b/Tests/OpenAPIRuntimeTests/Conversion/Test_Converter+Client.swift @@ -275,7 +275,7 @@ final class Test_ClientConverterExtensions: Test_Runtime { /// - message: An optional custom message to display upon test failure. /// - file: The file name to include in the failure message (default is the source file where this function is called). /// - line: The line number to include in the failure message (default is the line where this function is called). -public func XCTAssertEqualStringifiedData( +func XCTAssertEqualStringifiedData( _ expression1: @autoclosure () throws -> Data, _ expression2: @autoclosure () throws -> String, _ message: @autoclosure () -> String = "", diff --git a/Tests/OpenAPIRuntimeTests/EventStreams/Test_JSONLinesDecoding.swift b/Tests/OpenAPIRuntimeTests/EventStreams/Test_JSONLinesDecoding.swift index a841dc67..a21a5e5d 100644 --- a/Tests/OpenAPIRuntimeTests/EventStreams/Test_JSONLinesDecoding.swift +++ b/Tests/OpenAPIRuntimeTests/EventStreams/Test_JSONLinesDecoding.swift @@ -11,9 +11,14 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else +import Foundation +#endif import XCTest @_spi(Generated) @testable import OpenAPIRuntime -import Foundation final class Test_JSONLinesDecoding: Test_Runtime { func testParsed() async throws { diff --git a/Tests/OpenAPIRuntimeTests/EventStreams/Test_JSONLinesEncoding.swift b/Tests/OpenAPIRuntimeTests/EventStreams/Test_JSONLinesEncoding.swift index d7a44319..8b78ad49 100644 --- a/Tests/OpenAPIRuntimeTests/EventStreams/Test_JSONLinesEncoding.swift +++ b/Tests/OpenAPIRuntimeTests/EventStreams/Test_JSONLinesEncoding.swift @@ -11,9 +11,14 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else +import Foundation +#endif import XCTest @_spi(Generated) @testable import OpenAPIRuntime -import Foundation final class Test_JSONLinesEncoding: Test_Runtime { func testSerialized() async throws { diff --git a/Tests/OpenAPIRuntimeTests/EventStreams/Test_JSONSequenceDecoding.swift b/Tests/OpenAPIRuntimeTests/EventStreams/Test_JSONSequenceDecoding.swift index ab967e1e..0e58396e 100644 --- a/Tests/OpenAPIRuntimeTests/EventStreams/Test_JSONSequenceDecoding.swift +++ b/Tests/OpenAPIRuntimeTests/EventStreams/Test_JSONSequenceDecoding.swift @@ -11,9 +11,14 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else +import Foundation +#endif import XCTest @_spi(Generated) @testable import OpenAPIRuntime -import Foundation final class Test_JSONSequenceDecoding: Test_Runtime { func testParsed() async throws { diff --git a/Tests/OpenAPIRuntimeTests/EventStreams/Test_JSONSequenceEncoding.swift b/Tests/OpenAPIRuntimeTests/EventStreams/Test_JSONSequenceEncoding.swift index f03e00cd..112c23f4 100644 --- a/Tests/OpenAPIRuntimeTests/EventStreams/Test_JSONSequenceEncoding.swift +++ b/Tests/OpenAPIRuntimeTests/EventStreams/Test_JSONSequenceEncoding.swift @@ -11,9 +11,14 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else +import Foundation +#endif import XCTest @_spi(Generated) @testable import OpenAPIRuntime -import Foundation final class Test_JSONSequenceEncoding: Test_Runtime { func testSerialized() async throws { diff --git a/Tests/OpenAPIRuntimeTests/EventStreams/Test_ServerSentEventsDecoding.swift b/Tests/OpenAPIRuntimeTests/EventStreams/Test_ServerSentEventsDecoding.swift index 2a15b932..4711e5a2 100644 --- a/Tests/OpenAPIRuntimeTests/EventStreams/Test_ServerSentEventsDecoding.swift +++ b/Tests/OpenAPIRuntimeTests/EventStreams/Test_ServerSentEventsDecoding.swift @@ -11,9 +11,14 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else +import Foundation +#endif import XCTest @_spi(Generated) @testable import OpenAPIRuntime -import Foundation final class Test_ServerSentEventsDecoding: Test_Runtime { func _test( diff --git a/Tests/OpenAPIRuntimeTests/EventStreams/Test_ServerSentEventsEncoding.swift b/Tests/OpenAPIRuntimeTests/EventStreams/Test_ServerSentEventsEncoding.swift index ac8922da..03f4bf6a 100644 --- a/Tests/OpenAPIRuntimeTests/EventStreams/Test_ServerSentEventsEncoding.swift +++ b/Tests/OpenAPIRuntimeTests/EventStreams/Test_ServerSentEventsEncoding.swift @@ -11,9 +11,14 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else +import Foundation +#endif import XCTest @_spi(Generated) @testable import OpenAPIRuntime -import Foundation final class Test_ServerSentEventsEncoding: Test_Runtime { func _test(input: [ServerSentEvent], output: String, file: StaticString = #filePath, line: UInt = #line) diff --git a/Tests/OpenAPIRuntimeTests/Interface/Test_HTTPBody.swift b/Tests/OpenAPIRuntimeTests/Interface/Test_HTTPBody.swift index 1ae395f7..04c0f420 100644 --- a/Tests/OpenAPIRuntimeTests/Interface/Test_HTTPBody.swift +++ b/Tests/OpenAPIRuntimeTests/Interface/Test_HTTPBody.swift @@ -11,9 +11,14 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else +import Foundation +#endif import XCTest @_spi(Generated) @testable import OpenAPIRuntime -import Foundation final class Test_Body: Test_Runtime { diff --git a/Tests/OpenAPIRuntimeTests/Interface/Test_MultipartBody.swift b/Tests/OpenAPIRuntimeTests/Interface/Test_MultipartBody.swift index dfd7eab8..ac89b3dc 100644 --- a/Tests/OpenAPIRuntimeTests/Interface/Test_MultipartBody.swift +++ b/Tests/OpenAPIRuntimeTests/Interface/Test_MultipartBody.swift @@ -11,9 +11,14 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else +import Foundation +#endif import XCTest @_spi(Generated) @testable import OpenAPIRuntime -import Foundation final class Test_MultipartBody: XCTestCase { diff --git a/Tests/OpenAPIRuntimeTests/Interface/Test_UniversalClient.swift b/Tests/OpenAPIRuntimeTests/Interface/Test_UniversalClient.swift index b0063e70..6a20f63b 100644 --- a/Tests/OpenAPIRuntimeTests/Interface/Test_UniversalClient.swift +++ b/Tests/OpenAPIRuntimeTests/Interface/Test_UniversalClient.swift @@ -11,9 +11,14 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else +import Foundation +#endif import XCTest import HTTPTypes -import Foundation @_spi(Generated) @testable import OpenAPIRuntime struct MockClientTransport: ClientTransport { @@ -54,7 +59,7 @@ final class Test_UniversalClient: Test_Runtime { input: "input", forOperation: "op", serializer: { input in throw TestError() }, - deserializer: { response, body in fatalError() } + deserializer: { response, body in throw TestError() } ) } catch { let clientError = try XCTUnwrap(error as? ClientError) @@ -80,7 +85,7 @@ final class Test_UniversalClient: Test_Runtime { input: "input", forOperation: "op", serializer: { input in (HTTPRequest(soar_path: "/", method: .post), MockClientTransport.requestBody) }, - deserializer: { response, body in fatalError() } + deserializer: { response, body in throw TestError() } ) } catch { let clientError = try XCTUnwrap(error as? ClientError) @@ -103,7 +108,7 @@ final class Test_UniversalClient: Test_Runtime { input: "input", forOperation: "op", serializer: { input in (HTTPRequest(soar_path: "/", method: .post), MockClientTransport.requestBody) }, - deserializer: { response, body in fatalError() } + deserializer: { response, body in throw TestError() } ) } catch { let clientError = try XCTUnwrap(error as? ClientError) @@ -129,7 +134,7 @@ final class Test_UniversalClient: Test_Runtime { input: "input", forOperation: "op", serializer: { input in (HTTPRequest(soar_path: "/", method: .post), MockClientTransport.requestBody) }, - deserializer: { response, body in fatalError() } + deserializer: { response, body in throw TestError() } ) } catch { let clientError = try XCTUnwrap(error as? ClientError) diff --git a/Tests/OpenAPIRuntimeTests/Interface/Test_UniversalServer.swift b/Tests/OpenAPIRuntimeTests/Interface/Test_UniversalServer.swift index db0e318b..18e1df51 100644 --- a/Tests/OpenAPIRuntimeTests/Interface/Test_UniversalServer.swift +++ b/Tests/OpenAPIRuntimeTests/Interface/Test_UniversalServer.swift @@ -11,9 +11,14 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else +import Foundation +#endif import XCTest import HTTPTypes -import Foundation @_spi(Generated) @testable import OpenAPIRuntime struct MockHandler: Sendable { diff --git a/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartBoundaryGenerator.swift b/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartBoundaryGenerator.swift index edb8e033..b68b5679 100644 --- a/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartBoundaryGenerator.swift +++ b/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartBoundaryGenerator.swift @@ -11,9 +11,14 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else +import Foundation +#endif import XCTest @_spi(Generated) @testable import OpenAPIRuntime -import Foundation final class Test_MultipartBoundaryGenerator: Test_Runtime { diff --git a/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartBytesToFramesSequence.swift b/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartBytesToFramesSequence.swift index 36eb2301..afc3d44e 100644 --- a/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartBytesToFramesSequence.swift +++ b/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartBytesToFramesSequence.swift @@ -11,9 +11,14 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else +import Foundation +#endif import XCTest @_spi(Generated) @testable import OpenAPIRuntime -import Foundation import HTTPTypes final class Test_MultipartBytesToFramesSequence: Test_Runtime { @@ -22,8 +27,7 @@ final class Test_MultipartBytesToFramesSequence: Test_Runtime { "--__abcd__", #"Content-Disposition: form-data; name="name""#, "", "24", "--__abcd__", #"Content-Disposition: form-data; name="info""#, "", "{}", "--__abcd__--", ]) - var iterator = chunk.makeIterator() - let upstream = AsyncStream { iterator.next().map { ArraySlice([$0]) } } + let upstream = chunk.async.map { ArraySlice([$0]) } let sequence = MultipartBytesToFramesSequence(upstream: upstream, boundary: "__abcd__") var frames: [MultipartFrame] = [] for try await frame in sequence { frames.append(frame) } diff --git a/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartFramesToBytesSequence.swift b/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartFramesToBytesSequence.swift index da87af47..ba05083e 100644 --- a/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartFramesToBytesSequence.swift +++ b/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartFramesToBytesSequence.swift @@ -11,9 +11,14 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else +import Foundation +#endif import XCTest @_spi(Generated) @testable import OpenAPIRuntime -import Foundation import HTTPTypes final class Test_MultipartFramesToBytesSequence: Test_Runtime { @@ -23,8 +28,7 @@ final class Test_MultipartFramesToBytesSequence: Test_Runtime { .bodyChunk(chunkFromString("4")), .headerFields([.contentDisposition: #"form-data; name="info""#]), .bodyChunk(chunkFromString("{")), .bodyChunk(chunkFromString("}")), ] - var iterator = frames.makeIterator() - let upstream = AsyncStream { iterator.next() } + let upstream = frames.async let sequence = MultipartFramesToBytesSequence(upstream: upstream, boundary: "__abcd__") var bytes: ArraySlice = [] for try await chunk in sequence { bytes.append(contentsOf: chunk) } diff --git a/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartFramesToRawPartsSequence.swift b/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartFramesToRawPartsSequence.swift index 143993a7..933803fb 100644 --- a/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartFramesToRawPartsSequence.swift +++ b/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartFramesToRawPartsSequence.swift @@ -11,9 +11,14 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else +import Foundation +#endif import XCTest @_spi(Generated) @testable import OpenAPIRuntime -import Foundation import HTTPTypes final class Test_MultipartFramesToRawPartsSequence: Test_Runtime { @@ -23,8 +28,7 @@ final class Test_MultipartFramesToRawPartsSequence: Test_Runtime { .bodyChunk(chunkFromString("4")), .headerFields([.contentDisposition: #"form-data; name="info""#]), .bodyChunk(chunkFromString("{")), .bodyChunk(chunkFromString("}")), ] - var upstreamIterator = frames.makeIterator() - let upstream = AsyncStream { upstreamIterator.next() } + let upstream = frames.async let sequence = MultipartFramesToRawPartsSequence(upstream: upstream) var iterator = sequence.makeAsyncIterator() guard let part1 = try await iterator.next() else { @@ -52,9 +56,8 @@ final class Test_MultipartFramesToRawPartsSequenceIterator: Test_Runtime { .bodyChunk(chunkFromString("4")), .headerFields([.contentDisposition: #"form-data; name="info""#]), .bodyChunk(chunkFromString("{")), .bodyChunk(chunkFromString("}")), ] - var upstreamSyncIterator = frames.makeIterator() - let upstream = AsyncStream { upstreamSyncIterator.next() } - let sharedIterator = MultipartFramesToRawPartsSequence> + let upstream = frames.async + let sharedIterator = MultipartFramesToRawPartsSequence> .SharedIterator(makeUpstreamIterator: { upstream.makeAsyncIterator() }) let bodyClosure: @Sendable () async throws -> ArraySlice? = { try await sharedIterator.nextFromBodySubsequence() diff --git a/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartRawPartsToFramesSequence.swift b/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartRawPartsToFramesSequence.swift index 826ef34f..ac312e29 100644 --- a/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartRawPartsToFramesSequence.swift +++ b/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartRawPartsToFramesSequence.swift @@ -11,24 +11,29 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else +import Foundation +#endif import XCTest @_spi(Generated) @testable import OpenAPIRuntime -import Foundation import HTTPTypes final class Test_MultipartRawPartsToFramesSequence: Test_Runtime { func test() async throws { - var secondPartChunks = "{}".utf8.makeIterator() + let secondPartChunks = "{}".utf8.async let secondPartBody = HTTPBody( - AsyncStream(unfolding: { secondPartChunks.next().map { ArraySlice([$0]) } }), - length: .unknown + secondPartChunks.map { ArraySlice([$0]) }, + length: .unknown, + iterationBehavior: .multiple ) let parts: [MultipartRawPart] = [ .init(headerFields: [.contentDisposition: #"form-data; name="name""#], body: "24"), .init(headerFields: [.contentDisposition: #"form-data; name="info""#], body: secondPartBody), ] - var upstreamIterator = parts.makeIterator() - let upstream = AsyncStream { upstreamIterator.next() } + let upstream = parts.async let sequence = MultipartRawPartsToFramesSequence(upstream: upstream) var frames: [MultipartFrame] = [] @@ -44,18 +49,18 @@ final class Test_MultipartRawPartsToFramesSequence: Test_Runtime { final class Test_MultipartRawPartsToFramesSequenceSerializer: Test_Runtime { func test() async throws { - var secondPartChunks = "{}".utf8.makeIterator() + let secondPartChunks = "{}".utf8.async let secondPartBody = HTTPBody( - AsyncStream(unfolding: { secondPartChunks.next().map { ArraySlice([$0]) } }), - length: .unknown + secondPartChunks.map { ArraySlice([$0]) }, + length: .unknown, + iterationBehavior: .multiple ) let parts: [MultipartRawPart] = [ .init(headerFields: [.contentDisposition: #"form-data; name="name""#], body: "24"), .init(headerFields: [.contentDisposition: #"form-data; name="info""#], body: secondPartBody), ] - var upstreamIterator = parts.makeIterator() - let upstream = AsyncStream { upstreamIterator.next() } - var serializer = MultipartRawPartsToFramesSequence> + let upstream = parts.async + var serializer = MultipartRawPartsToFramesSequence> .Serializer(upstream: upstream.makeAsyncIterator()) var frames: [MultipartFrame] = [] while let frame = try await serializer.next() { frames.append(frame) } diff --git a/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartValidationSequence.swift b/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartValidationSequence.swift index 0343966a..8bb93a4e 100644 --- a/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartValidationSequence.swift +++ b/Tests/OpenAPIRuntimeTests/Multipart/Test_MultipartValidationSequence.swift @@ -11,9 +11,14 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else +import Foundation +#endif import XCTest @_spi(Generated) @testable import OpenAPIRuntime -import Foundation import HTTPTypes final class Test_MultipartValidationSequence: Test_Runtime { @@ -24,8 +29,7 @@ final class Test_MultipartValidationSequence: Test_Runtime { .init(headerFields: [.contentDisposition: #"form-data; name="name""#], body: firstBody), .init(headerFields: [.contentDisposition: #"form-data; name="info""#], body: secondBody), ] - var upstreamIterator = parts.makeIterator() - let upstream = AsyncStream { upstreamIterator.next() } + let upstream = parts.async let sequence = MultipartValidationSequence( upstream: upstream, requirements: .init( diff --git a/Tests/OpenAPIRuntimeTests/Test_Runtime.swift b/Tests/OpenAPIRuntimeTests/Test_Runtime.swift index 37184d58..65720988 100644 --- a/Tests/OpenAPIRuntimeTests/Test_Runtime.swift +++ b/Tests/OpenAPIRuntimeTests/Test_Runtime.swift @@ -264,7 +264,7 @@ struct MockCustomCoder: CustomCoder { /// - rhs: The expected absolute string representation. /// - file: The file name to include in the failure message (default is the source file where this function is called). /// - line: The line number to include in the failure message (default is the line where this function is called). -public func XCTAssertEqualURLString(_ lhs: URL?, _ rhs: String, file: StaticString = #filePath, line: UInt = #line) { +func XCTAssertEqualURLString(_ lhs: URL?, _ rhs: String, file: StaticString = #filePath, line: UInt = #line) { guard let lhs else { XCTFail("URL is nil") return @@ -389,7 +389,7 @@ public func XCTAssertEqualStringifiedData( /// - file: The file name to include in the failure message (default is the source file where this function is called). /// - line: The line number to include in the failure message (default is the line where this function is called). /// - Throws: If either of the autoclosures throws an error, the function will rethrow that error. -public func XCTAssertEqualStringifiedData( +func XCTAssertEqualStringifiedData( _ expression1: @autoclosure () throws -> HTTPBody?, _ expression2: @autoclosure () throws -> String, _ message: @autoclosure () -> String = "", @@ -479,7 +479,7 @@ public func XCTAssertEqualAsyncData( } /// Asserts that the data matches the expected value. -public func XCTAssertEqualData( +func XCTAssertEqualData( _ expression1: @autoclosure () throws -> HTTPBody?, _ expression2: @autoclosure () throws -> C, _ message: @autoclosure () -> String = "Data doesn't match.", diff --git a/Tests/OpenAPIRuntimeTests/URICoder/Decoder/Test_URIDecoder.swift b/Tests/OpenAPIRuntimeTests/URICoder/Decoder/Test_URIDecoder.swift index 0e611789..a0d9079b 100644 --- a/Tests/OpenAPIRuntimeTests/URICoder/Decoder/Test_URIDecoder.swift +++ b/Tests/OpenAPIRuntimeTests/URICoder/Decoder/Test_URIDecoder.swift @@ -170,7 +170,7 @@ extension Test_URIDecoder { _ value: T, forKey key: String, from inputs: Inputs, - file: StaticString = #file, + file: StaticString = #filePath, line: UInt = #line ) { func _run(name: String, configuration: URICoderConfiguration, sourceString: Substring) { diff --git a/Tests/OpenAPIRuntimeTests/URICoder/Test_URICodingRoundtrip.swift b/Tests/OpenAPIRuntimeTests/URICoder/Test_URICodingRoundtrip.swift index ac1fc00f..9c17d4e4 100644 --- a/Tests/OpenAPIRuntimeTests/URICoder/Test_URICodingRoundtrip.swift +++ b/Tests/OpenAPIRuntimeTests/URICoder/Test_URICodingRoundtrip.swift @@ -11,12 +11,13 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// -import XCTest -#if canImport(Darwin) || swift(>=5.9.1) -import struct Foundation.Date + +#if canImport(FoundationEssentials) +import FoundationEssentials #else -@preconcurrency import struct Foundation.Date +import Foundation #endif +import XCTest @_spi(Generated) @testable import OpenAPIRuntime final class Test_URICodingRoundtrip: Test_Runtime { From 9e45d75207eef18f0378caaa26563696d7738b77 Mon Sep 17 00:00:00 2001 From: Honza Dvorsky Date: Fri, 20 Feb 2026 17:33:16 +0100 Subject: [PATCH 2/5] For now don't add the devcontainer file --- .devcontainer/devcontainer.json | 39 --------------------------------- 1 file changed, 39 deletions(-) delete mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json deleted file mode 100644 index ec68805f..00000000 --- a/.devcontainer/devcontainer.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "Swift", - "image": "swift:6.2", - "features": { - "ghcr.io/devcontainers/features/common-utils:2": { - "installZsh": "false", - "username": "vscode", - "upgradePackages": "false" - }, - "ghcr.io/devcontainers/features/git:1": { - "version": "os-provided", - "ppa": "false" - } - }, - "runArgs": [ - "--cap-add=SYS_PTRACE", - "--security-opt", - "seccomp=unconfined" - ], - // Configure tool-specific properties. - "customizations": { - // Configure properties specific to VS Code. - "vscode": { - // Set *default* container specific settings.json values on container create. - "settings": { - "lldb.library": "/usr/lib/liblldb.so" - }, - // Add the IDs of extensions you want installed when the container is created. - "extensions": [ - "swiftlang.swift-vscode" - ] - } - }, - // Use 'forwardPorts' to make a list of ports inside the container available locally. - // "forwardPorts": [], - - // Set `remoteUser` to `root` to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. - "remoteUser": "vscode" -} From 555e18b02fee72b4c3b4b62cfaab768b87ce0a45 Mon Sep 17 00:00:00 2001 From: Honza Dvorsky Date: Fri, 20 Feb 2026 17:35:51 +0100 Subject: [PATCH 3/5] Fix format --- .../Base/ContentDisposition.swift | 3 +- .../OpenAPIRuntime/Base/CopyOnWriteBox.swift | 3 +- .../EventStreams/JSONLinesDecoding.swift | 3 +- .../EventStreams/JSONLinesEncoding.swift | 3 +- .../EventStreams/JSONSequenceDecoding.swift | 3 +- .../EventStreams/JSONSequenceEncoding.swift | 3 +- .../ServerSentEventsDecoding.swift | 6 +-- .../ServerSentEventsEncoding.swift | 3 +- .../Interface/AsyncSequenceCommon.swift | 9 ++-- .../OpenAPIRuntime/Interface/HTTPBody.swift | 3 +- .../Interface/SendableMetatype.swift | 4 +- .../Multipart/MultipartPublicTypes.swift | 3 +- .../AsyncSyncSequence.swift | 47 ++++++++----------- 13 files changed, 37 insertions(+), 56 deletions(-) diff --git a/Sources/OpenAPIRuntime/Base/ContentDisposition.swift b/Sources/OpenAPIRuntime/Base/ContentDisposition.swift index 09b501f3..eaac4fdc 100644 --- a/Sources/OpenAPIRuntime/Base/ContentDisposition.swift +++ b/Sources/OpenAPIRuntime/Base/ContentDisposition.swift @@ -107,7 +107,8 @@ extension ContentDisposition: RawRepresentable { var components = rawValue.split(separator: ";").map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } guard !components.isEmpty else { return nil } self.dispositionType = DispositionType(rawValue: components.removeFirst()) - let parameterTuples: [(ParameterName, String)] = components.compactMap { (component: String) -> (ParameterName, String)? in + let parameterTuples: [(ParameterName, String)] = components.compactMap { + (component: String) -> (ParameterName, String)? in let parameterComponents = component.split(separator: "=", maxSplits: 1) .map { $0.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) } guard parameterComponents.count == 2 else { return nil } diff --git a/Sources/OpenAPIRuntime/Base/CopyOnWriteBox.swift b/Sources/OpenAPIRuntime/Base/CopyOnWriteBox.swift index 7e433960..3b1aa1d7 100644 --- a/Sources/OpenAPIRuntime/Base/CopyOnWriteBox.swift +++ b/Sources/OpenAPIRuntime/Base/CopyOnWriteBox.swift @@ -46,8 +46,7 @@ } } -@available(*, unavailable) -extension CopyOnWriteBox.Storage: Sendable {} +@available(*, unavailable) extension CopyOnWriteBox.Storage: Sendable {} extension CopyOnWriteBox: Encodable where Wrapped: Encodable { diff --git a/Sources/OpenAPIRuntime/EventStreams/JSONLinesDecoding.swift b/Sources/OpenAPIRuntime/EventStreams/JSONLinesDecoding.swift index 3209e4cb..fc6423c6 100644 --- a/Sources/OpenAPIRuntime/EventStreams/JSONLinesDecoding.swift +++ b/Sources/OpenAPIRuntime/EventStreams/JSONLinesDecoding.swift @@ -71,8 +71,7 @@ extension JSONLinesDeserializationSequence: AsyncSequence { } } -@available(*, unavailable) -extension JSONLinesDeserializationSequence.Iterator: Sendable {} +@available(*, unavailable) extension JSONLinesDeserializationSequence.Iterator: Sendable {} extension AsyncSequence where Element == ArraySlice { diff --git a/Sources/OpenAPIRuntime/EventStreams/JSONLinesEncoding.swift b/Sources/OpenAPIRuntime/EventStreams/JSONLinesEncoding.swift index e56e9f0d..cc2101ed 100644 --- a/Sources/OpenAPIRuntime/EventStreams/JSONLinesEncoding.swift +++ b/Sources/OpenAPIRuntime/EventStreams/JSONLinesEncoding.swift @@ -69,8 +69,7 @@ extension JSONLinesSerializationSequence: AsyncSequence { } } -@available(*, unavailable) -extension JSONLinesSerializationSequence.Iterator: Sendable {} +@available(*, unavailable) extension JSONLinesSerializationSequence.Iterator: Sendable {} extension AsyncSequence where Element: Encodable & Sendable, Self: Sendable { diff --git a/Sources/OpenAPIRuntime/EventStreams/JSONSequenceDecoding.swift b/Sources/OpenAPIRuntime/EventStreams/JSONSequenceDecoding.swift index e61d2e4c..77df7bbb 100644 --- a/Sources/OpenAPIRuntime/EventStreams/JSONSequenceDecoding.swift +++ b/Sources/OpenAPIRuntime/EventStreams/JSONSequenceDecoding.swift @@ -90,8 +90,7 @@ extension JSONSequenceDeserializationSequence: AsyncSequence { } } -@available(*, unavailable) -extension JSONSequenceDeserializationSequence.Iterator: Sendable {} +@available(*, unavailable) extension JSONSequenceDeserializationSequence.Iterator: Sendable {} extension AsyncSequence where Element == ArraySlice { diff --git a/Sources/OpenAPIRuntime/EventStreams/JSONSequenceEncoding.swift b/Sources/OpenAPIRuntime/EventStreams/JSONSequenceEncoding.swift index a62acb31..87ea11a2 100644 --- a/Sources/OpenAPIRuntime/EventStreams/JSONSequenceEncoding.swift +++ b/Sources/OpenAPIRuntime/EventStreams/JSONSequenceEncoding.swift @@ -69,8 +69,7 @@ extension JSONSequenceSerializationSequence: AsyncSequence { } } -@available(*, unavailable) -extension JSONSequenceSerializationSequence.Iterator: Sendable {} +@available(*, unavailable) extension JSONSequenceSerializationSequence.Iterator: Sendable {} extension AsyncSequence where Element: Encodable & Sendable, Self: Sendable { diff --git a/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsDecoding.swift b/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsDecoding.swift index 33a9964c..2f4c71a9 100644 --- a/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsDecoding.swift +++ b/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsDecoding.swift @@ -93,8 +93,7 @@ extension ServerSentEventsDeserializationSequence: AsyncSequence { } } -@available(*, unavailable) -extension ServerSentEventsDeserializationSequence.Iterator: Sendable {} +@available(*, unavailable) extension ServerSentEventsDeserializationSequence.Iterator: Sendable {} extension AsyncSequence where Element == ArraySlice, Self: Sendable { @@ -348,8 +347,7 @@ extension ServerSentEventsLineDeserializationSequence: AsyncSequence { } } -@available(*, unavailable) -extension ServerSentEventsLineDeserializationSequence.Iterator: Sendable {} +@available(*, unavailable) extension ServerSentEventsLineDeserializationSequence.Iterator: Sendable {} extension ServerSentEventsLineDeserializationSequence.Iterator { diff --git a/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift b/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift index 557d622f..825542ce 100644 --- a/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift +++ b/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsEncoding.swift @@ -65,8 +65,7 @@ extension ServerSentEventsSerializationSequence: AsyncSequence { } } -@available(*, unavailable) -extension ServerSentEventsSerializationSequence.Iterator: Sendable {} +@available(*, unavailable) extension ServerSentEventsSerializationSequence.Iterator: Sendable {} extension AsyncSequence { diff --git a/Sources/OpenAPIRuntime/Interface/AsyncSequenceCommon.swift b/Sources/OpenAPIRuntime/Interface/AsyncSequenceCommon.swift index 24917a8c..04174e90 100644 --- a/Sources/OpenAPIRuntime/Interface/AsyncSequenceCommon.swift +++ b/Sources/OpenAPIRuntime/Interface/AsyncSequenceCommon.swift @@ -50,8 +50,7 @@ public enum IterationBehavior: Sendable { public mutating func next() async throws -> Element? { try await produceNext() } } -@available(*, unavailable) -extension AnyIterator: Sendable {} +@available(*, unavailable) extension AnyIterator: Sendable {} /// A type-erased async sequence that wraps input sequences. @usableFromInline struct AnySequence: AsyncSequence, Sendable { @@ -104,8 +103,7 @@ where Upstream.Element: Sendable { @usableFromInline func makeAsyncIterator() -> AsyncIterator { Iterator(iterator: sequence.makeIterator()) } } -@available(*, unavailable) -extension WrappedSyncSequence.Iterator: Sendable {} +@available(*, unavailable) extension WrappedSyncSequence.Iterator: Sendable {} /// An empty async sequence. @usableFromInline struct EmptySequence: AsyncSequence, Sendable { @@ -125,5 +123,4 @@ extension WrappedSyncSequence.Iterator: Sendable {} @usableFromInline func makeAsyncIterator() -> AsyncIterator { EmptyIterator() } } -@available(*, unavailable) -extension EmptySequence.EmptyIterator: Sendable {} +@available(*, unavailable) extension EmptySequence.EmptyIterator: Sendable {} diff --git a/Sources/OpenAPIRuntime/Interface/HTTPBody.swift b/Sources/OpenAPIRuntime/Interface/HTTPBody.swift index 114045df..b8afa096 100644 --- a/Sources/OpenAPIRuntime/Interface/HTTPBody.swift +++ b/Sources/OpenAPIRuntime/Interface/HTTPBody.swift @@ -561,5 +561,4 @@ extension HTTPBody { } } -@available(*, unavailable) -extension HTTPBody.Iterator: Sendable {} +@available(*, unavailable) extension HTTPBody.Iterator: Sendable {} diff --git a/Sources/OpenAPIRuntime/Interface/SendableMetatype.swift b/Sources/OpenAPIRuntime/Interface/SendableMetatype.swift index cc86343e..06a09505 100644 --- a/Sources/OpenAPIRuntime/Interface/SendableMetatype.swift +++ b/Sources/OpenAPIRuntime/Interface/SendableMetatype.swift @@ -13,7 +13,9 @@ //===----------------------------------------------------------------------===// #if compiler(>=6.2) +// swift-format-ignore: AllPublicDeclarationsHaveDocumentation public typealias _OpenAPIRuntimeSendableMetatype = SendableMetatype #else +// swift-format-ignore: AllPublicDeclarationsHaveDocumentation public typealias _OpenAPIRuntimeSendableMetatype = Any -#endif \ No newline at end of file +#endif diff --git a/Sources/OpenAPIRuntime/Multipart/MultipartPublicTypes.swift b/Sources/OpenAPIRuntime/Multipart/MultipartPublicTypes.swift index eccf0886..6834061a 100644 --- a/Sources/OpenAPIRuntime/Multipart/MultipartPublicTypes.swift +++ b/Sources/OpenAPIRuntime/Multipart/MultipartPublicTypes.swift @@ -359,5 +359,4 @@ extension MultipartBody { } } -@available(*, unavailable) -extension MultipartBody.Iterator: Sendable {} +@available(*, unavailable) extension MultipartBody.Iterator: Sendable {} diff --git a/Tests/OpenAPIRuntimeTests/AsyncSyncSequence.swift b/Tests/OpenAPIRuntimeTests/AsyncSyncSequence.swift index 07099a39..6b855437 100644 --- a/Tests/OpenAPIRuntimeTests/AsyncSyncSequence.swift +++ b/Tests/OpenAPIRuntimeTests/AsyncSyncSequence.swift @@ -24,12 +24,10 @@ //===----------------------------------------------------------------------===// extension Sequence { - /// An asynchronous sequence containing the same elements as this sequence, - /// but on which operations, such as `map` and `filter`, are - /// implemented asynchronously. - var async: AsyncSyncSequence { - AsyncSyncSequence(self) - } + /// An asynchronous sequence containing the same elements as this sequence, + /// but on which operations, such as `map` and `filter`, are + /// implemented asynchronously. + var async: AsyncSyncSequence { AsyncSyncSequence(self) } } /// An asynchronous sequence composed from a synchronous sequence. @@ -41,36 +39,29 @@ extension Sequence { /// This functions similarly to `LazySequence` by accessing elements sequentially /// in the iterator's `next()` method. struct AsyncSyncSequence: AsyncSequence { - typealias Element = Base.Element + typealias Element = Base.Element - struct Iterator: AsyncIteratorProtocol { - var iterator: Base.Iterator? + struct Iterator: AsyncIteratorProtocol { + var iterator: Base.Iterator? - init(_ iterator: Base.Iterator) { - self.iterator = iterator - } + init(_ iterator: Base.Iterator) { self.iterator = iterator } - mutating func next() async -> Base.Element? { - guard !Task.isCancelled, let value = iterator?.next() else { - iterator = nil - return nil - } - return value + mutating func next() async -> Base.Element? { + guard !Task.isCancelled, let value = iterator?.next() else { + iterator = nil + return nil + } + return value + } } - } - let base: Base + let base: Base - init(_ base: Base) { - self.base = base - } + init(_ base: Base) { self.base = base } - func makeAsyncIterator() -> Iterator { - Iterator(base.makeIterator()) - } + func makeAsyncIterator() -> Iterator { Iterator(base.makeIterator()) } } extension AsyncSyncSequence: Sendable where Base: Sendable {} -@available(*, unavailable) -extension AsyncSyncSequence.Iterator: Sendable {} +@available(*, unavailable) extension AsyncSyncSequence.Iterator: Sendable {} From 660316a0b24ce137c8516d2d2659a98e0c1f8a23 Mon Sep 17 00:00:00 2001 From: Honza Dvorsky Date: Fri, 20 Feb 2026 17:56:49 +0100 Subject: [PATCH 4/5] Avoid API breaks with sendable metatype --- Sources/OpenAPIRuntime/EventStreams/JSONLinesDecoding.swift | 2 +- Sources/OpenAPIRuntime/EventStreams/JSONSequenceDecoding.swift | 2 +- .../OpenAPIRuntime/EventStreams/ServerSentEventsDecoding.swift | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Sources/OpenAPIRuntime/EventStreams/JSONLinesDecoding.swift b/Sources/OpenAPIRuntime/EventStreams/JSONLinesDecoding.swift index fc6423c6..b00572ca 100644 --- a/Sources/OpenAPIRuntime/EventStreams/JSONLinesDecoding.swift +++ b/Sources/OpenAPIRuntime/EventStreams/JSONLinesDecoding.swift @@ -80,7 +80,7 @@ extension AsyncSequence where Element == ArraySlice { /// - eventType: The type to decode the JSON event into. /// - decoder: The JSON decoder to use. /// - Returns: A sequence that provides the decoded JSON events. - public func asDecodedJSONLines( + @preconcurrency public func asDecodedJSONLines( of eventType: Event.Type = Event.self, decoder: JSONDecoder = .init() ) -> AsyncThrowingMapSequence, Event> { diff --git a/Sources/OpenAPIRuntime/EventStreams/JSONSequenceDecoding.swift b/Sources/OpenAPIRuntime/EventStreams/JSONSequenceDecoding.swift index 77df7bbb..962e22d2 100644 --- a/Sources/OpenAPIRuntime/EventStreams/JSONSequenceDecoding.swift +++ b/Sources/OpenAPIRuntime/EventStreams/JSONSequenceDecoding.swift @@ -99,7 +99,7 @@ extension AsyncSequence where Element == ArraySlice { /// - eventType: The type to decode the JSON event into. /// - decoder: The JSON decoder to use. /// - Returns: A sequence that provides the decoded JSON events. - public func asDecodedJSONSequence( + @preconcurrency public func asDecodedJSONSequence( of eventType: Event.Type = Event.self, decoder: JSONDecoder = .init() ) -> AsyncThrowingMapSequence, Event> { diff --git a/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsDecoding.swift b/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsDecoding.swift index 2f4c71a9..813c265c 100644 --- a/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsDecoding.swift +++ b/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsDecoding.swift @@ -115,7 +115,8 @@ extension AsyncSequence where Element == ArraySlice, Self: Sendable { /// - decoder: The JSON decoder to use. /// - predicate: A closure that determines whether the given byte sequence is the terminating byte sequence defined by the API. /// - Returns: A sequence that provides the events with the decoded JSON data. - public func asDecodedServerSentEventsWithJSONData( + @preconcurrency + public func asDecodedServerSentEventsWithJSONData( of dataType: JSONDataType.Type = JSONDataType.self, decoder: JSONDecoder = .init(), while predicate: @escaping @Sendable (ArraySlice) -> Bool = { _ in true } From 832ccd32261e4ed83c9b34ff90a167b7cf8b2e12 Mon Sep 17 00:00:00 2001 From: Honza Dvorsky Date: Mon, 23 Feb 2026 19:37:13 +0100 Subject: [PATCH 5/5] Avoid breaking ABI --- .swiftformatignore | 3 +++ .../EventStreams/JSONLinesDecoding.swift | 9 ++++++++- .../EventStreams/JSONSequenceDecoding.swift | 9 ++++++++- .../EventStreams/ServerSentEventsDecoding.swift | 12 ++++++++++++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/.swiftformatignore b/.swiftformatignore index ef0b696a..7c62d389 100644 --- a/.swiftformatignore +++ b/.swiftformatignore @@ -1 +1,4 @@ **Package.swift +Sources/OpenAPIRuntime/EventStreams/JSONLinesDecoding.swift +Sources/OpenAPIRuntime/EventStreams/JSONSequenceDecoding.swift +Sources/OpenAPIRuntime/EventStreams/ServerSentEventsDecoding.swift diff --git a/Sources/OpenAPIRuntime/EventStreams/JSONLinesDecoding.swift b/Sources/OpenAPIRuntime/EventStreams/JSONLinesDecoding.swift index b00572ca..174a052c 100644 --- a/Sources/OpenAPIRuntime/EventStreams/JSONLinesDecoding.swift +++ b/Sources/OpenAPIRuntime/EventStreams/JSONLinesDecoding.swift @@ -80,7 +80,14 @@ extension AsyncSequence where Element == ArraySlice { /// - eventType: The type to decode the JSON event into. /// - decoder: The JSON decoder to use. /// - Returns: A sequence that provides the decoded JSON events. - @preconcurrency public func asDecodedJSONLines( + #if compiler(>=6.2) + @abi( + func asDecodedJSONLines(of eventType: Event.Type, decoder: JSONDecoder) + -> AsyncThrowingMapSequence, Event> + ) + #endif + @preconcurrency + public func asDecodedJSONLines( of eventType: Event.Type = Event.self, decoder: JSONDecoder = .init() ) -> AsyncThrowingMapSequence, Event> { diff --git a/Sources/OpenAPIRuntime/EventStreams/JSONSequenceDecoding.swift b/Sources/OpenAPIRuntime/EventStreams/JSONSequenceDecoding.swift index 962e22d2..b0e4c268 100644 --- a/Sources/OpenAPIRuntime/EventStreams/JSONSequenceDecoding.swift +++ b/Sources/OpenAPIRuntime/EventStreams/JSONSequenceDecoding.swift @@ -99,7 +99,14 @@ extension AsyncSequence where Element == ArraySlice { /// - eventType: The type to decode the JSON event into. /// - decoder: The JSON decoder to use. /// - Returns: A sequence that provides the decoded JSON events. - @preconcurrency public func asDecodedJSONSequence( + #if compiler(>=6.2) + @abi( + func asDecodedJSONSequence(of eventType: Event.Type, decoder: JSONDecoder) + -> AsyncThrowingMapSequence, Event> + ) + #endif + @preconcurrency + public func asDecodedJSONSequence( of eventType: Event.Type = Event.self, decoder: JSONDecoder = .init() ) -> AsyncThrowingMapSequence, Event> { diff --git a/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsDecoding.swift b/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsDecoding.swift index 813c265c..5679e8a7 100644 --- a/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsDecoding.swift +++ b/Sources/OpenAPIRuntime/EventStreams/ServerSentEventsDecoding.swift @@ -115,6 +115,18 @@ extension AsyncSequence where Element == ArraySlice, Self: Sendable { /// - decoder: The JSON decoder to use. /// - predicate: A closure that determines whether the given byte sequence is the terminating byte sequence defined by the API. /// - Returns: A sequence that provides the events with the decoded JSON data. + #if compiler(>=6.2) + @abi( + func asDecodedServerSentEventsWithJSONData( + of eventType: JSONDataType.Type, + decoder: JSONDecoder, + while predicate: @escaping @Sendable (ArraySlice) -> Bool + ) -> AsyncThrowingMapSequence< + ServerSentEventsDeserializationSequence>, + ServerSentEventWithJSONData + > + ) + #endif @preconcurrency public func asDecodedServerSentEventsWithJSONData( of dataType: JSONDataType.Type = JSONDataType.self,