io.getstream.result.Result.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of stream-result Show documentation
Show all versions of stream-result Show documentation
Result and error models for standardizing responses on Kotlin and Android.
/*
* Copyright (c) 2014-2022 Stream.io Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.getstream.result
/**
* A class which encapsulates a successful outcome with a value of type [A] or a failure with [Error].
*/
public sealed class Result {
/**
* Checks if the result is a [Success].
*/
public val isSuccess: Boolean
inline get() = this is Success
/**
* Check if the result is a [Failure].
*/
public val isFailure: Boolean
inline get() = this is Failure
/**
* Returns the encapsulated value if this instance represents [Success] [Result.isSuccess] or `null`
* if it is [Failure] [Result.isFailure].
*/
public fun getOrNull(): A? = when (this) {
is Success -> value
is Failure -> null
}
/**
* Returns the encapsulated value if this instance represents [Success] [Result.isSuccess]
* or throws the [IllegalStateException] exception if it is [Failure] [Result.isFailure].
*/
@Throws(IllegalStateException::class)
public fun getOrThrow(): A = when (this) {
is Success -> value
is Failure -> throw IllegalStateException("The Success::value cannot be accessed as the Result is a Failure.")
}
/**
* Returns the encapsulated [Error] if this instance represents [Failure] [isFailure] or `null`
* if it is [Success] [isSuccess].
*/
public fun errorOrNull(): Error? = when (this) {
is Success -> null
is Failure -> value
}
/**
* Represents successful result.
*
* @param value The [A] data associated with the result.
*/
public data class Success(val value: A) : Result()
/**
* Represents failed result.
*
* @param value The [Error] associated with the result.
*/
public data class Failure(val value: Error) : Result()
/**
* Returns a transformed [Result] of applying the given [f] function if the [Result]
* contains a successful data payload.
* Returns an original [Result] if the [Result] contains an error payload.
*
* @param f A lambda for mapping [Result] of [A] to [Result] of [C].
*
* @return A transformed instance of the [Result] or the original instance of the [Result].
*/
public inline fun map(f: (A) -> C): Result = flatMap { Success(f(it)) }
/**
* Returns a transformed [Result] of applying the given suspending [f] function if the [Result]
* contains a successful data payload.
* Returns an original [Result] if the [Result] contains an error payload.
*
* @param f A suspending lambda for mapping [Result] of [A] to [Result] of [C].
*
* @return A transformed instance of the [Result] or the original instance of the [Result].
*/
@JvmSynthetic
public suspend inline fun mapSuspend(crossinline f: suspend (A) -> C): Result =
flatMap { Success(f(it)) }
/**
* Returns a [Result] of [Unit] from any type of a [Result].
*
* @return [Result] of [Unit].
*/
public fun toUnitResult(): Result = map {}
/**
* Runs the [successSideEffect] lambda function if the [Result] contains a successful data payload.
*
* @param successSideEffect A lambda that receives the successful data payload.
*
* @return The original instance of the [Result].
*/
public inline fun onSuccess(
crossinline successSideEffect: (A) -> Unit
): Result =
also {
when (it) {
is Success -> successSideEffect(it.value)
is Failure -> Unit
}
}
/**
* Runs the [errorSideEffect] lambda function if the [Result] contains an error payload.
*
* @param errorSideEffect A lambda that receives the [Error] payload.
*
* @return The original instance of the [Result].
*/
public inline fun onError(
crossinline errorSideEffect: (Error) -> Unit
): Result =
also {
when (it) {
is Success -> Unit
is Failure -> errorSideEffect(it.value)
}
}
}
/**
* Returns a transformed [Result] from results of the [f] if the [Result] contains a successful data payload.
* Returns an original [Result] if the [Result] contains an error payload.
*
* @param f A lambda that returns [Result] of [C].
*
* @return A transformed instance of the [Result] or the original instance of the [Result].
*/
public inline fun Result.flatMap(f: (A) -> Result): Result {
return when (this) {
is Result.Success -> f(this.value)
is Result.Failure -> this
}
}
/**
* Returns a transformed [Result] from results of the suspending [f] if the [Result] contains a successful data
* payload.
* Returns an original [Result] if the [Result] contains an error payload.
*
* @param f A suspending lambda that returns [Result] of [C].
*
* @return A transformed instance of the [Result] or the original instance of the [Result].
*/
@JvmSynthetic
public suspend inline fun Result.flatMapSuspend(
crossinline f: suspend (A) -> Result
): Result {
return when (this) {
is Result.Success -> f(this.value)
is Result.Failure -> this
}
}
/**
* Runs the suspending [successSideEffect] lambda function if the [Result] contains a successful data payload.
*
* @param successSideEffect A suspending lambda that receives the successful data payload.
*
* @return The original instance of the [Result].
*/
@JvmSynthetic
public suspend inline fun Result.onSuccessSuspend(
crossinline successSideEffect: suspend (A) -> Unit
): Result =
also {
when (it) {
is Result.Success -> successSideEffect(it.value)
is Result.Failure -> Unit
}
}
/**
* Runs the suspending [errorSideEffect] lambda function if the [Result] contains an error payload.
*
* @param errorSideEffect A suspending lambda that receives the [Error] payload.
*
* @return The original instance of the [Result].
*/
@JvmSynthetic
public suspend inline fun Result.onErrorSuspend(
crossinline errorSideEffect: suspend (Error) -> Unit
): Result =
also {
when (it) {
is Result.Success -> Unit
is Result.Failure -> errorSideEffect(it.value)
}
}
/**
* Recovers the error payload by applying the given [errorMapper] function if the [Result]
* contains an error payload.
*
* @param errorMapper A lambda that receives [Error] and transforms it as a payload [A].
* @param errorMapper A lambda that receives [Error] and transforms it as a payload [A].
*
* @return A transformed instance of the [Result] or the original instance of the [Result].
*/
@JvmSynthetic
public fun Result.recover(errorMapper: (Error) -> A): Result.Success {
return when (this) {
is Result.Success -> this
is Result.Failure -> Result.Success(errorMapper(value))
}
}
/**
* Recovers the error payload by applying the given suspending [errorMapper] function if the [Result]
* contains an error payload.
*
* @param errorMapper A suspending lambda that receives [Error] and transforms it as a payload [A].
*
* @return A transformed instance of the [Result] or the original instance of the [Result].
*/
@JvmSynthetic
public suspend inline fun Result.recoverSuspend(
crossinline errorMapper: suspend (Error) -> A
): Result.Success {
return when (this) {
is Result.Success -> this
is Result.Failure -> Result.Success(errorMapper(value))
}
}
/**
* Composition the [Result] with a given [Result] from the [f].
*/
@JvmSynthetic
public inline infix fun Result.then(f: (T) -> Result): Result =
when (this) {
is Result.Success -> f(this.value)
is Result.Failure -> Result.Failure(this.value)
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy