All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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