
org.fernice.std.Result.kt Maven / Gradle / Ivy
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.fernice.std
fun Err(): Result {
return Err(Unit)
}
fun Ok(): Result {
return Ok(Unit)
}
/**
* Immutable monad representing the outcome of an operation by bearing either a value or an error.
* The positive outcome is represented by [Ok] and a negative outcome by [Err].
*/
sealed class Result {
/**
* Expects the outcome to be [Ok], otherwise throws an [IllegalStateException] bearing the
* specified [message].
*/
abstract fun expect(message: String): T
/**
* Turns the Result into a nullable value under the premise that [Ok] is expected. If the Result
* is [Err], the function will return [None] instead.
*/
abstract fun ok(): T?
/**
* Turns the Result into a nullable value under the premise that [Err] is expected. If the Result
* is [Ok], the function will return [None] instead.
*/
abstract fun err(): E?
/**
* Returns true if this Result is of type [Ok].
*/
abstract fun isOk(): Boolean
/**
* Returns true if this Result is of type [Err].
*/
abstract fun isErr(): Boolean
}
/**
* Concrete representation of a positive outcome of a [Result] bearing the value of the operation.
*/
data class Ok(val value: T) : Result() {
override fun expect(message: String): T {
return value
}
override fun ok(): T {
return value
}
override fun err(): Nothing? {
return null
}
override fun isOk(): Boolean {
return true
}
override fun isErr(): Boolean {
return false
}
}
/**
* Concrete representation of a negative outcome of a [Result] bearing the error of the operation.
*/
data class Err(val value: E) : Result() {
override fun expect(message: String): Nothing {
throw IllegalStateException("result is err")
}
override fun ok(): Nothing? {
return null
}
override fun err(): E {
return value
}
override fun isOk(): Boolean {
return false
}
override fun isErr(): Boolean {
return true
}
}
inline fun Result.propagate(block: (Err) -> Nothing): T = when (this) {
is Ok -> value
is Err -> block(this)
}
/**
* Maps the value of this Result using the specified [mapper] function and returns a Result
* containing it. If the Result is [Err], the result of this function will also be [Err].
*/
inline fun Result.map(mapper: (T) -> R): Result = when (this) {
is Ok -> Ok(mapper(value))
is Err -> this
}
/**
* Maps the error of this Result using the specified [mapper] function and returns a Result
* containing it. If the Result is [Ok], the result of this function will also be [Ok].
*/
inline fun Result.mapErr(mapper: (E) -> F): Result = when (this) {
is Ok -> this
is Err -> Err(mapper(value))
}
fun Result.unwrap(): T {
return when (this) {
is Ok -> this.value
is Err -> error("result was err: $value")
}
}
inline fun Result.unwrap(block: (Err) -> Nothing): T = when (this) {
is Ok -> value
is Err -> block(this)
}
fun Result.unwrapOr(alternative: T): T {
return when (this) {
is Ok -> this.value
is Err -> alternative
}
}
@Suppress("NOTHING_TO_INLINE")
inline fun Result.unwrapOrNull(): T? {
return when (this) {
is Ok -> this.value
is Err -> null
}
}
inline fun Result.unwrapOrElse(closure: (E) -> T): T {
return when (this) {
is Ok -> this.value
is Err -> closure(this.value)
}
}
inline fun Result.unwrapErr(block: (Ok) -> Nothing): E = when (this) {
is Ok -> block(this)
is Err -> value
}
fun Result.unwrapErr(): E {
return when (this) {
is Ok -> error("result was ok: $value")
is Err -> this.value
}
}
fun Result.unwrapErrOr(alternative: E): E {
return when (this) {
is Ok -> alternative
is Err -> this.value
}
}
@Suppress("NOTHING_TO_INLINE")
inline fun Result.unwrapErrOrNull(): E? {
return when (this) {
is Ok -> null
is Err -> this.value
}
}
inline fun Result.unwrapErrOrElse(closure: (T) -> E): E {
return when (this) {
is Ok -> closure(this.value)
is Err -> this.value
}
}
inline fun Result.orElse(block: (E) -> Result): Result {
if (this is Err) return block(this.value)
return this as Ok
}
inline fun Result.ifOk(closure: (T) -> Unit) {
when (this) {
is Ok -> closure(this.value)
is Err -> {}
}
}
inline fun Result.ifErr(closure: (E) -> Unit) {
when (this) {
is Ok -> {}
is Err -> closure(this.value)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy