Restore SuccessOrFailure.kt to bootstrap (to be removed later)

This commit is contained in:
Roman Elizarov
2018-09-09 11:34:49 +03:00
parent e2713501ce
commit 2406bf0536
@@ -17,6 +17,8 @@ import kotlin.contracts.*
import kotlin.internal.InlineOnly
import kotlin.jvm.JvmField
// TODO: REMOVE AFTER BOOTSTRAP
/**
* A discriminated union that encapsulates successful outcome with a value of type [T]
* or a failure with an arbitrary [Throwable] exception.
@@ -128,185 +130,3 @@ public inline class SuccessOrFailure<out T> @PublishedApi internal constructor(
override fun toString(): String = "Failure($exception)"
}
}
/**
* Calls the specified function [block] and returns its encapsulated result if invocation was successful,
* catching and encapsulating any thrown exception as a failure.
*/
@InlineOnly public inline fun <R> runCatching(block: () -> R): SuccessOrFailure<R> {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return try {
SuccessOrFailure.success(block())
} catch (e: Throwable) {
SuccessOrFailure.failure(e)
}
}
/**
* Calls the specified function [block] with `this` value as its receiver and returns its encapsulated result
* if invocation was successful, catching and encapsulating any thrown exception as a failure.
*/
@InlineOnly public inline fun <T, R> T.runCatching(block: T.() -> R): SuccessOrFailure<R> {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return try {
SuccessOrFailure.success(block())
} catch (e: Throwable) {
SuccessOrFailure.failure(e)
}
}
// -- extensions ---
/**
* Returns the encapsulated value if this instance represents [success][SuccessOrFailure.isSuccess] or the
* result of [onFailure] function for encapsulated exception if it is [failure][SuccessOrFailure.isFailure].
*
* Note, that an exception thrown by [onFailure] function is rethrown by this function.
*
* This function is shorthand for `fold(onSuccess = { it }, onFailure = onFailure)` (see [fold]).
*/
@InlineOnly public inline fun <R, T : R> SuccessOrFailure<T>.getOrElse(onFailure: (exception: Throwable) -> R): R {
contract {
callsInPlace(onFailure, InvocationKind.AT_MOST_ONCE)
}
return when(value) {
is SuccessOrFailure.Failure -> onFailure(value.exception)
else -> value as T
}
}
/**
* Returns the encapsulated value if this instance represents [success][SuccessOrFailure.isSuccess] or the
* [defaultValue] if it is [failure][SuccessOrFailure.isFailure].
*
* This function is shorthand for `getOrElse { defaultValue }` (see [getOrElse]).
*/
public fun <R, T : R> SuccessOrFailure<T>.getOrDefault(defaultValue: R): R =
getOrElse { defaultValue }
/**
* Returns the the result of [onSuccess] for encapsulated value if this instance represents [success][SuccessOrFailure.isSuccess]
* or the result of [onFailure] function for encapsulated exception if it is [failure][SuccessOrFailure.isFailure].
*
* Note, that an exception thrown by [onSuccess] or by [onFailure] function is rethrown by this function.
*/
@InlineOnly public inline fun <R, T> SuccessOrFailure<T>.fold(
onSuccess: (value: T) -> R,
onFailure: (exception: Throwable) -> R
): R {
contract {
callsInPlace(onSuccess, InvocationKind.AT_MOST_ONCE)
callsInPlace(onFailure, InvocationKind.AT_MOST_ONCE)
}
return when(value) {
is SuccessOrFailure.Failure -> onFailure(value.exception)
else -> onSuccess(value as T)
}
}
// transformation
/**
* Returns the encapsulated result of the given [transform] function applied to encapsulated value
* if this instance represents [success][SuccessOrFailure.isSuccess] or the
* original encapsulated exception if it is [failure][SuccessOrFailure.isFailure].
*
* Note, that an exception thrown by [transform] function is rethrown by this function.
* See [mapCatching] for an alternative that encapsulates exceptions.
*/
@InlineOnly public inline fun <R, T> SuccessOrFailure<T>.map(transform: (value: T) -> R): SuccessOrFailure<R> {
contract {
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
}
return when(value) {
is SuccessOrFailure.Failure -> SuccessOrFailure(value)
else -> SuccessOrFailure.success(transform(value as T))
}
}
/**
* Returns the encapsulated result of the given [transform] function applied to encapsulated value
* if this instance represents [success][SuccessOrFailure.isSuccess] or the
* original encapsulated exception if it is [failure][SuccessOrFailure.isFailure].
*
* Any exception thrown by [transform] function is caught, encapsulated as a failure and returned by this function.
* See [map] for an alternative that rethrows exceptions.
*/
@InlineOnly public inline fun <R, T> SuccessOrFailure<T>.mapCatching(transform: (value: T) -> R): SuccessOrFailure<R> {
contract {
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
}
return when(value) {
is SuccessOrFailure.Failure -> SuccessOrFailure(value)
else -> runCatching { transform(value as T) }
}
}
/**
* Returns the encapsulated result of the given [transform] function applied to encapsulated exception
* if this instance represents [failure][SuccessOrFailure.isFailure] or the
* original encapsulated value if it is [success][SuccessOrFailure.isSuccess].
*
* Note, that an exception thrown by [transform] function is rethrown by this function.
* See [recoverCatching] for an alternative that encapsulates exceptions.
*/
@InlineOnly public inline fun <R, T: R> SuccessOrFailure<T>.recover(transform: (exception: Throwable) -> R): SuccessOrFailure<R> {
contract {
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
}
return when(value) {
is SuccessOrFailure.Failure -> SuccessOrFailure.success(transform(value.exception))
else -> this
}
}
/**
* Returns the encapsulated result of the given [transform] function applied to encapsulated exception
* if this instance represents [failure][SuccessOrFailure.isFailure] or the
* original encapsulated value if it is [success][SuccessOrFailure.isSuccess].
*
* Any exception thrown by [transform] function is caught, encapsulated as a failure and returned by this function.
* See [recover] for an alternative that rethrows exceptions.
*/
@InlineOnly public inline fun <R, T: R> SuccessOrFailure<T>.recoverCatching(transform: (exception: Throwable) -> R): SuccessOrFailure<R> {
contract {
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
}
val value = value // workaround for inline classes BE bug
return when(value) {
is SuccessOrFailure.Failure -> runCatching { transform(value.exception) }
else -> this
}
}
// "peek" onto value/exception and pipe
/**
* Performs the given [action] on encapsulated value if this instance represents [success][SuccessOrFailure.isSuccess].
* Returns the original `SuccessOrFailure` unchanged.
*/
@InlineOnly public inline fun <T> SuccessOrFailure<T>.onFailure(action: (exception: Throwable) -> Unit): SuccessOrFailure<T> {
contract {
callsInPlace(action, InvocationKind.AT_MOST_ONCE)
}
if (value is SuccessOrFailure.Failure) action(value.exception)
return this
}
/**
* Performs the given [action] on encapsulated exception if this instance represents [failure][SuccessOrFailure.isFailure].
* Returns the original `SuccessOrFailure` unchanged.
*/
@InlineOnly public inline fun <T> SuccessOrFailure<T>.onSuccess(action: (value: T) -> Unit): SuccessOrFailure<T> {
contract {
callsInPlace(action, InvocationKind.AT_MOST_ONCE)
}
if (value !is SuccessOrFailure.Failure) action(value as T)
return this
}
// -------------------