commonMain.com.bkahlert.kommons.Either.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kommons-core-jvm Show documentation
Show all versions of kommons-core-jvm Show documentation
Kommons Core is a Kotlin Multiplatform Library that offers shared features for all Kommons modules.
package com.bkahlert.kommons
import com.bkahlert.kommons.Either.Left
import com.bkahlert.kommons.Either.Right
import kotlin.contracts.InvocationKind.AT_MOST_ONCE
import kotlin.contracts.contract
/**
* Represents a container containing either an instance of type [A] ([Left])
* or [B] ([Right]).
*/
public sealed interface Either {
/** Represents a container containing the left value. */
public data class Left(
/** The actual left value. */
public val value: A
) : Either
/** Represents a container containing the right value. */
public data class Right(
/** The actual right value. */
public val value: B
) : Either
}
/**
* Returns the encapsulated [Left.value] value if this instance represents [Left] or throws a [NoSuchElementException] otherwise.
*
* This function is a shorthand for `getLeftOrElse { throw it }` (see [getLeftOrElse]).
*/
@Suppress("NOTHING_TO_INLINE")
public inline fun Either.getLeftOrThrow(): A = when (this) {
is Left -> value
else -> throw NoSuchElementException()
}
/**
* Returns the encapsulated [Right.value] value if this instance represents [Right] or throws a [NoSuchElementException] otherwise.
*
* This function is a shorthand for `getRightOrElse { throw it }` (see [getRightOrElse]).
*/
@Suppress("NOTHING_TO_INLINE")
public inline fun Either.getRightOrThrow(): B = when (this) {
is Right -> value
else -> throw NoSuchElementException()
}
/**
* Returns the encapsulated [Left.value] value if this instance represents [Left] or the
* result of [onRight] function for the encapsulated [Right.value] value otherwise.
*
* This function is a shorthand for `fold(onLeft = { it }, onRight = onRight)` (see [fold]).
*/
public inline infix fun Either.getLeftOrElse(onRight: (B) -> R): R {
contract {
callsInPlace(onRight, AT_MOST_ONCE)
}
return when (this) {
is Left -> value
is Right -> onRight(value)
}
}
/**
* Returns the encapsulated [Right.value] value if this instance represents [Right] or the
* result of [onLeft] function for the encapsulated [Left.value] value otherwise.
*
* This function is a shorthand for `fold(onLeft = onLeft, onRight = { it })` (see [fold]).
*/
public inline infix fun Either.getRightOrElse(onLeft: (A) -> R): R {
contract {
callsInPlace(onLeft, AT_MOST_ONCE)
}
return when (this) {
is Left -> onLeft(value)
is Right -> value
}
}
/**
* Returns the encapsulated [Left.value] value if this instance represents [Left] or the
* [defaultValue] if it's [Right].
*
* This function is a shorthand for `getLeftOrElse { defaultValue }` (see [getLeftOrElse]).
*/
@Suppress("NOTHING_TO_INLINE")
public inline infix fun Either.getLeftOrDefault(defaultValue: R): R = when (this) {
is Left -> value
is Right -> defaultValue
}
/**
* Returns the encapsulated [Right.value] value if this instance represents [Right] or the
* [defaultValue] if it's [Left].
*
* This function is a shorthand for `getRightOrElse { defaultValue }` (see [getRightOrElse]).
*/
@Suppress("NOTHING_TO_INLINE")
public inline infix fun Either<*, B>.getRightOrDefault(defaultValue: R): R = when (this) {
is Left -> defaultValue
is Right -> value
}
/**
* Returns the encapsulated [Left.value] value if this instance represents [Left] or
* `null` if it's [Right].
*
* This function is a shorthand for `getLeftOrElse { null }` (see [getLeftOrElse]).
*/
@Suppress("NOTHING_TO_INLINE")
public inline fun Either.getLeftOrNull(): R? = when (this) {
is Left -> value
is Right -> null
}
/**
* Returns the encapsulated [Right.value] value if this instance represents [Right] or
* `null` if it's [Left].
*
* This function is a shorthand for `getRightOrElse { null }` (see [getRightOrElse]).
*/
@Suppress("NOTHING_TO_INLINE")
public inline fun Either<*, B>.getRightOrNull(): R? = when (this) {
is Left -> null
is Right -> value
}
/**
* Returns the result of [onLeft] for the encapsulated instance [A] or
* the result of [onRight] for the encapsulated instance [B].
*/
public inline fun Either.fold(
onLeft: (A) -> R,
onRight: (B) -> R,
): R {
contract {
callsInPlace(onLeft, AT_MOST_ONCE)
callsInPlace(onRight, AT_MOST_ONCE)
}
return when (this) {
is Left -> onLeft(value)
is Right -> onRight(value)
}
}
/**
* Returns the encapsulated result of the given [transform] function applied to the encapsulated value
* if this instance represents [Left] or the
* original encapsulated [Right] value if it's [Right].
*/
public inline infix fun Either.mapLeft(transform: (A) -> R): Either {
contract {
callsInPlace(transform, AT_MOST_ONCE)
}
return when (this) {
is Left -> Left(transform(value))
is Right -> @Suppress("UNCHECKED_CAST") (this as Either)
}
}
/**
* Returns the encapsulated result of the given [transform] function applied to the encapsulated value
* if this instance represents [Right] or the
* original encapsulated [Left] value if it's [Left].
*/
public inline infix fun Either.mapRight(transform: (B) -> R): Either {
contract {
callsInPlace(transform, AT_MOST_ONCE)
}
return when (this) {
is Left -> @Suppress("UNCHECKED_CAST") (this as Either)
is Right -> Right(transform(value))
}
}
/**
* Performs the given [action] on the encapsulated value if this instance represents [Left].
* Returns the original [Either] unchanged.
*/
public inline infix fun Either.onLeft(action: (A) -> Unit): Either {
contract {
callsInPlace(action, AT_MOST_ONCE)
}
if (this is Left) action(value)
return this
}
/**
* Performs the given [action] on the encapsulated value if this instance represents [Right].
* Returns the original [Either] unchanged.
*/
public inline infix fun Either.onRight(action: (B) -> Unit): Either {
contract {
callsInPlace(action, AT_MOST_ONCE)
}
if (this is Right) action(value)
return this
}
/** Converts this [Either] to a [Result]. */
@Suppress("NOTHING_TO_INLINE", "DirectUseOfResultType")
public inline fun Either.toResult(): Result =
mapLeft { Result.success(it) } getLeftOrElse { Result.failure(it) }
/** Converts this [Result] to an [Either]. */
@Suppress("NOTHING_TO_INLINE")
public inline fun Result.toEither(): Either =
fold({ Left(it) }, { Right(it) })
/**
* Returns this result's value if it represents [Result.success] and
* the caught [Throwable] if it represents [Result.failure].
*/
public fun Result.getOrException(): Pair =
fold({ it to null }, { null to it })
© 2015 - 2025 Weber Informatics LLC | Privacy Policy