Nenhuma Descrição

Result.swift 6.9KB

    // // Result.swift // // Copyright (c) 2014-2016 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. // 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<Value> { case success(Value) case failure(Error) /// Returns `true` if the result is a success, `false` otherwise. public var isSuccess: Bool { switch self { case .success: return true case .failure: return false } } /// Returns `true` if the result is a failure, `false` otherwise. public var isFailure: Bool { return !isSuccess } /// Returns the associated value if the result is a success, `nil` otherwise. public var value: Value? { switch self { case .success(let value): return value case .failure: return nil } } /// Returns the associated error value if the result is a failure, `nil` otherwise. public var error: Error? { switch self { case .success: return nil case .failure(let error): return error } } } // 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<String> /// /// 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<String> = .success("success") /// try print(possibleString.unwrap()) /// // Prints "success" /// /// let noString: Result<String> = .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<Data> = .success(Data()) /// let possibleInt = possibleData.map { $0.count } /// try print(possibleInt.unwrap()) /// // Prints "0" /// /// let noData: Result<Data> = .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<T>(_ transform: (Value) -> T) -> Result<T> { 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<Data> = .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<T>(_ transform: (Value) throws -> T) -> Result<T> { switch self { case .success(let value): do { return try .success(transform(value)) } catch { return .failure(error) } case .failure(let error): return .failure(error) } } }