ApiResult

value class ApiResult<out T>

A class that represents a result of an operation.

This class is efficient:

  • no actual objects are created,

  • all operations are inlined

  • no function resolution is performed.

ApiResult is not an Rx-style callback chain - the operators that are invoked are called immediately and in-place.

Types

Link copied to clipboard
object Companion

Properties

Link copied to clipboard
Link copied to clipboard

Whether this is Error

Link copied to clipboard

Whether this is Loading

Link copied to clipboard

Whether this is Success

Link copied to clipboard
Link copied to clipboard

ApiResult.Error.e's stack trace as string

Functions

Link copied to clipboard
infix inline fun <T, R> ApiResult<T>.apply(block: T.() -> R): ApiResult<R>

Alias for map that takes this as a parameter

Link copied to clipboard
infix inline fun <T> ApiResult<T>.chain(another: (T) -> ApiResult<*>): ApiResult<T>

Call another and retrieve the result. If the result is success, continue (the result of calling another is discarded). If the result is an error, propagate it to this. Effectively, requires for another ApiResult to succeed before proceeding with this one.

Link copied to clipboard
inline operator fun component1(): T?

Get the Success component of this result or null

Link copied to clipboard
inline operator fun component2(): Exception?

Get the Error component of this result or null

Link copied to clipboard
inline fun <T> ApiResult<T>.errorIf(exception: (T) -> Exception = { ConditionNotSatisfiedException() }, predicate: (T) -> Boolean): ApiResult<T>

Makes this an Error if predicate returns true

Link copied to clipboard
inline fun <T, R : Iterable<T>> ApiResult<R>.errorIfEmpty(exception: () -> Exception = { ConditionNotSatisfiedException("Collection was empty") }): ApiResult<R>
@JvmName(name = "sequenceErrorIfEmpty")
inline fun <T, R : Sequence<T>> ApiResult<R>.errorIfEmpty(exception: () -> Exception = { ConditionNotSatisfiedException("Sequence was empty") }): ApiResult<R>

Makes this an error if the collection is empty.

Link copied to clipboard
inline fun <T> ApiResult<T>.errorOnLoading(exception: () -> Exception = { NotFinishedException() }): ApiResult<T>

Makes this result an Error if this result is Loading

Link copied to clipboard
inline fun <T : Any> ApiResult<T?>?.errorOnNull(exception: () -> Exception = { ConditionNotSatisfiedException("Value was null") }): ApiResult<T>

Make this result an Error if Success value was null.

Link copied to clipboard
inline fun <T> ApiResult<T>.errorUnless(exception: (T) -> Exception = { ConditionNotSatisfiedException() }, predicate: (T) -> Boolean): ApiResult<T>

Makes this an Error if predicate returns false

Link copied to clipboard
Link copied to clipboard
infix inline fun <T : Iterable<R>, R> ApiResult<T>.filter(block: (R) -> Boolean): ApiResult<List<R>>

Filter the underlying collection.

@JvmName(name = "filterSequence")
infix inline fun <T : Sequence<R>, R> ApiResult<T>.filter(noinline block: (R) -> Boolean): ApiResult<Sequence<R>>

Filter the underlying sequence.

Link copied to clipboard
infix inline fun <T, R> ApiResult<T>.flatMap(another: (T) -> ApiResult<R>): ApiResult<R>

Call another and if it succeeds, continue with another's result. If it fails, propagate the error. An alias for then.

Link copied to clipboard
inline fun <T, R> ApiResult<T>.fold(onSuccess: (result: T) -> R, onError: (e: Exception) -> R, noinline onLoading: () -> R? = null): R

Fold this returning the result of onSuccess or onError By default, maps Loading to Error with NotFinishedException

Link copied to clipboard
infix inline fun <T : Iterable<R>, R> ApiResult<T>.ifEmpty(block: () -> Unit): ApiResult<T>

Execute block if this's collection is empty.

Link copied to clipboard
infix inline fun <T, R> ApiResult<T>.map(block: (T) -> R): ApiResult<R>

Change the type of the Success to R without affecting Error/Loading results

Link copied to clipboard
inline fun <T, R> ApiResult<T>.mapEither(success: (T) -> R, error: (Exception) -> Exception): ApiResult<R>

Map both Error and Success. Does not affect Loading

Link copied to clipboard
@JvmName(name = "mapErrorTyped")
infix inline fun <R : Exception, T> ApiResult<T>.mapError(block: (R) -> Exception): ApiResult<T>

Map the exception of the Error state, but only if this exception is of type R. Loading and Success are unaffected

infix inline fun <T> ApiResult<T>.mapError(block: (Exception) -> Exception): ApiResult<T>

Change the exception of the Error response without affecting loading/success results

Link copied to clipboard

Maps the error of the result, if present, to its cause, or self if cause is not available

Link copied to clipboard
infix inline fun <T, R : T> ApiResult<T>.mapLoading(block: () -> R): ApiResult<T>

Maps Loading to a Success, not affecting other states.

Link copied to clipboard
inline fun <T, R> ApiResult<T>.mapOrDefault(default: (e: Exception) -> R, transform: (T) -> R): R

Map the Success result using transform, and if the result is not a success, return default

Link copied to clipboard
infix inline fun <T, R> ApiResult<Iterable<T>>.mapValues(transform: (T) -> R): ApiResult<List<R>>

Executes ApiResult.map on each value of the collection

@JvmName(name = "sequenceMapValues")
infix inline fun <T, R> ApiResult<Sequence<T>>.mapValues(noinline transform: (T) -> R): ApiResult<Sequence<R>>

Executes ApiResult.map on each value of the sequence

Link copied to clipboard
inline fun <T> ApiResult<T>.merge(results: Iterable<ApiResult<T>>): ApiResult<List<T>>

Merges this results and all other results into a single result of type T.

Link copied to clipboard
inline operator fun not(): T

Bang operator returns the result or throws if it is an Error or Loading This is equivalent to calling orThrow

Link copied to clipboard
inline fun <T> ApiResult<T>.nullOnError(): ApiResult<T?>

Maps Error values to nulls

Link copied to clipboard
infix inline fun <T : Iterable<R>, R> ApiResult<T>.onEmpty(block: () -> Unit): ApiResult<T>

Execute block if this's collection is empty.

Link copied to clipboard
@JvmName(name = "onErrorTyped")
infix inline fun <E : Exception, T> ApiResult<T>.onError(block: (E) -> Unit): ApiResult<T>

Invoke a given block if this is Error and it's Error.e is of type E.

infix inline fun <T> ApiResult<T>.onError(block: (Exception) -> Unit): ApiResult<T>

Invoke a given block if this is Error

Link copied to clipboard
infix inline fun <T> ApiResult<T>.onLoading(block: () -> Unit): ApiResult<T>

Invoke given block if this is Loading

Link copied to clipboard
infix inline fun <T> ApiResult<T>.onSuccess(block: (T) -> Unit): ApiResult<T>

Invoke a given block if this is Success

Link copied to clipboard
infix inline fun <T, R : T> ApiResult<T>.or(defaultValue: R): T

If this is Error or Loading, returns defaultValue.

Link copied to clipboard
infix inline fun <T, R : T> ApiResult<T>.orElse(block: (e: Exception) -> R): T

Executes block if this is an ApiResult.Error, otherwise returns ApiResult.value.

Link copied to clipboard
inline fun <T> ApiResult<Set<T>>.orEmpty(): Set<T>
inline fun <T> ApiResult<Sequence<T>>.orEmpty(): Sequence<T>

Returns emptyList if this's collection is empty

inline fun <T> ApiResult<List<T>>.orEmpty(): List<T>

Returns emptyList if this's list is empty

inline fun <K, V> ApiResult<Map<K, V>>.orEmpty(): Map<K, V>

Returns emptyMap if this's map is empty

Link copied to clipboard
inline fun <T> ApiResult<T>?.orNull(): T?
Link copied to clipboard
inline fun <T> ApiResult<T>.orThrow(): T

Throws ApiResult.Error.e, or NotFinishedException if the request has not been completed yet.

Link copied to clipboard
@JvmName(name = "recoverTyped")
infix inline fun <T : Exception, R> ApiResult<R>.recover(another: (e: T) -> ApiResult<R>): ApiResult<R>

Recover from an exception of type R, else no-op. Does not affect Loading.

infix inline fun <T> ApiResult<T>.recover(another: (e: Exception) -> ApiResult<T>): ApiResult<T>

Recover from an exception. Does not affect Loading See also the typed version of this function to recover from a specific exception type

Link copied to clipboard
inline fun <T> ApiResult<T>.recoverIf(condition: (Exception) -> Boolean, block: (Exception) -> ApiResult<T>): ApiResult<T>

Recover from an Error only if the condition is true, else no-op. Does not affect Loading

Link copied to clipboard
inline fun <T> ApiResult<T>.require(): T

Alias for orThrow

inline fun <T> ApiResult<T>.require(message: (T) -> String? = { null }, predicate: (T) -> Boolean): ApiResult<T>

Makes this an error with ConditionNotSatisfiedException using specified message if the predicate returns false.

Link copied to clipboard
inline fun <R, T> ApiResult<T>.requireIs(exception: (T) -> Exception = { value -> "Result value is of type ${value?.let { it::class.simpleName }} but expected ${R::class.simpleName}" .let(::ConditionNotSatisfiedException) }): ApiResult<R>
Link copied to clipboard
inline fun <T> ApiResult<T?>?.requireNotNull(message: () -> String = { "ApiResult value was null" }): ApiResult<T & Any>

Alias for errorOnNull

Link copied to clipboard
inline fun <T : Exception, R> ApiResult<R>.rethrow(): ApiResult<R>

Throws if this result is an Error and Error.e is of type T. Ignores all other exceptions.

Link copied to clipboard

Throws CancellationExceptions if this is an Error.

Link copied to clipboard
infix inline fun <T, R> ApiResult<T>.then(another: (T) -> ApiResult<R>): ApiResult<R>

Call another and if it succeeds, continue with another's result. If it fails, propagate the error. Effectively, flatMap to another result.

Link copied to clipboard
open override fun toString(): String
Link copied to clipboard
infix inline fun <T> ApiResult<T>.tryChain(block: (T) -> Unit): ApiResult<T>

Call block, wrapping it in an ApiResult, and then discard the Success value, but propagate Errors.

Link copied to clipboard
infix inline fun <T, R> ApiResult<T>.tryMap(block: (T) -> R): ApiResult<R>

Change the type of successful result to R, also wrapping block in another result then folding it (handling exceptions)

Link copied to clipboard
@JvmName(name = "tryRecoverTyped")
infix inline fun <T : Exception, R> ApiResult<R>.tryRecover(block: (T) -> R): ApiResult<R>

calls recover catching and wrapping any exceptions thrown inside block.

infix inline fun <T> ApiResult<T>.tryRecover(block: (e: Exception) -> T): ApiResult<T>

Calls recover catching and wrapping any exceptions thrown inside block.

Link copied to clipboard
inline fun <T> ApiResult<T>.tryRecoverIf(condition: (Exception) -> Boolean, block: (Exception) -> T): ApiResult<T>

Recover from an Error only if the condition is true, else no-op. Does not affect Loading

Link copied to clipboard
inline fun ApiResult<*>.unit(): ApiResult<Unit>

Map this result to Unit, discarding the value

Link copied to clipboard
inline fun <T> ApiResult<ApiResult<T>>.unwrap(): ApiResult<T>

Unwrap an ApiResult<ApiResult<T>> to become ApiResult<T>