diff --git a/Changelog.md b/Changelog.md index a7856124..dc1cc76e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,5 @@ ## Changelog ### Next -- Updated CI to make sure PR requests are reviewed using Danger. \ No newline at end of file +- Updated CI to make sure PR requests are reviewed using Danger. +- Removed custom Result type. diff --git a/Example/CocoaPods-AppStoreConnect-Swift-SDK/Tests/APIProviderTests.swift b/Example/CocoaPods-AppStoreConnect-Swift-SDK/Tests/APIProviderTests.swift index 2867dba7..88017641 100644 --- a/Example/CocoaPods-AppStoreConnect-Swift-SDK/Tests/APIProviderTests.swift +++ b/Example/CocoaPods-AppStoreConnect-Swift-SDK/Tests/APIProviderTests.swift @@ -12,17 +12,17 @@ final class APIProviderTests: XCTestCase { private struct MockRequestExecutor: RequestExecutor { - let expectedResponse: Result + let expectedResponse: Result - init(expectedResponse: Result) { + init(expectedResponse: Result) { self.expectedResponse = expectedResponse } - func execute(_ urlRequest: URLRequest, completion: @escaping (Result) -> Void) { + func execute(_ urlRequest: URLRequest, completion: @escaping (Result) -> Void) { completion(expectedResponse) } - func retrieve(_ url: URL, completion: @escaping (Result) -> Void) { + func retrieve(_ url: URL, completion: @escaping (Result) -> Void) { completion(expectedResponse) } } diff --git a/Sources/APIProvider.swift b/Sources/APIProvider.swift index 2e642648..1f1084d7 100644 --- a/Sources/APIProvider.swift +++ b/Sources/APIProvider.swift @@ -7,7 +7,7 @@ import Foundation -public typealias RequestCompletionHandler = (Result) -> Void +public typealias RequestCompletionHandler = (Result) -> Void /// The configuration needed to set up the API Provider including all needed information for performing API requests. public struct APIConfiguration { @@ -153,7 +153,7 @@ private extension APIProvider { /// /// - Parameter result: A result type containing either the network response or an error /// - Returns: A result type containing either the decoded type or an error - func mapResponse(_ result: Result) -> Result { + func mapResponse(_ result: Result) -> Result { switch result { case .success(let response): guard let data = response.data, 200..<300 ~= response.statusCode else { @@ -173,7 +173,7 @@ private extension APIProvider { /// /// - Parameter result: A result type containing either the network response or an error /// - Returns: A result type containing either void or an error - func mapVoidResponse(_ result: Result) -> Result { + func mapVoidResponse(_ result: Result) -> Result { switch result { case .success(let response): guard 200..<300 ~= response.statusCode else { diff --git a/Sources/DefaultRequestExecutor.swift b/Sources/DefaultRequestExecutor.swift index d7ce07eb..ba0f4493 100644 --- a/Sources/DefaultRequestExecutor.swift +++ b/Sources/DefaultRequestExecutor.swift @@ -26,7 +26,7 @@ public final class DefaultRequestExecutor: RequestExecutor { /// - Parameters: /// - urlRequest: The URLRequest to execute /// - completion: A result type containing eiter the response or an error - public func execute(_ urlRequest: URLRequest, completion: @escaping (Result) -> Void) { + public func execute(_ urlRequest: URLRequest, completion: @escaping (Result) -> Void) { urlSession.dataTask(with: urlRequest) { data, response, error in completion(mapResponse(data: data, urlResponse: response, error: error)) }.resume() @@ -37,7 +37,7 @@ public final class DefaultRequestExecutor: RequestExecutor { /// - Parameters: /// - url: The URL where the resource is located /// - completion: A result type containing eiter the response or an error - public func retrieve(_ url: URL, completion: @escaping (Result) -> Void) { + public func retrieve(_ url: URL, completion: @escaping (Result) -> Void) { urlSession.dataTask(with: url) { data, response, error in completion(mapResponse(data: data, urlResponse: response, error: error)) }.resume() @@ -53,7 +53,7 @@ public final class DefaultRequestExecutor: RequestExecutor { /// - urlResponse: URLResponse returned from an URLSession data task /// - error: Error returned from an URLSession data task /// - completion: A result type containing eiter the response or an error -func mapResponse(data: Data?, urlResponse: URLResponse?, error: Error?) -> Result { +func mapResponse(data: Data?, urlResponse: URLResponse?, error: Error?) -> Result { if let error = error { return .failure(error) } else { diff --git a/Sources/RequestExecutor.swift b/Sources/RequestExecutor.swift index 0b618e4b..c8a184ac 100644 --- a/Sources/RequestExecutor.swift +++ b/Sources/RequestExecutor.swift @@ -24,8 +24,8 @@ public struct Response { public protocol RequestExecutor { /// Performs a URLRequest and returns a result - func execute(_ urlRequest: URLRequest, completion: @escaping (Result) -> Void) + func execute(_ urlRequest: URLRequest, completion: @escaping (Result) -> Void) /// Retrieves the content of a given URL - func retrieve(_ url: URL, completion: @escaping (Result) -> Void) + func retrieve(_ url: URL, completion: @escaping (Result) -> Void) } diff --git a/Sources/Result.swift b/Sources/Result.swift index 03078cff..1f56d5f9 100644 --- a/Sources/Result.swift +++ b/Sources/Result.swift @@ -1,41 +1,5 @@ -// -// Result.swift -// -// Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// -// swiftlint:disable nslog_prohibited - -import Foundation - -/// Used to represent whether a request was successful or encountered an error. -/// -/// - success: The request and all post processing operations were successful resulting in the serialization of the -/// provided associated value. -/// -/// - failure: The request encountered an error resulting in a failure. The associated values are the original data -/// provided by the server as well as the error that caused the failure. -public enum Result { - case success(Value) - case failure(Error) - +extension Result { + /// Returns `true` if the result is a success, `false` otherwise. public var isSuccess: Bool { switch self { @@ -52,7 +16,7 @@ public enum Result { } /// Returns the associated value if the result is a success, `nil` otherwise. - public var value: Value? { + public var value: Success? { switch self { case .success(let value): return value @@ -71,231 +35,3 @@ public enum Result { } } } - -// MARK: - CustomStringConvertible - -extension Result: CustomStringConvertible { - /// The textual representation used when written to an output stream, which includes whether the result was a - /// success or failure. - public var description: String { - switch self { - case .success: - return "SUCCESS" - case .failure: - return "FAILURE" - } - } -} - -// MARK: - CustomDebugStringConvertible - -extension Result: CustomDebugStringConvertible { - /// The debug textual representation used when written to an output stream, which includes whether the result was a - /// success or failure in addition to the value or error. - public var debugDescription: String { - switch self { - case .success(let value): - return "SUCCESS: \(value)" - case .failure(let error): - return "FAILURE: \(error)" - } - } -} - -// MARK: - Functional APIs - -extension Result { - /// Creates a `Result` instance from the result of a closure. - /// - /// A failure result is created when the closure throws, and a success result is created when the closure - /// succeeds without throwing an error. - /// - /// func someString() throws -> String { ... } - /// - /// let result = Result(value: { - /// return try someString() - /// }) - /// - /// // The type of result is Result - /// - /// The trailing closure syntax is also supported: - /// - /// let result = Result { try someString() } - /// - /// - parameter value: The closure to execute and create the result for. - public init(value: () throws -> Value) { - do { - self = try .success(value()) - } catch { - self = .failure(error) - } - } - - /// Returns the success value, or throws the failure error. - /// - /// let possibleString: Result = .success("success") - /// try print(possibleString.unwrap()) - /// // Prints "success" - /// - /// let noString: Result = .failure(error) - /// try print(noString.unwrap()) - /// // Throws error - public func unwrap() throws -> Value { - switch self { - case .success(let value): - return value - case .failure(let error): - throw error - } - } - - /// Evaluates the specified closure when the `Result` is a success, passing the unwrapped value as a parameter. - /// - /// Use the `map` method with a closure that does not throw. For example: - /// - /// let possibleData: Result = .success(Data()) - /// let possibleInt = possibleData.map { $0.count } - /// try print(possibleInt.unwrap()) - /// // Prints "0" - /// - /// let noData: Result = .failure(error) - /// let noInt = noData.map { $0.count } - /// try print(noInt.unwrap()) - /// // Throws error - /// - /// - parameter transform: A closure that takes the success value of the `Result` instance. - /// - /// - returns: A `Result` containing the result of the given closure. If this instance is a failure, returns the - /// same failure. - public func map(_ transform: (Value) -> T) -> Result { - switch self { - case .success(let value): - return .success(transform(value)) - case .failure(let error): - return .failure(error) - } - } - - /// Evaluates the specified closure when the `Result` is a success, passing the unwrapped value as a parameter. - /// - /// Use the `flatMap` method with a closure that may throw an error. For example: - /// - /// let possibleData: Result = .success(Data(...)) - /// let possibleObject = possibleData.flatMap { - /// try JSONSerialization.jsonObject(with: $0) - /// } - /// - /// - parameter transform: A closure that takes the success value of the instance. - /// - /// - returns: A `Result` containing the result of the given closure. If this instance is a failure, returns the - /// same failure. - public func flatMap(_ transform: (Value) throws -> T) -> Result { - switch self { - case .success(let value): - do { - return try .success(transform(value)) - } catch { - return .failure(error) - } - case .failure(let error): - return .failure(error) - } - } - - /// Evaluates the specified closure when the `Result` is a failure, passing the unwrapped error as a parameter. - /// - /// Use the `mapError` function with a closure that does not throw. For example: - /// - /// let possibleData: Result = .failure(someError) - /// let withMyError: Result = possibleData.mapError { MyError.error($0) } - /// - /// - Parameter transform: A closure that takes the error of the instance. - /// - Returns: A `Result` instance containing the result of the transform. If this instance is a success, returns - /// the same instance. - public func mapError(_ transform: (Error) -> T) -> Result { - switch self { - case .failure(let error): - return .failure(transform(error)) - case .success: - return self - } - } - - /// Evaluates the specified closure when the `Result` is a failure, passing the unwrapped error as a parameter. - /// - /// Use the `flatMapError` function with a closure that may throw an error. For example: - /// - /// let possibleData: Result = .success(Data(...)) - /// let possibleObject = possibleData.flatMapError { - /// try someFailableFunction(taking: $0) - /// } - /// - /// - Parameter transform: A throwing closure that takes the error of the instance. - /// - /// - Returns: A `Result` instance containing the result of the transform. If this instance is a success, returns - /// the same instance. - public func flatMapError(_ transform: (Error) throws -> T) -> Result { - switch self { - case .failure(let error): - do { - return try .failure(transform(error)) - } catch { - return .failure(error) - } - case .success: - return self - } - } - - /// Evaluates the specified closure when the `Result` is a success, passing the unwrapped value as a parameter. - /// - /// Use the `withValue` function to evaluate the passed closure without modifying the `Result` instance. - /// - /// - Parameter closure: A closure that takes the success value of this instance. - /// - Returns: This `Result` instance, unmodified. - @discardableResult - public func withValue(_ closure: (Value) throws -> Void) rethrows -> Result { - if case let .success(value) = self { try closure(value) } - - return self - } - - /// Evaluates the specified closure when the `Result` is a failure, passing the unwrapped error as a parameter. - /// - /// Use the `withError` function to evaluate the passed closure without modifying the `Result` instance. - /// - /// - Parameter closure: A closure that takes the success value of this instance. - /// - Returns: This `Result` instance, unmodified. - @discardableResult - public func withError(_ closure: (Error) throws -> Void) rethrows -> Result { - if case let .failure(error) = self { try closure(error) } - - return self - } - - /// Evaluates the specified closure when the `Result` is a success. - /// - /// Use the `ifSuccess` function to evaluate the passed closure without modifying the `Result` instance. - /// - /// - Parameter closure: A `Void` closure. - /// - Returns: This `Result` instance, unmodified. - @discardableResult - public func ifSuccess(_ closure: () throws -> Void) rethrows -> Result { - if isSuccess { try closure() } - - return self - } - - /// Evaluates the specified closure when the `Result` is a failure. - /// - /// Use the `ifFailure` function to evaluate the passed closure without modifying the `Result` instance. - /// - /// - Parameter closure: A `Void` closure. - /// - Returns: This `Result` instance, unmodified. - @discardableResult - public func ifFailure(_ closure: () throws -> Void) rethrows -> Result { - if isFailure { try closure() } - - return self - } -}