Skip to content

Commit

Permalink
Rename ResultBinding to BindingScope, SuspendableResultBinding to Cor…
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelbull committed Mar 10, 2024
1 parent 4974cb7 commit 3615705
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ import kotlin.coroutines.CoroutineContext
* This new scope is [cancelled][CoroutineScope.cancel] once a failing bind is encountered, eagerly cancelling all
* child [jobs][Job].
*/
public suspend inline fun <V, E> binding(crossinline block: suspend SuspendableResultBinding<E>.() -> V): Result<V, E> {
public suspend inline fun <V, E> binding(crossinline block: suspend CoroutineBindingScope<E>.() -> V): Result<V, E> {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}

lateinit var receiver: SuspendableResultBindingImpl<E>
lateinit var receiver: CoroutineBindingScopeImpl<E>

return try {
coroutineScope {
receiver = SuspendableResultBindingImpl(this)
receiver = CoroutineBindingScopeImpl(this)

with(receiver) {
Ok(block())
Expand All @@ -42,14 +42,20 @@ public suspend inline fun <V, E> binding(crossinline block: suspend SuspendableR

internal object BindCancellationException : CancellationException(null as String?)

public interface SuspendableResultBinding<E> : CoroutineScope {
@Deprecated(
message = "Use CoroutineBindingScope instead",
replaceWith = ReplaceWith("CoroutineBindingScope<E>")
)
public typealias SuspendableResultBinding<E> = CoroutineBindingScope<E>

public interface CoroutineBindingScope<E> : CoroutineScope {
public suspend fun <V> Result<V, E>.bind(): V
}

@PublishedApi
internal class SuspendableResultBindingImpl<E>(
internal class CoroutineBindingScopeImpl<E>(
delegate: CoroutineScope,
) : SuspendableResultBinding<E>, CoroutineScope by delegate {
) : CoroutineBindingScope<E>, CoroutineScope by delegate {

private val mutex = Mutex()
var result: Result<Nothing, E>? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import kotlin.contracts.InvocationKind
import kotlin.contracts.contract

/**
* Calls the specified function [block] with [ResultBinding] as its receiver and returns its [Result].
* Calls the specified function [block] with [BindingScope] as its receiver and returns its [Result].
*
* When inside a [binding] block, the [bind][ResultBinding.bind] function is accessible on any [Result]. Calling the
* [bind][ResultBinding.bind] function will attempt to unwrap the [Result] and locally return its [value][Ok.value]. If
* When inside a [binding] block, the [bind][BindingScope.bind] function is accessible on any [Result]. Calling the
* [bind][BindingScope.bind] function will attempt to unwrap the [Result] and locally return its [value][Ok.value]. If
* the [Result] is an [Err], the binding block will terminate with that bind and return that failed-to-bind [Err].
*
* Example:
Expand All @@ -22,12 +22,12 @@ import kotlin.contracts.contract
* }
* ```
*/
public inline fun <V, E> binding(crossinline block: ResultBinding<E>.() -> V): Result<V, E> {
public inline fun <V, E> binding(crossinline block: BindingScope<E>.() -> V): Result<V, E> {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}

return with(ResultBindingImpl<E>()) {
return with(BindingScopeImpl<E>()) {
try {
Ok(block())
} catch (ex: BindException) {
Expand All @@ -38,20 +38,26 @@ public inline fun <V, E> binding(crossinline block: ResultBinding<E>.() -> V): R

internal expect object BindException : Exception

public interface ResultBinding<E> {
@Deprecated(
message = "Use BindingScope instead",
replaceWith = ReplaceWith("BindingScope<E>")
)
public typealias ResultBinding<E> = BindingScope<E>

public interface BindingScope<E> {
public fun <V> Result<V, E>.bind(): V
}

@PublishedApi
internal class ResultBindingImpl<E> : ResultBinding<E> {
internal class BindingScopeImpl<E> : BindingScope<E> {

var result: Result<Nothing, E>? = null

override fun <V> Result<V, E>.bind(): V {
return when (this) {
is Ok -> value
is Err -> {
this@ResultBindingImpl.result = this
this@BindingScopeImpl.result = this
throw BindException
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.github.michaelbull.result.coroutines

import com.github.michaelbull.result.BindException
import com.github.michaelbull.result.BindingScope
import com.github.michaelbull.result.BindingScopeImpl
import com.github.michaelbull.result.Ok
import com.github.michaelbull.result.Result
import com.github.michaelbull.result.ResultBinding
import com.github.michaelbull.result.ResultBindingImpl
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract

Expand All @@ -17,12 +17,12 @@ import kotlin.contracts.contract
"Please import the kotlin-result-coroutines library to continue using this feature.",
level = DeprecationLevel.WARNING
)
public suspend inline fun <V, E> binding(crossinline block: suspend ResultBinding<E>.() -> V): Result<V, E> {
public suspend inline fun <V, E> binding(crossinline block: suspend BindingScope<E>.() -> V): Result<V, E> {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}

return with(ResultBindingImpl<E>()) {
return with(BindingScopeImpl<E>()) {
try {
Ok(block())
} catch (ex: BindException) {
Expand Down

0 comments on commit 3615705

Please sign in to comment.