Skip to content

Instantly share code, notes, and snippets.

@danielt1263
Last active May 15, 2020 14:46
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save danielt1263/d7b8d5c63cf0c91b85b629a419b98d7e to your computer and use it in GitHub Desktop.
Save danielt1263/d7b8d5c63cf0c91b85b629a419b98d7e to your computer and use it in GitHub Desktop.
//
// 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<Event<Input>>` and want to transform it into an
`Observable<Event<Output>>` through some means.
*/
extension ObservableType {
/// - parameter transform: `(Input) -> Output`
public func mapEvent<Input, Output>( _ transform: @escaping (Input) throws -> Output) -> Observable<Event<Output>> where Element == Event<Input> {
return map { $0.map(transform) }
}
/// - parameter transform: `(Input) -> Event<Output>`
public func mapEvent<Input, Output>( _ transform: @escaping (Input) throws -> Event<Output>) -> Observable<Event<Output>> where Element == Event<Input> {
return map { $0.flatMap(transform) }
}
/// - parameter transform: `(Input) -> Observable<Output>`.
public func flatMapEvent<Input, Output>(_ transform: @escaping (Input) throws -> Observable<Output>) -> Observable<Event<Output>> where Element == Event<Input> {
return flatMapEvent { try embedResult($0, transform) }
}
/// - parameter transform: `(Input) -> Observable<Output>`.
public func flatMapLatestEvent<Input, Output>(_ transform: @escaping (Input) throws -> Observable<Output>) -> Observable<Event<Output>> where Element == Event<Input> {
return flatMapLatestEvent { try embedResult($0, transform) }
}
/// - parameter transform: `(Input) -> Observable<Output>`.
public func flatMapFirstEvent<Input, Output>(_ transform: @escaping (Input) throws -> Observable<Output>) -> Observable<Event<Output>> where Element == Event<Input> {
return flatMapFirstEvent { try embedResult($0, transform) }
}
/// - parameter transform: `(Input) -> Observable<Output>`.
public func concatMapEvent<Input, Output>(_ transform: @escaping (Input) throws -> Observable<Output>) -> Observable<Event<Output>> where Element == Event<Input> {
return concatMapEvent { try embedResult($0, transform) }
}
/// - parameter transform: `(Input) -> Observable<Event<Output>>`.
public func flatMapEvent<Input, Output>(_ transform: @escaping (Input) throws -> Observable<Event<Output>>) -> Observable<Event<Output>> where Element == Event<Input> {
return flatMap { $0.embedIntoObservable(transform) }
}
/// - parameter transform: `(Input) -> Observable<Event<Output>>`.
public func flatMapLatestEvent<Input, Output>(_ transform: @escaping (Input) throws -> Observable<Event<Output>>) -> Observable<Event<Output>> where Element == Event<Input> {
return flatMapLatest { $0.embedIntoObservable(transform) }
}
/// - parameter transform: `(Input) -> Observable<Event<Output>>`.
public func flatMapFirstEvent<Input, Output>(_ transform: @escaping (Input) throws -> Observable<Event<Output>>) -> Observable<Event<Output>> where Element == Event<Input> {
return flatMapFirst { $0.embedIntoObservable(transform) }
}
/// - parameter transform: `(Input) -> Observable<Event<Output>>`.
public func concatMapEvent<Input, Output>(_ transform: @escaping (Input) throws -> Observable<Event<Output>>) -> Observable<Event<Output>> where Element == Event<Input> {
return concatMap { $0.embedIntoObservable(transform) }
}
}
extension ObservableType {
/**
Allows you to filter an Observable<Event<T>> based on a predicate that takes a T.
- parameter pred: `(Input) -> Bool`.
*/
public func filterEvent<Input>(includeErrors: Bool = true, _ pred: @escaping (Input) throws -> Bool) -> Observable<Event<Input>> where Element == Event<Input> {
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<T>(_ transform: (Element) throws -> Event<T>) -> Event<T> {
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<Output>(_ transform: @escaping (Element) throws -> Observable<Event<Output>>) -> Observable<Event<Output>> {
switch self {
case let .next(input):
do {
return try transform(input)
.catchError { Observable<Event<Output>>.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, Output>(_ input: Input, _ transform: @escaping (Input) throws -> Observable<Output>) throws -> Observable<Event<Output>> {
return try transform(input).map(Event<Output>.next)
.catchError { Observable<Event<Output>>.just(.error($0)) }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment