--- /dev/null
+//
+// Result.swift
+//
+// Copyright (c) 2014-2017 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)
+ }
+ }
+
+ /// 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<Data> = .failure(someError)
+ /// let withMyError: Result<Data> = 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<T: Error>(_ 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<Data> = .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<T: Error>(_ 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) -> Void) -> Result {
+ if case let .success(value) = self { 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) -> Void) -> Result {
+ if case let .failure(error) = self { 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: () -> Void) -> Result {
+ if isSuccess { 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: () -> Void) -> Result {
+ if isFailure { closure() }
+
+ return self
+ }
+}