From db7e6b5d4b017a76f6c55ffe00a1c9668d2d5af2 Mon Sep 17 00:00:00 2001 From: Stefano Bertagno Date: Fri, 27 Aug 2021 22:09:57 +0200 Subject: [PATCH] fix: add completion-based future --- .../Receivable/Receivables+Future.swift | 25 +++++++++++++++++++ .../Async/URLSessionAsyncReceivable.swift | 15 +++++++++++ .../Combine/URLSessionCombineReceivable.swift | 9 +++++++ .../URLSessionCompletionReceivable.swift | 12 ++++++++- 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 Sources/Requests/Receivable/Receivables+Future.swift diff --git a/Sources/Requests/Receivable/Receivables+Future.swift b/Sources/Requests/Receivable/Receivables+Future.swift new file mode 100644 index 00000000..07bf1a25 --- /dev/null +++ b/Sources/Requests/Receivable/Receivables+Future.swift @@ -0,0 +1,25 @@ +// +// Receivables+Future.swift +// ComposableRequest +// +// Created by Stefano Bertagno on 27/08/21. +// + +import Foundation + +public extension Receivables { + /// A `struct` defining a future receivable. + struct Future: Receivable { + /// The completion handler. + public let completion: (@escaping (Result) -> Void) -> Void + + /// Init. + /// + /// - parameters: + /// - requester: A valid `Requester`. + /// - completion: A valid completion handler. + public init(with requester: Requester, _ completion: @escaping (@escaping (Result) -> Void) -> Void) { + self.completion = completion + } + } +} diff --git a/Sources/Requests/Requester/Async/URLSessionAsyncReceivable.swift b/Sources/Requests/Requester/Async/URLSessionAsyncReceivable.swift index be43c61e..0b9e790e 100644 --- a/Sources/Requests/Requester/Async/URLSessionAsyncReceivable.swift +++ b/Sources/Requests/Requester/Async/URLSessionAsyncReceivable.swift @@ -84,6 +84,21 @@ where Parent: URLSessionAsyncReceivable { } } +@available(iOS 15, macOS 12, watchOS 8, tvOS 15, *) +extension Receivables.Future: URLSessionAsyncReceivable, URLSessionAsyncMockReceivable +where Requester.Output: URLSessionAsyncReceivable { + // swiftlint:disable empty_parentheses_with_trailing_closure + /// The underlying response. + public var response: URLSessionAsyncRequester.Response { + .init(priority: nil) { + try await withCheckedContinuation { resolve in + self.completion() { resolve.resume(returning: $0) } + }.get() + } + } + // swiftlint:enable empty_parentheses_with_trailing_closure +} + @available(iOS 15, macOS 12, watchOS 8, tvOS 15, *) extension Receivables.If: URLSessionAsyncReceivable, URLSessionAsyncMockReceivable where O1: URLSessionAsyncReceivable, O2: URLSessionAsyncReceivable { diff --git a/Sources/Requests/Requester/Combine/URLSessionCombineReceivable.swift b/Sources/Requests/Requester/Combine/URLSessionCombineReceivable.swift index 3dc9a7b4..78f1bcdf 100644 --- a/Sources/Requests/Requester/Combine/URLSessionCombineReceivable.swift +++ b/Sources/Requests/Requester/Combine/URLSessionCombineReceivable.swift @@ -73,6 +73,15 @@ where Parent: URLSessionCombineReceivable { } } +@available(iOS 13, macOS 10.15, tvOS 13, watchOS 6, *) +extension Receivables.Future: URLSessionCombineReceivable, URLSessionCombineMockReceivable +where Requester: URLSessionCombineReceivable { + /// The underlying response. + public var response: URLSessionCombineRequester.Response { + .init(publisher: Future { resolve in self.completion { resolve($0) } }) + } +} + @available(iOS 13, macOS 10.15, tvOS 13, watchOS 6, *) extension Receivables.If: URLSessionCombineReceivable, URLSessionCombineMockReceivable where O1: URLSessionCombineReceivable, O2: URLSessionCombineReceivable { diff --git a/Sources/Requests/Requester/Completion/URLSessionCompletionReceivable.swift b/Sources/Requests/Requester/Completion/URLSessionCompletionReceivable.swift index 9536e294..a7bcd738 100644 --- a/Sources/Requests/Requester/Completion/URLSessionCompletionReceivable.swift +++ b/Sources/Requests/Requester/Completion/URLSessionCompletionReceivable.swift @@ -79,6 +79,16 @@ where Parent: URLSessionCompletionReceivable { } } +extension Receivables.Future: URLSessionCompletionReceivable, URLSessionCompletionMockReceivable +where Requester.Output: URLSessionCompletionReceivable { + /// The response. + public var response: URLSessionCompletionRequester.Response { + let promise = Promise() + completion { promise.resolve(result: $0) } + return .init(future: promise.future) + } +} + extension Receivables.If: URLSessionCompletionReceivable, URLSessionCompletionMockReceivable where O1: URLSessionCompletionReceivable, O2: URLSessionCompletionReceivable { /// The response. @@ -107,7 +117,7 @@ extension Receivables.Once: URLSessionCompletionReceivable, URLSessionCompletion where Requester.Output: URLSessionCompletionReceivable { /// The response. public var response: URLSessionCompletionRequester.Response { - .init(task: nil, future: .init(result: result)) + .init(future: .init(result: result)) } }