| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- //
- // Result.swift
- // Kingfisher
- //
- // Created by onevcat on 2018/09/22.
- //
- // Copyright (c) 2018 Wei Wang <onevcat@gmail.com>
- //
- // 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
- // This is a copy from https://github.com/apple/swift/pull/19982
- // If this PR is merged to stblib later, we may need to remove these content by a Swift version flag.
- /// A value that represents either a success or failure, capturing associated
- /// values in both cases.
- public enum Result<Value, Error> {
- /// A success, storing a `Value`.
- case success(Value)
-
- /// A failure, storing an `Error`.
- case failure(Error)
-
- /// The stored value of a successful `Result`. `nil` if the `Result` was a
- /// failure.
- public var value: Value? {
- switch self {
- case let .success(value):
- return value
- case .failure:
- return nil
- }
- }
-
- /// The stored value of a failure `Result`. `nil` if the `Result` was a
- /// success.
- public var error: Error? {
- switch self {
- case let .failure(error):
- return error
- case .success:
- return nil
- }
- }
-
- /// A Boolean value indicating whether the `Result` as a success.
- public var isSuccess: Bool {
- switch self {
- case .success:
- return true
- case .failure:
- return false
- }
- }
-
- /// Evaluates the given transform closure when this `Result` instance is
- /// `.success`, passing the value as a parameter.
- ///
- /// Use the `map` method with a closure that returns a non-`Result` value.
- ///
- /// - Parameter transform: A closure that takes the successful value of the
- /// instance.
- /// - Returns: A new `Result` instance with the result of the transform, if
- /// it was applied.
- public func map<NewValue>(
- _ transform: (Value) -> NewValue
- ) -> Result<NewValue, Error> {
- switch self {
- case let .success(value):
- return .success(transform(value))
- case let .failure(error):
- return .failure(error)
- }
- }
-
- /// Evaluates the given transform closure when this `Result` instance is
- /// `.failure`, passing the error as a parameter.
- ///
- /// Use the `mapError` method with a closure that returns a non-`Result`
- /// value.
- ///
- /// - Parameter transform: A closure that takes the failure value of the
- /// instance.
- /// - Returns: A new `Result` instance with the result of the transform, if
- /// it was applied.
- public func mapError<NewError>(
- _ transform: (Error) -> NewError
- ) -> Result<Value, NewError> {
- switch self {
- case let .success(value):
- return .success(value)
- case let .failure(error):
- return .failure(transform(error))
- }
- }
-
- /// Evaluates the given transform closure when this `Result` instance is
- /// `.success`, passing the value as a parameter and flattening the result.
- ///
- /// - Parameter transform: A closure that takes the successful value of the
- /// instance.
- /// - Returns: A new `Result` instance, either from the transform or from
- /// the previous error value.
- public func flatMap<NewValue>(
- _ transform: (Value) -> Result<NewValue, Error>
- ) -> Result<NewValue, Error> {
- switch self {
- case let .success(value):
- return transform(value)
- case let .failure(error):
- return .failure(error)
- }
- }
-
- /// Evaluates the given transform closure when this `Result` instance is
- /// `.failure`, passing the error as a parameter and flattening the result.
- ///
- /// - Parameter transform: A closure that takes the error value of the
- /// instance.
- /// - Returns: A new `Result` instance, either from the transform or from
- /// the previous success value.
- public func flatMapError<NewError>(
- _ transform: (Error) -> Result<Value, NewError>
- ) -> Result<Value, NewError> {
- switch self {
- case let .success(value):
- return .success(value)
- case let .failure(error):
- return transform(error)
- }
- }
-
- /// Evaluates the given transform closures to create a single output value.
- ///
- /// - Parameters:
- /// - onSuccess: A closure that transforms the success value.
- /// - onFailure: A closure that transforms the error value.
- /// - Returns: A single `Output` value.
- public func fold<Output>(
- onSuccess: (Value) -> Output,
- onFailure: (Error) -> Output
- ) -> Output {
- switch self {
- case let .success(value):
- return onSuccess(value)
- case let .failure(error):
- return onFailure(error)
- }
- }
- }
- extension Result where Error : Swift.Error {
- /// Unwraps the `Result` into a throwing expression.
- ///
- /// - Returns: The success value, if the instance is a success.
- /// - Throws: The error value, if the instance is a failure.
- public func unwrapped() throws -> Value {
- switch self {
- case let .success(value):
- return value
- case let .failure(error):
- throw error
- }
- }
- }
- extension Result where Error == Swift.Error {
- /// Create an instance by capturing the output of a throwing closure.
- ///
- /// - Parameter throwing: A throwing closure to evaluate.
- @_transparent
- public init(_ throwing: () throws -> Value) {
- do {
- let value = try throwing()
- self = .success(value)
- } catch {
- self = .failure(error)
- }
- }
-
- /// Unwraps the `Result` into a throwing expression.
- ///
- /// - Returns: The success value, if the instance is a success.
- /// - Throws: The error value, if the instance is a failure.
- public func unwrapped() throws -> Value {
- switch self {
- case let .success(value):
- return value
- case let .failure(error):
- throw error
- }
- }
-
- /// Evaluates the given transform closure when this `Result` instance is
- /// `.success`, passing the value as a parameter and flattening the result.
- ///
- /// - Parameter transform: A closure that takes the successful value of the
- /// instance.
- /// - Returns: A new `Result` instance, either from the transform or from
- /// the previous error value.
- public func flatMap<NewValue>(
- _ transform: (Value) throws -> NewValue
- ) -> Result<NewValue, Error> {
- switch self {
- case let .success(value):
- do {
- return .success(try transform(value))
- } catch {
- return .failure(error)
- }
- case let .failure(error):
- return .failure(error)
- }
- }
- }
- extension Result : Equatable where Value : Equatable, Error : Equatable { }
- extension Result : Hashable where Value : Hashable, Error : Hashable {
- public func hash(into hasher: inout Hasher) {
- hasher.combine(value)
- hasher.combine(error)
- }
- }
- extension Result : CustomDebugStringConvertible {
- public var debugDescription: String {
- var output = "Result."
- switch self {
- case let .success(value):
- output += "success("
- debugPrint(value, terminator: "", to: &output)
- case let .failure(error):
- output += "failure("
- debugPrint(error, terminator: "", to: &output)
- }
- output += ")"
-
- return output
- }
- }
|