// // ObservableEventTransforms.swift // // Created by Daniel Tartaglia on 9/22/18. // Copyright © 2019 Daniel Tartaglia. MIT License. // import RxSwift /** All of the methods below assume that you have an `Observable>` and want to transform it into an `Observable>` through some means. */ extension ObservableType { /// - parameter transform: `(Input) -> Output` public func mapEvent( _ transform: @escaping (Input) throws -> Output) -> Observable> where Element == Event { return map { $0.map(transform) } } /// - parameter transform: `(Input) -> Event` public func mapEvent( _ transform: @escaping (Input) throws -> Event) -> Observable> where Element == Event { return map { $0.flatMap(transform) } } /// - parameter transform: `(Input) -> Observable`. public func flatMapEvent(_ transform: @escaping (Input) throws -> Observable) -> Observable> where Element == Event { return flatMapEvent { try embedResult($0, transform) } } /// - parameter transform: `(Input) -> Observable`. public func flatMapLatestEvent(_ transform: @escaping (Input) throws -> Observable) -> Observable> where Element == Event { return flatMapLatestEvent { try embedResult($0, transform) } } /// - parameter transform: `(Input) -> Observable`. public func flatMapFirstEvent(_ transform: @escaping (Input) throws -> Observable) -> Observable> where Element == Event { return flatMapFirstEvent { try embedResult($0, transform) } } /// - parameter transform: `(Input) -> Observable`. public func concatMapEvent(_ transform: @escaping (Input) throws -> Observable) -> Observable> where Element == Event { return concatMapEvent { try embedResult($0, transform) } } /// - parameter transform: `(Input) -> Observable>`. public func flatMapEvent(_ transform: @escaping (Input) throws -> Observable>) -> Observable> where Element == Event { return flatMap { $0.embedIntoObservable(transform) } } /// - parameter transform: `(Input) -> Observable>`. public func flatMapLatestEvent(_ transform: @escaping (Input) throws -> Observable>) -> Observable> where Element == Event { return flatMapLatest { $0.embedIntoObservable(transform) } } /// - parameter transform: `(Input) -> Observable>`. public func flatMapFirstEvent(_ transform: @escaping (Input) throws -> Observable>) -> Observable> where Element == Event { return flatMapFirst { $0.embedIntoObservable(transform) } } /// - parameter transform: `(Input) -> Observable>`. public func concatMapEvent(_ transform: @escaping (Input) throws -> Observable>) -> Observable> where Element == Event { return concatMap { $0.embedIntoObservable(transform) } } } extension ObservableType { /** Allows you to filter an Observable> based on a predicate that takes a T. - parameter pred: `(Input) -> Bool`. */ public func filterEvent(includeErrors: Bool = true, _ pred: @escaping (Input) throws -> Bool) -> Observable> where Element == Event { return filter { value in switch value { case let .next(input): do { return try pred(input) } catch { return includeErrors } case .error: return includeErrors case .completed: return true } } } } extension Event { public func flatMap(_ transform: (Element) throws -> Event) -> Event { switch self { case let .next(element): do { return try transform(element) } catch { return .error(error) } case let .error(error): return .error(error) case .completed: return .completed } } fileprivate func embedIntoObservable(_ transform: @escaping (Element) throws -> Observable>) -> Observable> { switch self { case let .next(input): do { return try transform(input) .catchError { Observable>.just(.error($0)) } } catch { return .just(.error(error)) } case let .error(error): return .just(.error(error)) case .completed: return .just(.completed) } } } private func embedResult(_ input: Input, _ transform: @escaping (Input) throws -> Observable) throws -> Observable> { return try transform(input).map(Event.next) .catchError { Observable>.just(.error($0)) } }