Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
//
// ObservableResultTransforms.swift
//
// Created by Daniel Tartaglia on 5/10/2019.
// Copyright © 2019 Daniel Tartaglia. MIT License.
//
import RxSwift
/**
All of the methods below assume that you have an `Observable<Result<Input, Failure>>` and want to transform it into an
`Observable<Result<Output, Failure>>` through some means.
*/
extension ObservableType {
/// - parameter transform: `(Input) -> Output`
public func mapResult<Input, Output, Failure>( _ transform: @escaping (Input) -> Output) -> Observable<Result<Output, Failure>> where Element == Result<Input, Failure> {
return map { $0.map(transform) }
}
/// - parameter transform: `(Input) -> Result<Output, Failure>`
public func mapResult<Input, Output, Failure>( _ transform: @escaping (Input) -> Result<Output, Failure>) -> Observable<Result<Output, Failure>> where Element == Result<Input, Failure> {
return map { $0.flatMap(transform) }
}
/// - parameter transform: `(Input) -> Observable<Output>`.
public func flatMapResult<Input, Output, Failure>(_ transform: @escaping (Input) -> Observable<Output>) -> Observable<Result<Output, Failure>> where Element == Result<Input, Failure> {
return flatMap { result -> Observable<Result<Output, Failure>> in
switch result {
case .success(let value):
return transform(value).map { Result.success($0) }
case .failure(let error):
return Observable.just(Result.failure(error))
}
}
}
/// - parameter transform: `(Input) -> Observable<Output>`.
public func flatMapLatestResult<Input, Output, Failure>(_ transform: @escaping (Input) -> Observable<Output>) -> Observable<Result<Output, Failure>> where Element == Result<Input, Failure> {
return flatMapLatest { result -> Observable<Result<Output, Failure>> in
switch result {
case .success(let value):
return transform(value).map { Result.success($0) }
case .failure(let error):
return Observable.just(Result.failure(error))
}
}
}
/// - parameter transform: `(Input) -> Observable<Output>`.
public func flatMapFirstResult<Input, Output, Failure>(_ transform: @escaping (Input) -> Observable<Output>) -> Observable<Result<Output, Failure>> where Element == Result<Input, Failure> {
return flatMapFirst { result -> Observable<Result<Output, Failure>> in
switch result {
case .success(let value):
return transform(value).map { Result.success($0) }
case .failure(let error):
return Observable.just(Result.failure(error))
}
}
}
/// - parameter transform: `(Input) -> Observable<Output>`.
public func concatMapResult<Input, Output, Failure>(_ transform: @escaping (Input) -> Observable<Output>) -> Observable<Result<Output, Failure>> where Element == Result<Input, Failure> {
return concatMap { result -> Observable<Result<Output, Failure>> in
switch result {
case .success(let value):
return transform(value).map { Result.success($0) }
case .failure(let error):
return Observable.just(Result.failure(error))
}
}
}
/// - parameter transform: `(Input) -> Observable<Result<Output, Failure>>`.
public func flatMapResult<Input, Output, Failure>(_ transform: @escaping (Input) -> Observable<Result<Output, Failure>>) -> Observable<Result<Output, Failure>> where Element == Result<Input, Failure> {
return flatMap { result -> Observable<Result<Output, Failure>> in
switch result.map(transform) {
case .success(let value):
return value
case .failure(let error):
return Observable.just(Result.failure(error))
}
}
}
/// - parameter transform: `(Input) -> Observable<Result<Output, Failure>>`.
public func flatMapLatestResult<Input, Output, Failure>(_ transform: @escaping (Input) -> Observable<Result<Output, Failure>>) -> Observable<Result<Output, Failure>> where Element == Result<Input, Failure> {
return flatMapLatest { result -> Observable<Result<Output, Failure>> in
switch result.map(transform) {
case .success(let value):
return value
case .failure(let error):
return Observable.just(Result.failure(error))
}
}
}
/// - parameter transform: `(Input) -> Observable<Result<Output, Failure>>`.
public func flatMapFirstResult<Input, Output, Failure>(_ transform: @escaping (Input) -> Observable<Result<Output, Failure>>) -> Observable<Result<Output, Failure>> where Element == Result<Input, Failure> {
return flatMapFirst { result -> Observable<Result<Output, Failure>> in
switch result.map(transform) {
case .success(let value):
return value
case .failure(let error):
return Observable.just(Result.failure(error))
}
}
}
/// - parameter transform: `(Input) -> Observable<Result<Output, Failure>>`.
public func concatMapResult<Input, Output, Failure>(_ transform: @escaping (Input) -> Observable<Result<Output, Failure>>) -> Observable<Result<Output, Failure>> where Element == Result<Input, Failure> {
return concatMap { result -> Observable<Result<Output, Failure>> in
switch result.map(transform) {
case .success(let value):
return value
case .failure(let error):
return Observable.just(Result.failure(error))
}
}
}
}
extension ObservableType {
/**
Allows you to filter an Observable<Result<T>> based on a predicate that takes a T.
- parameter pred: `(Input) -> Bool`.
*/
public func filterResult<Input, Failure>(includeFailures: Bool = true, _ pred: @escaping (Input) -> Bool) -> Observable<Result<Input, Failure>> where Element == Result<Input, Failure> {
return filter { value in
switch value {
case .success(let value):
return pred(value)
case .failure:
return includeFailures
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.