Add recoverIf and recoverUnless

These are similar to [toErrorIf] and [toErrorUnless], but maps from Err to Ok.
This commit is contained in:
Thomas Stenberg Oddsund 2020-11-28 01:24:52 +01:00 committed by Michael Bull
parent c8372a0522
commit 0fdd0f2c2b
2 changed files with 132 additions and 0 deletions

View File

@ -55,3 +55,43 @@ public inline infix fun <V, E> Result<V, E>.recover(transform: (E) -> V): Ok<V>
is Err -> Ok(transform(error)) is Err -> Ok(transform(error))
} }
} }
/**
* Returns the [transformation][transform] of the [error][Err.error] if this [Result] is [Err]
* and satisfies the given [predicate], otherwise this [Result].
*/
public inline fun <V, E> Result<V, E>.recoverIf(predicate: (E) -> Boolean, transform: (E) -> V): Result<V, E> {
contract {
callsInPlace(predicate, InvocationKind.AT_MOST_ONCE)
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
}
return when (this) {
is Ok -> this
is Err -> if (predicate(error)) {
Ok(transform(error))
} else {
this
}
}
}
/**
* Returns the [transformation][transform] of the [error][Err.error] if this [Result] is [Err]
* and _does not_ satisfies the given [predicate], otherwise this [Result].
*/
public inline fun <V, E> Result<V, E>.recoverUnless(predicate: (E) -> Boolean, transform: (E) -> V): Result<V, E> {
contract {
callsInPlace(predicate, InvocationKind.AT_MOST_ONCE)
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
}
return when (this) {
is Ok -> this
is Err -> if (!predicate(error)) {
Ok(transform(error))
} else {
this
}
}
}

View File

@ -59,4 +59,96 @@ class OrTest {
) )
} }
} }
class RecoverIf {
@Test
fun returnsValueIfOk() {
assertEquals(
expected = 3000,
actual = (Ok(3000) as Result<Int, Int>).recoverIf(
{ it == 4000 },
{ 2000 }
).get()
)
}
@Test
fun returnsTransformedErrorAsOkIfErrAndPredicateMatch() {
assertEquals(
expected = 2000,
actual = Err(4000).recoverIf(
{ it == 4000 },
{ 2000 }
).get()
)
}
@Test
fun doesNotReturnTransformedErrorAsOkIfErrAndPredicateDoesNotMatch() {
assertEquals(
expected = null,
actual = Err(4000).recoverIf(
{ it == 3000 },
{ 2000 }
).get()
)
}
@Test
fun returnErrIfErrAndPredicateDoesNotMatch() {
assertEquals(
expected = 4000,
actual = Err(4000).recoverIf(
{ it == 3000 },
{ 2000 }
).getError()
)
}
}
class RecoverUnless {
@Test
fun returnsValueIfOk() {
assertEquals(
expected = 3000,
actual = (Ok(3000) as Result<Int, Int>).recoverUnless(
{ it == 4000 },
{ 2000 }
).get()
)
}
@Test
fun returnsTransformedErrorAsOkIfErrAndPredicateDoesNotMatch() {
assertEquals(
expected = 2000,
actual = Err(4000).recoverUnless(
{ it == 3000 },
{ 2000 }
).get()
)
}
@Test
fun doesNotReturnTransformedErrorAsOkIfErrAndPredicateMatches() {
assertEquals(
expected = null,
actual = Err(4000).recoverUnless(
{ it == 4000 },
{ 2000 }
).get()
)
}
@Test
fun returnErrIfErrAndPredicateDoesMatch() {
assertEquals(
expected = 4000,
actual = Err(4000).recoverUnless(
{ it == 4000 },
{ 2000 }
).getError()
)
}
}
} }