4 // Copyright (c) 2014-2017 Alamofire Software Foundation (http://alamofire.org/)
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // of this software and associated documentation files (the "Software"), to deal
8 // in the Software without restriction, including without limitation the rights
9 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 // copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 /// Used to represent whether a request was successful or encountered an error.
29 /// - success: The request and all post processing operations were successful resulting in the serialization of the
30 /// provided associated value.
32 /// - failure: The request encountered an error resulting in a failure. The associated values are the original data
33 /// provided by the server as well as the error that caused the failure.
34 public enum Result<Value> {
38 /// Returns `true` if the result is a success, `false` otherwise.
39 public var isSuccess: Bool {
48 /// Returns `true` if the result is a failure, `false` otherwise.
49 public var isFailure: Bool {
53 /// Returns the associated value if the result is a success, `nil` otherwise.
54 public var value: Value? {
56 case .success(let value):
63 /// Returns the associated error value if the result is a failure, `nil` otherwise.
64 public var error: Error? {
68 case .failure(let error):
74 // MARK: - CustomStringConvertible
76 extension Result: CustomStringConvertible {
77 /// The textual representation used when written to an output stream, which includes whether the result was a
78 /// success or failure.
79 public var description: String {
89 // MARK: - CustomDebugStringConvertible
91 extension Result: CustomDebugStringConvertible {
92 /// The debug textual representation used when written to an output stream, which includes whether the result was a
93 /// success or failure in addition to the value or error.
94 public var debugDescription: String {
96 case .success(let value):
97 return "SUCCESS: \(value)"
98 case .failure(let error):
99 return "FAILURE: \(error)"
104 // MARK: - Functional APIs
107 /// Creates a `Result` instance from the result of a closure.
109 /// A failure result is created when the closure throws, and a success result is created when the closure
110 /// succeeds without throwing an error.
112 /// func someString() throws -> String { ... }
114 /// let result = Result(value: {
115 /// return try someString()
118 /// // The type of result is Result<String>
120 /// The trailing closure syntax is also supported:
122 /// let result = Result { try someString() }
124 /// - parameter value: The closure to execute and create the result for.
125 public init(value: () throws -> Value) {
127 self = try .success(value())
129 self = .failure(error)
133 /// Returns the success value, or throws the failure error.
135 /// let possibleString: Result<String> = .success("success")
136 /// try print(possibleString.unwrap())
137 /// // Prints "success"
139 /// let noString: Result<String> = .failure(error)
140 /// try print(noString.unwrap())
142 public func unwrap() throws -> Value {
144 case .success(let value):
146 case .failure(let error):
151 /// Evaluates the specified closure when the `Result` is a success, passing the unwrapped value as a parameter.
153 /// Use the `map` method with a closure that does not throw. For example:
155 /// let possibleData: Result<Data> = .success(Data())
156 /// let possibleInt = possibleData.map { $0.count }
157 /// try print(possibleInt.unwrap())
160 /// let noData: Result<Data> = .failure(error)
161 /// let noInt = noData.map { $0.count }
162 /// try print(noInt.unwrap())
165 /// - parameter transform: A closure that takes the success value of the `Result` instance.
167 /// - returns: A `Result` containing the result of the given closure. If this instance is a failure, returns the
169 public func map<T>(_ transform: (Value) -> T) -> Result<T> {
171 case .success(let value):
172 return .success(transform(value))
173 case .failure(let error):
174 return .failure(error)
178 /// Evaluates the specified closure when the `Result` is a success, passing the unwrapped value as a parameter.
180 /// Use the `flatMap` method with a closure that may throw an error. For example:
182 /// let possibleData: Result<Data> = .success(Data(...))
183 /// let possibleObject = possibleData.flatMap {
184 /// try JSONSerialization.jsonObject(with: $0)
187 /// - parameter transform: A closure that takes the success value of the instance.
189 /// - returns: A `Result` containing the result of the given closure. If this instance is a failure, returns the
191 public func flatMap<T>(_ transform: (Value) throws -> T) -> Result<T> {
193 case .success(let value):
195 return try .success(transform(value))
197 return .failure(error)
199 case .failure(let error):
200 return .failure(error)
204 /// Evaluates the specified closure when the `Result` is a failure, passing the unwrapped error as a parameter.
206 /// Use the `mapError` function with a closure that does not throw. For example:
208 /// let possibleData: Result<Data> = .failure(someError)
209 /// let withMyError: Result<Data> = possibleData.mapError { MyError.error($0) }
211 /// - Parameter transform: A closure that takes the error of the instance.
212 /// - Returns: A `Result` instance containing the result of the transform. If this instance is a success, returns
213 /// the same instance.
214 public func mapError<T: Error>(_ transform: (Error) -> T) -> Result {
216 case .failure(let error):
217 return .failure(transform(error))
223 /// Evaluates the specified closure when the `Result` is a failure, passing the unwrapped error as a parameter.
225 /// Use the `flatMapError` function with a closure that may throw an error. For example:
227 /// let possibleData: Result<Data> = .success(Data(...))
228 /// let possibleObject = possibleData.flatMapError {
229 /// try someFailableFunction(taking: $0)
232 /// - Parameter transform: A throwing closure that takes the error of the instance.
234 /// - Returns: A `Result` instance containing the result of the transform. If this instance is a success, returns
235 /// the same instance.
236 public func flatMapError<T: Error>(_ transform: (Error) throws -> T) -> Result {
238 case .failure(let error):
240 return try .failure(transform(error))
242 return .failure(error)
249 /// Evaluates the specified closure when the `Result` is a success, passing the unwrapped value as a parameter.
251 /// Use the `withValue` function to evaluate the passed closure without modifying the `Result` instance.
253 /// - Parameter closure: A closure that takes the success value of this instance.
254 /// - Returns: This `Result` instance, unmodified.
256 public func withValue(_ closure: (Value) -> Void) -> Result {
257 if case let .success(value) = self { closure(value) }
262 /// Evaluates the specified closure when the `Result` is a failure, passing the unwrapped error as a parameter.
264 /// Use the `withError` function to evaluate the passed closure without modifying the `Result` instance.
266 /// - Parameter closure: A closure that takes the success value of this instance.
267 /// - Returns: This `Result` instance, unmodified.
269 public func withError(_ closure: (Error) -> Void) -> Result {
270 if case let .failure(error) = self { closure(error) }
275 /// Evaluates the specified closure when the `Result` is a success.
277 /// Use the `ifSuccess` function to evaluate the passed closure without modifying the `Result` instance.
279 /// - Parameter closure: A `Void` closure.
280 /// - Returns: This `Result` instance, unmodified.
282 public func ifSuccess(_ closure: () -> Void) -> Result {
283 if isSuccess { closure() }
288 /// Evaluates the specified closure when the `Result` is a failure.
290 /// Use the `ifFailure` function to evaluate the passed closure without modifying the `Result` instance.
292 /// - Parameter closure: A `Void` closure.
293 /// - Returns: This `Result` instance, unmodified.
295 public func ifFailure(_ closure: () -> Void) -> Result {
296 if isFailure { closure() }