Convert Result to an inline value class
This commit is contained in:
parent
eecd1b7d99
commit
981fbe2812
@ -10,11 +10,6 @@ import kotlin.contracts.contract
|
||||
* - Rust: [Result.ok](https://doc.rust-lang.org/std/result/enum.Result.html#method.ok)
|
||||
*/
|
||||
public fun <V, E> Result<V, E>.get(): V? {
|
||||
contract {
|
||||
returnsNotNull() implies (this@get is Ok<V>)
|
||||
returns(null) implies (this@get is Err<E>)
|
||||
}
|
||||
|
||||
return when {
|
||||
isOk -> value
|
||||
else -> null
|
||||
@ -27,11 +22,6 @@ public fun <V, E> Result<V, E>.get(): V? {
|
||||
* - Rust: [Result.err](https://doc.rust-lang.org/std/result/enum.Result.html#method.err)
|
||||
*/
|
||||
public fun <V, E> Result<V, E>.getError(): E? {
|
||||
contract {
|
||||
returns(null) implies (this@getError is Ok<V>)
|
||||
returnsNotNull() implies (this@getError is Err<E>)
|
||||
}
|
||||
|
||||
return when {
|
||||
isErr -> error
|
||||
else -> null
|
||||
@ -111,10 +101,6 @@ public inline infix fun <V, E> Result<V, E>.getErrorOrElse(transform: (V) -> E):
|
||||
* This is functionally equivalent to [`getOrElse { throw it }`][getOrElse].
|
||||
*/
|
||||
public fun <V, E : Throwable> Result<V, E>.getOrThrow(): V {
|
||||
contract {
|
||||
returns() implies (this@getOrThrow is Ok<V>)
|
||||
}
|
||||
|
||||
return when {
|
||||
isOk -> value
|
||||
else -> throw error
|
||||
@ -127,7 +113,6 @@ public fun <V, E : Throwable> Result<V, E>.getOrThrow(): V {
|
||||
*/
|
||||
public inline infix fun <V, E> Result<V, E>.getOrThrow(transform: (E) -> Throwable): V {
|
||||
contract {
|
||||
returns() implies (this@getOrThrow is Ok<V>)
|
||||
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
|
@ -1,19 +1,21 @@
|
||||
package com.github.michaelbull.result
|
||||
|
||||
import kotlin.jvm.JvmInline
|
||||
|
||||
/**
|
||||
* Returns a [Result] that [is ok][Result.isOk] and contains a [value][Result.value].
|
||||
*/
|
||||
@Suppress("FunctionName", "DEPRECATION")
|
||||
@Suppress("FunctionName")
|
||||
public fun <V> Ok(value: V): Result<V, Nothing> {
|
||||
return Ok(value, null)
|
||||
return Result(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [Result] that [is an error][Result.isErr] and contains an [error][Result.error].
|
||||
*/
|
||||
@Suppress("FunctionName", "DEPRECATION")
|
||||
@Suppress("FunctionName")
|
||||
public fun <E> Err(error: E): Result<Nothing, E> {
|
||||
return Err(error, null)
|
||||
return Result(Failure(error))
|
||||
}
|
||||
|
||||
/**
|
||||
@ -37,94 +39,66 @@ public inline fun <V, E, F> Result<V, E>.asErr(): Result<Nothing, F> {
|
||||
/**
|
||||
* [Result] is a type that represents either success ([Ok]) or failure ([Err]).
|
||||
*
|
||||
* A [Result] that [is ok][Result.isOk] will have a [value][Result.value] of type [V], whereas a
|
||||
* [Result] that [is an error][Result.isErr] will have an [error][Result.error] of type [E].
|
||||
*
|
||||
* - Elm: [Result](http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Result)
|
||||
* - Haskell: [Data.Either](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html)
|
||||
* - Rust: [Result](https://doc.rust-lang.org/std/result/enum.Result.html)
|
||||
*/
|
||||
public sealed class Result<out V, out E> {
|
||||
@JvmInline
|
||||
public value class Result<out V, out E> internal constructor(
|
||||
private val inlineValue: Any?,
|
||||
) {
|
||||
|
||||
public abstract val value: V
|
||||
public abstract val error: E
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public val value: V
|
||||
get() = inlineValue as V
|
||||
|
||||
public abstract val isOk: Boolean
|
||||
public abstract val isErr: Boolean
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public val error: E
|
||||
get() = (inlineValue as Failure<E>).error
|
||||
|
||||
public abstract operator fun component1(): V?
|
||||
public abstract operator fun component2(): E?
|
||||
}
|
||||
public val isOk: Boolean
|
||||
get() = inlineValue !is Failure<*>
|
||||
|
||||
/**
|
||||
* Represents a successful [Result], containing a [value].
|
||||
*/
|
||||
@Deprecated(
|
||||
message = "Using Ok as a return type is deprecated.",
|
||||
replaceWith = ReplaceWith("Result<V, Nothing>"),
|
||||
)
|
||||
public class Ok<out V> internal constructor(
|
||||
override val value: V,
|
||||
@Suppress("UNUSED_PARAMETER") placeholder: Any?,
|
||||
) : Result<V, Nothing>() {
|
||||
public val isErr: Boolean
|
||||
get() = inlineValue is Failure<*>
|
||||
|
||||
override val error: Nothing
|
||||
get() {
|
||||
throw NoSuchElementException()
|
||||
public operator fun component1(): V? {
|
||||
return when {
|
||||
isOk -> value
|
||||
else -> null
|
||||
}
|
||||
|
||||
override val isOk: Boolean = true
|
||||
override val isErr: Boolean = false
|
||||
|
||||
override fun component1(): V = value
|
||||
override fun component2(): Nothing? = null
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other == null || this::class != other::class) return false
|
||||
|
||||
other as Ok<*>
|
||||
|
||||
if (value != other.value) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = value.hashCode()
|
||||
override fun toString(): String = "Ok($value)"
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a failed [Result], containing an [error].
|
||||
*/
|
||||
@Deprecated(
|
||||
message = "Using Err as a return type is deprecated.",
|
||||
replaceWith = ReplaceWith("Result<Nothing, E>"),
|
||||
)
|
||||
public class Err<out E> internal constructor(
|
||||
override val error: E,
|
||||
@Suppress("UNUSED_PARAMETER") placeholder: Any?,
|
||||
) : Result<Nothing, E>() {
|
||||
|
||||
override val value: Nothing
|
||||
get() {
|
||||
throw NoSuchElementException()
|
||||
public operator fun component2(): E? {
|
||||
return when {
|
||||
isErr -> error
|
||||
else -> null
|
||||
}
|
||||
|
||||
override val isOk: Boolean = false
|
||||
override val isErr: Boolean = true
|
||||
|
||||
override fun component1(): Nothing? = null
|
||||
override fun component2(): E = error
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other == null || this::class != other::class) return false
|
||||
|
||||
other as Err<*>
|
||||
|
||||
if (error != other.error) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = error.hashCode()
|
||||
override fun toString(): String = "Err($error)"
|
||||
override fun toString(): String {
|
||||
return when {
|
||||
isOk -> "Ok($value)"
|
||||
else -> "Err($error)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class Failure<out E>(
|
||||
val error: E,
|
||||
) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return other is Failure<*> && error == other.error
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return error.hashCode()
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "Failure($error)"
|
||||
}
|
||||
}
|
||||
|
@ -14,10 +14,6 @@ public class UnwrapException(message: String) : Exception(message)
|
||||
* @throws UnwrapException if this result [is an error][Result.isErr].
|
||||
*/
|
||||
public fun <V, E> Result<V, E>.unwrap(): V {
|
||||
contract {
|
||||
returns() implies (this@unwrap is Ok<V>)
|
||||
}
|
||||
|
||||
return when {
|
||||
isOk -> value
|
||||
else -> throw UnwrapException("called Result.unwrap on an Err value $error")
|
||||
@ -38,7 +34,6 @@ public fun <V, E> Result<V, E>.unwrap(): V {
|
||||
public inline infix fun <V, E> Result<V, E>.expect(message: () -> Any): V {
|
||||
contract {
|
||||
callsInPlace(message, InvocationKind.AT_MOST_ONCE)
|
||||
returns() implies (this@expect is Ok<V>)
|
||||
}
|
||||
|
||||
return when {
|
||||
@ -56,10 +51,6 @@ public inline infix fun <V, E> Result<V, E>.expect(message: () -> Any): V {
|
||||
* @throws UnwrapException if this result [is ok][Result.isOk].
|
||||
*/
|
||||
public fun <V, E> Result<V, E>.unwrapError(): E {
|
||||
contract {
|
||||
returns() implies (this@unwrapError is Err<E>)
|
||||
}
|
||||
|
||||
return when {
|
||||
isErr -> error
|
||||
else -> throw UnwrapException("called Result.unwrapError on an Ok value $value")
|
||||
@ -80,7 +71,6 @@ public fun <V, E> Result<V, E>.unwrapError(): E {
|
||||
public inline infix fun <V, E> Result<V, E>.expectError(message: () -> Any): E {
|
||||
contract {
|
||||
callsInPlace(message, InvocationKind.AT_MOST_ONCE)
|
||||
returns() implies (this@expectError is Err<E>)
|
||||
}
|
||||
|
||||
return when {
|
||||
|
Loading…
Reference in New Issue
Block a user