diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift6ClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift6ClientCodegen.java index caec04adb227..41d34b5ddbda 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift6ClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/Swift6ClientCodegen.java @@ -673,6 +673,9 @@ public void processOpts() { infrastructureFolder, "OpenAPIDateWithoutTime.swift")); } + supportingFiles.add(new SupportingFile("OpenAPIMutex.mustache", + infrastructureFolder, + "OpenAPIMutex.swift")); supportingFiles.add(new SupportingFile("APIs.mustache", infrastructureFolder, "APIs.swift")); diff --git a/modules/openapi-generator/src/main/resources/swift6/APIs.mustache b/modules/openapi-generator/src/main/resources/swift6/APIs.mustache index 78b13a080998..e30c565804ec 100644 --- a/modules/openapi-generator/src/main/resources/swift6/APIs.mustache +++ b/modules/openapi-generator/src/main/resources/swift6/APIs.mustache @@ -16,34 +16,116 @@ import Alamofire{{/useAlamofire}} {{/swiftUseApiNamespace}} {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class {{projectName}}APIConfiguration: @unchecked Sendable { - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var basePath: String{{#useVapor}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var customHeaders: HTTPHeaders - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var apiClient: Vapor.Client? - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var apiWrapper: @Sendable (inout Vapor.ClientRequest) throws -> () - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var contentConfiguration: ContentConfiguration{{/useVapor}}{{^useVapor}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var customHeaders: [String: String] - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var credential: URLCredential? - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var requestBuilderFactory: RequestBuilderFactory - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var apiResponseQueue: DispatchQueue - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var codableHelper: CodableHelper - - /// Configures the range of HTTP status codes that will result in a successful response + + // MARK: - Private state + + private struct State { + var basePath: String{{#useVapor}} + var customHeaders: HTTPHeaders + var apiClient: Vapor.Client? + var apiWrapper: @Sendable (inout Vapor.ClientRequest) throws -> () + var contentConfiguration: ContentConfiguration{{/useVapor}}{{^useVapor}} + var customHeaders: [String: String] + var credential: URLCredential? + var requestBuilderFactory: RequestBuilderFactory + var apiResponseQueue: DispatchQueue + var codableHelper: CodableHelper + var successfulStatusCodeRange: Range{{#useURLSession}} + var interceptor: OpenAPIInterceptor{{/useURLSession}}{{#useAlamofire}} + var interceptor: RequestInterceptor? + var dataResponseSerializer: AnyResponseSerializer + var stringResponseSerializer: AnyResponseSerializer{{/useAlamofire}}{{/useVapor}} + } + + private let _state: OpenAPIMutex + + // MARK: - Public interface + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var basePath: String { + get { _state.value.basePath } + set { _state.withValue { $0.basePath = newValue } } + }{{#useVapor}} + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var customHeaders: HTTPHeaders { + get { _state.value.customHeaders } + set { _state.withValue { $0.customHeaders = newValue } } + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var apiClient: Vapor.Client? { + get { _state.value.apiClient } + set { _state.withValue { $0.apiClient = newValue } } + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var apiWrapper: @Sendable (inout Vapor.ClientRequest) throws -> () { + get { _state.value.apiWrapper } + set { _state.withValue { $0.apiWrapper = newValue } } + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var contentConfiguration: ContentConfiguration { + get { _state.value.contentConfiguration } + set { _state.withValue { $0.contentConfiguration = newValue } } + }{{/useVapor}}{{^useVapor}} + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var customHeaders: [String: String] { + get { _state.value.customHeaders } + set { _state.withValue { $0.customHeaders = newValue } } + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var requestBuilderFactory: RequestBuilderFactory { + get { _state.value.requestBuilderFactory } + set { _state.withValue { $0.requestBuilderFactory = newValue } } + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var apiResponseQueue: DispatchQueue { + get { _state.value.apiResponseQueue } + set { _state.withValue { $0.apiResponseQueue = newValue } } + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var codableHelper: CodableHelper { + get { _state.value.codableHelper } + set { _state.withValue { $0.codableHelper = newValue } } + } + + /// Configures the range of HTTP status codes that will result in a successful response. /// /// If a HTTP status code is outside of this range the response will be interpreted as failed. - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var successfulStatusCodeRange: Range{{#useURLSession}} + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var successfulStatusCodeRange: Range { + get { _state.value.successfulStatusCodeRange } + set { _state.withValue { $0.successfulStatusCodeRange = newValue } } + }{{#useURLSession}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var interceptor: OpenAPIInterceptor{{/useURLSession}}{{#useAlamofire}} + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var interceptor: OpenAPIInterceptor { + get { _state.value.interceptor } + set { _state.withValue { $0.interceptor = newValue } } + }{{/useURLSession}}{{#useAlamofire}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var interceptor: RequestInterceptor? + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var interceptor: RequestInterceptor? { + get { _state.value.interceptor } + set { _state.withValue { $0.interceptor = newValue } } + } /// ResponseSerializer that will be used by the generator for `Data` responses /// - /// If unchanged, Alamofires default `DataResponseSerializer` will be used. - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var dataResponseSerializer: AnyResponseSerializer + /// If unchanged, Alamofires default `DataResponseSerializer` will be used. + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var dataResponseSerializer: AnyResponseSerializer { + get { _state.value.dataResponseSerializer } + set { _state.withValue { $0.dataResponseSerializer = newValue } } + } + /// ResponseSerializer that will be used by the generator for `String` responses /// - /// If unchanged, Alamofires default `StringResponseSerializer` will be used. - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var stringResponseSerializer: AnyResponseSerializer{{/useAlamofire}}{{/useVapor}} + /// If unchanged, Alamofires default `StringResponseSerializer` will be used. + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var stringResponseSerializer: AnyResponseSerializer { + get { _state.value.stringResponseSerializer } + set { _state.withValue { $0.stringResponseSerializer = newValue } } + }{{/useAlamofire}}{{/useVapor}} + + // MARK: - Init {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} init( basePath: String = "{{{basePath}}}",{{#useVapor}} @@ -62,29 +144,32 @@ import Alamofire{{/useAlamofire}} dataResponseSerializer: AnyResponseSerializer = AnyResponseSerializer(DataResponseSerializer()), stringResponseSerializer: AnyResponseSerializer = AnyResponseSerializer(StringResponseSerializer()){{/useAlamofire}}{{/useVapor}} ) { - self.basePath = basePath{{#useVapor}} - self.customHeaders = customHeaders - self.apiClient = apiClient - self.apiWrapper = apiWrapper - self.contentConfiguration = contentConfiguration{{/useVapor}}{{^useVapor}} - self.customHeaders = customHeaders - self.credential = credential - self.requestBuilderFactory = requestBuilderFactory - self.apiResponseQueue = apiResponseQueue - self.codableHelper = codableHelper - self.successfulStatusCodeRange = successfulStatusCodeRange{{#useURLSession}} - self.interceptor = interceptor{{/useURLSession}}{{#useAlamofire}} - self.interceptor = interceptor - self.dataResponseSerializer = dataResponseSerializer - self.stringResponseSerializer = stringResponseSerializer{{/useAlamofire}}{{/useVapor}} + _state = OpenAPIMutex(State( + basePath: basePath,{{#useVapor}} + customHeaders: customHeaders, + apiClient: apiClient, + apiWrapper: apiWrapper, + contentConfiguration: contentConfiguration{{/useVapor}}{{^useVapor}} + customHeaders: customHeaders, + credential: credential, + requestBuilderFactory: requestBuilderFactory, + apiResponseQueue: apiResponseQueue, + codableHelper: codableHelper, + successfulStatusCodeRange: successfulStatusCodeRange{{#useURLSession}}, + interceptor: interceptor{{/useURLSession}}{{#useAlamofire}}, + interceptor: interceptor, + dataResponseSerializer: dataResponseSerializer, + stringResponseSerializer: stringResponseSerializer{{/useAlamofire}}{{/useVapor}} + )) } {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static let shared = {{projectName}}APIConfiguration() }{{^useVapor}} {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class RequestBuilder: @unchecked Sendable, Identifiable { - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var credential: URLCredential? - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var headers: [String: String] + + // MARK: - Immutable properties + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} let parameters: [String: any Sendable]? {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} let method: String {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} let URLString: String @@ -92,24 +177,62 @@ import Alamofire{{/useAlamofire}} {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} let requiresAuthentication: Bool {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} let apiConfiguration: {{projectName}}APIConfiguration + // MARK: - Private mutable state + + private struct MutableState { + var credential: URLCredential? = nil + var headers: [String: String] + var onProgressReady: ((Progress) -> Void)? = nil + } + + private let _state: OpenAPIMutex + + // MARK: - Public mutable interface + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var headers: [String: String] { + get { _state.value.headers } + set { _state.withValue { $0.headers = newValue } } + } + /// Optional block to obtain a reference to the request's progress instance when available. - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var onProgressReady: ((Progress) -> Void)? + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var onProgressReady: ((Progress) -> Void)? { + get { _state.value.onProgressReady } + set { _state.withValue { $0.onProgressReady = newValue } } + } - required {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} init(method: String, URLString: String, parameters: [String: any Sendable]?, headers: [String: String] = [:], requiresAuthentication: Bool, apiConfiguration: {{projectName}}APIConfiguration = {{projectName}}APIConfiguration.shared) { + // MARK: - Init + + required {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} init( + method: String, + URLString: String, + parameters: [String: any Sendable]?, + headers: [String: String] = [:], + requiresAuthentication: Bool, + apiConfiguration: {{projectName}}APIConfiguration = {{projectName}}APIConfiguration.shared + ) { self.method = method self.URLString = URLString self.parameters = parameters - self.headers = headers self.requiresAuthentication = requiresAuthentication self.apiConfiguration = apiConfiguration + self._state = OpenAPIMutex(MutableState(headers: headers)) addHeaders(apiConfiguration.customHeaders) addCredential() } + // MARK: - Public methods + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} func addHeaders(_ aHeaders: [String: String]) { - for (header, value) in aHeaders { - headers[header] = value + _state.withValue { state in + for (header, value) in aHeaders { + state.headers[header] = value + } } } @@ -168,13 +291,15 @@ import Alamofire{{/useAlamofire}} {{/useAsyncAwait}} {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func addHeader(name: String, value: String) -> Self { if !value.isEmpty { - headers[name] = value + _state.withValue { $0.headers[name] = value } } return self } {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} func addCredential() { - credential = apiConfiguration.credential + _state.withValue { [apiConfiguration] state in + state.credential = apiConfiguration.credential + } } } diff --git a/modules/openapi-generator/src/main/resources/swift6/CodableHelper.mustache b/modules/openapi-generator/src/main/resources/swift6/CodableHelper.mustache index 8ce3ec679b74..f9bb64bb0b57 100644 --- a/modules/openapi-generator/src/main/resources/swift6/CodableHelper.mustache +++ b/modules/openapi-generator/src/main/resources/swift6/CodableHelper.mustache @@ -8,37 +8,56 @@ import Foundation {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class CodableHelper: @unchecked Sendable { - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} init() {} - private var customDateFormatter: DateFormatter? - private var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + // MARK: - Private state + + private struct State { + var customDateFormatter: DateFormatter? + var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + + var customJSONDecoder: JSONDecoder? + var defaultJSONDecoder: JSONDecoder = JSONDecoder() + + var customJSONEncoder: JSONEncoder? + var defaultJSONEncoder: JSONEncoder = JSONEncoder() + + init() { + defaultJSONEncoder.outputFormatting = .prettyPrinted + rebuildDefaultCoders() + } + + mutating func rebuildDefaultCoders() { + defaultJSONDecoder.dateDecodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + defaultJSONEncoder.dateEncodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + } + } + + private let _state = OpenAPIMutex(State()) + + // MARK: - Init - private var customJSONDecoder: JSONDecoder? - private lazy var defaultJSONDecoder: JSONDecoder = { - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .formatted(dateFormatter) - return decoder - }() + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} init() {} - private var customJSONEncoder: JSONEncoder? - private lazy var defaultJSONEncoder: JSONEncoder = { - let encoder = JSONEncoder() - encoder.dateEncodingStrategy = .formatted(dateFormatter) - encoder.outputFormatting = .prettyPrinted - return encoder - }() + // MARK: - Public interface {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var dateFormatter: DateFormatter { - get { return customDateFormatter ?? defaultDateFormatter } - set { customDateFormatter = newValue } + get { _state.withValue { $0.customDateFormatter ?? $0.defaultDateFormatter } } + set { + _state.withValue { state in + state.customDateFormatter = newValue + state.rebuildDefaultCoders() + } + } } + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var jsonDecoder: JSONDecoder { - get { return customJSONDecoder ?? defaultJSONDecoder } - set { customJSONDecoder = newValue } + get { _state.withValue { $0.customJSONDecoder ?? $0.defaultJSONDecoder } } + set { _state.withValue { $0.customJSONDecoder = newValue } } } + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var jsonEncoder: JSONEncoder { - get { return customJSONEncoder ?? defaultJSONEncoder } - set { customJSONEncoder = newValue } + get { _state.withValue { $0.customJSONEncoder ?? $0.defaultJSONEncoder } } + set { _state.withValue { $0.customJSONEncoder = newValue } } } {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} func decode(_ type: T.Type, from data: Data) -> Swift.Result where T: Decodable { diff --git a/modules/openapi-generator/src/main/resources/swift6/Models.mustache b/modules/openapi-generator/src/main/resources/swift6/Models.mustache index 0a1f951e7682..1189b1d836cf 100644 --- a/modules/openapi-generator/src/main/resources/swift6/Models.mustache +++ b/modules/openapi-generator/src/main/resources/swift6/Models.mustache @@ -133,48 +133,39 @@ extension Response : Sendable where T : Sendable {}{{#useAlamofire}} }{{/useAlamofire}} {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} final class RequestTask: @unchecked Sendable { - private let lock = NSRecursiveLock() {{#useAlamofire}} - private var request: Request? + private let _state = OpenAPIMutex(nil) internal func set(request: Request) { - lock.withLock { - self.request = request - } + _state.withValue { $0 = request } } internal func get() -> Request? { - lock.withLock { - request - } + _state.value } {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func cancel() { - lock.withLock { - request?.cancel() - request = nil + _state.withValue { + $0?.cancel() + $0 = nil } } {{/useAlamofire}} {{^useAlamofire}} - private var task: URLSessionDataTaskProtocol? + private let _state = OpenAPIMutex(nil) internal func set(task: URLSessionDataTaskProtocol) { - lock.withLock { - self.task = task - } + _state.withValue { $0 = task } } internal func get() -> URLSessionDataTaskProtocol? { - lock.withLock { - task - } + _state.value } {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func cancel() { - lock.withLock { - task?.cancel() - task = nil + _state.withValue { + $0?.cancel() + $0 = nil } } {{/useAlamofire}} diff --git a/modules/openapi-generator/src/main/resources/swift6/OpenAPIMutex.mustache b/modules/openapi-generator/src/main/resources/swift6/OpenAPIMutex.mustache new file mode 100644 index 000000000000..d7be0b6bd92e --- /dev/null +++ b/modules/openapi-generator/src/main/resources/swift6/OpenAPIMutex.mustache @@ -0,0 +1,28 @@ +// OpenAPIMutex.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +internal final class OpenAPIMutex: @unchecked Sendable { + + private var _value: Value + private let lock = NSRecursiveLock() + + internal init(_ value: Value) { + self._value = value + } + + internal var value: Value { + lock.withLock { _value } + } + + @discardableResult + internal func withValue( + _ body: (inout Value) throws -> Result + ) rethrows -> Result { + try lock.withLock { try body(&_value) } + } +} diff --git a/modules/openapi-generator/src/main/resources/swift6/SynchronizedDictionary.mustache b/modules/openapi-generator/src/main/resources/swift6/SynchronizedDictionary.mustache index 0d2714ca7b02..6c80862c6a0b 100644 --- a/modules/openapi-generator/src/main/resources/swift6/SynchronizedDictionary.mustache +++ b/modules/openapi-generator/src/main/resources/swift6/SynchronizedDictionary.mustache @@ -6,21 +6,12 @@ import Foundation -internal class SynchronizedDictionary : @unchecked Sendable { +internal final class SynchronizedDictionary: @unchecked Sendable { - private var dictionary = [K: V]() - private let lock = NSRecursiveLock() + private let _state = OpenAPIMutex<[K: V]>([:]) internal subscript(key: K) -> V? { - get { - lock.withLock { - self.dictionary[key] - } - } - set { - lock.withLock { - self.dictionary[key] = newValue - } - } + get { _state.value[key] } + set { _state.withValue { $0[key] = newValue } } } } diff --git a/modules/openapi-generator/src/main/resources/swift6/api.mustache b/modules/openapi-generator/src/main/resources/swift6/api.mustache index 2180f72bda6d..2cd9f43c2f64 100644 --- a/modules/openapi-generator/src/main/resources/swift6/api.mustache +++ b/modules/openapi-generator/src/main/resources/swift6/api.mustache @@ -351,7 +351,7 @@ extension {{projectName}}API { {{#isDeprecated}} @available(*, deprecated, message: "This operation is deprecated.") {{/isDeprecated}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} {{#apiStaticMethod}}class {{/apiStaticMethod}}func {{operationId}}Raw({{#allParams}}{{paramName}}: {{#isEnum}}{{#isArray}}[{{enumName}}_{{operationId}}]{{/isArray}}{{^isArray}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}headers: HTTPHeaders? = nil, apiConfiguration: {{projectName}}APIConfiguration = {{projectName}}APIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} {{#apiStaticMethod}}class {{/apiStaticMethod}}func {{operationId}}Raw({{#allParams}}{{paramName}}: {{#isEnum}}{{#isArray}}[{{enumName}}_{{operationId}}]{{/isArray}}{{^isArray}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}headers: HTTPHeaders? = nil, apiConfiguration: {{projectName}}APIConfiguration = {{projectName}}APIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { {{^pathParams}}let{{/pathParams}}{{#pathParams}}{{#-first}}var{{/-first}}{{/pathParams}} localVariablePath = "{{{path}}}"{{#pathParams}} let {{paramName}}PreEscape = String(describing: {{#isEnum}}{{paramName}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}.rawValue{{/isContainer}}{{/isEnum}}{{^isEnum}}{{paramName}}{{/isEnum}}) let {{paramName}}PostEscape = {{paramName}}PreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" @@ -431,7 +431,7 @@ extension {{projectName}}API { {{#isDeprecated}} @available(*, deprecated, message: "This operation is deprecated.") {{/isDeprecated}} - {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} {{#apiStaticMethod}}class {{/apiStaticMethod}}func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isArray}}[{{enumName}}_{{operationId}}]{{/isArray}}{{^isArray}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}headers: HTTPHeaders? = nil, apiConfiguration: {{projectName}}APIConfiguration = {{projectName}}APIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture<{{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}> { + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} {{#apiStaticMethod}}class {{/apiStaticMethod}}func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isArray}}[{{enumName}}_{{operationId}}]{{/isArray}}{{^isArray}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}headers: HTTPHeaders? = nil, apiConfiguration: {{projectName}}APIConfiguration = {{projectName}}APIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture<{{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}> { return {{operationId}}Raw({{#allParams}}{{paramName}}: {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> {{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}} in switch response.status.code { {{#responses}} diff --git a/samples/client/petstore/swift6/alamofireLibrary/.openapi-generator/FILES b/samples/client/petstore/swift6/alamofireLibrary/.openapi-generator/FILES index 6efbd60dd6a9..5052951cf63e 100644 --- a/samples/client/petstore/swift6/alamofireLibrary/.openapi-generator/FILES +++ b/samples/client/petstore/swift6/alamofireLibrary/.openapi-generator/FILES @@ -20,6 +20,7 @@ Sources/PetstoreClient/Infrastructure/JSONEncodingHelper.swift Sources/PetstoreClient/Infrastructure/JSONValue.swift Sources/PetstoreClient/Infrastructure/Models.swift Sources/PetstoreClient/Infrastructure/OpenAPIDateWithoutTime.swift +Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift Sources/PetstoreClient/Infrastructure/OpenISO8601DateFormatter.swift Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift Sources/PetstoreClient/Infrastructure/Validation.swift diff --git a/samples/client/petstore/swift6/alamofireLibrary/Sources/PetstoreClient/Infrastructure/APIs.swift b/samples/client/petstore/swift6/alamofireLibrary/Sources/PetstoreClient/Infrastructure/APIs.swift index 542ab429d641..47e96cb5f692 100644 --- a/samples/client/petstore/swift6/alamofireLibrary/Sources/PetstoreClient/Infrastructure/APIs.swift +++ b/samples/client/petstore/swift6/alamofireLibrary/Sources/PetstoreClient/Infrastructure/APIs.swift @@ -11,28 +11,86 @@ import FoundationNetworking import Alamofire open class PetstoreClientAPIConfiguration: @unchecked Sendable { - public var basePath: String - public var customHeaders: [String: String] - public var credential: URLCredential? - public var requestBuilderFactory: RequestBuilderFactory - public var apiResponseQueue: DispatchQueue - public var codableHelper: CodableHelper - - /// Configures the range of HTTP status codes that will result in a successful response + + // MARK: - Private state + + private struct State { + var basePath: String + var customHeaders: [String: String] + var credential: URLCredential? + var requestBuilderFactory: RequestBuilderFactory + var apiResponseQueue: DispatchQueue + var codableHelper: CodableHelper + var successfulStatusCodeRange: Range + var interceptor: RequestInterceptor? + var dataResponseSerializer: AnyResponseSerializer + var stringResponseSerializer: AnyResponseSerializer + } + + private let _state: OpenAPIMutex + + // MARK: - Public interface + + public var basePath: String { + get { _state.value.basePath } + set { _state.withValue { $0.basePath = newValue } } + } + + public var customHeaders: [String: String] { + get { _state.value.customHeaders } + set { _state.withValue { $0.customHeaders = newValue } } + } + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var requestBuilderFactory: RequestBuilderFactory { + get { _state.value.requestBuilderFactory } + set { _state.withValue { $0.requestBuilderFactory = newValue } } + } + + public var apiResponseQueue: DispatchQueue { + get { _state.value.apiResponseQueue } + set { _state.withValue { $0.apiResponseQueue = newValue } } + } + + public var codableHelper: CodableHelper { + get { _state.value.codableHelper } + set { _state.withValue { $0.codableHelper = newValue } } + } + + /// Configures the range of HTTP status codes that will result in a successful response. /// /// If a HTTP status code is outside of this range the response will be interpreted as failed. - public var successfulStatusCodeRange: Range + public var successfulStatusCodeRange: Range { + get { _state.value.successfulStatusCodeRange } + set { _state.withValue { $0.successfulStatusCodeRange = newValue } } + } - public var interceptor: RequestInterceptor? + public var interceptor: RequestInterceptor? { + get { _state.value.interceptor } + set { _state.withValue { $0.interceptor = newValue } } + } /// ResponseSerializer that will be used by the generator for `Data` responses /// - /// If unchanged, Alamofires default `DataResponseSerializer` will be used. - public var dataResponseSerializer: AnyResponseSerializer + /// If unchanged, Alamofires default `DataResponseSerializer` will be used. + public var dataResponseSerializer: AnyResponseSerializer { + get { _state.value.dataResponseSerializer } + set { _state.withValue { $0.dataResponseSerializer = newValue } } + } + /// ResponseSerializer that will be used by the generator for `String` responses /// - /// If unchanged, Alamofires default `StringResponseSerializer` will be used. - public var stringResponseSerializer: AnyResponseSerializer + /// If unchanged, Alamofires default `StringResponseSerializer` will be used. + public var stringResponseSerializer: AnyResponseSerializer { + get { _state.value.stringResponseSerializer } + set { _state.withValue { $0.stringResponseSerializer = newValue } } + } + + // MARK: - Init public init( basePath: String = "http://petstore.swagger.io:80/v2", @@ -46,24 +104,27 @@ open class PetstoreClientAPIConfiguration: @unchecked Sendable { dataResponseSerializer: AnyResponseSerializer = AnyResponseSerializer(DataResponseSerializer()), stringResponseSerializer: AnyResponseSerializer = AnyResponseSerializer(StringResponseSerializer()) ) { - self.basePath = basePath - self.customHeaders = customHeaders - self.credential = credential - self.requestBuilderFactory = requestBuilderFactory - self.apiResponseQueue = apiResponseQueue - self.codableHelper = codableHelper - self.successfulStatusCodeRange = successfulStatusCodeRange - self.interceptor = interceptor - self.dataResponseSerializer = dataResponseSerializer - self.stringResponseSerializer = stringResponseSerializer + _state = OpenAPIMutex(State( + basePath: basePath, + customHeaders: customHeaders, + credential: credential, + requestBuilderFactory: requestBuilderFactory, + apiResponseQueue: apiResponseQueue, + codableHelper: codableHelper, + successfulStatusCodeRange: successfulStatusCodeRange, + interceptor: interceptor, + dataResponseSerializer: dataResponseSerializer, + stringResponseSerializer: stringResponseSerializer + )) } public static let shared = PetstoreClientAPIConfiguration() } open class RequestBuilder: @unchecked Sendable, Identifiable { - public var credential: URLCredential? - public var headers: [String: String] + + // MARK: - Immutable properties + public let parameters: [String: any Sendable]? public let method: String public let URLString: String @@ -71,24 +132,62 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public let requiresAuthentication: Bool public let apiConfiguration: PetstoreClientAPIConfiguration + // MARK: - Private mutable state + + private struct MutableState { + var credential: URLCredential? = nil + var headers: [String: String] + var onProgressReady: ((Progress) -> Void)? = nil + } + + private let _state: OpenAPIMutex + + // MARK: - Public mutable interface + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var headers: [String: String] { + get { _state.value.headers } + set { _state.withValue { $0.headers = newValue } } + } + /// Optional block to obtain a reference to the request's progress instance when available. - public var onProgressReady: ((Progress) -> Void)? + public var onProgressReady: ((Progress) -> Void)? { + get { _state.value.onProgressReady } + set { _state.withValue { $0.onProgressReady = newValue } } + } - required public init(method: String, URLString: String, parameters: [String: any Sendable]?, headers: [String: String] = [:], requiresAuthentication: Bool, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared) { + // MARK: - Init + + required public init( + method: String, + URLString: String, + parameters: [String: any Sendable]?, + headers: [String: String] = [:], + requiresAuthentication: Bool, + apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared + ) { self.method = method self.URLString = URLString self.parameters = parameters - self.headers = headers self.requiresAuthentication = requiresAuthentication self.apiConfiguration = apiConfiguration + self._state = OpenAPIMutex(MutableState(headers: headers)) addHeaders(apiConfiguration.customHeaders) addCredential() } + // MARK: - Public methods + open func addHeaders(_ aHeaders: [String: String]) { - for (header, value) in aHeaders { - headers[header] = value + _state.withValue { state in + for (header, value) in aHeaders { + state.headers[header] = value + } } } @@ -99,13 +198,15 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public func addHeader(name: String, value: String) -> Self { if !value.isEmpty { - headers[name] = value + _state.withValue { $0.headers[name] = value } } return self } open func addCredential() { - credential = apiConfiguration.credential + _state.withValue { [apiConfiguration] state in + state.credential = apiConfiguration.credential + } } } diff --git a/samples/client/petstore/swift6/alamofireLibrary/Sources/PetstoreClient/Infrastructure/CodableHelper.swift b/samples/client/petstore/swift6/alamofireLibrary/Sources/PetstoreClient/Infrastructure/CodableHelper.swift index b8990f975bcd..7d6f7a6fd1bd 100644 --- a/samples/client/petstore/swift6/alamofireLibrary/Sources/PetstoreClient/Infrastructure/CodableHelper.swift +++ b/samples/client/petstore/swift6/alamofireLibrary/Sources/PetstoreClient/Infrastructure/CodableHelper.swift @@ -8,37 +8,56 @@ import Foundation open class CodableHelper: @unchecked Sendable { - public init() {} - private var customDateFormatter: DateFormatter? - private var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + // MARK: - Private state + + private struct State { + var customDateFormatter: DateFormatter? + var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + + var customJSONDecoder: JSONDecoder? + var defaultJSONDecoder: JSONDecoder = JSONDecoder() + + var customJSONEncoder: JSONEncoder? + var defaultJSONEncoder: JSONEncoder = JSONEncoder() + + init() { + defaultJSONEncoder.outputFormatting = .prettyPrinted + rebuildDefaultCoders() + } + + mutating func rebuildDefaultCoders() { + defaultJSONDecoder.dateDecodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + defaultJSONEncoder.dateEncodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + } + } + + private let _state = OpenAPIMutex(State()) + + // MARK: - Init - private var customJSONDecoder: JSONDecoder? - private lazy var defaultJSONDecoder: JSONDecoder = { - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .formatted(dateFormatter) - return decoder - }() + public init() {} - private var customJSONEncoder: JSONEncoder? - private lazy var defaultJSONEncoder: JSONEncoder = { - let encoder = JSONEncoder() - encoder.dateEncodingStrategy = .formatted(dateFormatter) - encoder.outputFormatting = .prettyPrinted - return encoder - }() + // MARK: - Public interface public var dateFormatter: DateFormatter { - get { return customDateFormatter ?? defaultDateFormatter } - set { customDateFormatter = newValue } + get { _state.withValue { $0.customDateFormatter ?? $0.defaultDateFormatter } } + set { + _state.withValue { state in + state.customDateFormatter = newValue + state.rebuildDefaultCoders() + } + } } + public var jsonDecoder: JSONDecoder { - get { return customJSONDecoder ?? defaultJSONDecoder } - set { customJSONDecoder = newValue } + get { _state.withValue { $0.customJSONDecoder ?? $0.defaultJSONDecoder } } + set { _state.withValue { $0.customJSONDecoder = newValue } } } + public var jsonEncoder: JSONEncoder { - get { return customJSONEncoder ?? defaultJSONEncoder } - set { customJSONEncoder = newValue } + get { _state.withValue { $0.customJSONEncoder ?? $0.defaultJSONEncoder } } + set { _state.withValue { $0.customJSONEncoder = newValue } } } open func decode(_ type: T.Type, from data: Data) -> Swift.Result where T: Decodable { diff --git a/samples/client/petstore/swift6/alamofireLibrary/Sources/PetstoreClient/Infrastructure/Models.swift b/samples/client/petstore/swift6/alamofireLibrary/Sources/PetstoreClient/Infrastructure/Models.swift index c1df20ed54ce..ef2c6e25cf9e 100644 --- a/samples/client/petstore/swift6/alamofireLibrary/Sources/PetstoreClient/Infrastructure/Models.swift +++ b/samples/client/petstore/swift6/alamofireLibrary/Sources/PetstoreClient/Infrastructure/Models.swift @@ -133,25 +133,20 @@ public struct AnyResponseSerializer: ResponseSerializer { } public final class RequestTask: @unchecked Sendable { - private let lock = NSRecursiveLock() - private var request: Request? + private let _state = OpenAPIMutex(nil) internal func set(request: Request) { - lock.withLock { - self.request = request - } + _state.withValue { $0 = request } } internal func get() -> Request? { - lock.withLock { - request - } + _state.value } public func cancel() { - lock.withLock { - request?.cancel() - request = nil + _state.withValue { + $0?.cancel() + $0 = nil } } } diff --git a/samples/client/petstore/swift6/alamofireLibrary/Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift b/samples/client/petstore/swift6/alamofireLibrary/Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift new file mode 100644 index 000000000000..d7be0b6bd92e --- /dev/null +++ b/samples/client/petstore/swift6/alamofireLibrary/Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift @@ -0,0 +1,28 @@ +// OpenAPIMutex.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +internal final class OpenAPIMutex: @unchecked Sendable { + + private var _value: Value + private let lock = NSRecursiveLock() + + internal init(_ value: Value) { + self._value = value + } + + internal var value: Value { + lock.withLock { _value } + } + + @discardableResult + internal func withValue( + _ body: (inout Value) throws -> Result + ) rethrows -> Result { + try lock.withLock { try body(&_value) } + } +} diff --git a/samples/client/petstore/swift6/alamofireLibrary/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift b/samples/client/petstore/swift6/alamofireLibrary/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift index 0d2714ca7b02..6c80862c6a0b 100644 --- a/samples/client/petstore/swift6/alamofireLibrary/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift +++ b/samples/client/petstore/swift6/alamofireLibrary/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift @@ -6,21 +6,12 @@ import Foundation -internal class SynchronizedDictionary : @unchecked Sendable { +internal final class SynchronizedDictionary: @unchecked Sendable { - private var dictionary = [K: V]() - private let lock = NSRecursiveLock() + private let _state = OpenAPIMutex<[K: V]>([:]) internal subscript(key: K) -> V? { - get { - lock.withLock { - self.dictionary[key] - } - } - set { - lock.withLock { - self.dictionary[key] = newValue - } - } + get { _state.value[key] } + set { _state.withValue { $0[key] = newValue } } } } diff --git a/samples/client/petstore/swift6/apiNonStaticMethod/.openapi-generator/FILES b/samples/client/petstore/swift6/apiNonStaticMethod/.openapi-generator/FILES index 36369982241d..85454172acb7 100644 --- a/samples/client/petstore/swift6/apiNonStaticMethod/.openapi-generator/FILES +++ b/samples/client/petstore/swift6/apiNonStaticMethod/.openapi-generator/FILES @@ -19,6 +19,7 @@ Sources/PetstoreClient/Infrastructure/JSONDataEncoding.swift Sources/PetstoreClient/Infrastructure/JSONEncodingHelper.swift Sources/PetstoreClient/Infrastructure/JSONValue.swift Sources/PetstoreClient/Infrastructure/Models.swift +Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift Sources/PetstoreClient/Infrastructure/OpenISO8601DateFormatter.swift Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift Sources/PetstoreClient/Infrastructure/Validation.swift diff --git a/samples/client/petstore/swift6/apiNonStaticMethod/Sources/PetstoreClient/Infrastructure/APIs.swift b/samples/client/petstore/swift6/apiNonStaticMethod/Sources/PetstoreClient/Infrastructure/APIs.swift index 7af51bae5a73..79e4d35c04d3 100644 --- a/samples/client/petstore/swift6/apiNonStaticMethod/Sources/PetstoreClient/Infrastructure/APIs.swift +++ b/samples/client/petstore/swift6/apiNonStaticMethod/Sources/PetstoreClient/Infrastructure/APIs.swift @@ -11,28 +11,86 @@ import FoundationNetworking import Alamofire open class PetstoreClientAPIConfiguration: @unchecked Sendable { - public var basePath: String - public var customHeaders: [String: String] - public var credential: URLCredential? - public var requestBuilderFactory: RequestBuilderFactory - public var apiResponseQueue: DispatchQueue - public var codableHelper: CodableHelper - - /// Configures the range of HTTP status codes that will result in a successful response + + // MARK: - Private state + + private struct State { + var basePath: String + var customHeaders: [String: String] + var credential: URLCredential? + var requestBuilderFactory: RequestBuilderFactory + var apiResponseQueue: DispatchQueue + var codableHelper: CodableHelper + var successfulStatusCodeRange: Range + var interceptor: RequestInterceptor? + var dataResponseSerializer: AnyResponseSerializer + var stringResponseSerializer: AnyResponseSerializer + } + + private let _state: OpenAPIMutex + + // MARK: - Public interface + + public var basePath: String { + get { _state.value.basePath } + set { _state.withValue { $0.basePath = newValue } } + } + + public var customHeaders: [String: String] { + get { _state.value.customHeaders } + set { _state.withValue { $0.customHeaders = newValue } } + } + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var requestBuilderFactory: RequestBuilderFactory { + get { _state.value.requestBuilderFactory } + set { _state.withValue { $0.requestBuilderFactory = newValue } } + } + + public var apiResponseQueue: DispatchQueue { + get { _state.value.apiResponseQueue } + set { _state.withValue { $0.apiResponseQueue = newValue } } + } + + public var codableHelper: CodableHelper { + get { _state.value.codableHelper } + set { _state.withValue { $0.codableHelper = newValue } } + } + + /// Configures the range of HTTP status codes that will result in a successful response. /// /// If a HTTP status code is outside of this range the response will be interpreted as failed. - public var successfulStatusCodeRange: Range + public var successfulStatusCodeRange: Range { + get { _state.value.successfulStatusCodeRange } + set { _state.withValue { $0.successfulStatusCodeRange = newValue } } + } - public var interceptor: RequestInterceptor? + public var interceptor: RequestInterceptor? { + get { _state.value.interceptor } + set { _state.withValue { $0.interceptor = newValue } } + } /// ResponseSerializer that will be used by the generator for `Data` responses /// - /// If unchanged, Alamofires default `DataResponseSerializer` will be used. - public var dataResponseSerializer: AnyResponseSerializer + /// If unchanged, Alamofires default `DataResponseSerializer` will be used. + public var dataResponseSerializer: AnyResponseSerializer { + get { _state.value.dataResponseSerializer } + set { _state.withValue { $0.dataResponseSerializer = newValue } } + } + /// ResponseSerializer that will be used by the generator for `String` responses /// - /// If unchanged, Alamofires default `StringResponseSerializer` will be used. - public var stringResponseSerializer: AnyResponseSerializer + /// If unchanged, Alamofires default `StringResponseSerializer` will be used. + public var stringResponseSerializer: AnyResponseSerializer { + get { _state.value.stringResponseSerializer } + set { _state.withValue { $0.stringResponseSerializer = newValue } } + } + + // MARK: - Init public init( basePath: String = "http://petstore.swagger.io:80/v2", @@ -46,24 +104,27 @@ open class PetstoreClientAPIConfiguration: @unchecked Sendable { dataResponseSerializer: AnyResponseSerializer = AnyResponseSerializer(DataResponseSerializer()), stringResponseSerializer: AnyResponseSerializer = AnyResponseSerializer(StringResponseSerializer()) ) { - self.basePath = basePath - self.customHeaders = customHeaders - self.credential = credential - self.requestBuilderFactory = requestBuilderFactory - self.apiResponseQueue = apiResponseQueue - self.codableHelper = codableHelper - self.successfulStatusCodeRange = successfulStatusCodeRange - self.interceptor = interceptor - self.dataResponseSerializer = dataResponseSerializer - self.stringResponseSerializer = stringResponseSerializer + _state = OpenAPIMutex(State( + basePath: basePath, + customHeaders: customHeaders, + credential: credential, + requestBuilderFactory: requestBuilderFactory, + apiResponseQueue: apiResponseQueue, + codableHelper: codableHelper, + successfulStatusCodeRange: successfulStatusCodeRange, + interceptor: interceptor, + dataResponseSerializer: dataResponseSerializer, + stringResponseSerializer: stringResponseSerializer + )) } public static let shared = PetstoreClientAPIConfiguration() } open class RequestBuilder: @unchecked Sendable, Identifiable { - public var credential: URLCredential? - public var headers: [String: String] + + // MARK: - Immutable properties + public let parameters: [String: any Sendable]? public let method: String public let URLString: String @@ -71,24 +132,62 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public let requiresAuthentication: Bool public let apiConfiguration: PetstoreClientAPIConfiguration + // MARK: - Private mutable state + + private struct MutableState { + var credential: URLCredential? = nil + var headers: [String: String] + var onProgressReady: ((Progress) -> Void)? = nil + } + + private let _state: OpenAPIMutex + + // MARK: - Public mutable interface + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var headers: [String: String] { + get { _state.value.headers } + set { _state.withValue { $0.headers = newValue } } + } + /// Optional block to obtain a reference to the request's progress instance when available. - public var onProgressReady: ((Progress) -> Void)? + public var onProgressReady: ((Progress) -> Void)? { + get { _state.value.onProgressReady } + set { _state.withValue { $0.onProgressReady = newValue } } + } - required public init(method: String, URLString: String, parameters: [String: any Sendable]?, headers: [String: String] = [:], requiresAuthentication: Bool, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared) { + // MARK: - Init + + required public init( + method: String, + URLString: String, + parameters: [String: any Sendable]?, + headers: [String: String] = [:], + requiresAuthentication: Bool, + apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared + ) { self.method = method self.URLString = URLString self.parameters = parameters - self.headers = headers self.requiresAuthentication = requiresAuthentication self.apiConfiguration = apiConfiguration + self._state = OpenAPIMutex(MutableState(headers: headers)) addHeaders(apiConfiguration.customHeaders) addCredential() } + // MARK: - Public methods + open func addHeaders(_ aHeaders: [String: String]) { - for (header, value) in aHeaders { - headers[header] = value + _state.withValue { state in + for (header, value) in aHeaders { + state.headers[header] = value + } } } @@ -145,13 +244,15 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public func addHeader(name: String, value: String) -> Self { if !value.isEmpty { - headers[name] = value + _state.withValue { $0.headers[name] = value } } return self } open func addCredential() { - credential = apiConfiguration.credential + _state.withValue { [apiConfiguration] state in + state.credential = apiConfiguration.credential + } } } diff --git a/samples/client/petstore/swift6/apiNonStaticMethod/Sources/PetstoreClient/Infrastructure/CodableHelper.swift b/samples/client/petstore/swift6/apiNonStaticMethod/Sources/PetstoreClient/Infrastructure/CodableHelper.swift index b8990f975bcd..7d6f7a6fd1bd 100644 --- a/samples/client/petstore/swift6/apiNonStaticMethod/Sources/PetstoreClient/Infrastructure/CodableHelper.swift +++ b/samples/client/petstore/swift6/apiNonStaticMethod/Sources/PetstoreClient/Infrastructure/CodableHelper.swift @@ -8,37 +8,56 @@ import Foundation open class CodableHelper: @unchecked Sendable { - public init() {} - private var customDateFormatter: DateFormatter? - private var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + // MARK: - Private state + + private struct State { + var customDateFormatter: DateFormatter? + var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + + var customJSONDecoder: JSONDecoder? + var defaultJSONDecoder: JSONDecoder = JSONDecoder() + + var customJSONEncoder: JSONEncoder? + var defaultJSONEncoder: JSONEncoder = JSONEncoder() + + init() { + defaultJSONEncoder.outputFormatting = .prettyPrinted + rebuildDefaultCoders() + } + + mutating func rebuildDefaultCoders() { + defaultJSONDecoder.dateDecodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + defaultJSONEncoder.dateEncodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + } + } + + private let _state = OpenAPIMutex(State()) + + // MARK: - Init - private var customJSONDecoder: JSONDecoder? - private lazy var defaultJSONDecoder: JSONDecoder = { - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .formatted(dateFormatter) - return decoder - }() + public init() {} - private var customJSONEncoder: JSONEncoder? - private lazy var defaultJSONEncoder: JSONEncoder = { - let encoder = JSONEncoder() - encoder.dateEncodingStrategy = .formatted(dateFormatter) - encoder.outputFormatting = .prettyPrinted - return encoder - }() + // MARK: - Public interface public var dateFormatter: DateFormatter { - get { return customDateFormatter ?? defaultDateFormatter } - set { customDateFormatter = newValue } + get { _state.withValue { $0.customDateFormatter ?? $0.defaultDateFormatter } } + set { + _state.withValue { state in + state.customDateFormatter = newValue + state.rebuildDefaultCoders() + } + } } + public var jsonDecoder: JSONDecoder { - get { return customJSONDecoder ?? defaultJSONDecoder } - set { customJSONDecoder = newValue } + get { _state.withValue { $0.customJSONDecoder ?? $0.defaultJSONDecoder } } + set { _state.withValue { $0.customJSONDecoder = newValue } } } + public var jsonEncoder: JSONEncoder { - get { return customJSONEncoder ?? defaultJSONEncoder } - set { customJSONEncoder = newValue } + get { _state.withValue { $0.customJSONEncoder ?? $0.defaultJSONEncoder } } + set { _state.withValue { $0.customJSONEncoder = newValue } } } open func decode(_ type: T.Type, from data: Data) -> Swift.Result where T: Decodable { diff --git a/samples/client/petstore/swift6/apiNonStaticMethod/Sources/PetstoreClient/Infrastructure/Models.swift b/samples/client/petstore/swift6/apiNonStaticMethod/Sources/PetstoreClient/Infrastructure/Models.swift index c1df20ed54ce..ef2c6e25cf9e 100644 --- a/samples/client/petstore/swift6/apiNonStaticMethod/Sources/PetstoreClient/Infrastructure/Models.swift +++ b/samples/client/petstore/swift6/apiNonStaticMethod/Sources/PetstoreClient/Infrastructure/Models.swift @@ -133,25 +133,20 @@ public struct AnyResponseSerializer: ResponseSerializer { } public final class RequestTask: @unchecked Sendable { - private let lock = NSRecursiveLock() - private var request: Request? + private let _state = OpenAPIMutex(nil) internal func set(request: Request) { - lock.withLock { - self.request = request - } + _state.withValue { $0 = request } } internal func get() -> Request? { - lock.withLock { - request - } + _state.value } public func cancel() { - lock.withLock { - request?.cancel() - request = nil + _state.withValue { + $0?.cancel() + $0 = nil } } } diff --git a/samples/client/petstore/swift6/apiNonStaticMethod/Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift b/samples/client/petstore/swift6/apiNonStaticMethod/Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift new file mode 100644 index 000000000000..d7be0b6bd92e --- /dev/null +++ b/samples/client/petstore/swift6/apiNonStaticMethod/Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift @@ -0,0 +1,28 @@ +// OpenAPIMutex.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +internal final class OpenAPIMutex: @unchecked Sendable { + + private var _value: Value + private let lock = NSRecursiveLock() + + internal init(_ value: Value) { + self._value = value + } + + internal var value: Value { + lock.withLock { _value } + } + + @discardableResult + internal func withValue( + _ body: (inout Value) throws -> Result + ) rethrows -> Result { + try lock.withLock { try body(&_value) } + } +} diff --git a/samples/client/petstore/swift6/apiNonStaticMethod/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift b/samples/client/petstore/swift6/apiNonStaticMethod/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift index 0d2714ca7b02..6c80862c6a0b 100644 --- a/samples/client/petstore/swift6/apiNonStaticMethod/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift +++ b/samples/client/petstore/swift6/apiNonStaticMethod/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift @@ -6,21 +6,12 @@ import Foundation -internal class SynchronizedDictionary : @unchecked Sendable { +internal final class SynchronizedDictionary: @unchecked Sendable { - private var dictionary = [K: V]() - private let lock = NSRecursiveLock() + private let _state = OpenAPIMutex<[K: V]>([:]) internal subscript(key: K) -> V? { - get { - lock.withLock { - self.dictionary[key] - } - } - set { - lock.withLock { - self.dictionary[key] = newValue - } - } + get { _state.value[key] } + set { _state.withValue { $0[key] = newValue } } } } diff --git a/samples/client/petstore/swift6/asyncAwaitLibrary/.openapi-generator/FILES b/samples/client/petstore/swift6/asyncAwaitLibrary/.openapi-generator/FILES index dbd6732f0444..e8d5c4bbbb91 100644 --- a/samples/client/petstore/swift6/asyncAwaitLibrary/.openapi-generator/FILES +++ b/samples/client/petstore/swift6/asyncAwaitLibrary/.openapi-generator/FILES @@ -18,6 +18,7 @@ Sources/PetstoreClient/Infrastructure/JSONDataEncoding.swift Sources/PetstoreClient/Infrastructure/JSONEncodingHelper.swift Sources/PetstoreClient/Infrastructure/JSONValue.swift Sources/PetstoreClient/Infrastructure/Models.swift +Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift Sources/PetstoreClient/Infrastructure/OpenISO8601DateFormatter.swift Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift Sources/PetstoreClient/Infrastructure/URLSessionImplementations.swift diff --git a/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/APIs.swift b/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/APIs.swift index 89dc30b72299..aa5b2fe89e7c 100644 --- a/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/APIs.swift +++ b/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/APIs.swift @@ -10,19 +10,68 @@ import FoundationNetworking #endif open class PetstoreClientAPIConfiguration: @unchecked Sendable { - public var basePath: String - public var customHeaders: [String: String] - public var credential: URLCredential? - public var requestBuilderFactory: RequestBuilderFactory - public var apiResponseQueue: DispatchQueue - public var codableHelper: CodableHelper - - /// Configures the range of HTTP status codes that will result in a successful response + + // MARK: - Private state + + private struct State { + var basePath: String + var customHeaders: [String: String] + var credential: URLCredential? + var requestBuilderFactory: RequestBuilderFactory + var apiResponseQueue: DispatchQueue + var codableHelper: CodableHelper + var successfulStatusCodeRange: Range + var interceptor: OpenAPIInterceptor + } + + private let _state: OpenAPIMutex + + // MARK: - Public interface + + public var basePath: String { + get { _state.value.basePath } + set { _state.withValue { $0.basePath = newValue } } + } + + public var customHeaders: [String: String] { + get { _state.value.customHeaders } + set { _state.withValue { $0.customHeaders = newValue } } + } + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var requestBuilderFactory: RequestBuilderFactory { + get { _state.value.requestBuilderFactory } + set { _state.withValue { $0.requestBuilderFactory = newValue } } + } + + public var apiResponseQueue: DispatchQueue { + get { _state.value.apiResponseQueue } + set { _state.withValue { $0.apiResponseQueue = newValue } } + } + + public var codableHelper: CodableHelper { + get { _state.value.codableHelper } + set { _state.withValue { $0.codableHelper = newValue } } + } + + /// Configures the range of HTTP status codes that will result in a successful response. /// /// If a HTTP status code is outside of this range the response will be interpreted as failed. - public var successfulStatusCodeRange: Range + public var successfulStatusCodeRange: Range { + get { _state.value.successfulStatusCodeRange } + set { _state.withValue { $0.successfulStatusCodeRange = newValue } } + } - public var interceptor: OpenAPIInterceptor + public var interceptor: OpenAPIInterceptor { + get { _state.value.interceptor } + set { _state.withValue { $0.interceptor = newValue } } + } + + // MARK: - Init public init( basePath: String = "http://petstore.swagger.io:80/v2", @@ -34,22 +83,25 @@ open class PetstoreClientAPIConfiguration: @unchecked Sendable { successfulStatusCodeRange: Range = 200..<300, interceptor: OpenAPIInterceptor = DefaultOpenAPIInterceptor() ) { - self.basePath = basePath - self.customHeaders = customHeaders - self.credential = credential - self.requestBuilderFactory = requestBuilderFactory - self.apiResponseQueue = apiResponseQueue - self.codableHelper = codableHelper - self.successfulStatusCodeRange = successfulStatusCodeRange - self.interceptor = interceptor + _state = OpenAPIMutex(State( + basePath: basePath, + customHeaders: customHeaders, + credential: credential, + requestBuilderFactory: requestBuilderFactory, + apiResponseQueue: apiResponseQueue, + codableHelper: codableHelper, + successfulStatusCodeRange: successfulStatusCodeRange, + interceptor: interceptor + )) } public static let shared = PetstoreClientAPIConfiguration() } open class RequestBuilder: @unchecked Sendable, Identifiable { - public var credential: URLCredential? - public var headers: [String: String] + + // MARK: - Immutable properties + public let parameters: [String: any Sendable]? public let method: String public let URLString: String @@ -57,24 +109,62 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public let requiresAuthentication: Bool public let apiConfiguration: PetstoreClientAPIConfiguration + // MARK: - Private mutable state + + private struct MutableState { + var credential: URLCredential? = nil + var headers: [String: String] + var onProgressReady: ((Progress) -> Void)? = nil + } + + private let _state: OpenAPIMutex + + // MARK: - Public mutable interface + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var headers: [String: String] { + get { _state.value.headers } + set { _state.withValue { $0.headers = newValue } } + } + /// Optional block to obtain a reference to the request's progress instance when available. - public var onProgressReady: ((Progress) -> Void)? + public var onProgressReady: ((Progress) -> Void)? { + get { _state.value.onProgressReady } + set { _state.withValue { $0.onProgressReady = newValue } } + } + + // MARK: - Init - required public init(method: String, URLString: String, parameters: [String: any Sendable]?, headers: [String: String] = [:], requiresAuthentication: Bool, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared) { + required public init( + method: String, + URLString: String, + parameters: [String: any Sendable]?, + headers: [String: String] = [:], + requiresAuthentication: Bool, + apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared + ) { self.method = method self.URLString = URLString self.parameters = parameters - self.headers = headers self.requiresAuthentication = requiresAuthentication self.apiConfiguration = apiConfiguration + self._state = OpenAPIMutex(MutableState(headers: headers)) addHeaders(apiConfiguration.customHeaders) addCredential() } + // MARK: - Public methods + open func addHeaders(_ aHeaders: [String: String]) { - for (header, value) in aHeaders { - headers[header] = value + _state.withValue { state in + for (header, value) in aHeaders { + state.headers[header] = value + } } } @@ -131,13 +221,15 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public func addHeader(name: String, value: String) -> Self { if !value.isEmpty { - headers[name] = value + _state.withValue { $0.headers[name] = value } } return self } open func addCredential() { - credential = apiConfiguration.credential + _state.withValue { [apiConfiguration] state in + state.credential = apiConfiguration.credential + } } } diff --git a/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/CodableHelper.swift b/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/CodableHelper.swift index b8990f975bcd..7d6f7a6fd1bd 100644 --- a/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/CodableHelper.swift +++ b/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/CodableHelper.swift @@ -8,37 +8,56 @@ import Foundation open class CodableHelper: @unchecked Sendable { - public init() {} - private var customDateFormatter: DateFormatter? - private var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + // MARK: - Private state + + private struct State { + var customDateFormatter: DateFormatter? + var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + + var customJSONDecoder: JSONDecoder? + var defaultJSONDecoder: JSONDecoder = JSONDecoder() + + var customJSONEncoder: JSONEncoder? + var defaultJSONEncoder: JSONEncoder = JSONEncoder() + + init() { + defaultJSONEncoder.outputFormatting = .prettyPrinted + rebuildDefaultCoders() + } + + mutating func rebuildDefaultCoders() { + defaultJSONDecoder.dateDecodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + defaultJSONEncoder.dateEncodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + } + } + + private let _state = OpenAPIMutex(State()) + + // MARK: - Init - private var customJSONDecoder: JSONDecoder? - private lazy var defaultJSONDecoder: JSONDecoder = { - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .formatted(dateFormatter) - return decoder - }() + public init() {} - private var customJSONEncoder: JSONEncoder? - private lazy var defaultJSONEncoder: JSONEncoder = { - let encoder = JSONEncoder() - encoder.dateEncodingStrategy = .formatted(dateFormatter) - encoder.outputFormatting = .prettyPrinted - return encoder - }() + // MARK: - Public interface public var dateFormatter: DateFormatter { - get { return customDateFormatter ?? defaultDateFormatter } - set { customDateFormatter = newValue } + get { _state.withValue { $0.customDateFormatter ?? $0.defaultDateFormatter } } + set { + _state.withValue { state in + state.customDateFormatter = newValue + state.rebuildDefaultCoders() + } + } } + public var jsonDecoder: JSONDecoder { - get { return customJSONDecoder ?? defaultJSONDecoder } - set { customJSONDecoder = newValue } + get { _state.withValue { $0.customJSONDecoder ?? $0.defaultJSONDecoder } } + set { _state.withValue { $0.customJSONDecoder = newValue } } } + public var jsonEncoder: JSONEncoder { - get { return customJSONEncoder ?? defaultJSONEncoder } - set { customJSONEncoder = newValue } + get { _state.withValue { $0.customJSONEncoder ?? $0.defaultJSONEncoder } } + set { _state.withValue { $0.customJSONEncoder = newValue } } } open func decode(_ type: T.Type, from data: Data) -> Swift.Result where T: Decodable { diff --git a/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/Models.swift b/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/Models.swift index f7a9f4f40195..e98056ea6658 100644 --- a/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/Models.swift +++ b/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/Models.swift @@ -116,25 +116,20 @@ public struct Response { extension Response : Sendable where T : Sendable {} public final class RequestTask: @unchecked Sendable { - private let lock = NSRecursiveLock() - private var task: URLSessionDataTaskProtocol? + private let _state = OpenAPIMutex(nil) internal func set(task: URLSessionDataTaskProtocol) { - lock.withLock { - self.task = task - } + _state.withValue { $0 = task } } internal func get() -> URLSessionDataTaskProtocol? { - lock.withLock { - task - } + _state.value } public func cancel() { - lock.withLock { - task?.cancel() - task = nil + _state.withValue { + $0?.cancel() + $0 = nil } } } diff --git a/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift b/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift new file mode 100644 index 000000000000..d7be0b6bd92e --- /dev/null +++ b/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift @@ -0,0 +1,28 @@ +// OpenAPIMutex.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +internal final class OpenAPIMutex: @unchecked Sendable { + + private var _value: Value + private let lock = NSRecursiveLock() + + internal init(_ value: Value) { + self._value = value + } + + internal var value: Value { + lock.withLock { _value } + } + + @discardableResult + internal func withValue( + _ body: (inout Value) throws -> Result + ) rethrows -> Result { + try lock.withLock { try body(&_value) } + } +} diff --git a/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift b/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift index 0d2714ca7b02..6c80862c6a0b 100644 --- a/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift +++ b/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift @@ -6,21 +6,12 @@ import Foundation -internal class SynchronizedDictionary : @unchecked Sendable { +internal final class SynchronizedDictionary: @unchecked Sendable { - private var dictionary = [K: V]() - private let lock = NSRecursiveLock() + private let _state = OpenAPIMutex<[K: V]>([:]) internal subscript(key: K) -> V? { - get { - lock.withLock { - self.dictionary[key] - } - } - set { - lock.withLock { - self.dictionary[key] = newValue - } - } + get { _state.value[key] } + set { _state.withValue { $0[key] = newValue } } } } diff --git a/samples/client/petstore/swift6/combineDeferredLibrary/.openapi-generator/FILES b/samples/client/petstore/swift6/combineDeferredLibrary/.openapi-generator/FILES index 3689e4184e32..7782fcf4f6c6 100644 --- a/samples/client/petstore/swift6/combineDeferredLibrary/.openapi-generator/FILES +++ b/samples/client/petstore/swift6/combineDeferredLibrary/.openapi-generator/FILES @@ -17,6 +17,7 @@ PetstoreClient/Classes/OpenAPIs/Infrastructure/JSONDataEncoding.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/JSONEncodingHelper.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/JSONValue.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift +PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenISO8601DateFormatter.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift diff --git a/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift b/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift index c7f49fa11157..fb5fcd0dc4fe 100644 --- a/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift +++ b/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift @@ -10,19 +10,68 @@ import FoundationNetworking #endif open class PetstoreClientAPIConfiguration: @unchecked Sendable { - public var basePath: String - public var customHeaders: [String: String] - public var credential: URLCredential? - public var requestBuilderFactory: RequestBuilderFactory - public var apiResponseQueue: DispatchQueue - public var codableHelper: CodableHelper - - /// Configures the range of HTTP status codes that will result in a successful response + + // MARK: - Private state + + private struct State { + var basePath: String + var customHeaders: [String: String] + var credential: URLCredential? + var requestBuilderFactory: RequestBuilderFactory + var apiResponseQueue: DispatchQueue + var codableHelper: CodableHelper + var successfulStatusCodeRange: Range + var interceptor: OpenAPIInterceptor + } + + private let _state: OpenAPIMutex + + // MARK: - Public interface + + public var basePath: String { + get { _state.value.basePath } + set { _state.withValue { $0.basePath = newValue } } + } + + public var customHeaders: [String: String] { + get { _state.value.customHeaders } + set { _state.withValue { $0.customHeaders = newValue } } + } + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var requestBuilderFactory: RequestBuilderFactory { + get { _state.value.requestBuilderFactory } + set { _state.withValue { $0.requestBuilderFactory = newValue } } + } + + public var apiResponseQueue: DispatchQueue { + get { _state.value.apiResponseQueue } + set { _state.withValue { $0.apiResponseQueue = newValue } } + } + + public var codableHelper: CodableHelper { + get { _state.value.codableHelper } + set { _state.withValue { $0.codableHelper = newValue } } + } + + /// Configures the range of HTTP status codes that will result in a successful response. /// /// If a HTTP status code is outside of this range the response will be interpreted as failed. - public var successfulStatusCodeRange: Range + public var successfulStatusCodeRange: Range { + get { _state.value.successfulStatusCodeRange } + set { _state.withValue { $0.successfulStatusCodeRange = newValue } } + } - public var interceptor: OpenAPIInterceptor + public var interceptor: OpenAPIInterceptor { + get { _state.value.interceptor } + set { _state.withValue { $0.interceptor = newValue } } + } + + // MARK: - Init public init( basePath: String = "http://petstore.swagger.io:80/v2", @@ -34,22 +83,25 @@ open class PetstoreClientAPIConfiguration: @unchecked Sendable { successfulStatusCodeRange: Range = 200..<300, interceptor: OpenAPIInterceptor = DefaultOpenAPIInterceptor() ) { - self.basePath = basePath - self.customHeaders = customHeaders - self.credential = credential - self.requestBuilderFactory = requestBuilderFactory - self.apiResponseQueue = apiResponseQueue - self.codableHelper = codableHelper - self.successfulStatusCodeRange = successfulStatusCodeRange - self.interceptor = interceptor + _state = OpenAPIMutex(State( + basePath: basePath, + customHeaders: customHeaders, + credential: credential, + requestBuilderFactory: requestBuilderFactory, + apiResponseQueue: apiResponseQueue, + codableHelper: codableHelper, + successfulStatusCodeRange: successfulStatusCodeRange, + interceptor: interceptor + )) } public static let shared = PetstoreClientAPIConfiguration() } open class RequestBuilder: @unchecked Sendable, Identifiable { - public var credential: URLCredential? - public var headers: [String: String] + + // MARK: - Immutable properties + public let parameters: [String: any Sendable]? public let method: String public let URLString: String @@ -57,24 +109,62 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public let requiresAuthentication: Bool public let apiConfiguration: PetstoreClientAPIConfiguration + // MARK: - Private mutable state + + private struct MutableState { + var credential: URLCredential? = nil + var headers: [String: String] + var onProgressReady: ((Progress) -> Void)? = nil + } + + private let _state: OpenAPIMutex + + // MARK: - Public mutable interface + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var headers: [String: String] { + get { _state.value.headers } + set { _state.withValue { $0.headers = newValue } } + } + /// Optional block to obtain a reference to the request's progress instance when available. - public var onProgressReady: ((Progress) -> Void)? + public var onProgressReady: ((Progress) -> Void)? { + get { _state.value.onProgressReady } + set { _state.withValue { $0.onProgressReady = newValue } } + } - required public init(method: String, URLString: String, parameters: [String: any Sendable]?, headers: [String: String] = [:], requiresAuthentication: Bool, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared) { + // MARK: - Init + + required public init( + method: String, + URLString: String, + parameters: [String: any Sendable]?, + headers: [String: String] = [:], + requiresAuthentication: Bool, + apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared + ) { self.method = method self.URLString = URLString self.parameters = parameters - self.headers = headers self.requiresAuthentication = requiresAuthentication self.apiConfiguration = apiConfiguration + self._state = OpenAPIMutex(MutableState(headers: headers)) addHeaders(apiConfiguration.customHeaders) addCredential() } + // MARK: - Public methods + open func addHeaders(_ aHeaders: [String: String]) { - for (header, value) in aHeaders { - headers[header] = value + _state.withValue { state in + for (header, value) in aHeaders { + state.headers[header] = value + } } } @@ -85,13 +175,15 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public func addHeader(name: String, value: String) -> Self { if !value.isEmpty { - headers[name] = value + _state.withValue { $0.headers[name] = value } } return self } open func addCredential() { - credential = apiConfiguration.credential + _state.withValue { [apiConfiguration] state in + state.credential = apiConfiguration.credential + } } } diff --git a/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift b/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift index b8990f975bcd..7d6f7a6fd1bd 100644 --- a/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift +++ b/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift @@ -8,37 +8,56 @@ import Foundation open class CodableHelper: @unchecked Sendable { - public init() {} - private var customDateFormatter: DateFormatter? - private var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + // MARK: - Private state + + private struct State { + var customDateFormatter: DateFormatter? + var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + + var customJSONDecoder: JSONDecoder? + var defaultJSONDecoder: JSONDecoder = JSONDecoder() + + var customJSONEncoder: JSONEncoder? + var defaultJSONEncoder: JSONEncoder = JSONEncoder() + + init() { + defaultJSONEncoder.outputFormatting = .prettyPrinted + rebuildDefaultCoders() + } + + mutating func rebuildDefaultCoders() { + defaultJSONDecoder.dateDecodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + defaultJSONEncoder.dateEncodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + } + } + + private let _state = OpenAPIMutex(State()) + + // MARK: - Init - private var customJSONDecoder: JSONDecoder? - private lazy var defaultJSONDecoder: JSONDecoder = { - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .formatted(dateFormatter) - return decoder - }() + public init() {} - private var customJSONEncoder: JSONEncoder? - private lazy var defaultJSONEncoder: JSONEncoder = { - let encoder = JSONEncoder() - encoder.dateEncodingStrategy = .formatted(dateFormatter) - encoder.outputFormatting = .prettyPrinted - return encoder - }() + // MARK: - Public interface public var dateFormatter: DateFormatter { - get { return customDateFormatter ?? defaultDateFormatter } - set { customDateFormatter = newValue } + get { _state.withValue { $0.customDateFormatter ?? $0.defaultDateFormatter } } + set { + _state.withValue { state in + state.customDateFormatter = newValue + state.rebuildDefaultCoders() + } + } } + public var jsonDecoder: JSONDecoder { - get { return customJSONDecoder ?? defaultJSONDecoder } - set { customJSONDecoder = newValue } + get { _state.withValue { $0.customJSONDecoder ?? $0.defaultJSONDecoder } } + set { _state.withValue { $0.customJSONDecoder = newValue } } } + public var jsonEncoder: JSONEncoder { - get { return customJSONEncoder ?? defaultJSONEncoder } - set { customJSONEncoder = newValue } + get { _state.withValue { $0.customJSONEncoder ?? $0.defaultJSONEncoder } } + set { _state.withValue { $0.customJSONEncoder = newValue } } } open func decode(_ type: T.Type, from data: Data) -> Swift.Result where T: Decodable { diff --git a/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift b/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift index f7a9f4f40195..e98056ea6658 100644 --- a/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift +++ b/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift @@ -116,25 +116,20 @@ public struct Response { extension Response : Sendable where T : Sendable {} public final class RequestTask: @unchecked Sendable { - private let lock = NSRecursiveLock() - private var task: URLSessionDataTaskProtocol? + private let _state = OpenAPIMutex(nil) internal func set(task: URLSessionDataTaskProtocol) { - lock.withLock { - self.task = task - } + _state.withValue { $0 = task } } internal func get() -> URLSessionDataTaskProtocol? { - lock.withLock { - task - } + _state.value } public func cancel() { - lock.withLock { - task?.cancel() - task = nil + _state.withValue { + $0?.cancel() + $0 = nil } } } diff --git a/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift b/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift new file mode 100644 index 000000000000..d7be0b6bd92e --- /dev/null +++ b/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift @@ -0,0 +1,28 @@ +// OpenAPIMutex.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +internal final class OpenAPIMutex: @unchecked Sendable { + + private var _value: Value + private let lock = NSRecursiveLock() + + internal init(_ value: Value) { + self._value = value + } + + internal var value: Value { + lock.withLock { _value } + } + + @discardableResult + internal func withValue( + _ body: (inout Value) throws -> Result + ) rethrows -> Result { + try lock.withLock { try body(&_value) } + } +} diff --git a/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift b/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift index 0d2714ca7b02..6c80862c6a0b 100644 --- a/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift +++ b/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift @@ -6,21 +6,12 @@ import Foundation -internal class SynchronizedDictionary : @unchecked Sendable { +internal final class SynchronizedDictionary: @unchecked Sendable { - private var dictionary = [K: V]() - private let lock = NSRecursiveLock() + private let _state = OpenAPIMutex<[K: V]>([:]) internal subscript(key: K) -> V? { - get { - lock.withLock { - self.dictionary[key] - } - } - set { - lock.withLock { - self.dictionary[key] = newValue - } - } + get { _state.value[key] } + set { _state.withValue { $0[key] = newValue } } } } diff --git a/samples/client/petstore/swift6/combineLibrary/.openapi-generator/FILES b/samples/client/petstore/swift6/combineLibrary/.openapi-generator/FILES index 744a4713bbac..45ecec912ad2 100644 --- a/samples/client/petstore/swift6/combineLibrary/.openapi-generator/FILES +++ b/samples/client/petstore/swift6/combineLibrary/.openapi-generator/FILES @@ -18,6 +18,7 @@ Sources/CombineLibrary/Infrastructure/JSONDataEncoding.swift Sources/CombineLibrary/Infrastructure/JSONEncodingHelper.swift Sources/CombineLibrary/Infrastructure/JSONValue.swift Sources/CombineLibrary/Infrastructure/Models.swift +Sources/CombineLibrary/Infrastructure/OpenAPIMutex.swift Sources/CombineLibrary/Infrastructure/OpenISO8601DateFormatter.swift Sources/CombineLibrary/Infrastructure/SynchronizedDictionary.swift Sources/CombineLibrary/Infrastructure/URLSessionImplementations.swift diff --git a/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/APIs.swift b/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/APIs.swift index c7f49fa11157..fb5fcd0dc4fe 100644 --- a/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/APIs.swift +++ b/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/APIs.swift @@ -10,19 +10,68 @@ import FoundationNetworking #endif open class PetstoreClientAPIConfiguration: @unchecked Sendable { - public var basePath: String - public var customHeaders: [String: String] - public var credential: URLCredential? - public var requestBuilderFactory: RequestBuilderFactory - public var apiResponseQueue: DispatchQueue - public var codableHelper: CodableHelper - - /// Configures the range of HTTP status codes that will result in a successful response + + // MARK: - Private state + + private struct State { + var basePath: String + var customHeaders: [String: String] + var credential: URLCredential? + var requestBuilderFactory: RequestBuilderFactory + var apiResponseQueue: DispatchQueue + var codableHelper: CodableHelper + var successfulStatusCodeRange: Range + var interceptor: OpenAPIInterceptor + } + + private let _state: OpenAPIMutex + + // MARK: - Public interface + + public var basePath: String { + get { _state.value.basePath } + set { _state.withValue { $0.basePath = newValue } } + } + + public var customHeaders: [String: String] { + get { _state.value.customHeaders } + set { _state.withValue { $0.customHeaders = newValue } } + } + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var requestBuilderFactory: RequestBuilderFactory { + get { _state.value.requestBuilderFactory } + set { _state.withValue { $0.requestBuilderFactory = newValue } } + } + + public var apiResponseQueue: DispatchQueue { + get { _state.value.apiResponseQueue } + set { _state.withValue { $0.apiResponseQueue = newValue } } + } + + public var codableHelper: CodableHelper { + get { _state.value.codableHelper } + set { _state.withValue { $0.codableHelper = newValue } } + } + + /// Configures the range of HTTP status codes that will result in a successful response. /// /// If a HTTP status code is outside of this range the response will be interpreted as failed. - public var successfulStatusCodeRange: Range + public var successfulStatusCodeRange: Range { + get { _state.value.successfulStatusCodeRange } + set { _state.withValue { $0.successfulStatusCodeRange = newValue } } + } - public var interceptor: OpenAPIInterceptor + public var interceptor: OpenAPIInterceptor { + get { _state.value.interceptor } + set { _state.withValue { $0.interceptor = newValue } } + } + + // MARK: - Init public init( basePath: String = "http://petstore.swagger.io:80/v2", @@ -34,22 +83,25 @@ open class PetstoreClientAPIConfiguration: @unchecked Sendable { successfulStatusCodeRange: Range = 200..<300, interceptor: OpenAPIInterceptor = DefaultOpenAPIInterceptor() ) { - self.basePath = basePath - self.customHeaders = customHeaders - self.credential = credential - self.requestBuilderFactory = requestBuilderFactory - self.apiResponseQueue = apiResponseQueue - self.codableHelper = codableHelper - self.successfulStatusCodeRange = successfulStatusCodeRange - self.interceptor = interceptor + _state = OpenAPIMutex(State( + basePath: basePath, + customHeaders: customHeaders, + credential: credential, + requestBuilderFactory: requestBuilderFactory, + apiResponseQueue: apiResponseQueue, + codableHelper: codableHelper, + successfulStatusCodeRange: successfulStatusCodeRange, + interceptor: interceptor + )) } public static let shared = PetstoreClientAPIConfiguration() } open class RequestBuilder: @unchecked Sendable, Identifiable { - public var credential: URLCredential? - public var headers: [String: String] + + // MARK: - Immutable properties + public let parameters: [String: any Sendable]? public let method: String public let URLString: String @@ -57,24 +109,62 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public let requiresAuthentication: Bool public let apiConfiguration: PetstoreClientAPIConfiguration + // MARK: - Private mutable state + + private struct MutableState { + var credential: URLCredential? = nil + var headers: [String: String] + var onProgressReady: ((Progress) -> Void)? = nil + } + + private let _state: OpenAPIMutex + + // MARK: - Public mutable interface + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var headers: [String: String] { + get { _state.value.headers } + set { _state.withValue { $0.headers = newValue } } + } + /// Optional block to obtain a reference to the request's progress instance when available. - public var onProgressReady: ((Progress) -> Void)? + public var onProgressReady: ((Progress) -> Void)? { + get { _state.value.onProgressReady } + set { _state.withValue { $0.onProgressReady = newValue } } + } - required public init(method: String, URLString: String, parameters: [String: any Sendable]?, headers: [String: String] = [:], requiresAuthentication: Bool, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared) { + // MARK: - Init + + required public init( + method: String, + URLString: String, + parameters: [String: any Sendable]?, + headers: [String: String] = [:], + requiresAuthentication: Bool, + apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared + ) { self.method = method self.URLString = URLString self.parameters = parameters - self.headers = headers self.requiresAuthentication = requiresAuthentication self.apiConfiguration = apiConfiguration + self._state = OpenAPIMutex(MutableState(headers: headers)) addHeaders(apiConfiguration.customHeaders) addCredential() } + // MARK: - Public methods + open func addHeaders(_ aHeaders: [String: String]) { - for (header, value) in aHeaders { - headers[header] = value + _state.withValue { state in + for (header, value) in aHeaders { + state.headers[header] = value + } } } @@ -85,13 +175,15 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public func addHeader(name: String, value: String) -> Self { if !value.isEmpty { - headers[name] = value + _state.withValue { $0.headers[name] = value } } return self } open func addCredential() { - credential = apiConfiguration.credential + _state.withValue { [apiConfiguration] state in + state.credential = apiConfiguration.credential + } } } diff --git a/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/CodableHelper.swift b/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/CodableHelper.swift index b8990f975bcd..7d6f7a6fd1bd 100644 --- a/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/CodableHelper.swift +++ b/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/CodableHelper.swift @@ -8,37 +8,56 @@ import Foundation open class CodableHelper: @unchecked Sendable { - public init() {} - private var customDateFormatter: DateFormatter? - private var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + // MARK: - Private state + + private struct State { + var customDateFormatter: DateFormatter? + var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + + var customJSONDecoder: JSONDecoder? + var defaultJSONDecoder: JSONDecoder = JSONDecoder() + + var customJSONEncoder: JSONEncoder? + var defaultJSONEncoder: JSONEncoder = JSONEncoder() + + init() { + defaultJSONEncoder.outputFormatting = .prettyPrinted + rebuildDefaultCoders() + } + + mutating func rebuildDefaultCoders() { + defaultJSONDecoder.dateDecodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + defaultJSONEncoder.dateEncodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + } + } + + private let _state = OpenAPIMutex(State()) + + // MARK: - Init - private var customJSONDecoder: JSONDecoder? - private lazy var defaultJSONDecoder: JSONDecoder = { - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .formatted(dateFormatter) - return decoder - }() + public init() {} - private var customJSONEncoder: JSONEncoder? - private lazy var defaultJSONEncoder: JSONEncoder = { - let encoder = JSONEncoder() - encoder.dateEncodingStrategy = .formatted(dateFormatter) - encoder.outputFormatting = .prettyPrinted - return encoder - }() + // MARK: - Public interface public var dateFormatter: DateFormatter { - get { return customDateFormatter ?? defaultDateFormatter } - set { customDateFormatter = newValue } + get { _state.withValue { $0.customDateFormatter ?? $0.defaultDateFormatter } } + set { + _state.withValue { state in + state.customDateFormatter = newValue + state.rebuildDefaultCoders() + } + } } + public var jsonDecoder: JSONDecoder { - get { return customJSONDecoder ?? defaultJSONDecoder } - set { customJSONDecoder = newValue } + get { _state.withValue { $0.customJSONDecoder ?? $0.defaultJSONDecoder } } + set { _state.withValue { $0.customJSONDecoder = newValue } } } + public var jsonEncoder: JSONEncoder { - get { return customJSONEncoder ?? defaultJSONEncoder } - set { customJSONEncoder = newValue } + get { _state.withValue { $0.customJSONEncoder ?? $0.defaultJSONEncoder } } + set { _state.withValue { $0.customJSONEncoder = newValue } } } open func decode(_ type: T.Type, from data: Data) -> Swift.Result where T: Decodable { diff --git a/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/Models.swift b/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/Models.swift index f7a9f4f40195..e98056ea6658 100644 --- a/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/Models.swift +++ b/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/Models.swift @@ -116,25 +116,20 @@ public struct Response { extension Response : Sendable where T : Sendable {} public final class RequestTask: @unchecked Sendable { - private let lock = NSRecursiveLock() - private var task: URLSessionDataTaskProtocol? + private let _state = OpenAPIMutex(nil) internal func set(task: URLSessionDataTaskProtocol) { - lock.withLock { - self.task = task - } + _state.withValue { $0 = task } } internal func get() -> URLSessionDataTaskProtocol? { - lock.withLock { - task - } + _state.value } public func cancel() { - lock.withLock { - task?.cancel() - task = nil + _state.withValue { + $0?.cancel() + $0 = nil } } } diff --git a/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/OpenAPIMutex.swift b/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/OpenAPIMutex.swift new file mode 100644 index 000000000000..d7be0b6bd92e --- /dev/null +++ b/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/OpenAPIMutex.swift @@ -0,0 +1,28 @@ +// OpenAPIMutex.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +internal final class OpenAPIMutex: @unchecked Sendable { + + private var _value: Value + private let lock = NSRecursiveLock() + + internal init(_ value: Value) { + self._value = value + } + + internal var value: Value { + lock.withLock { _value } + } + + @discardableResult + internal func withValue( + _ body: (inout Value) throws -> Result + ) rethrows -> Result { + try lock.withLock { try body(&_value) } + } +} diff --git a/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/SynchronizedDictionary.swift b/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/SynchronizedDictionary.swift index 0d2714ca7b02..6c80862c6a0b 100644 --- a/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/SynchronizedDictionary.swift +++ b/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/SynchronizedDictionary.swift @@ -6,21 +6,12 @@ import Foundation -internal class SynchronizedDictionary : @unchecked Sendable { +internal final class SynchronizedDictionary: @unchecked Sendable { - private var dictionary = [K: V]() - private let lock = NSRecursiveLock() + private let _state = OpenAPIMutex<[K: V]>([:]) internal subscript(key: K) -> V? { - get { - lock.withLock { - self.dictionary[key] - } - } - set { - lock.withLock { - self.dictionary[key] = newValue - } - } + get { _state.value[key] } + set { _state.withValue { $0[key] = newValue } } } } diff --git a/samples/client/petstore/swift6/default/.openapi-generator/FILES b/samples/client/petstore/swift6/default/.openapi-generator/FILES index 514c4440a32d..a44b0115caa5 100644 --- a/samples/client/petstore/swift6/default/.openapi-generator/FILES +++ b/samples/client/petstore/swift6/default/.openapi-generator/FILES @@ -18,6 +18,7 @@ Sources/PetstoreClient/Infrastructure/JSONDataEncoding.swift Sources/PetstoreClient/Infrastructure/JSONEncodingHelper.swift Sources/PetstoreClient/Infrastructure/JSONValue.swift Sources/PetstoreClient/Infrastructure/Models.swift +Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift Sources/PetstoreClient/Infrastructure/OpenISO8601DateFormatter.swift Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift Sources/PetstoreClient/Infrastructure/URLSessionImplementations.swift diff --git a/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/APIs.swift b/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/APIs.swift index 89dc30b72299..aa5b2fe89e7c 100644 --- a/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/APIs.swift +++ b/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/APIs.swift @@ -10,19 +10,68 @@ import FoundationNetworking #endif open class PetstoreClientAPIConfiguration: @unchecked Sendable { - public var basePath: String - public var customHeaders: [String: String] - public var credential: URLCredential? - public var requestBuilderFactory: RequestBuilderFactory - public var apiResponseQueue: DispatchQueue - public var codableHelper: CodableHelper - - /// Configures the range of HTTP status codes that will result in a successful response + + // MARK: - Private state + + private struct State { + var basePath: String + var customHeaders: [String: String] + var credential: URLCredential? + var requestBuilderFactory: RequestBuilderFactory + var apiResponseQueue: DispatchQueue + var codableHelper: CodableHelper + var successfulStatusCodeRange: Range + var interceptor: OpenAPIInterceptor + } + + private let _state: OpenAPIMutex + + // MARK: - Public interface + + public var basePath: String { + get { _state.value.basePath } + set { _state.withValue { $0.basePath = newValue } } + } + + public var customHeaders: [String: String] { + get { _state.value.customHeaders } + set { _state.withValue { $0.customHeaders = newValue } } + } + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var requestBuilderFactory: RequestBuilderFactory { + get { _state.value.requestBuilderFactory } + set { _state.withValue { $0.requestBuilderFactory = newValue } } + } + + public var apiResponseQueue: DispatchQueue { + get { _state.value.apiResponseQueue } + set { _state.withValue { $0.apiResponseQueue = newValue } } + } + + public var codableHelper: CodableHelper { + get { _state.value.codableHelper } + set { _state.withValue { $0.codableHelper = newValue } } + } + + /// Configures the range of HTTP status codes that will result in a successful response. /// /// If a HTTP status code is outside of this range the response will be interpreted as failed. - public var successfulStatusCodeRange: Range + public var successfulStatusCodeRange: Range { + get { _state.value.successfulStatusCodeRange } + set { _state.withValue { $0.successfulStatusCodeRange = newValue } } + } - public var interceptor: OpenAPIInterceptor + public var interceptor: OpenAPIInterceptor { + get { _state.value.interceptor } + set { _state.withValue { $0.interceptor = newValue } } + } + + // MARK: - Init public init( basePath: String = "http://petstore.swagger.io:80/v2", @@ -34,22 +83,25 @@ open class PetstoreClientAPIConfiguration: @unchecked Sendable { successfulStatusCodeRange: Range = 200..<300, interceptor: OpenAPIInterceptor = DefaultOpenAPIInterceptor() ) { - self.basePath = basePath - self.customHeaders = customHeaders - self.credential = credential - self.requestBuilderFactory = requestBuilderFactory - self.apiResponseQueue = apiResponseQueue - self.codableHelper = codableHelper - self.successfulStatusCodeRange = successfulStatusCodeRange - self.interceptor = interceptor + _state = OpenAPIMutex(State( + basePath: basePath, + customHeaders: customHeaders, + credential: credential, + requestBuilderFactory: requestBuilderFactory, + apiResponseQueue: apiResponseQueue, + codableHelper: codableHelper, + successfulStatusCodeRange: successfulStatusCodeRange, + interceptor: interceptor + )) } public static let shared = PetstoreClientAPIConfiguration() } open class RequestBuilder: @unchecked Sendable, Identifiable { - public var credential: URLCredential? - public var headers: [String: String] + + // MARK: - Immutable properties + public let parameters: [String: any Sendable]? public let method: String public let URLString: String @@ -57,24 +109,62 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public let requiresAuthentication: Bool public let apiConfiguration: PetstoreClientAPIConfiguration + // MARK: - Private mutable state + + private struct MutableState { + var credential: URLCredential? = nil + var headers: [String: String] + var onProgressReady: ((Progress) -> Void)? = nil + } + + private let _state: OpenAPIMutex + + // MARK: - Public mutable interface + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var headers: [String: String] { + get { _state.value.headers } + set { _state.withValue { $0.headers = newValue } } + } + /// Optional block to obtain a reference to the request's progress instance when available. - public var onProgressReady: ((Progress) -> Void)? + public var onProgressReady: ((Progress) -> Void)? { + get { _state.value.onProgressReady } + set { _state.withValue { $0.onProgressReady = newValue } } + } + + // MARK: - Init - required public init(method: String, URLString: String, parameters: [String: any Sendable]?, headers: [String: String] = [:], requiresAuthentication: Bool, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared) { + required public init( + method: String, + URLString: String, + parameters: [String: any Sendable]?, + headers: [String: String] = [:], + requiresAuthentication: Bool, + apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared + ) { self.method = method self.URLString = URLString self.parameters = parameters - self.headers = headers self.requiresAuthentication = requiresAuthentication self.apiConfiguration = apiConfiguration + self._state = OpenAPIMutex(MutableState(headers: headers)) addHeaders(apiConfiguration.customHeaders) addCredential() } + // MARK: - Public methods + open func addHeaders(_ aHeaders: [String: String]) { - for (header, value) in aHeaders { - headers[header] = value + _state.withValue { state in + for (header, value) in aHeaders { + state.headers[header] = value + } } } @@ -131,13 +221,15 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public func addHeader(name: String, value: String) -> Self { if !value.isEmpty { - headers[name] = value + _state.withValue { $0.headers[name] = value } } return self } open func addCredential() { - credential = apiConfiguration.credential + _state.withValue { [apiConfiguration] state in + state.credential = apiConfiguration.credential + } } } diff --git a/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/CodableHelper.swift b/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/CodableHelper.swift index b8990f975bcd..7d6f7a6fd1bd 100644 --- a/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/CodableHelper.swift +++ b/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/CodableHelper.swift @@ -8,37 +8,56 @@ import Foundation open class CodableHelper: @unchecked Sendable { - public init() {} - private var customDateFormatter: DateFormatter? - private var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + // MARK: - Private state + + private struct State { + var customDateFormatter: DateFormatter? + var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + + var customJSONDecoder: JSONDecoder? + var defaultJSONDecoder: JSONDecoder = JSONDecoder() + + var customJSONEncoder: JSONEncoder? + var defaultJSONEncoder: JSONEncoder = JSONEncoder() + + init() { + defaultJSONEncoder.outputFormatting = .prettyPrinted + rebuildDefaultCoders() + } + + mutating func rebuildDefaultCoders() { + defaultJSONDecoder.dateDecodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + defaultJSONEncoder.dateEncodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + } + } + + private let _state = OpenAPIMutex(State()) + + // MARK: - Init - private var customJSONDecoder: JSONDecoder? - private lazy var defaultJSONDecoder: JSONDecoder = { - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .formatted(dateFormatter) - return decoder - }() + public init() {} - private var customJSONEncoder: JSONEncoder? - private lazy var defaultJSONEncoder: JSONEncoder = { - let encoder = JSONEncoder() - encoder.dateEncodingStrategy = .formatted(dateFormatter) - encoder.outputFormatting = .prettyPrinted - return encoder - }() + // MARK: - Public interface public var dateFormatter: DateFormatter { - get { return customDateFormatter ?? defaultDateFormatter } - set { customDateFormatter = newValue } + get { _state.withValue { $0.customDateFormatter ?? $0.defaultDateFormatter } } + set { + _state.withValue { state in + state.customDateFormatter = newValue + state.rebuildDefaultCoders() + } + } } + public var jsonDecoder: JSONDecoder { - get { return customJSONDecoder ?? defaultJSONDecoder } - set { customJSONDecoder = newValue } + get { _state.withValue { $0.customJSONDecoder ?? $0.defaultJSONDecoder } } + set { _state.withValue { $0.customJSONDecoder = newValue } } } + public var jsonEncoder: JSONEncoder { - get { return customJSONEncoder ?? defaultJSONEncoder } - set { customJSONEncoder = newValue } + get { _state.withValue { $0.customJSONEncoder ?? $0.defaultJSONEncoder } } + set { _state.withValue { $0.customJSONEncoder = newValue } } } open func decode(_ type: T.Type, from data: Data) -> Swift.Result where T: Decodable { diff --git a/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/Models.swift b/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/Models.swift index f7a9f4f40195..e98056ea6658 100644 --- a/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/Models.swift +++ b/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/Models.swift @@ -116,25 +116,20 @@ public struct Response { extension Response : Sendable where T : Sendable {} public final class RequestTask: @unchecked Sendable { - private let lock = NSRecursiveLock() - private var task: URLSessionDataTaskProtocol? + private let _state = OpenAPIMutex(nil) internal func set(task: URLSessionDataTaskProtocol) { - lock.withLock { - self.task = task - } + _state.withValue { $0 = task } } internal func get() -> URLSessionDataTaskProtocol? { - lock.withLock { - task - } + _state.value } public func cancel() { - lock.withLock { - task?.cancel() - task = nil + _state.withValue { + $0?.cancel() + $0 = nil } } } diff --git a/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift b/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift new file mode 100644 index 000000000000..d7be0b6bd92e --- /dev/null +++ b/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift @@ -0,0 +1,28 @@ +// OpenAPIMutex.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +internal final class OpenAPIMutex: @unchecked Sendable { + + private var _value: Value + private let lock = NSRecursiveLock() + + internal init(_ value: Value) { + self._value = value + } + + internal var value: Value { + lock.withLock { _value } + } + + @discardableResult + internal func withValue( + _ body: (inout Value) throws -> Result + ) rethrows -> Result { + try lock.withLock { try body(&_value) } + } +} diff --git a/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift b/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift index 0d2714ca7b02..6c80862c6a0b 100644 --- a/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift +++ b/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift @@ -6,21 +6,12 @@ import Foundation -internal class SynchronizedDictionary : @unchecked Sendable { +internal final class SynchronizedDictionary: @unchecked Sendable { - private var dictionary = [K: V]() - private let lock = NSRecursiveLock() + private let _state = OpenAPIMutex<[K: V]>([:]) internal subscript(key: K) -> V? { - get { - lock.withLock { - self.dictionary[key] - } - } - set { - lock.withLock { - self.dictionary[key] = newValue - } - } + get { _state.value[key] } + set { _state.withValue { $0[key] = newValue } } } } diff --git a/samples/client/petstore/swift6/objcCompatible/.openapi-generator/FILES b/samples/client/petstore/swift6/objcCompatible/.openapi-generator/FILES index dbd6732f0444..e8d5c4bbbb91 100644 --- a/samples/client/petstore/swift6/objcCompatible/.openapi-generator/FILES +++ b/samples/client/petstore/swift6/objcCompatible/.openapi-generator/FILES @@ -18,6 +18,7 @@ Sources/PetstoreClient/Infrastructure/JSONDataEncoding.swift Sources/PetstoreClient/Infrastructure/JSONEncodingHelper.swift Sources/PetstoreClient/Infrastructure/JSONValue.swift Sources/PetstoreClient/Infrastructure/Models.swift +Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift Sources/PetstoreClient/Infrastructure/OpenISO8601DateFormatter.swift Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift Sources/PetstoreClient/Infrastructure/URLSessionImplementations.swift diff --git a/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/APIs.swift b/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/APIs.swift index c7f49fa11157..fb5fcd0dc4fe 100644 --- a/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/APIs.swift +++ b/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/APIs.swift @@ -10,19 +10,68 @@ import FoundationNetworking #endif open class PetstoreClientAPIConfiguration: @unchecked Sendable { - public var basePath: String - public var customHeaders: [String: String] - public var credential: URLCredential? - public var requestBuilderFactory: RequestBuilderFactory - public var apiResponseQueue: DispatchQueue - public var codableHelper: CodableHelper - - /// Configures the range of HTTP status codes that will result in a successful response + + // MARK: - Private state + + private struct State { + var basePath: String + var customHeaders: [String: String] + var credential: URLCredential? + var requestBuilderFactory: RequestBuilderFactory + var apiResponseQueue: DispatchQueue + var codableHelper: CodableHelper + var successfulStatusCodeRange: Range + var interceptor: OpenAPIInterceptor + } + + private let _state: OpenAPIMutex + + // MARK: - Public interface + + public var basePath: String { + get { _state.value.basePath } + set { _state.withValue { $0.basePath = newValue } } + } + + public var customHeaders: [String: String] { + get { _state.value.customHeaders } + set { _state.withValue { $0.customHeaders = newValue } } + } + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var requestBuilderFactory: RequestBuilderFactory { + get { _state.value.requestBuilderFactory } + set { _state.withValue { $0.requestBuilderFactory = newValue } } + } + + public var apiResponseQueue: DispatchQueue { + get { _state.value.apiResponseQueue } + set { _state.withValue { $0.apiResponseQueue = newValue } } + } + + public var codableHelper: CodableHelper { + get { _state.value.codableHelper } + set { _state.withValue { $0.codableHelper = newValue } } + } + + /// Configures the range of HTTP status codes that will result in a successful response. /// /// If a HTTP status code is outside of this range the response will be interpreted as failed. - public var successfulStatusCodeRange: Range + public var successfulStatusCodeRange: Range { + get { _state.value.successfulStatusCodeRange } + set { _state.withValue { $0.successfulStatusCodeRange = newValue } } + } - public var interceptor: OpenAPIInterceptor + public var interceptor: OpenAPIInterceptor { + get { _state.value.interceptor } + set { _state.withValue { $0.interceptor = newValue } } + } + + // MARK: - Init public init( basePath: String = "http://petstore.swagger.io:80/v2", @@ -34,22 +83,25 @@ open class PetstoreClientAPIConfiguration: @unchecked Sendable { successfulStatusCodeRange: Range = 200..<300, interceptor: OpenAPIInterceptor = DefaultOpenAPIInterceptor() ) { - self.basePath = basePath - self.customHeaders = customHeaders - self.credential = credential - self.requestBuilderFactory = requestBuilderFactory - self.apiResponseQueue = apiResponseQueue - self.codableHelper = codableHelper - self.successfulStatusCodeRange = successfulStatusCodeRange - self.interceptor = interceptor + _state = OpenAPIMutex(State( + basePath: basePath, + customHeaders: customHeaders, + credential: credential, + requestBuilderFactory: requestBuilderFactory, + apiResponseQueue: apiResponseQueue, + codableHelper: codableHelper, + successfulStatusCodeRange: successfulStatusCodeRange, + interceptor: interceptor + )) } public static let shared = PetstoreClientAPIConfiguration() } open class RequestBuilder: @unchecked Sendable, Identifiable { - public var credential: URLCredential? - public var headers: [String: String] + + // MARK: - Immutable properties + public let parameters: [String: any Sendable]? public let method: String public let URLString: String @@ -57,24 +109,62 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public let requiresAuthentication: Bool public let apiConfiguration: PetstoreClientAPIConfiguration + // MARK: - Private mutable state + + private struct MutableState { + var credential: URLCredential? = nil + var headers: [String: String] + var onProgressReady: ((Progress) -> Void)? = nil + } + + private let _state: OpenAPIMutex + + // MARK: - Public mutable interface + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var headers: [String: String] { + get { _state.value.headers } + set { _state.withValue { $0.headers = newValue } } + } + /// Optional block to obtain a reference to the request's progress instance when available. - public var onProgressReady: ((Progress) -> Void)? + public var onProgressReady: ((Progress) -> Void)? { + get { _state.value.onProgressReady } + set { _state.withValue { $0.onProgressReady = newValue } } + } - required public init(method: String, URLString: String, parameters: [String: any Sendable]?, headers: [String: String] = [:], requiresAuthentication: Bool, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared) { + // MARK: - Init + + required public init( + method: String, + URLString: String, + parameters: [String: any Sendable]?, + headers: [String: String] = [:], + requiresAuthentication: Bool, + apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared + ) { self.method = method self.URLString = URLString self.parameters = parameters - self.headers = headers self.requiresAuthentication = requiresAuthentication self.apiConfiguration = apiConfiguration + self._state = OpenAPIMutex(MutableState(headers: headers)) addHeaders(apiConfiguration.customHeaders) addCredential() } + // MARK: - Public methods + open func addHeaders(_ aHeaders: [String: String]) { - for (header, value) in aHeaders { - headers[header] = value + _state.withValue { state in + for (header, value) in aHeaders { + state.headers[header] = value + } } } @@ -85,13 +175,15 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public func addHeader(name: String, value: String) -> Self { if !value.isEmpty { - headers[name] = value + _state.withValue { $0.headers[name] = value } } return self } open func addCredential() { - credential = apiConfiguration.credential + _state.withValue { [apiConfiguration] state in + state.credential = apiConfiguration.credential + } } } diff --git a/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/CodableHelper.swift b/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/CodableHelper.swift index b8990f975bcd..7d6f7a6fd1bd 100644 --- a/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/CodableHelper.swift +++ b/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/CodableHelper.swift @@ -8,37 +8,56 @@ import Foundation open class CodableHelper: @unchecked Sendable { - public init() {} - private var customDateFormatter: DateFormatter? - private var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + // MARK: - Private state + + private struct State { + var customDateFormatter: DateFormatter? + var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + + var customJSONDecoder: JSONDecoder? + var defaultJSONDecoder: JSONDecoder = JSONDecoder() + + var customJSONEncoder: JSONEncoder? + var defaultJSONEncoder: JSONEncoder = JSONEncoder() + + init() { + defaultJSONEncoder.outputFormatting = .prettyPrinted + rebuildDefaultCoders() + } + + mutating func rebuildDefaultCoders() { + defaultJSONDecoder.dateDecodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + defaultJSONEncoder.dateEncodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + } + } + + private let _state = OpenAPIMutex(State()) + + // MARK: - Init - private var customJSONDecoder: JSONDecoder? - private lazy var defaultJSONDecoder: JSONDecoder = { - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .formatted(dateFormatter) - return decoder - }() + public init() {} - private var customJSONEncoder: JSONEncoder? - private lazy var defaultJSONEncoder: JSONEncoder = { - let encoder = JSONEncoder() - encoder.dateEncodingStrategy = .formatted(dateFormatter) - encoder.outputFormatting = .prettyPrinted - return encoder - }() + // MARK: - Public interface public var dateFormatter: DateFormatter { - get { return customDateFormatter ?? defaultDateFormatter } - set { customDateFormatter = newValue } + get { _state.withValue { $0.customDateFormatter ?? $0.defaultDateFormatter } } + set { + _state.withValue { state in + state.customDateFormatter = newValue + state.rebuildDefaultCoders() + } + } } + public var jsonDecoder: JSONDecoder { - get { return customJSONDecoder ?? defaultJSONDecoder } - set { customJSONDecoder = newValue } + get { _state.withValue { $0.customJSONDecoder ?? $0.defaultJSONDecoder } } + set { _state.withValue { $0.customJSONDecoder = newValue } } } + public var jsonEncoder: JSONEncoder { - get { return customJSONEncoder ?? defaultJSONEncoder } - set { customJSONEncoder = newValue } + get { _state.withValue { $0.customJSONEncoder ?? $0.defaultJSONEncoder } } + set { _state.withValue { $0.customJSONEncoder = newValue } } } open func decode(_ type: T.Type, from data: Data) -> Swift.Result where T: Decodable { diff --git a/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/Models.swift b/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/Models.swift index f7a9f4f40195..e98056ea6658 100644 --- a/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/Models.swift +++ b/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/Models.swift @@ -116,25 +116,20 @@ public struct Response { extension Response : Sendable where T : Sendable {} public final class RequestTask: @unchecked Sendable { - private let lock = NSRecursiveLock() - private var task: URLSessionDataTaskProtocol? + private let _state = OpenAPIMutex(nil) internal func set(task: URLSessionDataTaskProtocol) { - lock.withLock { - self.task = task - } + _state.withValue { $0 = task } } internal func get() -> URLSessionDataTaskProtocol? { - lock.withLock { - task - } + _state.value } public func cancel() { - lock.withLock { - task?.cancel() - task = nil + _state.withValue { + $0?.cancel() + $0 = nil } } } diff --git a/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift b/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift new file mode 100644 index 000000000000..d7be0b6bd92e --- /dev/null +++ b/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift @@ -0,0 +1,28 @@ +// OpenAPIMutex.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +internal final class OpenAPIMutex: @unchecked Sendable { + + private var _value: Value + private let lock = NSRecursiveLock() + + internal init(_ value: Value) { + self._value = value + } + + internal var value: Value { + lock.withLock { _value } + } + + @discardableResult + internal func withValue( + _ body: (inout Value) throws -> Result + ) rethrows -> Result { + try lock.withLock { try body(&_value) } + } +} diff --git a/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift b/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift index 0d2714ca7b02..6c80862c6a0b 100644 --- a/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift +++ b/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift @@ -6,21 +6,12 @@ import Foundation -internal class SynchronizedDictionary : @unchecked Sendable { +internal final class SynchronizedDictionary: @unchecked Sendable { - private var dictionary = [K: V]() - private let lock = NSRecursiveLock() + private let _state = OpenAPIMutex<[K: V]>([:]) internal subscript(key: K) -> V? { - get { - lock.withLock { - self.dictionary[key] - } - } - set { - lock.withLock { - self.dictionary[key] = newValue - } - } + get { _state.value[key] } + set { _state.withValue { $0[key] = newValue } } } } diff --git a/samples/client/petstore/swift6/oneOf/.openapi-generator/FILES b/samples/client/petstore/swift6/oneOf/.openapi-generator/FILES index 959ebf8f5dc2..5527650451b6 100644 --- a/samples/client/petstore/swift6/oneOf/.openapi-generator/FILES +++ b/samples/client/petstore/swift6/oneOf/.openapi-generator/FILES @@ -12,6 +12,7 @@ PetstoreClient/Classes/OpenAPIs/Infrastructure/JSONDataEncoding.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/JSONEncodingHelper.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/JSONValue.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift +PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenISO8601DateFormatter.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift diff --git a/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift b/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift index 2aa84c29d112..c5e729f78b11 100644 --- a/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift +++ b/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift @@ -10,19 +10,68 @@ import FoundationNetworking #endif open class PetstoreClientAPIConfiguration: @unchecked Sendable { - public var basePath: String - public var customHeaders: [String: String] - public var credential: URLCredential? - public var requestBuilderFactory: RequestBuilderFactory - public var apiResponseQueue: DispatchQueue - public var codableHelper: CodableHelper - - /// Configures the range of HTTP status codes that will result in a successful response + + // MARK: - Private state + + private struct State { + var basePath: String + var customHeaders: [String: String] + var credential: URLCredential? + var requestBuilderFactory: RequestBuilderFactory + var apiResponseQueue: DispatchQueue + var codableHelper: CodableHelper + var successfulStatusCodeRange: Range + var interceptor: OpenAPIInterceptor + } + + private let _state: OpenAPIMutex + + // MARK: - Public interface + + public var basePath: String { + get { _state.value.basePath } + set { _state.withValue { $0.basePath = newValue } } + } + + public var customHeaders: [String: String] { + get { _state.value.customHeaders } + set { _state.withValue { $0.customHeaders = newValue } } + } + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var requestBuilderFactory: RequestBuilderFactory { + get { _state.value.requestBuilderFactory } + set { _state.withValue { $0.requestBuilderFactory = newValue } } + } + + public var apiResponseQueue: DispatchQueue { + get { _state.value.apiResponseQueue } + set { _state.withValue { $0.apiResponseQueue = newValue } } + } + + public var codableHelper: CodableHelper { + get { _state.value.codableHelper } + set { _state.withValue { $0.codableHelper = newValue } } + } + + /// Configures the range of HTTP status codes that will result in a successful response. /// /// If a HTTP status code is outside of this range the response will be interpreted as failed. - public var successfulStatusCodeRange: Range + public var successfulStatusCodeRange: Range { + get { _state.value.successfulStatusCodeRange } + set { _state.withValue { $0.successfulStatusCodeRange = newValue } } + } - public var interceptor: OpenAPIInterceptor + public var interceptor: OpenAPIInterceptor { + get { _state.value.interceptor } + set { _state.withValue { $0.interceptor = newValue } } + } + + // MARK: - Init public init( basePath: String = "http://localhost", @@ -34,22 +83,25 @@ open class PetstoreClientAPIConfiguration: @unchecked Sendable { successfulStatusCodeRange: Range = 200..<300, interceptor: OpenAPIInterceptor = DefaultOpenAPIInterceptor() ) { - self.basePath = basePath - self.customHeaders = customHeaders - self.credential = credential - self.requestBuilderFactory = requestBuilderFactory - self.apiResponseQueue = apiResponseQueue - self.codableHelper = codableHelper - self.successfulStatusCodeRange = successfulStatusCodeRange - self.interceptor = interceptor + _state = OpenAPIMutex(State( + basePath: basePath, + customHeaders: customHeaders, + credential: credential, + requestBuilderFactory: requestBuilderFactory, + apiResponseQueue: apiResponseQueue, + codableHelper: codableHelper, + successfulStatusCodeRange: successfulStatusCodeRange, + interceptor: interceptor + )) } public static let shared = PetstoreClientAPIConfiguration() } open class RequestBuilder: @unchecked Sendable, Identifiable { - public var credential: URLCredential? - public var headers: [String: String] + + // MARK: - Immutable properties + public let parameters: [String: any Sendable]? public let method: String public let URLString: String @@ -57,24 +109,62 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public let requiresAuthentication: Bool public let apiConfiguration: PetstoreClientAPIConfiguration + // MARK: - Private mutable state + + private struct MutableState { + var credential: URLCredential? = nil + var headers: [String: String] + var onProgressReady: ((Progress) -> Void)? = nil + } + + private let _state: OpenAPIMutex + + // MARK: - Public mutable interface + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var headers: [String: String] { + get { _state.value.headers } + set { _state.withValue { $0.headers = newValue } } + } + /// Optional block to obtain a reference to the request's progress instance when available. - public var onProgressReady: ((Progress) -> Void)? + public var onProgressReady: ((Progress) -> Void)? { + get { _state.value.onProgressReady } + set { _state.withValue { $0.onProgressReady = newValue } } + } - required public init(method: String, URLString: String, parameters: [String: any Sendable]?, headers: [String: String] = [:], requiresAuthentication: Bool, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared) { + // MARK: - Init + + required public init( + method: String, + URLString: String, + parameters: [String: any Sendable]?, + headers: [String: String] = [:], + requiresAuthentication: Bool, + apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared + ) { self.method = method self.URLString = URLString self.parameters = parameters - self.headers = headers self.requiresAuthentication = requiresAuthentication self.apiConfiguration = apiConfiguration + self._state = OpenAPIMutex(MutableState(headers: headers)) addHeaders(apiConfiguration.customHeaders) addCredential() } + // MARK: - Public methods + open func addHeaders(_ aHeaders: [String: String]) { - for (header, value) in aHeaders { - headers[header] = value + _state.withValue { state in + for (header, value) in aHeaders { + state.headers[header] = value + } } } @@ -85,13 +175,15 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public func addHeader(name: String, value: String) -> Self { if !value.isEmpty { - headers[name] = value + _state.withValue { $0.headers[name] = value } } return self } open func addCredential() { - credential = apiConfiguration.credential + _state.withValue { [apiConfiguration] state in + state.credential = apiConfiguration.credential + } } } diff --git a/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift b/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift index b8990f975bcd..7d6f7a6fd1bd 100644 --- a/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift +++ b/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift @@ -8,37 +8,56 @@ import Foundation open class CodableHelper: @unchecked Sendable { - public init() {} - private var customDateFormatter: DateFormatter? - private var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + // MARK: - Private state + + private struct State { + var customDateFormatter: DateFormatter? + var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + + var customJSONDecoder: JSONDecoder? + var defaultJSONDecoder: JSONDecoder = JSONDecoder() + + var customJSONEncoder: JSONEncoder? + var defaultJSONEncoder: JSONEncoder = JSONEncoder() + + init() { + defaultJSONEncoder.outputFormatting = .prettyPrinted + rebuildDefaultCoders() + } + + mutating func rebuildDefaultCoders() { + defaultJSONDecoder.dateDecodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + defaultJSONEncoder.dateEncodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + } + } + + private let _state = OpenAPIMutex(State()) + + // MARK: - Init - private var customJSONDecoder: JSONDecoder? - private lazy var defaultJSONDecoder: JSONDecoder = { - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .formatted(dateFormatter) - return decoder - }() + public init() {} - private var customJSONEncoder: JSONEncoder? - private lazy var defaultJSONEncoder: JSONEncoder = { - let encoder = JSONEncoder() - encoder.dateEncodingStrategy = .formatted(dateFormatter) - encoder.outputFormatting = .prettyPrinted - return encoder - }() + // MARK: - Public interface public var dateFormatter: DateFormatter { - get { return customDateFormatter ?? defaultDateFormatter } - set { customDateFormatter = newValue } + get { _state.withValue { $0.customDateFormatter ?? $0.defaultDateFormatter } } + set { + _state.withValue { state in + state.customDateFormatter = newValue + state.rebuildDefaultCoders() + } + } } + public var jsonDecoder: JSONDecoder { - get { return customJSONDecoder ?? defaultJSONDecoder } - set { customJSONDecoder = newValue } + get { _state.withValue { $0.customJSONDecoder ?? $0.defaultJSONDecoder } } + set { _state.withValue { $0.customJSONDecoder = newValue } } } + public var jsonEncoder: JSONEncoder { - get { return customJSONEncoder ?? defaultJSONEncoder } - set { customJSONEncoder = newValue } + get { _state.withValue { $0.customJSONEncoder ?? $0.defaultJSONEncoder } } + set { _state.withValue { $0.customJSONEncoder = newValue } } } open func decode(_ type: T.Type, from data: Data) -> Swift.Result where T: Decodable { diff --git a/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift b/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift index f7a9f4f40195..e98056ea6658 100644 --- a/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift +++ b/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift @@ -116,25 +116,20 @@ public struct Response { extension Response : Sendable where T : Sendable {} public final class RequestTask: @unchecked Sendable { - private let lock = NSRecursiveLock() - private var task: URLSessionDataTaskProtocol? + private let _state = OpenAPIMutex(nil) internal func set(task: URLSessionDataTaskProtocol) { - lock.withLock { - self.task = task - } + _state.withValue { $0 = task } } internal func get() -> URLSessionDataTaskProtocol? { - lock.withLock { - task - } + _state.value } public func cancel() { - lock.withLock { - task?.cancel() - task = nil + _state.withValue { + $0?.cancel() + $0 = nil } } } diff --git a/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift b/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift new file mode 100644 index 000000000000..d7be0b6bd92e --- /dev/null +++ b/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift @@ -0,0 +1,28 @@ +// OpenAPIMutex.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +internal final class OpenAPIMutex: @unchecked Sendable { + + private var _value: Value + private let lock = NSRecursiveLock() + + internal init(_ value: Value) { + self._value = value + } + + internal var value: Value { + lock.withLock { _value } + } + + @discardableResult + internal func withValue( + _ body: (inout Value) throws -> Result + ) rethrows -> Result { + try lock.withLock { try body(&_value) } + } +} diff --git a/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift b/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift index 0d2714ca7b02..6c80862c6a0b 100644 --- a/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift +++ b/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift @@ -6,21 +6,12 @@ import Foundation -internal class SynchronizedDictionary : @unchecked Sendable { +internal final class SynchronizedDictionary: @unchecked Sendable { - private var dictionary = [K: V]() - private let lock = NSRecursiveLock() + private let _state = OpenAPIMutex<[K: V]>([:]) internal subscript(key: K) -> V? { - get { - lock.withLock { - self.dictionary[key] - } - } - set { - lock.withLock { - self.dictionary[key] = newValue - } - } + get { _state.value[key] } + set { _state.withValue { $0[key] = newValue } } } } diff --git a/samples/client/petstore/swift6/promisekitLibrary/.openapi-generator/FILES b/samples/client/petstore/swift6/promisekitLibrary/.openapi-generator/FILES index 3689e4184e32..7782fcf4f6c6 100644 --- a/samples/client/petstore/swift6/promisekitLibrary/.openapi-generator/FILES +++ b/samples/client/petstore/swift6/promisekitLibrary/.openapi-generator/FILES @@ -17,6 +17,7 @@ PetstoreClient/Classes/OpenAPIs/Infrastructure/JSONDataEncoding.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/JSONEncodingHelper.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/JSONValue.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift +PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenISO8601DateFormatter.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift diff --git a/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift b/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift index c7f49fa11157..fb5fcd0dc4fe 100644 --- a/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift +++ b/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift @@ -10,19 +10,68 @@ import FoundationNetworking #endif open class PetstoreClientAPIConfiguration: @unchecked Sendable { - public var basePath: String - public var customHeaders: [String: String] - public var credential: URLCredential? - public var requestBuilderFactory: RequestBuilderFactory - public var apiResponseQueue: DispatchQueue - public var codableHelper: CodableHelper - - /// Configures the range of HTTP status codes that will result in a successful response + + // MARK: - Private state + + private struct State { + var basePath: String + var customHeaders: [String: String] + var credential: URLCredential? + var requestBuilderFactory: RequestBuilderFactory + var apiResponseQueue: DispatchQueue + var codableHelper: CodableHelper + var successfulStatusCodeRange: Range + var interceptor: OpenAPIInterceptor + } + + private let _state: OpenAPIMutex + + // MARK: - Public interface + + public var basePath: String { + get { _state.value.basePath } + set { _state.withValue { $0.basePath = newValue } } + } + + public var customHeaders: [String: String] { + get { _state.value.customHeaders } + set { _state.withValue { $0.customHeaders = newValue } } + } + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var requestBuilderFactory: RequestBuilderFactory { + get { _state.value.requestBuilderFactory } + set { _state.withValue { $0.requestBuilderFactory = newValue } } + } + + public var apiResponseQueue: DispatchQueue { + get { _state.value.apiResponseQueue } + set { _state.withValue { $0.apiResponseQueue = newValue } } + } + + public var codableHelper: CodableHelper { + get { _state.value.codableHelper } + set { _state.withValue { $0.codableHelper = newValue } } + } + + /// Configures the range of HTTP status codes that will result in a successful response. /// /// If a HTTP status code is outside of this range the response will be interpreted as failed. - public var successfulStatusCodeRange: Range + public var successfulStatusCodeRange: Range { + get { _state.value.successfulStatusCodeRange } + set { _state.withValue { $0.successfulStatusCodeRange = newValue } } + } - public var interceptor: OpenAPIInterceptor + public var interceptor: OpenAPIInterceptor { + get { _state.value.interceptor } + set { _state.withValue { $0.interceptor = newValue } } + } + + // MARK: - Init public init( basePath: String = "http://petstore.swagger.io:80/v2", @@ -34,22 +83,25 @@ open class PetstoreClientAPIConfiguration: @unchecked Sendable { successfulStatusCodeRange: Range = 200..<300, interceptor: OpenAPIInterceptor = DefaultOpenAPIInterceptor() ) { - self.basePath = basePath - self.customHeaders = customHeaders - self.credential = credential - self.requestBuilderFactory = requestBuilderFactory - self.apiResponseQueue = apiResponseQueue - self.codableHelper = codableHelper - self.successfulStatusCodeRange = successfulStatusCodeRange - self.interceptor = interceptor + _state = OpenAPIMutex(State( + basePath: basePath, + customHeaders: customHeaders, + credential: credential, + requestBuilderFactory: requestBuilderFactory, + apiResponseQueue: apiResponseQueue, + codableHelper: codableHelper, + successfulStatusCodeRange: successfulStatusCodeRange, + interceptor: interceptor + )) } public static let shared = PetstoreClientAPIConfiguration() } open class RequestBuilder: @unchecked Sendable, Identifiable { - public var credential: URLCredential? - public var headers: [String: String] + + // MARK: - Immutable properties + public let parameters: [String: any Sendable]? public let method: String public let URLString: String @@ -57,24 +109,62 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public let requiresAuthentication: Bool public let apiConfiguration: PetstoreClientAPIConfiguration + // MARK: - Private mutable state + + private struct MutableState { + var credential: URLCredential? = nil + var headers: [String: String] + var onProgressReady: ((Progress) -> Void)? = nil + } + + private let _state: OpenAPIMutex + + // MARK: - Public mutable interface + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var headers: [String: String] { + get { _state.value.headers } + set { _state.withValue { $0.headers = newValue } } + } + /// Optional block to obtain a reference to the request's progress instance when available. - public var onProgressReady: ((Progress) -> Void)? + public var onProgressReady: ((Progress) -> Void)? { + get { _state.value.onProgressReady } + set { _state.withValue { $0.onProgressReady = newValue } } + } - required public init(method: String, URLString: String, parameters: [String: any Sendable]?, headers: [String: String] = [:], requiresAuthentication: Bool, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared) { + // MARK: - Init + + required public init( + method: String, + URLString: String, + parameters: [String: any Sendable]?, + headers: [String: String] = [:], + requiresAuthentication: Bool, + apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared + ) { self.method = method self.URLString = URLString self.parameters = parameters - self.headers = headers self.requiresAuthentication = requiresAuthentication self.apiConfiguration = apiConfiguration + self._state = OpenAPIMutex(MutableState(headers: headers)) addHeaders(apiConfiguration.customHeaders) addCredential() } + // MARK: - Public methods + open func addHeaders(_ aHeaders: [String: String]) { - for (header, value) in aHeaders { - headers[header] = value + _state.withValue { state in + for (header, value) in aHeaders { + state.headers[header] = value + } } } @@ -85,13 +175,15 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public func addHeader(name: String, value: String) -> Self { if !value.isEmpty { - headers[name] = value + _state.withValue { $0.headers[name] = value } } return self } open func addCredential() { - credential = apiConfiguration.credential + _state.withValue { [apiConfiguration] state in + state.credential = apiConfiguration.credential + } } } diff --git a/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift b/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift index b8990f975bcd..7d6f7a6fd1bd 100644 --- a/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift +++ b/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift @@ -8,37 +8,56 @@ import Foundation open class CodableHelper: @unchecked Sendable { - public init() {} - private var customDateFormatter: DateFormatter? - private var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + // MARK: - Private state + + private struct State { + var customDateFormatter: DateFormatter? + var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + + var customJSONDecoder: JSONDecoder? + var defaultJSONDecoder: JSONDecoder = JSONDecoder() + + var customJSONEncoder: JSONEncoder? + var defaultJSONEncoder: JSONEncoder = JSONEncoder() + + init() { + defaultJSONEncoder.outputFormatting = .prettyPrinted + rebuildDefaultCoders() + } + + mutating func rebuildDefaultCoders() { + defaultJSONDecoder.dateDecodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + defaultJSONEncoder.dateEncodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + } + } + + private let _state = OpenAPIMutex(State()) + + // MARK: - Init - private var customJSONDecoder: JSONDecoder? - private lazy var defaultJSONDecoder: JSONDecoder = { - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .formatted(dateFormatter) - return decoder - }() + public init() {} - private var customJSONEncoder: JSONEncoder? - private lazy var defaultJSONEncoder: JSONEncoder = { - let encoder = JSONEncoder() - encoder.dateEncodingStrategy = .formatted(dateFormatter) - encoder.outputFormatting = .prettyPrinted - return encoder - }() + // MARK: - Public interface public var dateFormatter: DateFormatter { - get { return customDateFormatter ?? defaultDateFormatter } - set { customDateFormatter = newValue } + get { _state.withValue { $0.customDateFormatter ?? $0.defaultDateFormatter } } + set { + _state.withValue { state in + state.customDateFormatter = newValue + state.rebuildDefaultCoders() + } + } } + public var jsonDecoder: JSONDecoder { - get { return customJSONDecoder ?? defaultJSONDecoder } - set { customJSONDecoder = newValue } + get { _state.withValue { $0.customJSONDecoder ?? $0.defaultJSONDecoder } } + set { _state.withValue { $0.customJSONDecoder = newValue } } } + public var jsonEncoder: JSONEncoder { - get { return customJSONEncoder ?? defaultJSONEncoder } - set { customJSONEncoder = newValue } + get { _state.withValue { $0.customJSONEncoder ?? $0.defaultJSONEncoder } } + set { _state.withValue { $0.customJSONEncoder = newValue } } } open func decode(_ type: T.Type, from data: Data) -> Swift.Result where T: Decodable { diff --git a/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift b/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift index f7a9f4f40195..e98056ea6658 100644 --- a/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift +++ b/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift @@ -116,25 +116,20 @@ public struct Response { extension Response : Sendable where T : Sendable {} public final class RequestTask: @unchecked Sendable { - private let lock = NSRecursiveLock() - private var task: URLSessionDataTaskProtocol? + private let _state = OpenAPIMutex(nil) internal func set(task: URLSessionDataTaskProtocol) { - lock.withLock { - self.task = task - } + _state.withValue { $0 = task } } internal func get() -> URLSessionDataTaskProtocol? { - lock.withLock { - task - } + _state.value } public func cancel() { - lock.withLock { - task?.cancel() - task = nil + _state.withValue { + $0?.cancel() + $0 = nil } } } diff --git a/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift b/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift new file mode 100644 index 000000000000..d7be0b6bd92e --- /dev/null +++ b/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift @@ -0,0 +1,28 @@ +// OpenAPIMutex.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +internal final class OpenAPIMutex: @unchecked Sendable { + + private var _value: Value + private let lock = NSRecursiveLock() + + internal init(_ value: Value) { + self._value = value + } + + internal var value: Value { + lock.withLock { _value } + } + + @discardableResult + internal func withValue( + _ body: (inout Value) throws -> Result + ) rethrows -> Result { + try lock.withLock { try body(&_value) } + } +} diff --git a/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift b/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift index 0d2714ca7b02..6c80862c6a0b 100644 --- a/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift +++ b/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift @@ -6,21 +6,12 @@ import Foundation -internal class SynchronizedDictionary : @unchecked Sendable { +internal final class SynchronizedDictionary: @unchecked Sendable { - private var dictionary = [K: V]() - private let lock = NSRecursiveLock() + private let _state = OpenAPIMutex<[K: V]>([:]) internal subscript(key: K) -> V? { - get { - lock.withLock { - self.dictionary[key] - } - } - set { - lock.withLock { - self.dictionary[key] = newValue - } - } + get { _state.value[key] } + set { _state.withValue { $0[key] = newValue } } } } diff --git a/samples/client/petstore/swift6/resultLibrary/.openapi-generator/FILES b/samples/client/petstore/swift6/resultLibrary/.openapi-generator/FILES index 3689e4184e32..7782fcf4f6c6 100644 --- a/samples/client/petstore/swift6/resultLibrary/.openapi-generator/FILES +++ b/samples/client/petstore/swift6/resultLibrary/.openapi-generator/FILES @@ -17,6 +17,7 @@ PetstoreClient/Classes/OpenAPIs/Infrastructure/JSONDataEncoding.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/JSONEncodingHelper.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/JSONValue.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift +PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenISO8601DateFormatter.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift diff --git a/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift b/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift index fc4bec788267..5ea9cdb01978 100644 --- a/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift +++ b/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift @@ -10,19 +10,68 @@ import FoundationNetworking #endif internal class PetstoreClientAPIConfiguration: @unchecked Sendable { - internal var basePath: String - internal var customHeaders: [String: String] - internal var credential: URLCredential? - internal var requestBuilderFactory: RequestBuilderFactory - internal var apiResponseQueue: DispatchQueue - internal var codableHelper: CodableHelper - - /// Configures the range of HTTP status codes that will result in a successful response + + // MARK: - Private state + + private struct State { + var basePath: String + var customHeaders: [String: String] + var credential: URLCredential? + var requestBuilderFactory: RequestBuilderFactory + var apiResponseQueue: DispatchQueue + var codableHelper: CodableHelper + var successfulStatusCodeRange: Range + var interceptor: OpenAPIInterceptor + } + + private let _state: OpenAPIMutex + + // MARK: - Public interface + + internal var basePath: String { + get { _state.value.basePath } + set { _state.withValue { $0.basePath = newValue } } + } + + internal var customHeaders: [String: String] { + get { _state.value.customHeaders } + set { _state.withValue { $0.customHeaders = newValue } } + } + + internal var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + internal var requestBuilderFactory: RequestBuilderFactory { + get { _state.value.requestBuilderFactory } + set { _state.withValue { $0.requestBuilderFactory = newValue } } + } + + internal var apiResponseQueue: DispatchQueue { + get { _state.value.apiResponseQueue } + set { _state.withValue { $0.apiResponseQueue = newValue } } + } + + internal var codableHelper: CodableHelper { + get { _state.value.codableHelper } + set { _state.withValue { $0.codableHelper = newValue } } + } + + /// Configures the range of HTTP status codes that will result in a successful response. /// /// If a HTTP status code is outside of this range the response will be interpreted as failed. - internal var successfulStatusCodeRange: Range + internal var successfulStatusCodeRange: Range { + get { _state.value.successfulStatusCodeRange } + set { _state.withValue { $0.successfulStatusCodeRange = newValue } } + } - internal var interceptor: OpenAPIInterceptor + internal var interceptor: OpenAPIInterceptor { + get { _state.value.interceptor } + set { _state.withValue { $0.interceptor = newValue } } + } + + // MARK: - Init internal init( basePath: String = "http://petstore.swagger.io:80/v2", @@ -34,22 +83,25 @@ internal class PetstoreClientAPIConfiguration: @unchecked Sendable { successfulStatusCodeRange: Range = 200..<300, interceptor: OpenAPIInterceptor = DefaultOpenAPIInterceptor() ) { - self.basePath = basePath - self.customHeaders = customHeaders - self.credential = credential - self.requestBuilderFactory = requestBuilderFactory - self.apiResponseQueue = apiResponseQueue - self.codableHelper = codableHelper - self.successfulStatusCodeRange = successfulStatusCodeRange - self.interceptor = interceptor + _state = OpenAPIMutex(State( + basePath: basePath, + customHeaders: customHeaders, + credential: credential, + requestBuilderFactory: requestBuilderFactory, + apiResponseQueue: apiResponseQueue, + codableHelper: codableHelper, + successfulStatusCodeRange: successfulStatusCodeRange, + interceptor: interceptor + )) } internal static let shared = PetstoreClientAPIConfiguration() } internal class RequestBuilder: @unchecked Sendable, Identifiable { - internal var credential: URLCredential? - internal var headers: [String: String] + + // MARK: - Immutable properties + internal let parameters: [String: any Sendable]? internal let method: String internal let URLString: String @@ -57,24 +109,62 @@ internal class RequestBuilder: @unchecked Sendable, Identifiable { internal let requiresAuthentication: Bool internal let apiConfiguration: PetstoreClientAPIConfiguration + // MARK: - Private mutable state + + private struct MutableState { + var credential: URLCredential? = nil + var headers: [String: String] + var onProgressReady: ((Progress) -> Void)? = nil + } + + private let _state: OpenAPIMutex + + // MARK: - Public mutable interface + + internal var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + internal var headers: [String: String] { + get { _state.value.headers } + set { _state.withValue { $0.headers = newValue } } + } + /// Optional block to obtain a reference to the request's progress instance when available. - internal var onProgressReady: ((Progress) -> Void)? + internal var onProgressReady: ((Progress) -> Void)? { + get { _state.value.onProgressReady } + set { _state.withValue { $0.onProgressReady = newValue } } + } - required internal init(method: String, URLString: String, parameters: [String: any Sendable]?, headers: [String: String] = [:], requiresAuthentication: Bool, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared) { + // MARK: - Init + + required internal init( + method: String, + URLString: String, + parameters: [String: any Sendable]?, + headers: [String: String] = [:], + requiresAuthentication: Bool, + apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared + ) { self.method = method self.URLString = URLString self.parameters = parameters - self.headers = headers self.requiresAuthentication = requiresAuthentication self.apiConfiguration = apiConfiguration + self._state = OpenAPIMutex(MutableState(headers: headers)) addHeaders(apiConfiguration.customHeaders) addCredential() } + // MARK: - Public methods + internal func addHeaders(_ aHeaders: [String: String]) { - for (header, value) in aHeaders { - headers[header] = value + _state.withValue { state in + for (header, value) in aHeaders { + state.headers[header] = value + } } } @@ -85,13 +175,15 @@ internal class RequestBuilder: @unchecked Sendable, Identifiable { internal func addHeader(name: String, value: String) -> Self { if !value.isEmpty { - headers[name] = value + _state.withValue { $0.headers[name] = value } } return self } internal func addCredential() { - credential = apiConfiguration.credential + _state.withValue { [apiConfiguration] state in + state.credential = apiConfiguration.credential + } } } diff --git a/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift b/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift index 5abbd26a7948..5010af68e47a 100644 --- a/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift +++ b/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift @@ -8,37 +8,56 @@ import Foundation internal class CodableHelper: @unchecked Sendable { - internal init() {} - private var customDateFormatter: DateFormatter? - private var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + // MARK: - Private state + + private struct State { + var customDateFormatter: DateFormatter? + var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + + var customJSONDecoder: JSONDecoder? + var defaultJSONDecoder: JSONDecoder = JSONDecoder() + + var customJSONEncoder: JSONEncoder? + var defaultJSONEncoder: JSONEncoder = JSONEncoder() + + init() { + defaultJSONEncoder.outputFormatting = .prettyPrinted + rebuildDefaultCoders() + } + + mutating func rebuildDefaultCoders() { + defaultJSONDecoder.dateDecodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + defaultJSONEncoder.dateEncodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + } + } + + private let _state = OpenAPIMutex(State()) + + // MARK: - Init - private var customJSONDecoder: JSONDecoder? - private lazy var defaultJSONDecoder: JSONDecoder = { - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .formatted(dateFormatter) - return decoder - }() + internal init() {} - private var customJSONEncoder: JSONEncoder? - private lazy var defaultJSONEncoder: JSONEncoder = { - let encoder = JSONEncoder() - encoder.dateEncodingStrategy = .formatted(dateFormatter) - encoder.outputFormatting = .prettyPrinted - return encoder - }() + // MARK: - Public interface internal var dateFormatter: DateFormatter { - get { return customDateFormatter ?? defaultDateFormatter } - set { customDateFormatter = newValue } + get { _state.withValue { $0.customDateFormatter ?? $0.defaultDateFormatter } } + set { + _state.withValue { state in + state.customDateFormatter = newValue + state.rebuildDefaultCoders() + } + } } + internal var jsonDecoder: JSONDecoder { - get { return customJSONDecoder ?? defaultJSONDecoder } - set { customJSONDecoder = newValue } + get { _state.withValue { $0.customJSONDecoder ?? $0.defaultJSONDecoder } } + set { _state.withValue { $0.customJSONDecoder = newValue } } } + internal var jsonEncoder: JSONEncoder { - get { return customJSONEncoder ?? defaultJSONEncoder } - set { customJSONEncoder = newValue } + get { _state.withValue { $0.customJSONEncoder ?? $0.defaultJSONEncoder } } + set { _state.withValue { $0.customJSONEncoder = newValue } } } internal func decode(_ type: T.Type, from data: Data) -> Swift.Result where T: Decodable { diff --git a/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift b/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift index d7086fdd4de4..ca30258f63d4 100644 --- a/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift +++ b/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift @@ -116,25 +116,20 @@ internal struct Response { extension Response : Sendable where T : Sendable {} internal final class RequestTask: @unchecked Sendable { - private let lock = NSRecursiveLock() - private var task: URLSessionDataTaskProtocol? + private let _state = OpenAPIMutex(nil) internal func set(task: URLSessionDataTaskProtocol) { - lock.withLock { - self.task = task - } + _state.withValue { $0 = task } } internal func get() -> URLSessionDataTaskProtocol? { - lock.withLock { - task - } + _state.value } internal func cancel() { - lock.withLock { - task?.cancel() - task = nil + _state.withValue { + $0?.cancel() + $0 = nil } } } diff --git a/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift b/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift new file mode 100644 index 000000000000..d7be0b6bd92e --- /dev/null +++ b/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift @@ -0,0 +1,28 @@ +// OpenAPIMutex.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +internal final class OpenAPIMutex: @unchecked Sendable { + + private var _value: Value + private let lock = NSRecursiveLock() + + internal init(_ value: Value) { + self._value = value + } + + internal var value: Value { + lock.withLock { _value } + } + + @discardableResult + internal func withValue( + _ body: (inout Value) throws -> Result + ) rethrows -> Result { + try lock.withLock { try body(&_value) } + } +} diff --git a/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift b/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift index 0d2714ca7b02..6c80862c6a0b 100644 --- a/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift +++ b/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift @@ -6,21 +6,12 @@ import Foundation -internal class SynchronizedDictionary : @unchecked Sendable { +internal final class SynchronizedDictionary: @unchecked Sendable { - private var dictionary = [K: V]() - private let lock = NSRecursiveLock() + private let _state = OpenAPIMutex<[K: V]>([:]) internal subscript(key: K) -> V? { - get { - lock.withLock { - self.dictionary[key] - } - } - set { - lock.withLock { - self.dictionary[key] = newValue - } - } + get { _state.value[key] } + set { _state.withValue { $0[key] = newValue } } } } diff --git a/samples/client/petstore/swift6/rxswiftLibrary/.openapi-generator/FILES b/samples/client/petstore/swift6/rxswiftLibrary/.openapi-generator/FILES index 3689e4184e32..7782fcf4f6c6 100644 --- a/samples/client/petstore/swift6/rxswiftLibrary/.openapi-generator/FILES +++ b/samples/client/petstore/swift6/rxswiftLibrary/.openapi-generator/FILES @@ -17,6 +17,7 @@ PetstoreClient/Classes/OpenAPIs/Infrastructure/JSONDataEncoding.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/JSONEncodingHelper.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/JSONValue.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift +PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenISO8601DateFormatter.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift diff --git a/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift b/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift index c7f49fa11157..fb5fcd0dc4fe 100644 --- a/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift +++ b/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift @@ -10,19 +10,68 @@ import FoundationNetworking #endif open class PetstoreClientAPIConfiguration: @unchecked Sendable { - public var basePath: String - public var customHeaders: [String: String] - public var credential: URLCredential? - public var requestBuilderFactory: RequestBuilderFactory - public var apiResponseQueue: DispatchQueue - public var codableHelper: CodableHelper - - /// Configures the range of HTTP status codes that will result in a successful response + + // MARK: - Private state + + private struct State { + var basePath: String + var customHeaders: [String: String] + var credential: URLCredential? + var requestBuilderFactory: RequestBuilderFactory + var apiResponseQueue: DispatchQueue + var codableHelper: CodableHelper + var successfulStatusCodeRange: Range + var interceptor: OpenAPIInterceptor + } + + private let _state: OpenAPIMutex + + // MARK: - Public interface + + public var basePath: String { + get { _state.value.basePath } + set { _state.withValue { $0.basePath = newValue } } + } + + public var customHeaders: [String: String] { + get { _state.value.customHeaders } + set { _state.withValue { $0.customHeaders = newValue } } + } + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var requestBuilderFactory: RequestBuilderFactory { + get { _state.value.requestBuilderFactory } + set { _state.withValue { $0.requestBuilderFactory = newValue } } + } + + public var apiResponseQueue: DispatchQueue { + get { _state.value.apiResponseQueue } + set { _state.withValue { $0.apiResponseQueue = newValue } } + } + + public var codableHelper: CodableHelper { + get { _state.value.codableHelper } + set { _state.withValue { $0.codableHelper = newValue } } + } + + /// Configures the range of HTTP status codes that will result in a successful response. /// /// If a HTTP status code is outside of this range the response will be interpreted as failed. - public var successfulStatusCodeRange: Range + public var successfulStatusCodeRange: Range { + get { _state.value.successfulStatusCodeRange } + set { _state.withValue { $0.successfulStatusCodeRange = newValue } } + } - public var interceptor: OpenAPIInterceptor + public var interceptor: OpenAPIInterceptor { + get { _state.value.interceptor } + set { _state.withValue { $0.interceptor = newValue } } + } + + // MARK: - Init public init( basePath: String = "http://petstore.swagger.io:80/v2", @@ -34,22 +83,25 @@ open class PetstoreClientAPIConfiguration: @unchecked Sendable { successfulStatusCodeRange: Range = 200..<300, interceptor: OpenAPIInterceptor = DefaultOpenAPIInterceptor() ) { - self.basePath = basePath - self.customHeaders = customHeaders - self.credential = credential - self.requestBuilderFactory = requestBuilderFactory - self.apiResponseQueue = apiResponseQueue - self.codableHelper = codableHelper - self.successfulStatusCodeRange = successfulStatusCodeRange - self.interceptor = interceptor + _state = OpenAPIMutex(State( + basePath: basePath, + customHeaders: customHeaders, + credential: credential, + requestBuilderFactory: requestBuilderFactory, + apiResponseQueue: apiResponseQueue, + codableHelper: codableHelper, + successfulStatusCodeRange: successfulStatusCodeRange, + interceptor: interceptor + )) } public static let shared = PetstoreClientAPIConfiguration() } open class RequestBuilder: @unchecked Sendable, Identifiable { - public var credential: URLCredential? - public var headers: [String: String] + + // MARK: - Immutable properties + public let parameters: [String: any Sendable]? public let method: String public let URLString: String @@ -57,24 +109,62 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public let requiresAuthentication: Bool public let apiConfiguration: PetstoreClientAPIConfiguration + // MARK: - Private mutable state + + private struct MutableState { + var credential: URLCredential? = nil + var headers: [String: String] + var onProgressReady: ((Progress) -> Void)? = nil + } + + private let _state: OpenAPIMutex + + // MARK: - Public mutable interface + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var headers: [String: String] { + get { _state.value.headers } + set { _state.withValue { $0.headers = newValue } } + } + /// Optional block to obtain a reference to the request's progress instance when available. - public var onProgressReady: ((Progress) -> Void)? + public var onProgressReady: ((Progress) -> Void)? { + get { _state.value.onProgressReady } + set { _state.withValue { $0.onProgressReady = newValue } } + } - required public init(method: String, URLString: String, parameters: [String: any Sendable]?, headers: [String: String] = [:], requiresAuthentication: Bool, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared) { + // MARK: - Init + + required public init( + method: String, + URLString: String, + parameters: [String: any Sendable]?, + headers: [String: String] = [:], + requiresAuthentication: Bool, + apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared + ) { self.method = method self.URLString = URLString self.parameters = parameters - self.headers = headers self.requiresAuthentication = requiresAuthentication self.apiConfiguration = apiConfiguration + self._state = OpenAPIMutex(MutableState(headers: headers)) addHeaders(apiConfiguration.customHeaders) addCredential() } + // MARK: - Public methods + open func addHeaders(_ aHeaders: [String: String]) { - for (header, value) in aHeaders { - headers[header] = value + _state.withValue { state in + for (header, value) in aHeaders { + state.headers[header] = value + } } } @@ -85,13 +175,15 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public func addHeader(name: String, value: String) -> Self { if !value.isEmpty { - headers[name] = value + _state.withValue { $0.headers[name] = value } } return self } open func addCredential() { - credential = apiConfiguration.credential + _state.withValue { [apiConfiguration] state in + state.credential = apiConfiguration.credential + } } } diff --git a/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift b/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift index b8990f975bcd..7d6f7a6fd1bd 100644 --- a/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift +++ b/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift @@ -8,37 +8,56 @@ import Foundation open class CodableHelper: @unchecked Sendable { - public init() {} - private var customDateFormatter: DateFormatter? - private var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + // MARK: - Private state + + private struct State { + var customDateFormatter: DateFormatter? + var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + + var customJSONDecoder: JSONDecoder? + var defaultJSONDecoder: JSONDecoder = JSONDecoder() + + var customJSONEncoder: JSONEncoder? + var defaultJSONEncoder: JSONEncoder = JSONEncoder() + + init() { + defaultJSONEncoder.outputFormatting = .prettyPrinted + rebuildDefaultCoders() + } + + mutating func rebuildDefaultCoders() { + defaultJSONDecoder.dateDecodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + defaultJSONEncoder.dateEncodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + } + } + + private let _state = OpenAPIMutex(State()) + + // MARK: - Init - private var customJSONDecoder: JSONDecoder? - private lazy var defaultJSONDecoder: JSONDecoder = { - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .formatted(dateFormatter) - return decoder - }() + public init() {} - private var customJSONEncoder: JSONEncoder? - private lazy var defaultJSONEncoder: JSONEncoder = { - let encoder = JSONEncoder() - encoder.dateEncodingStrategy = .formatted(dateFormatter) - encoder.outputFormatting = .prettyPrinted - return encoder - }() + // MARK: - Public interface public var dateFormatter: DateFormatter { - get { return customDateFormatter ?? defaultDateFormatter } - set { customDateFormatter = newValue } + get { _state.withValue { $0.customDateFormatter ?? $0.defaultDateFormatter } } + set { + _state.withValue { state in + state.customDateFormatter = newValue + state.rebuildDefaultCoders() + } + } } + public var jsonDecoder: JSONDecoder { - get { return customJSONDecoder ?? defaultJSONDecoder } - set { customJSONDecoder = newValue } + get { _state.withValue { $0.customJSONDecoder ?? $0.defaultJSONDecoder } } + set { _state.withValue { $0.customJSONDecoder = newValue } } } + public var jsonEncoder: JSONEncoder { - get { return customJSONEncoder ?? defaultJSONEncoder } - set { customJSONEncoder = newValue } + get { _state.withValue { $0.customJSONEncoder ?? $0.defaultJSONEncoder } } + set { _state.withValue { $0.customJSONEncoder = newValue } } } open func decode(_ type: T.Type, from data: Data) -> Swift.Result where T: Decodable { diff --git a/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift b/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift index f7a9f4f40195..e98056ea6658 100644 --- a/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift +++ b/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift @@ -116,25 +116,20 @@ public struct Response { extension Response : Sendable where T : Sendable {} public final class RequestTask: @unchecked Sendable { - private let lock = NSRecursiveLock() - private var task: URLSessionDataTaskProtocol? + private let _state = OpenAPIMutex(nil) internal func set(task: URLSessionDataTaskProtocol) { - lock.withLock { - self.task = task - } + _state.withValue { $0 = task } } internal func get() -> URLSessionDataTaskProtocol? { - lock.withLock { - task - } + _state.value } public func cancel() { - lock.withLock { - task?.cancel() - task = nil + _state.withValue { + $0?.cancel() + $0 = nil } } } diff --git a/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift b/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift new file mode 100644 index 000000000000..d7be0b6bd92e --- /dev/null +++ b/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift @@ -0,0 +1,28 @@ +// OpenAPIMutex.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +internal final class OpenAPIMutex: @unchecked Sendable { + + private var _value: Value + private let lock = NSRecursiveLock() + + internal init(_ value: Value) { + self._value = value + } + + internal var value: Value { + lock.withLock { _value } + } + + @discardableResult + internal func withValue( + _ body: (inout Value) throws -> Result + ) rethrows -> Result { + try lock.withLock { try body(&_value) } + } +} diff --git a/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift b/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift index 0d2714ca7b02..6c80862c6a0b 100644 --- a/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift +++ b/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift @@ -6,21 +6,12 @@ import Foundation -internal class SynchronizedDictionary : @unchecked Sendable { +internal final class SynchronizedDictionary: @unchecked Sendable { - private var dictionary = [K: V]() - private let lock = NSRecursiveLock() + private let _state = OpenAPIMutex<[K: V]>([:]) internal subscript(key: K) -> V? { - get { - lock.withLock { - self.dictionary[key] - } - } - set { - lock.withLock { - self.dictionary[key] = newValue - } - } + get { _state.value[key] } + set { _state.withValue { $0[key] = newValue } } } } diff --git a/samples/client/petstore/swift6/urlsessionLibrary/.openapi-generator/FILES b/samples/client/petstore/swift6/urlsessionLibrary/.openapi-generator/FILES index dbd6732f0444..e8d5c4bbbb91 100644 --- a/samples/client/petstore/swift6/urlsessionLibrary/.openapi-generator/FILES +++ b/samples/client/petstore/swift6/urlsessionLibrary/.openapi-generator/FILES @@ -18,6 +18,7 @@ Sources/PetstoreClient/Infrastructure/JSONDataEncoding.swift Sources/PetstoreClient/Infrastructure/JSONEncodingHelper.swift Sources/PetstoreClient/Infrastructure/JSONValue.swift Sources/PetstoreClient/Infrastructure/Models.swift +Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift Sources/PetstoreClient/Infrastructure/OpenISO8601DateFormatter.swift Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift Sources/PetstoreClient/Infrastructure/URLSessionImplementations.swift diff --git a/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/APIs.swift b/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/APIs.swift index 6c19df9add1e..29583785ae12 100644 --- a/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/APIs.swift +++ b/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/APIs.swift @@ -12,19 +12,68 @@ import FoundationNetworking public enum PetstoreClientAPI {} open class PetstoreClientAPIConfiguration: @unchecked Sendable { - public var basePath: String - public var customHeaders: [String: String] - public var credential: URLCredential? - public var requestBuilderFactory: RequestBuilderFactory - public var apiResponseQueue: DispatchQueue - public var codableHelper: CodableHelper - - /// Configures the range of HTTP status codes that will result in a successful response + + // MARK: - Private state + + private struct State { + var basePath: String + var customHeaders: [String: String] + var credential: URLCredential? + var requestBuilderFactory: RequestBuilderFactory + var apiResponseQueue: DispatchQueue + var codableHelper: CodableHelper + var successfulStatusCodeRange: Range + var interceptor: OpenAPIInterceptor + } + + private let _state: OpenAPIMutex + + // MARK: - Public interface + + public var basePath: String { + get { _state.value.basePath } + set { _state.withValue { $0.basePath = newValue } } + } + + public var customHeaders: [String: String] { + get { _state.value.customHeaders } + set { _state.withValue { $0.customHeaders = newValue } } + } + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var requestBuilderFactory: RequestBuilderFactory { + get { _state.value.requestBuilderFactory } + set { _state.withValue { $0.requestBuilderFactory = newValue } } + } + + public var apiResponseQueue: DispatchQueue { + get { _state.value.apiResponseQueue } + set { _state.withValue { $0.apiResponseQueue = newValue } } + } + + public var codableHelper: CodableHelper { + get { _state.value.codableHelper } + set { _state.withValue { $0.codableHelper = newValue } } + } + + /// Configures the range of HTTP status codes that will result in a successful response. /// /// If a HTTP status code is outside of this range the response will be interpreted as failed. - public var successfulStatusCodeRange: Range + public var successfulStatusCodeRange: Range { + get { _state.value.successfulStatusCodeRange } + set { _state.withValue { $0.successfulStatusCodeRange = newValue } } + } - public var interceptor: OpenAPIInterceptor + public var interceptor: OpenAPIInterceptor { + get { _state.value.interceptor } + set { _state.withValue { $0.interceptor = newValue } } + } + + // MARK: - Init public init( basePath: String = "http://petstore.swagger.io:80/v2", @@ -36,22 +85,25 @@ open class PetstoreClientAPIConfiguration: @unchecked Sendable { successfulStatusCodeRange: Range = 200..<300, interceptor: OpenAPIInterceptor = DefaultOpenAPIInterceptor() ) { - self.basePath = basePath - self.customHeaders = customHeaders - self.credential = credential - self.requestBuilderFactory = requestBuilderFactory - self.apiResponseQueue = apiResponseQueue - self.codableHelper = codableHelper - self.successfulStatusCodeRange = successfulStatusCodeRange - self.interceptor = interceptor + _state = OpenAPIMutex(State( + basePath: basePath, + customHeaders: customHeaders, + credential: credential, + requestBuilderFactory: requestBuilderFactory, + apiResponseQueue: apiResponseQueue, + codableHelper: codableHelper, + successfulStatusCodeRange: successfulStatusCodeRange, + interceptor: interceptor + )) } public static let shared = PetstoreClientAPIConfiguration() } open class RequestBuilder: @unchecked Sendable, Identifiable { - public var credential: URLCredential? - public var headers: [String: String] + + // MARK: - Immutable properties + public let parameters: [String: any Sendable]? public let method: String public let URLString: String @@ -59,24 +111,62 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public let requiresAuthentication: Bool public let apiConfiguration: PetstoreClientAPIConfiguration + // MARK: - Private mutable state + + private struct MutableState { + var credential: URLCredential? = nil + var headers: [String: String] + var onProgressReady: ((Progress) -> Void)? = nil + } + + private let _state: OpenAPIMutex + + // MARK: - Public mutable interface + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var headers: [String: String] { + get { _state.value.headers } + set { _state.withValue { $0.headers = newValue } } + } + /// Optional block to obtain a reference to the request's progress instance when available. - public var onProgressReady: ((Progress) -> Void)? + public var onProgressReady: ((Progress) -> Void)? { + get { _state.value.onProgressReady } + set { _state.withValue { $0.onProgressReady = newValue } } + } - required public init(method: String, URLString: String, parameters: [String: any Sendable]?, headers: [String: String] = [:], requiresAuthentication: Bool, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared) { + // MARK: - Init + + required public init( + method: String, + URLString: String, + parameters: [String: any Sendable]?, + headers: [String: String] = [:], + requiresAuthentication: Bool, + apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared + ) { self.method = method self.URLString = URLString self.parameters = parameters - self.headers = headers self.requiresAuthentication = requiresAuthentication self.apiConfiguration = apiConfiguration + self._state = OpenAPIMutex(MutableState(headers: headers)) addHeaders(apiConfiguration.customHeaders) addCredential() } + // MARK: - Public methods + open func addHeaders(_ aHeaders: [String: String]) { - for (header, value) in aHeaders { - headers[header] = value + _state.withValue { state in + for (header, value) in aHeaders { + state.headers[header] = value + } } } @@ -87,13 +177,15 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public func addHeader(name: String, value: String) -> Self { if !value.isEmpty { - headers[name] = value + _state.withValue { $0.headers[name] = value } } return self } open func addCredential() { - credential = apiConfiguration.credential + _state.withValue { [apiConfiguration] state in + state.credential = apiConfiguration.credential + } } } diff --git a/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/CodableHelper.swift b/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/CodableHelper.swift index b8990f975bcd..7d6f7a6fd1bd 100644 --- a/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/CodableHelper.swift +++ b/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/CodableHelper.swift @@ -8,37 +8,56 @@ import Foundation open class CodableHelper: @unchecked Sendable { - public init() {} - private var customDateFormatter: DateFormatter? - private var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + // MARK: - Private state + + private struct State { + var customDateFormatter: DateFormatter? + var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + + var customJSONDecoder: JSONDecoder? + var defaultJSONDecoder: JSONDecoder = JSONDecoder() + + var customJSONEncoder: JSONEncoder? + var defaultJSONEncoder: JSONEncoder = JSONEncoder() + + init() { + defaultJSONEncoder.outputFormatting = .prettyPrinted + rebuildDefaultCoders() + } + + mutating func rebuildDefaultCoders() { + defaultJSONDecoder.dateDecodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + defaultJSONEncoder.dateEncodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + } + } + + private let _state = OpenAPIMutex(State()) + + // MARK: - Init - private var customJSONDecoder: JSONDecoder? - private lazy var defaultJSONDecoder: JSONDecoder = { - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .formatted(dateFormatter) - return decoder - }() + public init() {} - private var customJSONEncoder: JSONEncoder? - private lazy var defaultJSONEncoder: JSONEncoder = { - let encoder = JSONEncoder() - encoder.dateEncodingStrategy = .formatted(dateFormatter) - encoder.outputFormatting = .prettyPrinted - return encoder - }() + // MARK: - Public interface public var dateFormatter: DateFormatter { - get { return customDateFormatter ?? defaultDateFormatter } - set { customDateFormatter = newValue } + get { _state.withValue { $0.customDateFormatter ?? $0.defaultDateFormatter } } + set { + _state.withValue { state in + state.customDateFormatter = newValue + state.rebuildDefaultCoders() + } + } } + public var jsonDecoder: JSONDecoder { - get { return customJSONDecoder ?? defaultJSONDecoder } - set { customJSONDecoder = newValue } + get { _state.withValue { $0.customJSONDecoder ?? $0.defaultJSONDecoder } } + set { _state.withValue { $0.customJSONDecoder = newValue } } } + public var jsonEncoder: JSONEncoder { - get { return customJSONEncoder ?? defaultJSONEncoder } - set { customJSONEncoder = newValue } + get { _state.withValue { $0.customJSONEncoder ?? $0.defaultJSONEncoder } } + set { _state.withValue { $0.customJSONEncoder = newValue } } } open func decode(_ type: T.Type, from data: Data) -> Swift.Result where T: Decodable { diff --git a/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/Models.swift b/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/Models.swift index f7a9f4f40195..e98056ea6658 100644 --- a/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/Models.swift +++ b/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/Models.swift @@ -116,25 +116,20 @@ public struct Response { extension Response : Sendable where T : Sendable {} public final class RequestTask: @unchecked Sendable { - private let lock = NSRecursiveLock() - private var task: URLSessionDataTaskProtocol? + private let _state = OpenAPIMutex(nil) internal func set(task: URLSessionDataTaskProtocol) { - lock.withLock { - self.task = task - } + _state.withValue { $0 = task } } internal func get() -> URLSessionDataTaskProtocol? { - lock.withLock { - task - } + _state.value } public func cancel() { - lock.withLock { - task?.cancel() - task = nil + _state.withValue { + $0?.cancel() + $0 = nil } } } diff --git a/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift b/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift new file mode 100644 index 000000000000..d7be0b6bd92e --- /dev/null +++ b/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift @@ -0,0 +1,28 @@ +// OpenAPIMutex.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +internal final class OpenAPIMutex: @unchecked Sendable { + + private var _value: Value + private let lock = NSRecursiveLock() + + internal init(_ value: Value) { + self._value = value + } + + internal var value: Value { + lock.withLock { _value } + } + + @discardableResult + internal func withValue( + _ body: (inout Value) throws -> Result + ) rethrows -> Result { + try lock.withLock { try body(&_value) } + } +} diff --git a/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift b/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift index 0d2714ca7b02..6c80862c6a0b 100644 --- a/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift +++ b/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/SynchronizedDictionary.swift @@ -6,21 +6,12 @@ import Foundation -internal class SynchronizedDictionary : @unchecked Sendable { +internal final class SynchronizedDictionary: @unchecked Sendable { - private var dictionary = [K: V]() - private let lock = NSRecursiveLock() + private let _state = OpenAPIMutex<[K: V]>([:]) internal subscript(key: K) -> V? { - get { - lock.withLock { - self.dictionary[key] - } - } - set { - lock.withLock { - self.dictionary[key] = newValue - } - } + get { _state.value[key] } + set { _state.withValue { $0[key] = newValue } } } } diff --git a/samples/client/petstore/swift6/validation/.openapi-generator/FILES b/samples/client/petstore/swift6/validation/.openapi-generator/FILES index 04ff438677b7..d68234852319 100644 --- a/samples/client/petstore/swift6/validation/.openapi-generator/FILES +++ b/samples/client/petstore/swift6/validation/.openapi-generator/FILES @@ -12,6 +12,7 @@ PetstoreClient/Classes/OpenAPIs/Infrastructure/JSONDataEncoding.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/JSONEncodingHelper.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/JSONValue.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift +PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenISO8601DateFormatter.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift diff --git a/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift b/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift index e7d8bacb8197..8c73ca6fc6ff 100644 --- a/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift +++ b/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/APIs.swift @@ -10,19 +10,68 @@ import FoundationNetworking #endif open class PetstoreClientAPIConfiguration: @unchecked Sendable { - public var basePath: String - public var customHeaders: [String: String] - public var credential: URLCredential? - public var requestBuilderFactory: RequestBuilderFactory - public var apiResponseQueue: DispatchQueue - public var codableHelper: CodableHelper - - /// Configures the range of HTTP status codes that will result in a successful response + + // MARK: - Private state + + private struct State { + var basePath: String + var customHeaders: [String: String] + var credential: URLCredential? + var requestBuilderFactory: RequestBuilderFactory + var apiResponseQueue: DispatchQueue + var codableHelper: CodableHelper + var successfulStatusCodeRange: Range + var interceptor: OpenAPIInterceptor + } + + private let _state: OpenAPIMutex + + // MARK: - Public interface + + public var basePath: String { + get { _state.value.basePath } + set { _state.withValue { $0.basePath = newValue } } + } + + public var customHeaders: [String: String] { + get { _state.value.customHeaders } + set { _state.withValue { $0.customHeaders = newValue } } + } + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var requestBuilderFactory: RequestBuilderFactory { + get { _state.value.requestBuilderFactory } + set { _state.withValue { $0.requestBuilderFactory = newValue } } + } + + public var apiResponseQueue: DispatchQueue { + get { _state.value.apiResponseQueue } + set { _state.withValue { $0.apiResponseQueue = newValue } } + } + + public var codableHelper: CodableHelper { + get { _state.value.codableHelper } + set { _state.withValue { $0.codableHelper = newValue } } + } + + /// Configures the range of HTTP status codes that will result in a successful response. /// /// If a HTTP status code is outside of this range the response will be interpreted as failed. - public var successfulStatusCodeRange: Range + public var successfulStatusCodeRange: Range { + get { _state.value.successfulStatusCodeRange } + set { _state.withValue { $0.successfulStatusCodeRange = newValue } } + } - public var interceptor: OpenAPIInterceptor + public var interceptor: OpenAPIInterceptor { + get { _state.value.interceptor } + set { _state.withValue { $0.interceptor = newValue } } + } + + // MARK: - Init public init( basePath: String = "http://localhost", @@ -34,22 +83,25 @@ open class PetstoreClientAPIConfiguration: @unchecked Sendable { successfulStatusCodeRange: Range = 200..<300, interceptor: OpenAPIInterceptor = DefaultOpenAPIInterceptor() ) { - self.basePath = basePath - self.customHeaders = customHeaders - self.credential = credential - self.requestBuilderFactory = requestBuilderFactory - self.apiResponseQueue = apiResponseQueue - self.codableHelper = codableHelper - self.successfulStatusCodeRange = successfulStatusCodeRange - self.interceptor = interceptor + _state = OpenAPIMutex(State( + basePath: basePath, + customHeaders: customHeaders, + credential: credential, + requestBuilderFactory: requestBuilderFactory, + apiResponseQueue: apiResponseQueue, + codableHelper: codableHelper, + successfulStatusCodeRange: successfulStatusCodeRange, + interceptor: interceptor + )) } public static let shared = PetstoreClientAPIConfiguration() } open class RequestBuilder: @unchecked Sendable, Identifiable { - public var credential: URLCredential? - public var headers: [String: String] + + // MARK: - Immutable properties + public let parameters: [String: any Sendable]? public let method: String public let URLString: String @@ -57,24 +109,62 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public let requiresAuthentication: Bool public let apiConfiguration: PetstoreClientAPIConfiguration + // MARK: - Private mutable state + + private struct MutableState { + var credential: URLCredential? = nil + var headers: [String: String] + var onProgressReady: ((Progress) -> Void)? = nil + } + + private let _state: OpenAPIMutex + + // MARK: - Public mutable interface + + public var credential: URLCredential? { + get { _state.value.credential } + set { _state.withValue { $0.credential = newValue } } + } + + public var headers: [String: String] { + get { _state.value.headers } + set { _state.withValue { $0.headers = newValue } } + } + /// Optional block to obtain a reference to the request's progress instance when available. - public var onProgressReady: ((Progress) -> Void)? + public var onProgressReady: ((Progress) -> Void)? { + get { _state.value.onProgressReady } + set { _state.withValue { $0.onProgressReady = newValue } } + } + + // MARK: - Init - required public init(method: String, URLString: String, parameters: [String: any Sendable]?, headers: [String: String] = [:], requiresAuthentication: Bool, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared) { + required public init( + method: String, + URLString: String, + parameters: [String: any Sendable]?, + headers: [String: String] = [:], + requiresAuthentication: Bool, + apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared + ) { self.method = method self.URLString = URLString self.parameters = parameters - self.headers = headers self.requiresAuthentication = requiresAuthentication self.apiConfiguration = apiConfiguration + self._state = OpenAPIMutex(MutableState(headers: headers)) addHeaders(apiConfiguration.customHeaders) addCredential() } + // MARK: - Public methods + open func addHeaders(_ aHeaders: [String: String]) { - for (header, value) in aHeaders { - headers[header] = value + _state.withValue { state in + for (header, value) in aHeaders { + state.headers[header] = value + } } } @@ -131,13 +221,15 @@ open class RequestBuilder: @unchecked Sendable, Identifiable { public func addHeader(name: String, value: String) -> Self { if !value.isEmpty { - headers[name] = value + _state.withValue { $0.headers[name] = value } } return self } open func addCredential() { - credential = apiConfiguration.credential + _state.withValue { [apiConfiguration] state in + state.credential = apiConfiguration.credential + } } } diff --git a/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift b/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift index b8990f975bcd..7d6f7a6fd1bd 100644 --- a/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift +++ b/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/CodableHelper.swift @@ -8,37 +8,56 @@ import Foundation open class CodableHelper: @unchecked Sendable { - public init() {} - private var customDateFormatter: DateFormatter? - private var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + // MARK: - Private state + + private struct State { + var customDateFormatter: DateFormatter? + var defaultDateFormatter: DateFormatter = OpenISO8601DateFormatter() + + var customJSONDecoder: JSONDecoder? + var defaultJSONDecoder: JSONDecoder = JSONDecoder() + + var customJSONEncoder: JSONEncoder? + var defaultJSONEncoder: JSONEncoder = JSONEncoder() + + init() { + defaultJSONEncoder.outputFormatting = .prettyPrinted + rebuildDefaultCoders() + } + + mutating func rebuildDefaultCoders() { + defaultJSONDecoder.dateDecodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + defaultJSONEncoder.dateEncodingStrategy = .formatted(customDateFormatter ?? defaultDateFormatter) + } + } + + private let _state = OpenAPIMutex(State()) + + // MARK: - Init - private var customJSONDecoder: JSONDecoder? - private lazy var defaultJSONDecoder: JSONDecoder = { - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .formatted(dateFormatter) - return decoder - }() + public init() {} - private var customJSONEncoder: JSONEncoder? - private lazy var defaultJSONEncoder: JSONEncoder = { - let encoder = JSONEncoder() - encoder.dateEncodingStrategy = .formatted(dateFormatter) - encoder.outputFormatting = .prettyPrinted - return encoder - }() + // MARK: - Public interface public var dateFormatter: DateFormatter { - get { return customDateFormatter ?? defaultDateFormatter } - set { customDateFormatter = newValue } + get { _state.withValue { $0.customDateFormatter ?? $0.defaultDateFormatter } } + set { + _state.withValue { state in + state.customDateFormatter = newValue + state.rebuildDefaultCoders() + } + } } + public var jsonDecoder: JSONDecoder { - get { return customJSONDecoder ?? defaultJSONDecoder } - set { customJSONDecoder = newValue } + get { _state.withValue { $0.customJSONDecoder ?? $0.defaultJSONDecoder } } + set { _state.withValue { $0.customJSONDecoder = newValue } } } + public var jsonEncoder: JSONEncoder { - get { return customJSONEncoder ?? defaultJSONEncoder } - set { customJSONEncoder = newValue } + get { _state.withValue { $0.customJSONEncoder ?? $0.defaultJSONEncoder } } + set { _state.withValue { $0.customJSONEncoder = newValue } } } open func decode(_ type: T.Type, from data: Data) -> Swift.Result where T: Decodable { diff --git a/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift b/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift index f7a9f4f40195..e98056ea6658 100644 --- a/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift +++ b/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/Models.swift @@ -116,25 +116,20 @@ public struct Response { extension Response : Sendable where T : Sendable {} public final class RequestTask: @unchecked Sendable { - private let lock = NSRecursiveLock() - private var task: URLSessionDataTaskProtocol? + private let _state = OpenAPIMutex(nil) internal func set(task: URLSessionDataTaskProtocol) { - lock.withLock { - self.task = task - } + _state.withValue { $0 = task } } internal func get() -> URLSessionDataTaskProtocol? { - lock.withLock { - task - } + _state.value } public func cancel() { - lock.withLock { - task?.cancel() - task = nil + _state.withValue { + $0?.cancel() + $0 = nil } } } diff --git a/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift b/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift new file mode 100644 index 000000000000..d7be0b6bd92e --- /dev/null +++ b/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/OpenAPIMutex.swift @@ -0,0 +1,28 @@ +// OpenAPIMutex.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +internal final class OpenAPIMutex: @unchecked Sendable { + + private var _value: Value + private let lock = NSRecursiveLock() + + internal init(_ value: Value) { + self._value = value + } + + internal var value: Value { + lock.withLock { _value } + } + + @discardableResult + internal func withValue( + _ body: (inout Value) throws -> Result + ) rethrows -> Result { + try lock.withLock { try body(&_value) } + } +} diff --git a/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift b/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift index 0d2714ca7b02..6c80862c6a0b 100644 --- a/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift +++ b/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/SynchronizedDictionary.swift @@ -6,21 +6,12 @@ import Foundation -internal class SynchronizedDictionary : @unchecked Sendable { +internal final class SynchronizedDictionary: @unchecked Sendable { - private var dictionary = [K: V]() - private let lock = NSRecursiveLock() + private let _state = OpenAPIMutex<[K: V]>([:]) internal subscript(key: K) -> V? { - get { - lock.withLock { - self.dictionary[key] - } - } - set { - lock.withLock { - self.dictionary[key] = newValue - } - } + get { _state.value[key] } + set { _state.withValue { $0[key] = newValue } } } } diff --git a/samples/client/petstore/swift6/vaporLibrary/.openapi-generator/FILES b/samples/client/petstore/swift6/vaporLibrary/.openapi-generator/FILES index 7a99b2aa1483..4e8aa3f1bbec 100644 --- a/samples/client/petstore/swift6/vaporLibrary/.openapi-generator/FILES +++ b/samples/client/petstore/swift6/vaporLibrary/.openapi-generator/FILES @@ -11,6 +11,7 @@ Sources/PetstoreClient/APIs/UserAPI.swift Sources/PetstoreClient/Infrastructure/APIs.swift Sources/PetstoreClient/Infrastructure/Extensions.swift Sources/PetstoreClient/Infrastructure/JSONValue.swift +Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift Sources/PetstoreClient/Infrastructure/OpenISO8601DateFormatter.swift Sources/PetstoreClient/Infrastructure/Validation.swift Sources/PetstoreClient/Models/AdditionalPropertiesAnyType.swift diff --git a/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/AnotherFakeAPI.swift b/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/AnotherFakeAPI.swift index 1900176b6f1d..8bdbff42ae16 100644 --- a/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/AnotherFakeAPI.swift +++ b/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/AnotherFakeAPI.swift @@ -18,7 +18,7 @@ open class AnotherFakeAPI { - parameter body: (body) client model - returns: `EventLoopFuture` of `ClientResponse` */ - open class func call123testSpecialTagsRaw(uuidTest: UUID, body: Client, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func call123testSpecialTagsRaw(uuidTest: UUID, body: Client, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/another-fake/dummy" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -51,7 +51,7 @@ open class AnotherFakeAPI { - parameter body: (body) client model - returns: `EventLoopFuture` of `Call123testSpecialTags` */ - open class func call123testSpecialTags(uuidTest: UUID, body: Client, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func call123testSpecialTags(uuidTest: UUID, body: Client, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return call123testSpecialTagsRaw(uuidTest: uuidTest, body: body, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> Call123testSpecialTags in switch response.status.code { case 200: diff --git a/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/FakeAPI.swift b/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/FakeAPI.swift index 649edd9863b4..d9cdaa7a60c8 100644 --- a/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/FakeAPI.swift +++ b/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/FakeAPI.swift @@ -17,7 +17,7 @@ open class FakeAPI { - parameter xmlItem: (body) XmlItem Body - returns: `EventLoopFuture` of `ClientResponse` */ - open class func createXmlItemRaw(xmlItem: XmlItem, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func createXmlItemRaw(xmlItem: XmlItem, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/fake/create_xml_item" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -47,7 +47,7 @@ open class FakeAPI { - parameter xmlItem: (body) XmlItem Body - returns: `EventLoopFuture` of `CreateXmlItem` */ - open class func createXmlItem(xmlItem: XmlItem, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func createXmlItem(xmlItem: XmlItem, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return createXmlItemRaw(xmlItem: xmlItem, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> CreateXmlItem in switch response.status.code { case 200: @@ -64,7 +64,7 @@ open class FakeAPI { - parameter body: (body) Input boolean as post body (optional) - returns: `EventLoopFuture` of `ClientResponse` */ - open class func fakeOuterBooleanSerializeRaw(body: Bool? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func fakeOuterBooleanSerializeRaw(body: Bool? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/fake/outer/boolean" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -95,7 +95,7 @@ open class FakeAPI { - parameter body: (body) Input boolean as post body (optional) - returns: `EventLoopFuture` of `FakeOuterBooleanSerialize` */ - open class func fakeOuterBooleanSerialize(body: Bool? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func fakeOuterBooleanSerialize(body: Bool? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return fakeOuterBooleanSerializeRaw(body: body, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> FakeOuterBooleanSerialize in switch response.status.code { case 200: @@ -112,7 +112,7 @@ open class FakeAPI { - parameter body: (body) Input composite as post body (optional) - returns: `EventLoopFuture` of `ClientResponse` */ - open class func fakeOuterCompositeSerializeRaw(body: OuterComposite? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func fakeOuterCompositeSerializeRaw(body: OuterComposite? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/fake/outer/composite" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -143,7 +143,7 @@ open class FakeAPI { - parameter body: (body) Input composite as post body (optional) - returns: `EventLoopFuture` of `FakeOuterCompositeSerialize` */ - open class func fakeOuterCompositeSerialize(body: OuterComposite? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func fakeOuterCompositeSerialize(body: OuterComposite? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return fakeOuterCompositeSerializeRaw(body: body, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> FakeOuterCompositeSerialize in switch response.status.code { case 200: @@ -160,7 +160,7 @@ open class FakeAPI { - parameter body: (body) Input number as post body (optional) - returns: `EventLoopFuture` of `ClientResponse` */ - open class func fakeOuterNumberSerializeRaw(body: Double? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func fakeOuterNumberSerializeRaw(body: Double? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/fake/outer/number" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -191,7 +191,7 @@ open class FakeAPI { - parameter body: (body) Input number as post body (optional) - returns: `EventLoopFuture` of `FakeOuterNumberSerialize` */ - open class func fakeOuterNumberSerialize(body: Double? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func fakeOuterNumberSerialize(body: Double? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return fakeOuterNumberSerializeRaw(body: body, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> FakeOuterNumberSerialize in switch response.status.code { case 200: @@ -208,7 +208,7 @@ open class FakeAPI { - parameter body: (body) Input string as post body (optional) - returns: `EventLoopFuture` of `ClientResponse` */ - open class func fakeOuterStringSerializeRaw(body: String? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func fakeOuterStringSerializeRaw(body: String? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/fake/outer/string" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -239,7 +239,7 @@ open class FakeAPI { - parameter body: (body) Input string as post body (optional) - returns: `EventLoopFuture` of `FakeOuterStringSerialize` */ - open class func fakeOuterStringSerialize(body: String? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func fakeOuterStringSerialize(body: String? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return fakeOuterStringSerializeRaw(body: body, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> FakeOuterStringSerialize in switch response.status.code { case 200: @@ -256,7 +256,7 @@ open class FakeAPI { - parameter body: (body) - returns: `EventLoopFuture` of `ClientResponse` */ - open class func testBodyWithFileSchemaRaw(body: FileSchemaTestClass, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func testBodyWithFileSchemaRaw(body: FileSchemaTestClass, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/fake/body-with-file-schema" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -285,7 +285,7 @@ open class FakeAPI { - parameter body: (body) - returns: `EventLoopFuture` of `TestBodyWithFileSchema` */ - open class func testBodyWithFileSchema(body: FileSchemaTestClass, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func testBodyWithFileSchema(body: FileSchemaTestClass, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return testBodyWithFileSchemaRaw(body: body, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> TestBodyWithFileSchema in switch response.status.code { case 200: @@ -302,7 +302,7 @@ open class FakeAPI { - parameter body: (body) - returns: `EventLoopFuture` of `ClientResponse` */ - open class func testBodyWithQueryParamsRaw(query: String, body: User, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func testBodyWithQueryParamsRaw(query: String, body: User, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/fake/body-with-query-params" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -338,7 +338,7 @@ open class FakeAPI { - parameter body: (body) - returns: `EventLoopFuture` of `TestBodyWithQueryParams` */ - open class func testBodyWithQueryParams(query: String, body: User, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func testBodyWithQueryParams(query: String, body: User, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return testBodyWithQueryParamsRaw(query: query, body: body, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> TestBodyWithQueryParams in switch response.status.code { case 200: @@ -356,7 +356,7 @@ open class FakeAPI { - parameter body: (body) client model - returns: `EventLoopFuture` of `ClientResponse` */ - open class func testClientModelRaw(body: Client, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func testClientModelRaw(body: Client, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/fake" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -386,7 +386,7 @@ open class FakeAPI { - parameter body: (body) client model - returns: `EventLoopFuture` of `TestClientModel` */ - open class func testClientModel(body: Client, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func testClientModel(body: Client, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return testClientModelRaw(body: body, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> TestClientModel in switch response.status.code { case 200: @@ -420,7 +420,7 @@ open class FakeAPI { - parameter callback: (form) None (optional) - returns: `EventLoopFuture` of `ClientResponse` */ - open class func testEndpointParametersRaw(number: Double, double: Double, patternWithoutDelimiter: String, byte: Data, integer: Int? = nil, int32: Int? = nil, int64: Int64? = nil, float: Float? = nil, string: String? = nil, binary: Data? = nil, date: Date? = nil, dateTime: Date? = nil, password: String? = nil, callback: String? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func testEndpointParametersRaw(number: Double, double: Double, patternWithoutDelimiter: String, byte: Data, integer: Int? = nil, int32: Int? = nil, int64: Int64? = nil, float: Float? = nil, string: String? = nil, binary: Data? = nil, date: Date? = nil, dateTime: Date? = nil, password: String? = nil, callback: String? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/fake" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -483,7 +483,7 @@ open class FakeAPI { - parameter callback: (form) None (optional) - returns: `EventLoopFuture` of `TestEndpointParameters` */ - open class func testEndpointParameters(number: Double, double: Double, patternWithoutDelimiter: String, byte: Data, integer: Int? = nil, int32: Int? = nil, int64: Int64? = nil, float: Float? = nil, string: String? = nil, binary: Data? = nil, date: Date? = nil, dateTime: Date? = nil, password: String? = nil, callback: String? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func testEndpointParameters(number: Double, double: Double, patternWithoutDelimiter: String, byte: Data, integer: Int? = nil, int32: Int? = nil, int64: Int64? = nil, float: Float? = nil, string: String? = nil, binary: Data? = nil, date: Date? = nil, dateTime: Date? = nil, password: String? = nil, callback: String? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return testEndpointParametersRaw(number: number, double: double, patternWithoutDelimiter: patternWithoutDelimiter, byte: byte, integer: integer, int32: int32, int64: int64, float: float, string: string, binary: binary, date: date, dateTime: dateTime, password: password, callback: callback, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> TestEndpointParameters in switch response.status.code { case 400: @@ -577,7 +577,7 @@ open class FakeAPI { - parameter enumFormString: (form) Form parameter enum test (string) (optional, default to .efg) - returns: `EventLoopFuture` of `ClientResponse` */ - open class func testEnumParametersRaw(enumHeaderStringArray: [EnumHeaderStringArray_testEnumParameters]? = nil, enumHeaderString: EnumHeaderString_testEnumParameters? = nil, enumQueryStringArray: [EnumQueryStringArray_testEnumParameters]? = nil, enumQueryString: EnumQueryString_testEnumParameters? = nil, enumQueryInteger: EnumQueryInteger_testEnumParameters? = nil, enumQueryDouble: EnumQueryDouble_testEnumParameters? = nil, enumFormStringArray: [EnumFormStringArray_testEnumParameters]? = nil, enumFormString: EnumFormString_testEnumParameters? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func testEnumParametersRaw(enumHeaderStringArray: [EnumHeaderStringArray_testEnumParameters]? = nil, enumHeaderString: EnumHeaderString_testEnumParameters? = nil, enumQueryStringArray: [EnumQueryStringArray_testEnumParameters]? = nil, enumQueryString: EnumQueryString_testEnumParameters? = nil, enumQueryInteger: EnumQueryInteger_testEnumParameters? = nil, enumQueryDouble: EnumQueryDouble_testEnumParameters? = nil, enumFormStringArray: [EnumFormStringArray_testEnumParameters]? = nil, enumFormString: EnumFormString_testEnumParameters? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/fake" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -636,7 +636,7 @@ open class FakeAPI { - parameter enumFormString: (form) Form parameter enum test (string) (optional, default to .efg) - returns: `EventLoopFuture` of `TestEnumParameters` */ - open class func testEnumParameters(enumHeaderStringArray: [EnumHeaderStringArray_testEnumParameters]? = nil, enumHeaderString: EnumHeaderString_testEnumParameters? = nil, enumQueryStringArray: [EnumQueryStringArray_testEnumParameters]? = nil, enumQueryString: EnumQueryString_testEnumParameters? = nil, enumQueryInteger: EnumQueryInteger_testEnumParameters? = nil, enumQueryDouble: EnumQueryDouble_testEnumParameters? = nil, enumFormStringArray: [EnumFormStringArray_testEnumParameters]? = nil, enumFormString: EnumFormString_testEnumParameters? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func testEnumParameters(enumHeaderStringArray: [EnumHeaderStringArray_testEnumParameters]? = nil, enumHeaderString: EnumHeaderString_testEnumParameters? = nil, enumQueryStringArray: [EnumQueryStringArray_testEnumParameters]? = nil, enumQueryString: EnumQueryString_testEnumParameters? = nil, enumQueryInteger: EnumQueryInteger_testEnumParameters? = nil, enumQueryDouble: EnumQueryDouble_testEnumParameters? = nil, enumFormStringArray: [EnumFormStringArray_testEnumParameters]? = nil, enumFormString: EnumFormString_testEnumParameters? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return testEnumParametersRaw(enumHeaderStringArray: enumHeaderStringArray, enumHeaderString: enumHeaderString, enumQueryStringArray: enumQueryStringArray, enumQueryString: enumQueryString, enumQueryInteger: enumQueryInteger, enumQueryDouble: enumQueryDouble, enumFormStringArray: enumFormStringArray, enumFormString: enumFormString, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> TestEnumParameters in switch response.status.code { case 400: @@ -661,7 +661,7 @@ open class FakeAPI { - parameter int64Group: (query) Integer in group parameters (optional) - returns: `EventLoopFuture` of `ClientResponse` */ - open class func testGroupParametersRaw(requiredStringGroup: Int, requiredBooleanGroup: Bool, requiredInt64Group: Int64, stringGroup: Int? = nil, booleanGroup: Bool? = nil, int64Group: Int64? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func testGroupParametersRaw(requiredStringGroup: Int, requiredBooleanGroup: Bool, requiredInt64Group: Int64, stringGroup: Int? = nil, booleanGroup: Bool? = nil, int64Group: Int64? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/fake" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -712,7 +712,7 @@ open class FakeAPI { - parameter int64Group: (query) Integer in group parameters (optional) - returns: `EventLoopFuture` of `TestGroupParameters` */ - open class func testGroupParameters(requiredStringGroup: Int, requiredBooleanGroup: Bool, requiredInt64Group: Int64, stringGroup: Int? = nil, booleanGroup: Bool? = nil, int64Group: Int64? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func testGroupParameters(requiredStringGroup: Int, requiredBooleanGroup: Bool, requiredInt64Group: Int64, stringGroup: Int? = nil, booleanGroup: Bool? = nil, int64Group: Int64? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return testGroupParametersRaw(requiredStringGroup: requiredStringGroup, requiredBooleanGroup: requiredBooleanGroup, requiredInt64Group: requiredInt64Group, stringGroup: stringGroup, booleanGroup: booleanGroup, int64Group: int64Group, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> TestGroupParameters in switch response.status.code { case 400: @@ -729,7 +729,7 @@ open class FakeAPI { - parameter param: (body) request body - returns: `EventLoopFuture` of `ClientResponse` */ - open class func testInlineAdditionalPropertiesRaw(param: [String: String], headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func testInlineAdditionalPropertiesRaw(param: [String: String], headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/fake/inline-additionalProperties" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -758,7 +758,7 @@ open class FakeAPI { - parameter param: (body) request body - returns: `EventLoopFuture` of `TestInlineAdditionalProperties` */ - open class func testInlineAdditionalProperties(param: [String: String], headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func testInlineAdditionalProperties(param: [String: String], headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return testInlineAdditionalPropertiesRaw(param: param, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> TestInlineAdditionalProperties in switch response.status.code { case 200: @@ -776,7 +776,7 @@ open class FakeAPI { - parameter param2: (form) field2 - returns: `EventLoopFuture` of `ClientResponse` */ - open class func testJsonFormDataRaw(param: String, param2: String, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func testJsonFormDataRaw(param: String, param2: String, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/fake/jsonFormData" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -810,7 +810,7 @@ open class FakeAPI { - parameter param2: (form) field2 - returns: `EventLoopFuture` of `TestJsonFormData` */ - open class func testJsonFormData(param: String, param2: String, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func testJsonFormData(param: String, param2: String, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return testJsonFormDataRaw(param: param, param2: param2, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> TestJsonFormData in switch response.status.code { case 200: @@ -831,7 +831,7 @@ open class FakeAPI { - parameter context: (query) - returns: `EventLoopFuture` of `ClientResponse` */ - open class func testQueryParameterCollectionFormatRaw(pipe: [String], ioutil: [String], http: [String], url: [String], context: [String], headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func testQueryParameterCollectionFormatRaw(pipe: [String], ioutil: [String], http: [String], url: [String], context: [String], headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/fake/test-query-parameters" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -878,7 +878,7 @@ open class FakeAPI { - parameter context: (query) - returns: `EventLoopFuture` of `TestQueryParameterCollectionFormat` */ - open class func testQueryParameterCollectionFormat(pipe: [String], ioutil: [String], http: [String], url: [String], context: [String], headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func testQueryParameterCollectionFormat(pipe: [String], ioutil: [String], http: [String], url: [String], context: [String], headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return testQueryParameterCollectionFormatRaw(pipe: pipe, ioutil: ioutil, http: http, url: url, context: context, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> TestQueryParameterCollectionFormat in switch response.status.code { case 200: diff --git a/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/FakeClassnameTags123API.swift b/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/FakeClassnameTags123API.swift index 352c9326d0ee..3c779ed3b13d 100644 --- a/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/FakeClassnameTags123API.swift +++ b/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/FakeClassnameTags123API.swift @@ -20,7 +20,7 @@ open class FakeClassnameTags123API { - parameter body: (body) client model - returns: `EventLoopFuture` of `ClientResponse` */ - open class func testClassnameRaw(body: Client, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func testClassnameRaw(body: Client, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/fake_classname_test" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -53,7 +53,7 @@ open class FakeClassnameTags123API { - parameter body: (body) client model - returns: `EventLoopFuture` of `TestClassname` */ - open class func testClassname(body: Client, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func testClassname(body: Client, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return testClassnameRaw(body: body, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> TestClassname in switch response.status.code { case 200: diff --git a/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/PetAPI.swift b/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/PetAPI.swift index 70e8d3407a36..f8ef558aad3a 100644 --- a/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/PetAPI.swift +++ b/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/PetAPI.swift @@ -19,7 +19,7 @@ open class PetAPI { - parameter body: (body) Pet object that needs to be added to the store - returns: `EventLoopFuture` of `ClientResponse` */ - open class func addPetRaw(body: Pet, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func addPetRaw(body: Pet, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/pet" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -52,7 +52,7 @@ open class PetAPI { - parameter body: (body) Pet object that needs to be added to the store - returns: `EventLoopFuture` of `AddPet` */ - open class func addPet(body: Pet, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func addPet(body: Pet, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return addPetRaw(body: body, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> AddPet in switch response.status.code { case 200: @@ -75,7 +75,7 @@ open class PetAPI { - parameter apiKey: (header) (optional) - returns: `EventLoopFuture` of `ClientResponse` */ - open class func deletePetRaw(petId: Int64, apiKey: String? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func deletePetRaw(petId: Int64, apiKey: String? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { var localVariablePath = "/pet/{petId}" let petIdPreEscape = String(describing: petId) let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" @@ -113,7 +113,7 @@ open class PetAPI { - parameter apiKey: (header) (optional) - returns: `EventLoopFuture` of `DeletePet` */ - open class func deletePet(petId: Int64, apiKey: String? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func deletePet(petId: Int64, apiKey: String? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return deletePetRaw(petId: petId, apiKey: apiKey, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> DeletePet in switch response.status.code { case 200: @@ -145,7 +145,7 @@ open class PetAPI { - parameter status: (query) Status values that need to be considered for filter - returns: `EventLoopFuture` of `ClientResponse` */ - open class func findPetsByStatusRaw(status: [Status_findPetsByStatus], headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func findPetsByStatusRaw(status: [Status_findPetsByStatus], headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/pet/findByStatus" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -185,7 +185,7 @@ open class PetAPI { - parameter status: (query) Status values that need to be considered for filter - returns: `EventLoopFuture` of `FindPetsByStatus` */ - open class func findPetsByStatus(status: [Status_findPetsByStatus], headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func findPetsByStatus(status: [Status_findPetsByStatus], headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return findPetsByStatusRaw(status: status, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> FindPetsByStatus in switch response.status.code { case 200: @@ -209,7 +209,7 @@ open class PetAPI { - returns: `EventLoopFuture` of `ClientResponse` */ @available(*, deprecated, message: "This operation is deprecated.") - open class func findPetsByTagsRaw(tags: Set, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func findPetsByTagsRaw(tags: Set, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/pet/findByTags" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -250,7 +250,7 @@ open class PetAPI { - returns: `EventLoopFuture` of `FindPetsByTags` */ @available(*, deprecated, message: "This operation is deprecated.") - open class func findPetsByTags(tags: Set, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func findPetsByTags(tags: Set, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return findPetsByTagsRaw(tags: tags, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> FindPetsByTags in switch response.status.code { case 200: @@ -273,7 +273,7 @@ open class PetAPI { - parameter petId: (path) ID of pet to return - returns: `EventLoopFuture` of `ClientResponse` */ - open class func getPetByIdRaw(petId: Int64, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func getPetByIdRaw(petId: Int64, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { var localVariablePath = "/pet/{petId}" let petIdPreEscape = String(describing: petId) let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" @@ -310,7 +310,7 @@ open class PetAPI { - parameter petId: (path) ID of pet to return - returns: `EventLoopFuture` of `GetPetById` */ - open class func getPetById(petId: Int64, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func getPetById(petId: Int64, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return getPetByIdRaw(petId: petId, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> GetPetById in switch response.status.code { case 200: @@ -334,7 +334,7 @@ open class PetAPI { - parameter body: (body) Pet object that needs to be added to the store - returns: `EventLoopFuture` of `ClientResponse` */ - open class func updatePetRaw(body: Pet, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func updatePetRaw(body: Pet, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/pet" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -369,7 +369,7 @@ open class PetAPI { - parameter body: (body) Pet object that needs to be added to the store - returns: `EventLoopFuture` of `UpdatePet` */ - open class func updatePet(body: Pet, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func updatePet(body: Pet, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return updatePetRaw(body: body, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> UpdatePet in switch response.status.code { case 200: @@ -397,7 +397,7 @@ open class PetAPI { - parameter status: (form) Updated status of the pet (optional) - returns: `EventLoopFuture` of `ClientResponse` */ - open class func updatePetWithFormRaw(petId: Int64, name: String? = nil, status: String? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func updatePetWithFormRaw(petId: Int64, name: String? = nil, status: String? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { var localVariablePath = "/pet/{petId}" let petIdPreEscape = String(describing: petId) let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" @@ -438,7 +438,7 @@ open class PetAPI { - parameter status: (form) Updated status of the pet (optional) - returns: `EventLoopFuture` of `UpdatePetWithForm` */ - open class func updatePetWithForm(petId: Int64, name: String? = nil, status: String? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func updatePetWithForm(petId: Int64, name: String? = nil, status: String? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return updatePetWithFormRaw(petId: petId, name: name, status: status, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> UpdatePetWithForm in switch response.status.code { case 405: @@ -460,7 +460,7 @@ open class PetAPI { - parameter file: (form) file to upload (optional) - returns: `EventLoopFuture` of `ClientResponse` */ - open class func uploadFileRaw(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func uploadFileRaw(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { var localVariablePath = "/pet/{petId}/uploadImage" let petIdPreEscape = String(describing: petId) let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" @@ -501,7 +501,7 @@ open class PetAPI { - parameter file: (form) file to upload (optional) - returns: `EventLoopFuture` of `UploadFile` */ - open class func uploadFile(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func uploadFile(petId: Int64, additionalMetadata: String? = nil, file: Data? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return uploadFileRaw(petId: petId, additionalMetadata: additionalMetadata, file: file, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> UploadFile in switch response.status.code { case 200: @@ -523,7 +523,7 @@ open class PetAPI { - parameter additionalMetadata: (form) Additional data to pass to server (optional) - returns: `EventLoopFuture` of `ClientResponse` */ - open class func uploadFileWithRequiredFileRaw(petId: Int64, requiredFile: Data, additionalMetadata: String? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func uploadFileWithRequiredFileRaw(petId: Int64, requiredFile: Data, additionalMetadata: String? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { var localVariablePath = "/fake/{petId}/uploadImageWithRequiredFile" let petIdPreEscape = String(describing: petId) let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" @@ -564,7 +564,7 @@ open class PetAPI { - parameter additionalMetadata: (form) Additional data to pass to server (optional) - returns: `EventLoopFuture` of `UploadFileWithRequiredFile` */ - open class func uploadFileWithRequiredFile(petId: Int64, requiredFile: Data, additionalMetadata: String? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func uploadFileWithRequiredFile(petId: Int64, requiredFile: Data, additionalMetadata: String? = nil, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return uploadFileWithRequiredFileRaw(petId: petId, requiredFile: requiredFile, additionalMetadata: additionalMetadata, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> UploadFileWithRequiredFile in switch response.status.code { case 200: diff --git a/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/StoreAPI.swift b/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/StoreAPI.swift index 8e6b7a55d3ae..ce64814e1550 100644 --- a/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/StoreAPI.swift +++ b/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/StoreAPI.swift @@ -17,7 +17,7 @@ open class StoreAPI { - parameter orderId: (path) ID of the order that needs to be deleted - returns: `EventLoopFuture` of `ClientResponse` */ - open class func deleteOrderRaw(orderId: String, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func deleteOrderRaw(orderId: String, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { var localVariablePath = "/store/order/{order_id}" let orderIdPreEscape = String(describing: orderId) let orderIdPostEscape = orderIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" @@ -50,7 +50,7 @@ open class StoreAPI { - parameter orderId: (path) ID of the order that needs to be deleted - returns: `EventLoopFuture` of `DeleteOrder` */ - open class func deleteOrder(orderId: String, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func deleteOrder(orderId: String, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return deleteOrderRaw(orderId: orderId, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> DeleteOrder in switch response.status.code { case 400: @@ -72,7 +72,7 @@ open class StoreAPI { - name: api_key - returns: `EventLoopFuture` of `ClientResponse` */ - open class func getInventoryRaw(headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func getInventoryRaw(headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/store/inventory" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -103,7 +103,7 @@ open class StoreAPI { - name: api_key - returns: `EventLoopFuture` of `GetInventory` */ - open class func getInventory(headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func getInventory(headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return getInventoryRaw(headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> GetInventory in switch response.status.code { case 200: @@ -121,7 +121,7 @@ open class StoreAPI { - parameter orderId: (path) ID of pet that needs to be fetched - returns: `EventLoopFuture` of `ClientResponse` */ - open class func getOrderByIdRaw(orderId: Int64, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func getOrderByIdRaw(orderId: Int64, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { var localVariablePath = "/store/order/{order_id}" let orderIdPreEscape = String(describing: orderId) let orderIdPostEscape = orderIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" @@ -155,7 +155,7 @@ open class StoreAPI { - parameter orderId: (path) ID of pet that needs to be fetched - returns: `EventLoopFuture` of `GetOrderById` */ - open class func getOrderById(orderId: Int64, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func getOrderById(orderId: Int64, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return getOrderByIdRaw(orderId: orderId, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> GetOrderById in switch response.status.code { case 200: @@ -176,7 +176,7 @@ open class StoreAPI { - parameter body: (body) order placed for purchasing the pet - returns: `EventLoopFuture` of `ClientResponse` */ - open class func placeOrderRaw(body: Order, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func placeOrderRaw(body: Order, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/store/order" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -206,7 +206,7 @@ open class StoreAPI { - parameter body: (body) order placed for purchasing the pet - returns: `EventLoopFuture` of `PlaceOrder` */ - open class func placeOrder(body: Order, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func placeOrder(body: Order, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return placeOrderRaw(body: body, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> PlaceOrder in switch response.status.code { case 200: diff --git a/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/UserAPI.swift b/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/UserAPI.swift index 4f11c38a091e..21def54b7556 100644 --- a/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/UserAPI.swift +++ b/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/APIs/UserAPI.swift @@ -17,7 +17,7 @@ open class UserAPI { - parameter body: (body) Created user object - returns: `EventLoopFuture` of `ClientResponse` */ - open class func createUserRaw(body: User, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func createUserRaw(body: User, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/user" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -46,7 +46,7 @@ open class UserAPI { - parameter body: (body) Created user object - returns: `EventLoopFuture` of `CreateUser` */ - open class func createUser(body: User, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func createUser(body: User, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return createUserRaw(body: body, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> CreateUser in switch response.status.code { default: @@ -61,7 +61,7 @@ open class UserAPI { - parameter body: (body) List of user object - returns: `EventLoopFuture` of `ClientResponse` */ - open class func createUsersWithArrayInputRaw(body: [User], headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func createUsersWithArrayInputRaw(body: [User], headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/user/createWithArray" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -89,7 +89,7 @@ open class UserAPI { - parameter body: (body) List of user object - returns: `EventLoopFuture` of `CreateUsersWithArrayInput` */ - open class func createUsersWithArrayInput(body: [User], headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func createUsersWithArrayInput(body: [User], headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return createUsersWithArrayInputRaw(body: body, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> CreateUsersWithArrayInput in switch response.status.code { default: @@ -104,7 +104,7 @@ open class UserAPI { - parameter body: (body) List of user object - returns: `EventLoopFuture` of `ClientResponse` */ - open class func createUsersWithListInputRaw(body: [User], headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func createUsersWithListInputRaw(body: [User], headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/user/createWithList" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -132,7 +132,7 @@ open class UserAPI { - parameter body: (body) List of user object - returns: `EventLoopFuture` of `CreateUsersWithListInput` */ - open class func createUsersWithListInput(body: [User], headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func createUsersWithListInput(body: [User], headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return createUsersWithListInputRaw(body: body, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> CreateUsersWithListInput in switch response.status.code { default: @@ -148,7 +148,7 @@ open class UserAPI { - parameter username: (path) The name that needs to be deleted - returns: `EventLoopFuture` of `ClientResponse` */ - open class func deleteUserRaw(username: String, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func deleteUserRaw(username: String, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { var localVariablePath = "/user/{username}" let usernamePreEscape = String(describing: username) let usernamePostEscape = usernamePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" @@ -181,7 +181,7 @@ open class UserAPI { - parameter username: (path) The name that needs to be deleted - returns: `EventLoopFuture` of `DeleteUser` */ - open class func deleteUser(username: String, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func deleteUser(username: String, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return deleteUserRaw(username: username, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> DeleteUser in switch response.status.code { case 400: @@ -200,7 +200,7 @@ open class UserAPI { - parameter username: (path) The name that needs to be fetched. Use user1 for testing. - returns: `EventLoopFuture` of `ClientResponse` */ - open class func getUserByNameRaw(username: String, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func getUserByNameRaw(username: String, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { var localVariablePath = "/user/{username}" let usernamePreEscape = String(describing: username) let usernamePostEscape = usernamePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" @@ -233,7 +233,7 @@ open class UserAPI { - parameter username: (path) The name that needs to be fetched. Use user1 for testing. - returns: `EventLoopFuture` of `GetUserByName` */ - open class func getUserByName(username: String, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func getUserByName(username: String, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return getUserByNameRaw(username: username, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> GetUserByName in switch response.status.code { case 200: @@ -256,7 +256,7 @@ open class UserAPI { - parameter password: (query) The password for login in clear text - returns: `EventLoopFuture` of `ClientResponse` */ - open class func loginUserRaw(username: String, password: String, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func loginUserRaw(username: String, password: String, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/user/login" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -296,7 +296,7 @@ open class UserAPI { - parameter password: (query) The password for login in clear text - returns: `EventLoopFuture` of `LoginUser` */ - open class func loginUser(username: String, password: String, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func loginUser(username: String, password: String, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return loginUserRaw(username: username, password: password, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> LoginUser in switch response.status.code { case 200: @@ -314,7 +314,7 @@ open class UserAPI { GET /user/logout - returns: `EventLoopFuture` of `ClientResponse` */ - open class func logoutUserRaw(headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func logoutUserRaw(headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { let localVariablePath = "/user/logout" let localVariableURLString = apiConfiguration.basePath + localVariablePath @@ -340,7 +340,7 @@ open class UserAPI { GET /user/logout - returns: `EventLoopFuture` of `LogoutUser` */ - open class func logoutUser(headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func logoutUser(headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return logoutUserRaw(headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> LogoutUser in switch response.status.code { default: @@ -357,7 +357,7 @@ open class UserAPI { - parameter body: (body) Updated user object - returns: `EventLoopFuture` of `ClientResponse` */ - open class func updateUserRaw(username: String, body: User, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func updateUserRaw(username: String, body: User, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { var localVariablePath = "/user/{username}" let usernamePreEscape = String(describing: username) let usernamePostEscape = usernamePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" @@ -392,7 +392,7 @@ open class UserAPI { - parameter body: (body) Updated user object - returns: `EventLoopFuture` of `UpdateUser` */ - open class func updateUser(username: String, body: User, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { + open class func updateUser(username: String, body: User, headers: HTTPHeaders? = nil, apiConfiguration: PetstoreClientAPIConfiguration = PetstoreClientAPIConfiguration.shared, beforeSend: @Sendable (inout ClientRequest) throws -> () = { _ in }) -> EventLoopFuture { return updateUserRaw(username: username, body: body, headers: headers, apiConfiguration: apiConfiguration, beforeSend: beforeSend).flatMapThrowing { response -> UpdateUser in switch response.status.code { case 400: diff --git a/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/Infrastructure/APIs.swift b/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/Infrastructure/APIs.swift index d6f62668b5d4..4ad1e866717c 100644 --- a/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/Infrastructure/APIs.swift +++ b/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/Infrastructure/APIs.swift @@ -11,11 +11,47 @@ import FoundationNetworking import Vapor open class PetstoreClientAPIConfiguration: @unchecked Sendable { - public var basePath: String - public var customHeaders: HTTPHeaders - public var apiClient: Vapor.Client? - public var apiWrapper: @Sendable (inout Vapor.ClientRequest) throws -> () - public var contentConfiguration: ContentConfiguration + + // MARK: - Private state + + private struct State { + var basePath: String + var customHeaders: HTTPHeaders + var apiClient: Vapor.Client? + var apiWrapper: @Sendable (inout Vapor.ClientRequest) throws -> () + var contentConfiguration: ContentConfiguration + } + + private let _state: OpenAPIMutex + + // MARK: - Public interface + + public var basePath: String { + get { _state.value.basePath } + set { _state.withValue { $0.basePath = newValue } } + } + + public var customHeaders: HTTPHeaders { + get { _state.value.customHeaders } + set { _state.withValue { $0.customHeaders = newValue } } + } + + public var apiClient: Vapor.Client? { + get { _state.value.apiClient } + set { _state.withValue { $0.apiClient = newValue } } + } + + public var apiWrapper: @Sendable (inout Vapor.ClientRequest) throws -> () { + get { _state.value.apiWrapper } + set { _state.withValue { $0.apiWrapper = newValue } } + } + + public var contentConfiguration: ContentConfiguration { + get { _state.value.contentConfiguration } + set { _state.withValue { $0.contentConfiguration = newValue } } + } + + // MARK: - Init public init( basePath: String = "http://petstore.swagger.io:80/v2", @@ -24,11 +60,13 @@ open class PetstoreClientAPIConfiguration: @unchecked Sendable { apiWrapper: @escaping @Sendable (inout Vapor.ClientRequest) throws -> () = { _ in }, contentConfiguration: ContentConfiguration = ContentConfiguration.default() ) { - self.basePath = basePath - self.customHeaders = customHeaders - self.apiClient = apiClient - self.apiWrapper = apiWrapper - self.contentConfiguration = contentConfiguration + _state = OpenAPIMutex(State( + basePath: basePath, + customHeaders: customHeaders, + apiClient: apiClient, + apiWrapper: apiWrapper, + contentConfiguration: contentConfiguration + )) } public static let shared = PetstoreClientAPIConfiguration() diff --git a/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift b/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift new file mode 100644 index 000000000000..d7be0b6bd92e --- /dev/null +++ b/samples/client/petstore/swift6/vaporLibrary/Sources/PetstoreClient/Infrastructure/OpenAPIMutex.swift @@ -0,0 +1,28 @@ +// OpenAPIMutex.swift +// +// Generated by openapi-generator +// https://openapi-generator.tech +// + +import Foundation + +internal final class OpenAPIMutex: @unchecked Sendable { + + private var _value: Value + private let lock = NSRecursiveLock() + + internal init(_ value: Value) { + self._value = value + } + + internal var value: Value { + lock.withLock { _value } + } + + @discardableResult + internal func withValue( + _ body: (inout Value) throws -> Result + ) rethrows -> Result { + try lock.withLock { try body(&_value) } + } +}