Skip to content

Commit

Permalink
greatly clean up catching methods
Browse files Browse the repository at this point in the history
  • Loading branch information
iaik-jheher committed Oct 25, 2024
1 parent 8e97246 commit b36fe62
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 321 deletions.
245 changes: 0 additions & 245 deletions kmmresult/src/commonMain/kotlin/at/asitplus/KmmResult.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@

package at.asitplus

import at.asitplus.KmmResult.Companion.wrap
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.experimental.ExperimentalObjCName
import kotlin.experimental.ExperimentalObjCRefinement
import kotlin.jvm.JvmName
import kotlin.jvm.JvmStatic
import kotlin.native.HiddenFromObjC
import kotlin.native.ObjCName
Expand Down Expand Up @@ -266,246 +264,3 @@ inline fun <R, T : R> KmmResult<T>.recoverCatching(block: (error: Throwable) ->
else -> catching { block(x) }
}
}

/**
* Non-fatal-only-catching version of stdlib's [runCatching], directly returning a [KmmResult] --
* Re-throws any fatal exceptions, such as `OutOfMemoryError`. Re-implements [Arrow](https://arrow-kt.io)'s
* [nonFatalOrThrow](https://apidocs.arrow-kt.io/arrow-core/arrow.core/non-fatal-or-throw.html)
* logic to avoid a dependency on Arrow for a single function.
*/
@Suppress("TooGenericExceptionCaught")
inline fun <T> catching(block: () -> T): KmmResult<T> {
contract {
// not EXACTLY_ONCE, because inside a try block!
callsInPlace(block, InvocationKind.AT_MOST_ONCE)
}
return try {
KmmResult.success(block())
} catch (e: Throwable) {
KmmResult.failure(e)
}
}

/**
* Non-fatal-only-catching version of stdlib's [runCatching] (calling the specified function [block] with `this` value
* as its receiver), directly returning a [KmmResult] --
* Re-throws any fatal exceptions, such as `OutOfMemoryError`. Re-implements [Arrow](https://arrow-kt.io)'s
* [nonFatalOrThrow](https://apidocs.arrow-kt.io/arrow-core/arrow.core/non-fatal-or-throw.html)
* logic to avoid a dependency on Arrow for a single function.
*/
@Suppress("TooGenericExceptionCaught")
inline fun <T, R> T.catching(block: T.() -> R): KmmResult<R> {
contract {
// not EXACTLY_ONCE, because inside a try block!
callsInPlace(block, InvocationKind.AT_MOST_ONCE)
}
return try {
KmmResult.success(block())
} catch (e: Throwable) {
KmmResult.failure(e)
}
}

@Deprecated("Function name was misleading", ReplaceWith("catchingAs(type, block)"))
@Suppress("TooGenericExceptionCaught")
inline fun <reified E : Throwable, R> wrapping(asA: (String?, Throwable) -> E, block: () -> R): KmmResult<R> =
catchingAs(asA, block)

/**
* Runs the specified function [block], returning a [KmmResult].
* Any non-fatal exception will be wrapped as the specified exception, unless it is already the specified type.
*
* Usage: `catchingAs(type = ::ThrowableType) { block }`.
*/
@Suppress("TooGenericExceptionCaught")
inline fun <reified E : Throwable, R> catchingAs(type: (String?, Throwable) -> E, block: () -> R): KmmResult<R> =
catchingUnwrappedAs(type, block).wrap()

/**
* Runs the specified function [block], returning a [Result].
* Any non-fatal exception will be wrapped as the specified exception, unless it is already the specified type.
*
* Usage: `catchingAs(typeWithoutMessage = ::ThrowableType) { block }`.
*/
@Suppress("TooGenericExceptionCaught")
@JvmName("#catchingUnwrappedAs")
inline fun <reified E : Throwable, R> catchingUnwrappedAs(
crossinline typeWithoutMessage: (Throwable) -> E,
block: () -> R
): Result<R> = catchingUnwrappedAs(type = { str, t ->
when (t) {
is E -> t
else -> typeWithoutMessage(t)
}
}, block)

/**
* Runs the specified function [block], returning a [KmmResult].
* Any non-fatal exception will be wrapped as the specified exception, unless it is already the specified type.
*
* Usage: `catchingAs(typeWithoutMessage = ::ThrowableType) { block }`.
*/
@JvmName("#catchingAs")
inline fun <reified E : Throwable, R> catchingAs(
crossinline typeWithoutMessage: (Throwable) -> E,
block: () -> R
): KmmResult<R> =
catchingUnwrappedAs(typeWithoutMessage, block).wrap()

/**
* Runs the specified function [block], returning a [Result].
* Any non-fatal exception will be wrapped as the specified exception, unless it is already the specified type.
*
* Usage: `catchingAs(typeWithMessage = ::ThrowableType) { block }`.
*/
@Suppress("TooGenericExceptionCaught")
inline fun <reified E : Throwable, R> catchingUnwrappedAs(
crossinline typeWithMessage: (String?) -> E,
block: () -> R
): Result<R> =
catchingUnwrappedAs(type = { str, t ->
when (t) {
is E -> t
else -> typeWithMessage(str)
}
}, block)

/**
* Runs the specified function [block], returning a [KmmResult].
* Any non-fatal exception will be wrapped as the specified exception, unless it is already the specified type.
*
* Usage: `catchingAs(typeWithMessage = ::ThrowableType) { block }`.
*/
inline fun <reified E : Throwable, R> catchingAs(
crossinline typeWithMessage: (String?) -> E,
block: () -> R
): KmmResult<R> =
catchingUnwrappedAs(typeWithMessage, block).wrap()

/**
* Runs the specified function [block], returning a [Result].
* Any non-fatal exception will be wrapped as the specified exception, unless it is already the specified type.
*
* Usage: `catchingUnwrappedAs(type = ::ThrowableType) { block }`.
*/
@Suppress("TooGenericExceptionCaught")
inline fun <reified E : Throwable, R> catchingUnwrappedAs(type: (String?, Throwable) -> E, block: () -> R): Result<R> {
contract {
callsInPlace(type, InvocationKind.AT_MOST_ONCE)
// not EXACTLY_ONCE, because inside a try block!
callsInPlace(block, InvocationKind.AT_MOST_ONCE)
}
return try {
Result.success(block())
} catch (e: Throwable) {
Result.failure(
when (e.nonFatalOrThrow()) {
is E -> e
else -> type(e.message, e)
}
)
}
}

@Deprecated("Function name was misleading", ReplaceWith("catchingAs(type, block)"))
@Suppress("TooGenericExceptionCaught")
inline fun <reified E : Throwable, T, R> T.wrapping(
asA: (String?, Throwable) -> E,
block: T.() -> R
): KmmResult<R> = catchingAs(asA, block)

/**
* Runs the specified function [block] with `this` as its receiver, returning a [KmmResult].
* Any non-fatal exception will be wrapped as the specified exception, unless it is already the specified type.
*
* Usage: `catchingAs(type = ::ThrowableType) { block }`.
*/
@Suppress("TooGenericExceptionCaught")
inline fun <reified E : Throwable, T, R> T.catchingAs(
type: (String?, Throwable) -> E,
block: T.() -> R
): KmmResult<R> = this.catchingUnwrappedAs(type, block).wrap()

/**
* Runs the specified function [block] with `this` as its receiver, returning a [Result].
* Any non-fatal exception will be wrapped as the specified exception, unless it is already the specified type.
*
* Usage: `catchingUnwrappedAd(type = ::ThrowableType) { block }`.
*/
@Suppress("TooGenericExceptionCaught")
inline fun <reified E : Throwable, T, R> T.catchingUnwrappedAs(
type: (String?, Throwable) -> E,
block: T.() -> R
): Result<R> {
contract {
callsInPlace(type, InvocationKind.AT_MOST_ONCE)
// not EXACTLY_ONCE, because inside a try block!
callsInPlace(block, InvocationKind.AT_MOST_ONCE)
}
return try {
Result.success(block())
} catch (e: Throwable) {
Result.failure(
when (e.nonFatalOrThrow()) {
is E -> e
else -> type(e.message, e)
}
)
}
}

/**
* Runs the specified function [block] with `this` as its receiver, returning a [Result].
* Any non-fatal exception will be wrapped as the specified exception, unless it is already the specified type.
*
* Usage: `catchingUnwrappedAd(typeWithMessage = ::ThrowableType) { block }`.
*/
@JvmName("#catchingUnwrappedAsWithString")
inline fun <reified E : Throwable, T, R> T.catchingUnwrappedAs(
typeWithMessage: (String?) -> E,
block: T.() -> R
): Result<R> = this.catchingUnwrappedAs(type = { str, t ->
when (t) {
is E -> t
else -> typeWithMessage(str)
}
}, block)

/**
* Runs the specified function [block] with `this` as its receiver, returning a [Result].
* Any non-fatal exception will be wrapped as the specified exception, unless it is already the specified type.
*
* Usage: `catchingUnwrappedAd(typeWithoutMessage = ::ThrowableType) { block }`.
*/
inline fun <reified E : Throwable, T, R> T.catchingUnwrappedAs(
typeWithoutMessage: (Throwable) -> E,
block: T.() -> R
): Result<R> = this.catchingUnwrappedAs(type = { str, t ->
when (t) {
is E -> t
else -> typeWithoutMessage(t)
}
}, block)

/**
* Runs the specified function [block] with `this` as its receiver, returning a [KmmResult].
* Any non-fatal exception will be wrapped as the specified exception, unless it is already the specified type.
*
* Usage: `catchingUnwrappedAd(typeWithMessage = ::ThrowableType) { block }`.
*/
@JvmName("#catchingAsWithString")
inline fun <reified E : Throwable, T, R> T.catchingAs(
typeWithMessage: (String?) -> E,
block: T.() -> R
): KmmResult<R> = this.catchingUnwrappedAs(typeWithMessage, block).wrap()

/**
* Runs the specified function [block] with `this` as its receiver, returning a [KmmResult].
* Any non-fatal exception will be wrapped as the specified exception, unless it is already the specified type.
*
* Usage: `catchingUnwrappedAd(typeWithoutMessage = ::ThrowableType) { block }`.
*/
inline fun <reified E : Throwable, T, R> T.catchingAs(
typeWithoutMessage: (Throwable) -> E,
block: T.() -> R
): KmmResult<R> = this.catchingUnwrappedAs(typeWithoutMessage, block).wrap()
37 changes: 0 additions & 37 deletions kmmresult/src/commonMain/kotlin/at/asitplus/NonFatal.kt

This file was deleted.

Loading

0 comments on commit b36fe62

Please sign in to comment.