From 549ee790d3e52bc62565ddf92e6a556e98b5195e Mon Sep 17 00:00:00 2001 From: Harsh Shandilya Date: Fri, 15 Jul 2022 00:53:48 +0530 Subject: all: re-do package structure yet again --- .../util/coroutines/DispatcherProvider.kt | 22 ++++++++++ .../util/coroutines/RunSuspendCatching.kt | 49 ++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 coroutine-utils/src/main/kotlin/app/passwordstore/util/coroutines/DispatcherProvider.kt create mode 100644 coroutine-utils/src/main/kotlin/app/passwordstore/util/coroutines/RunSuspendCatching.kt (limited to 'coroutine-utils/src/main/kotlin/app') diff --git a/coroutine-utils/src/main/kotlin/app/passwordstore/util/coroutines/DispatcherProvider.kt b/coroutine-utils/src/main/kotlin/app/passwordstore/util/coroutines/DispatcherProvider.kt new file mode 100644 index 00000000..c8edd654 --- /dev/null +++ b/coroutine-utils/src/main/kotlin/app/passwordstore/util/coroutines/DispatcherProvider.kt @@ -0,0 +1,22 @@ +/* + * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. + * SPDX-License-Identifier: GPL-3.0-only + */ + +package app.passwordstore.util.coroutines + +import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers + +/** Interface to allow abstracting individual [CoroutineDispatcher]s out of class dependencies. */ +public interface DispatcherProvider { + + public fun main(): CoroutineDispatcher = Dispatchers.Main + public fun default(): CoroutineDispatcher = Dispatchers.Default + public fun io(): CoroutineDispatcher = Dispatchers.IO + public fun unconfined(): CoroutineDispatcher = Dispatchers.Unconfined +} + +/** Concrete type for [DispatcherProvider] with all the defaults from the class. */ +public class DefaultDispatcherProvider @Inject constructor() : DispatcherProvider diff --git a/coroutine-utils/src/main/kotlin/app/passwordstore/util/coroutines/RunSuspendCatching.kt b/coroutine-utils/src/main/kotlin/app/passwordstore/util/coroutines/RunSuspendCatching.kt new file mode 100644 index 00000000..c650c14b --- /dev/null +++ b/coroutine-utils/src/main/kotlin/app/passwordstore/util/coroutines/RunSuspendCatching.kt @@ -0,0 +1,49 @@ +@file:OptIn(ExperimentalContracts::class) +@file:Suppress("RedundantSuspendModifier") + +package app.passwordstore.util.coroutines + +import com.github.michaelbull.result.Err +import com.github.michaelbull.result.Ok +import com.github.michaelbull.result.Result +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract +import kotlinx.coroutines.CancellationException + +/** + * Calls the specified function [block] and returns its encapsulated result if invocation was + * successful, catching any [Throwable] except [CancellationException] that was thrown from the + * [block] function execution and encapsulating it as a failure. + */ +@OptIn(ExperimentalContracts::class) +public suspend inline fun runSuspendCatching(block: () -> V): Result { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + + return try { + Ok(block()) + } catch (e: Throwable) { + if (e is CancellationException) throw e + Err(e) + } +} + +/** + * Calls the specified function [block] with [this] value as its receiver and returns its + * encapsulated result if invocation was successful, catching any [Throwable] except + * [CancellationException] that was thrown from the [block] function execution and encapsulating it + * as a failure. + */ +@OptIn(ExperimentalContracts::class) +public suspend inline infix fun T.runSuspendCatching( + block: T.() -> V +): Result { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + + return try { + Ok(block()) + } catch (e: Throwable) { + if (e is CancellationException) throw e + Err(e) + } +} -- cgit v1.2.3