Move release coroutines sources into the corresponding stdlib sourcesets
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmName("SequencesKt")
|
||||
@file:UseExperimental(ExperimentalTypeInference::class)
|
||||
|
||||
package kotlin.sequences
|
||||
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
import kotlin.experimental.ExperimentalTypeInference
|
||||
|
||||
/**
|
||||
* Builds a [Sequence] lazily yielding values one by one.
|
||||
*
|
||||
* @see kotlin.sequences.generateSequence
|
||||
*
|
||||
* @sample samples.collections.Sequences.Building.buildSequenceYieldAll
|
||||
* @sample samples.collections.Sequences.Building.buildFibonacciSequence
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
public fun <T> sequence(@BuilderInference block: suspend SequenceScope<T>.() -> Unit): Sequence<T> = Sequence { iterator(block) }
|
||||
|
||||
@SinceKotlin("1.3")
|
||||
@Deprecated("Use 'sequence { }' function instead.", ReplaceWith("sequence(builderAction)"), level = DeprecationLevel.ERROR)
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <T> buildSequence(@BuilderInference noinline builderAction: suspend SequenceScope<T>.() -> Unit): Sequence<T> = Sequence { iterator(builderAction) }
|
||||
|
||||
/**
|
||||
* Builds an [Iterator] lazily yielding values one by one.
|
||||
*
|
||||
* @sample samples.collections.Sequences.Building.buildIterator
|
||||
* @sample samples.collections.Iterables.Building.iterable
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
public fun <T> iterator(@BuilderInference block: suspend SequenceScope<T>.() -> Unit): Iterator<T> {
|
||||
val iterator = SequenceBuilderIterator<T>()
|
||||
iterator.nextStep = block.createCoroutineUnintercepted(receiver = iterator, completion = iterator)
|
||||
return iterator
|
||||
}
|
||||
|
||||
@SinceKotlin("1.3")
|
||||
@Deprecated("Use 'iterator { }' function instead.", ReplaceWith("iterator(builderAction)"), level = DeprecationLevel.ERROR)
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <T> buildIterator(@BuilderInference noinline builderAction: suspend SequenceScope<T>.() -> Unit): Iterator<T> = iterator(builderAction)
|
||||
|
||||
/**
|
||||
* The scope for yielding values of a [Sequence] or an [Iterator], provides [yield] and [yieldAll] suspension functions.
|
||||
*
|
||||
* @see sequence
|
||||
* @see iterator
|
||||
*
|
||||
* @sample samples.collections.Sequences.Building.buildSequenceYieldAll
|
||||
* @sample samples.collections.Sequences.Building.buildFibonacciSequence
|
||||
*/
|
||||
@RestrictsSuspension
|
||||
@SinceKotlin("1.3")
|
||||
public abstract class SequenceScope<in T> internal constructor() {
|
||||
/**
|
||||
* Yields a value to the [Iterator] being built.
|
||||
*
|
||||
* @sample samples.collections.Sequences.Building.buildSequenceYieldAll
|
||||
* @sample samples.collections.Sequences.Building.buildFibonacciSequence
|
||||
*/
|
||||
public abstract suspend fun yield(value: T)
|
||||
|
||||
/**
|
||||
* Yields all values from the `iterator` to the [Iterator] being built.
|
||||
*
|
||||
* The sequence of values returned by the given iterator can be potentially infinite.
|
||||
*
|
||||
* @sample samples.collections.Sequences.Building.buildSequenceYieldAll
|
||||
*/
|
||||
public abstract suspend fun yieldAll(iterator: Iterator<T>)
|
||||
|
||||
/**
|
||||
* Yields a collections of values to the [Iterator] being built.
|
||||
*
|
||||
* @sample samples.collections.Sequences.Building.buildSequenceYieldAll
|
||||
*/
|
||||
public suspend fun yieldAll(elements: Iterable<T>) {
|
||||
if (elements is Collection && elements.isEmpty()) return
|
||||
return yieldAll(elements.iterator())
|
||||
}
|
||||
|
||||
/**
|
||||
* Yields potentially infinite sequence of values to the [Iterator] being built.
|
||||
*
|
||||
* The sequence can be potentially infinite.
|
||||
*
|
||||
* @sample samples.collections.Sequences.Building.buildSequenceYieldAll
|
||||
*/
|
||||
public suspend fun yieldAll(sequence: Sequence<T>) = yieldAll(sequence.iterator())
|
||||
}
|
||||
|
||||
@Deprecated("Use SequenceScope class instead.", ReplaceWith("SequenceScope<T>"), level = DeprecationLevel.ERROR)
|
||||
public typealias SequenceBuilder<T> = SequenceScope<T>
|
||||
|
||||
private typealias State = Int
|
||||
|
||||
private const val State_NotReady: State = 0
|
||||
private const val State_ManyNotReady: State = 1
|
||||
private const val State_ManyReady: State = 2
|
||||
private const val State_Ready: State = 3
|
||||
private const val State_Done: State = 4
|
||||
private const val State_Failed: State = 5
|
||||
|
||||
private class SequenceBuilderIterator<T> : SequenceScope<T>(), Iterator<T>, Continuation<Unit> {
|
||||
private var state = State_NotReady
|
||||
private var nextValue: T? = null
|
||||
private var nextIterator: Iterator<T>? = null
|
||||
var nextStep: Continuation<Unit>? = null
|
||||
|
||||
override fun hasNext(): Boolean {
|
||||
while (true) {
|
||||
when (state) {
|
||||
State_NotReady -> {}
|
||||
State_ManyNotReady ->
|
||||
if (nextIterator!!.hasNext()) {
|
||||
state = State_ManyReady
|
||||
return true
|
||||
} else {
|
||||
nextIterator = null
|
||||
}
|
||||
State_Done -> return false
|
||||
State_Ready, State_ManyReady -> return true
|
||||
else -> throw exceptionalState()
|
||||
}
|
||||
|
||||
state = State_Failed
|
||||
val step = nextStep!!
|
||||
nextStep = null
|
||||
step.resume(Unit)
|
||||
}
|
||||
}
|
||||
|
||||
override fun next(): T {
|
||||
when (state) {
|
||||
State_NotReady, State_ManyNotReady -> return nextNotReady()
|
||||
State_ManyReady -> {
|
||||
state = State_ManyNotReady
|
||||
return nextIterator!!.next()
|
||||
}
|
||||
State_Ready -> {
|
||||
state = State_NotReady
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val result = nextValue as T
|
||||
nextValue = null
|
||||
return result
|
||||
}
|
||||
else -> throw exceptionalState()
|
||||
}
|
||||
}
|
||||
|
||||
private fun nextNotReady(): T {
|
||||
if (!hasNext()) throw NoSuchElementException() else return next()
|
||||
}
|
||||
|
||||
private fun exceptionalState(): Throwable = when (state) {
|
||||
State_Done -> NoSuchElementException()
|
||||
State_Failed -> IllegalStateException("Iterator has failed.")
|
||||
else -> IllegalStateException("Unexpected state of the iterator: $state")
|
||||
}
|
||||
|
||||
|
||||
override suspend fun yield(value: T) {
|
||||
nextValue = value
|
||||
state = State_Ready
|
||||
return suspendCoroutineUninterceptedOrReturn { c ->
|
||||
nextStep = c
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun yieldAll(iterator: Iterator<T>) {
|
||||
if (!iterator.hasNext()) return
|
||||
nextIterator = iterator
|
||||
state = State_ManyReady
|
||||
return suspendCoroutineUninterceptedOrReturn { c ->
|
||||
nextStep = c
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
// Completion continuation implementation
|
||||
override fun resumeWith(result: Result<Unit>) {
|
||||
result.getOrThrow() // just rethrow exception if it is there
|
||||
state = State_Done
|
||||
}
|
||||
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package kotlin.coroutines
|
||||
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
import kotlin.internal.InlineOnly
|
||||
|
||||
/**
|
||||
* Interface representing a continuation after a suspension point that returns value of type `T`.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
public interface Continuation<in T> {
|
||||
/**
|
||||
* Context of the coroutine that corresponds to this continuation.
|
||||
*/
|
||||
public val context: CoroutineContext
|
||||
|
||||
/**
|
||||
* Resumes the execution of the corresponding coroutine passing successful or failed [result] as the
|
||||
* return value of the last suspension point.
|
||||
*/
|
||||
public fun resumeWith(result: Result<T>)
|
||||
}
|
||||
|
||||
/**
|
||||
* Classes and interfaces marked with this annotation are restricted when used as receivers for extension
|
||||
* `suspend` functions. These `suspend` extensions can only invoke other member or extension `suspend` functions on this particular
|
||||
* receiver only and are restricted from calling arbitrary suspension functions.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
public annotation class RestrictsSuspension
|
||||
|
||||
/**
|
||||
* Resumes the execution of the corresponding coroutine passing [value] as the return value of the last suspension point.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@InlineOnly
|
||||
public inline fun <T> Continuation<T>.resume(value: T): Unit =
|
||||
resumeWith(Result.success(value))
|
||||
|
||||
/**
|
||||
* Resumes the execution of the corresponding coroutine so that the [exception] is re-thrown right after the
|
||||
* last suspension point.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@InlineOnly
|
||||
public inline fun <T> Continuation<T>.resumeWithException(exception: Throwable): Unit =
|
||||
resumeWith(Result.failure(exception))
|
||||
|
||||
|
||||
/**
|
||||
* Creates [Continuation] instance with a given [context] and a given implementation of [resumeWith] method.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@InlineOnly
|
||||
public inline fun <T> Continuation(
|
||||
context: CoroutineContext,
|
||||
crossinline resumeWith: (Result<T>) -> Unit
|
||||
): Continuation<T> =
|
||||
object : Continuation<T> {
|
||||
override val context: CoroutineContext
|
||||
get() = context
|
||||
|
||||
override fun resumeWith(result: Result<T>) =
|
||||
resumeWith(result)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a coroutine without receiver and with result type [T].
|
||||
* This function creates a new, fresh instance of suspendable computation every time it is invoked.
|
||||
*
|
||||
* To start executing the created coroutine, invoke `resume(Unit)` on the returned [Continuation] instance.
|
||||
* The [completion] continuation is invoked when coroutine completes with result or exception.
|
||||
* Repeated invocation of any resume function on the resulting continuation produces [IllegalStateException].
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public fun <T> (suspend () -> T).createCoroutine(
|
||||
completion: Continuation<T>
|
||||
): Continuation<Unit> =
|
||||
SafeContinuation(createCoroutineUnintercepted(completion).intercepted(), COROUTINE_SUSPENDED)
|
||||
|
||||
/**
|
||||
* Creates a coroutine with receiver type [R] and result type [T].
|
||||
* This function creates a new, fresh instance of suspendable computation every time it is invoked.
|
||||
*
|
||||
* To start executing the created coroutine, invoke `resume(Unit)` on the returned [Continuation] instance.
|
||||
* The [completion] continuation is invoked when coroutine completes with result or exception.
|
||||
* Repeated invocation of any resume function on the resulting continuation produces [IllegalStateException].
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public fun <R, T> (suspend R.() -> T).createCoroutine(
|
||||
receiver: R,
|
||||
completion: Continuation<T>
|
||||
): Continuation<Unit> =
|
||||
SafeContinuation(createCoroutineUnintercepted(receiver, completion).intercepted(), COROUTINE_SUSPENDED)
|
||||
|
||||
/**
|
||||
* Starts coroutine without receiver and with result type [T].
|
||||
* This function creates and start a new, fresh instance of suspendable computation every time it is invoked.
|
||||
* The [completion] continuation is invoked when coroutine completes with result or exception.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public fun <T> (suspend () -> T).startCoroutine(
|
||||
completion: Continuation<T>
|
||||
) {
|
||||
createCoroutineUnintercepted(completion).intercepted().resume(Unit)
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts coroutine with receiver type [R] and result type [T].
|
||||
* This function creates and start a new, fresh instance of suspendable computation every time it is invoked.
|
||||
* The [completion] continuation is invoked when coroutine completes with result or exception.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public fun <R, T> (suspend R.() -> T).startCoroutine(
|
||||
receiver: R,
|
||||
completion: Continuation<T>
|
||||
) {
|
||||
createCoroutineUnintercepted(receiver, completion).intercepted().resume(Unit)
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the current continuation instance inside suspend functions and suspends
|
||||
* currently running coroutine.
|
||||
*
|
||||
* In this function both [Continuation.resume] and [Continuation.resumeWithException] can be used either synchronously in
|
||||
* the same stack-frame where suspension function is run or asynchronously later in the same thread or
|
||||
* from a different thread of execution. Repeated invocation of any resume function produces [IllegalStateException].
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@InlineOnly
|
||||
public suspend inline fun <T> suspendCoroutine(crossinline block: (Continuation<T>) -> Unit): T =
|
||||
suspendCoroutineUninterceptedOrReturn { c: Continuation<T> ->
|
||||
val safe = SafeContinuation(c.intercepted())
|
||||
block(safe)
|
||||
safe.getOrThrow()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns context of the current coroutine.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@Suppress("WRONG_MODIFIER_TARGET")
|
||||
@InlineOnly
|
||||
public suspend inline val coroutineContext: CoroutineContext
|
||||
get() {
|
||||
throw NotImplementedError("Implemented as intrinsic")
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package kotlin.coroutines
|
||||
|
||||
/**
|
||||
* Marks coroutine context element that intercepts coroutine continuations.
|
||||
* The coroutines framework uses [ContinuationInterceptor.Key] to retrieve the interceptor and
|
||||
* intercepts all coroutine continuations with [interceptContinuation] invocations.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
public interface ContinuationInterceptor : CoroutineContext.Element {
|
||||
/**
|
||||
* The key that defines *the* context interceptor.
|
||||
*/
|
||||
companion object Key : CoroutineContext.Key<ContinuationInterceptor>
|
||||
|
||||
/**
|
||||
* Returns continuation that wraps the original [continuation], thus intercepting all resumptions.
|
||||
* This function is invoked by coroutines framework when needed and the resulting continuations are
|
||||
* cached internally per each instance of the original [continuation].
|
||||
*
|
||||
* This function may simply return original [continuation] if it does not want to intercept this particular continuation.
|
||||
*
|
||||
* When the original [continuation] completes, coroutine framework invokes [releaseInterceptedContinuation]
|
||||
* with the resulting continuation if it was intercepted, that is if `interceptContinuation` had previously
|
||||
* returned a different continuation instance.
|
||||
*/
|
||||
public fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T>
|
||||
|
||||
/**
|
||||
* Invoked for the continuation instance returned by [interceptContinuation] when the original
|
||||
* continuation completes and will not be used anymore. This function is invoked only if [interceptContinuation]
|
||||
* had returned a different continuation instance from the one it was invoked with.
|
||||
*
|
||||
* Default implementation does nothing.
|
||||
*
|
||||
* @param continuation Continuation instance returned by this interceptor's [interceptContinuation] invocation.
|
||||
*/
|
||||
public fun releaseInterceptedContinuation(continuation: Continuation<*>) {
|
||||
/* do nothing by default */
|
||||
}
|
||||
|
||||
// Performance optimization for a singleton Key
|
||||
public override operator fun <E : CoroutineContext.Element> get(key: CoroutineContext.Key<E>): E? =
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
if (key === Key) this as E else null
|
||||
|
||||
// Performance optimization to a singleton Key
|
||||
public override fun minusKey(key: CoroutineContext.Key<*>): CoroutineContext =
|
||||
if (key === Key) EmptyCoroutineContext else this
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package kotlin.coroutines
|
||||
|
||||
/**
|
||||
* Persistent context for the coroutine. It is an indexed set of [Element] instances.
|
||||
* An indexed set is a mix between a set and a map.
|
||||
* Every element in this set has a unique [Key]. Keys are compared _by reference_.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
public interface CoroutineContext {
|
||||
/**
|
||||
* Returns the element with the given [key] from this context or `null`.
|
||||
* Keys are compared _by reference_, that is to get an element from the context the reference to its actual key
|
||||
* object must be presented to this function.
|
||||
*/
|
||||
public operator fun <E : Element> get(key: Key<E>): E?
|
||||
|
||||
/**
|
||||
* Accumulates entries of this context starting with [initial] value and applying [operation]
|
||||
* from left to right to current accumulator value and each element of this context.
|
||||
*/
|
||||
public fun <R> fold(initial: R, operation: (R, Element) -> R): R
|
||||
|
||||
/**
|
||||
* Returns a context containing elements from this context and elements from other [context].
|
||||
* The elements from this context with the same key as in the other one are dropped.
|
||||
*/
|
||||
public operator fun plus(context: CoroutineContext): CoroutineContext =
|
||||
if (context === EmptyCoroutineContext) this else // fast path -- avoid lambda creation
|
||||
context.fold(this) { acc, element ->
|
||||
val removed = acc.minusKey(element.key)
|
||||
if (removed === EmptyCoroutineContext) element else {
|
||||
// make sure interceptor is always last in the context (and thus is fast to get when present)
|
||||
val interceptor = removed[ContinuationInterceptor]
|
||||
if (interceptor == null) CombinedContext(removed, element) else {
|
||||
val left = removed.minusKey(ContinuationInterceptor)
|
||||
if (left === EmptyCoroutineContext) CombinedContext(element, interceptor) else
|
||||
CombinedContext(CombinedContext(left, element), interceptor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a context containing elements from this context, but without an element with
|
||||
* the specified [key]. Keys are compared _by reference_, that is to remove an element from the context
|
||||
* the reference to its actual key object must be presented to this function.
|
||||
*/
|
||||
public fun minusKey(key: Key<*>): CoroutineContext
|
||||
|
||||
/**
|
||||
* Key for the elements of [CoroutineContext]. [E] is a type of element with this key.
|
||||
* Keys in the context are compared _by reference_.
|
||||
*/
|
||||
public interface Key<E : Element>
|
||||
|
||||
/**
|
||||
* An element of the [CoroutineContext]. An element of the coroutine context is a singleton context by itself.
|
||||
*/
|
||||
public interface Element : CoroutineContext {
|
||||
/**
|
||||
* A key of this coroutine context element.
|
||||
*/
|
||||
public val key: Key<*>
|
||||
|
||||
public override operator fun <E : Element> get(key: Key<E>): E? =
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
if (this.key == key) this as E else null
|
||||
|
||||
public override fun <R> fold(initial: R, operation: (R, Element) -> R): R =
|
||||
operation(initial, this)
|
||||
|
||||
public override fun minusKey(key: Key<*>): CoroutineContext =
|
||||
if (this.key == key) EmptyCoroutineContext else this
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package kotlin.coroutines
|
||||
|
||||
import kotlin.coroutines.CoroutineContext.*
|
||||
import kotlin.io.Serializable
|
||||
|
||||
/**
|
||||
* Base class for [CoroutineContext.Element] implementations.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
public abstract class AbstractCoroutineContextElement(public override val key: Key<*>) : Element
|
||||
|
||||
/**
|
||||
* An empty coroutine context.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
public object EmptyCoroutineContext : CoroutineContext, Serializable {
|
||||
private const val serialVersionUID: Long = 0
|
||||
private fun readResolve(): Any = EmptyCoroutineContext
|
||||
|
||||
public override fun <E : Element> get(key: Key<E>): E? = null
|
||||
public override fun <R> fold(initial: R, operation: (R, Element) -> R): R = initial
|
||||
public override fun plus(context: CoroutineContext): CoroutineContext = context
|
||||
public override fun minusKey(key: Key<*>): CoroutineContext = this
|
||||
public override fun hashCode(): Int = 0
|
||||
public override fun toString(): String = "EmptyCoroutineContext"
|
||||
}
|
||||
|
||||
//--------------------- internal impl ---------------------
|
||||
|
||||
// this class is not exposed, but is hidden inside implementations
|
||||
// this is a left-biased list, so that `plus` works naturally
|
||||
@SinceKotlin("1.3")
|
||||
internal class CombinedContext(
|
||||
private val left: CoroutineContext,
|
||||
private val element: Element
|
||||
) : CoroutineContext, Serializable {
|
||||
|
||||
override fun <E : Element> get(key: Key<E>): E? {
|
||||
var cur = this
|
||||
while (true) {
|
||||
cur.element[key]?.let { return it }
|
||||
val next = cur.left
|
||||
if (next is CombinedContext) {
|
||||
cur = next
|
||||
} else {
|
||||
return next[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override fun <R> fold(initial: R, operation: (R, Element) -> R): R =
|
||||
operation(left.fold(initial, operation), element)
|
||||
|
||||
public override fun minusKey(key: Key<*>): CoroutineContext {
|
||||
element[key]?.let { return left }
|
||||
val newLeft = left.minusKey(key)
|
||||
return when {
|
||||
newLeft === left -> this
|
||||
newLeft === EmptyCoroutineContext -> element
|
||||
else -> CombinedContext(newLeft, element)
|
||||
}
|
||||
}
|
||||
|
||||
private fun size(): Int {
|
||||
var cur = this
|
||||
var size = 2
|
||||
while (true) {
|
||||
cur = cur.left as? CombinedContext ?: return size
|
||||
size++
|
||||
}
|
||||
}
|
||||
|
||||
private fun contains(element: Element): Boolean =
|
||||
get(element.key) == element
|
||||
|
||||
private fun containsAll(context: CombinedContext): Boolean {
|
||||
var cur = context
|
||||
while (true) {
|
||||
if (!contains(cur.element)) return false
|
||||
val next = cur.left
|
||||
if (next is CombinedContext) {
|
||||
cur = next
|
||||
} else {
|
||||
return contains(next as Element)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
this === other || other is CombinedContext && other.size() == size() && other.containsAll(this)
|
||||
|
||||
override fun hashCode(): Int = left.hashCode() + element.hashCode()
|
||||
|
||||
override fun toString(): String =
|
||||
"[" + fold("") { acc, element ->
|
||||
if (acc.isEmpty()) element.toString() else "$acc, $element"
|
||||
} + "]"
|
||||
|
||||
private fun writeReplace(): Any {
|
||||
val n = size()
|
||||
val elements = arrayOfNulls<CoroutineContext>(n)
|
||||
var index = 0
|
||||
fold(Unit) { _, element -> elements[index++] = element }
|
||||
check(index == n)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return Serialized(elements as Array<CoroutineContext>)
|
||||
}
|
||||
|
||||
private class Serialized(val elements: Array<CoroutineContext>) : Serializable {
|
||||
companion object {
|
||||
private const val serialVersionUID: Long = 0L
|
||||
}
|
||||
|
||||
private fun readResolve(): Any = elements.fold(EmptyCoroutineContext, CoroutineContext::plus)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package kotlin.coroutines
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
internal expect class SafeContinuation<in T> : Continuation<T> {
|
||||
internal constructor(delegate: Continuation<T>, initialResult: Any?)
|
||||
|
||||
@PublishedApi
|
||||
internal constructor(delegate: Continuation<T>)
|
||||
|
||||
@PublishedApi
|
||||
internal fun getOrThrow(): Any?
|
||||
|
||||
override val context: CoroutineContext
|
||||
override fun resumeWith(result: Result<T>): Unit
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package kotlin.coroutines.intrinsics
|
||||
|
||||
import kotlin.coroutines.Continuation
|
||||
import kotlin.coroutines.ContinuationInterceptor
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
/**
|
||||
* Starts unintercepted coroutine without receiver and with result type [T] and executes it until its first suspension.
|
||||
* Returns the result of the coroutine or throws its exception if it does not suspend or [COROUTINE_SUSPENDED] if it suspends.
|
||||
* In the later case, the [completion] continuation is invoked when coroutine completes with result or exception.
|
||||
*
|
||||
* The coroutine is started directly in the invoker's thread without going through the [ContinuationInterceptor] that might
|
||||
* be present in the completion's [CoroutineContext]. It is invoker's responsibility to ensure that the proper invocation
|
||||
* context is established.
|
||||
*
|
||||
* This function is designed to be used from inside of [suspendCoroutineUninterceptedOrReturn] to resume the execution of suspended
|
||||
* coroutine using a reference to the suspending function.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
public expect inline fun <T> (suspend () -> T).startCoroutineUninterceptedOrReturn(
|
||||
completion: Continuation<T>
|
||||
): Any?
|
||||
|
||||
/**
|
||||
* Starts unintercepted coroutine with receiver type [R] and result type [T] and executes it until its first suspension.
|
||||
* Returns the result of the coroutine or throws its exception if it does not suspend or [COROUTINE_SUSPENDED] if it suspends.
|
||||
* In the later case, the [completion] continuation is invoked when coroutine completes with result or exception.
|
||||
*
|
||||
* The coroutine is started directly in the invoker's thread without going through the [ContinuationInterceptor] that might
|
||||
* be present in the completion's [CoroutineContext]. It is invoker's responsibility to ensure that the proper invocation
|
||||
* context is established.
|
||||
*
|
||||
* This function is designed to be used from inside of [suspendCoroutineUninterceptedOrReturn] to resume the execution of suspended
|
||||
* coroutine using a reference to the suspending function.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
public expect inline fun <R, T> (suspend R.() -> T).startCoroutineUninterceptedOrReturn(
|
||||
receiver: R,
|
||||
completion: Continuation<T>
|
||||
): Any?
|
||||
|
||||
@SinceKotlin("1.3")
|
||||
public expect fun <T> (suspend () -> T).createCoroutineUnintercepted(
|
||||
completion: Continuation<T>
|
||||
): Continuation<Unit>
|
||||
|
||||
@SinceKotlin("1.3")
|
||||
public expect fun <R, T> (suspend R.() -> T).createCoroutineUnintercepted(
|
||||
receiver: R,
|
||||
completion: Continuation<T>
|
||||
): Continuation<Unit>
|
||||
|
||||
/**
|
||||
* Intercepts this continuation with [ContinuationInterceptor].
|
||||
*
|
||||
* This function shall be used on the immediate result of [createCoroutineUnintercepted] or [suspendCoroutineUninterceptedOrReturn],
|
||||
* in which case it checks for [ContinuationInterceptor] in the continuation's [context][Continuation.context],
|
||||
* invokes [ContinuationInterceptor.interceptContinuation], caches and returns result.
|
||||
*
|
||||
* If this function is invoked on other [Continuation] instances it returns `this` continuation unchanged.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
public expect fun <T> Continuation<T>.intercepted(): Continuation<T>
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:kotlin.jvm.JvmName("IntrinsicsKt")
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
|
||||
package kotlin.coroutines.intrinsics
|
||||
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.internal.InlineOnly
|
||||
|
||||
/**
|
||||
* Obtains the current continuation instance inside suspend functions and either suspends
|
||||
* currently running coroutine or returns result immediately without suspension.
|
||||
*
|
||||
* If the [block] returns the special [COROUTINE_SUSPENDED] value, it means that suspend function did suspend the execution and will
|
||||
* not return any result immediately. In this case, the [Continuation] provided to the [block] shall be
|
||||
* resumed by invoking [Continuation.resumeWith] at some moment in the
|
||||
* future when the result becomes available to resume the computation.
|
||||
*
|
||||
* Otherwise, the return value of the [block] must have a type assignable to [T] and represents the result of this suspend function.
|
||||
* It means that the execution was not suspended and the [Continuation] provided to the [block] shall not be invoked.
|
||||
* As the result type of the [block] is declared as `Any?` and cannot be correctly type-checked,
|
||||
* its proper return type remains on the conscience of the suspend function's author.
|
||||
*
|
||||
* Invocation of [Continuation.resumeWith] resumes coroutine directly in the invoker's thread without going through the
|
||||
* [ContinuationInterceptor] that might be present in the coroutine's [CoroutineContext].
|
||||
* It is invoker's responsibility to ensure that the proper invocation context is established.
|
||||
* [Continuation.intercepted] can be used to acquire the intercepted continuation.
|
||||
*
|
||||
* Note that it is not recommended to call either [Continuation.resume] nor [Continuation.resumeWithException] functions synchronously
|
||||
* in the same stackframe where suspension function is run. Use [suspendCoroutine] as a safer way to obtain current
|
||||
* continuation instance.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@InlineOnly
|
||||
@Suppress("UNUSED_PARAMETER", "RedundantSuspendModifier")
|
||||
public suspend inline fun <T> suspendCoroutineUninterceptedOrReturn(crossinline block: (Continuation<T>) -> Any?): T =
|
||||
throw NotImplementedError("Implementation of suspendCoroutineUninterceptedOrReturn is intrinsic")
|
||||
|
||||
/**
|
||||
* This value is used as a return value of [suspendCoroutineUninterceptedOrReturn] `block` argument to state that
|
||||
* the execution was suspended and will not return any result immediately.
|
||||
*/
|
||||
// It is implemented as property with getter to avoid ProGuard <clinit> problem with multifile IntrinsicsKt class
|
||||
@SinceKotlin("1.3")
|
||||
public val COROUTINE_SUSPENDED: Any get() = CoroutineSingletons.COROUTINE_SUSPENDED
|
||||
|
||||
// Using enum here ensures two important properties:
|
||||
// 1. It makes SafeContinuation serializable with all kinds of serialization frameworks (since all of them natively support enums)
|
||||
// 2. It improves debugging experience, since you clearly see toString() value of those objects and what package they come from
|
||||
@SinceKotlin("1.3")
|
||||
@PublishedApi // This class is Published API via serialized representation of SafeContinuation, don't rename/move
|
||||
internal enum class CoroutineSingletons { COROUTINE_SUSPENDED, UNDECIDED, RESUMED }
|
||||
@@ -0,0 +1,334 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:Suppress("UNCHECKED_CAST", "RedundantVisibilityModifier")
|
||||
|
||||
package kotlin
|
||||
|
||||
import kotlin.contracts.*
|
||||
import kotlin.internal.InlineOnly
|
||||
import kotlin.jvm.JvmField
|
||||
|
||||
/**
|
||||
* A discriminated union that encapsulates successful outcome with a value of type [T]
|
||||
* or a failure with an arbitrary [Throwable] exception.
|
||||
*/
|
||||
@Suppress("NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS")
|
||||
@SinceKotlin("1.3")
|
||||
public inline class Result<out T> @PublishedApi internal constructor(
|
||||
@PublishedApi
|
||||
internal val value: Any?
|
||||
) : Serializable {
|
||||
// discovery
|
||||
|
||||
/**
|
||||
* Returns `true` if this instance represents successful outcome.
|
||||
* In this case [isFailure] returns `false`.
|
||||
*/
|
||||
public val isSuccess: Boolean get() = value !is Failure
|
||||
|
||||
/**
|
||||
* Returns `true` if this instance represents failed outcome.
|
||||
* In this case [isSuccess] returns `false`.
|
||||
*/
|
||||
public val isFailure: Boolean get() = value is Failure
|
||||
|
||||
// value & exception retrieval
|
||||
|
||||
/**
|
||||
* Returns the encapsulated value if this instance represents [success][Result.isSuccess] or `null`
|
||||
* if it is [failure][Result.isFailure].
|
||||
*
|
||||
* This function is shorthand for `getOrElse { null }` (see [getOrElse]) or
|
||||
* `fold(onSuccess = { it }, onFailure = { null })` (see [fold]).
|
||||
*/
|
||||
@InlineOnly
|
||||
public inline fun getOrNull(): T? =
|
||||
when {
|
||||
isFailure -> null
|
||||
else -> value as T
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the encapsulated exception if this instance represents [failure][isFailure] or `null`
|
||||
* if it is [success][isSuccess].
|
||||
*
|
||||
* This function is shorthand for `fold(onSuccess = { null }, onFailure = { it })` (see [fold]).
|
||||
*/
|
||||
public fun exceptionOrNull(): Throwable? =
|
||||
when (value) {
|
||||
is Failure -> value.exception
|
||||
else -> null
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string `Success(v)` if this instance represents [success][Result.isSuccess]
|
||||
* where `v` is a string representation of the value or a string `Failure(x)` if
|
||||
* it is [failure][isFailure] where `x` is a string representation of the exception.
|
||||
*/
|
||||
public override fun toString(): String =
|
||||
when (value) {
|
||||
is Failure -> value.toString() // "Failure($exception)"
|
||||
else -> "Success($value)"
|
||||
}
|
||||
|
||||
// companion with constructors
|
||||
|
||||
/**
|
||||
* Companion object for [Result] class that contains its constructor functions
|
||||
* [success] and [failure].
|
||||
*/
|
||||
public companion object {
|
||||
/**
|
||||
* Returns an instance that encapsulates the given [value] as successful value.
|
||||
*/
|
||||
@InlineOnly
|
||||
public inline fun <T> success(value: T): Result<T> =
|
||||
Result(value)
|
||||
|
||||
/**
|
||||
* Returns an instance that encapsulates the given [exception] as failure.
|
||||
*/
|
||||
@InlineOnly
|
||||
public inline fun <T> failure(exception: Throwable): Result<T> =
|
||||
Result(createFailure(exception))
|
||||
}
|
||||
|
||||
internal class Failure(
|
||||
@JvmField
|
||||
val exception: Throwable
|
||||
) : Serializable {
|
||||
override fun equals(other: Any?): Boolean = other is Failure && exception == other.exception
|
||||
override fun hashCode(): Int = exception.hashCode()
|
||||
override fun toString(): String = "Failure($exception)"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of internal marker [Result.Failure] class to
|
||||
* make sure that this class is not exposed in ABI.
|
||||
*/
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
internal fun createFailure(exception: Throwable): Any =
|
||||
Result.Failure(exception)
|
||||
|
||||
/**
|
||||
* Throws exception if the result is failure. This internal function minimizes
|
||||
* inlined bytecode for [getOrThrow] and makes sure that in the future we can
|
||||
* add some exception-augmenting logic here (if needed).
|
||||
*/
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
internal fun Result<*>.throwOnFailure() {
|
||||
if (value is Result.Failure) throw value.exception
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the specified function [block] and returns its encapsulated result if invocation was successful,
|
||||
* catching and encapsulating any thrown exception as a failure.
|
||||
*/
|
||||
@InlineOnly
|
||||
@SinceKotlin("1.3")
|
||||
public inline fun <R> runCatching(block: () -> R): Result<R> {
|
||||
return try {
|
||||
Result.success(block())
|
||||
} catch (e: Throwable) {
|
||||
Result.failure(e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the specified function [block] with `this` value as its receiver and returns its encapsulated result
|
||||
* if invocation was successful, catching and encapsulating any thrown exception as a failure.
|
||||
*/
|
||||
@InlineOnly
|
||||
@SinceKotlin("1.3")
|
||||
public inline fun <T, R> T.runCatching(block: T.() -> R): Result<R> {
|
||||
return try {
|
||||
Result.success(block())
|
||||
} catch (e: Throwable) {
|
||||
Result.failure(e)
|
||||
}
|
||||
}
|
||||
|
||||
// -- extensions ---
|
||||
|
||||
/**
|
||||
* Returns the encapsulated value if this instance represents [success][Result.isSuccess] or throws the encapsulated exception
|
||||
* if it is [failure][Result.isFailure].
|
||||
*
|
||||
* This function is shorthand for `getOrElse { throw it }` (see [getOrElse]).
|
||||
*/
|
||||
@InlineOnly
|
||||
@SinceKotlin("1.3")
|
||||
public inline fun <T> Result<T>.getOrThrow(): T {
|
||||
throwOnFailure()
|
||||
return value as T
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the encapsulated value if this instance represents [success][Result.isSuccess] or the
|
||||
* result of [onFailure] function for encapsulated exception if it is [failure][Result.isFailure].
|
||||
*
|
||||
* Note, that an exception thrown by [onFailure] function is rethrown by this function.
|
||||
*
|
||||
* This function is shorthand for `fold(onSuccess = { it }, onFailure = onFailure)` (see [fold]).
|
||||
*/
|
||||
@InlineOnly
|
||||
@SinceKotlin("1.3")
|
||||
public inline fun <R, T : R> Result<T>.getOrElse(onFailure: (exception: Throwable) -> R): R {
|
||||
contract {
|
||||
callsInPlace(onFailure, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
return when (val exception = exceptionOrNull()) {
|
||||
null -> value as T
|
||||
else -> onFailure(exception)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the encapsulated value if this instance represents [success][Result.isSuccess] or the
|
||||
* [defaultValue] if it is [failure][Result.isFailure].
|
||||
*
|
||||
* This function is shorthand for `getOrElse { defaultValue }` (see [getOrElse]).
|
||||
*/
|
||||
@InlineOnly
|
||||
@SinceKotlin("1.3")
|
||||
public inline fun <R, T : R> Result<T>.getOrDefault(defaultValue: R): R {
|
||||
if (isFailure) return defaultValue
|
||||
return value as T
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the the result of [onSuccess] for encapsulated value if this instance represents [success][Result.isSuccess]
|
||||
* or the result of [onFailure] function for encapsulated exception if it is [failure][Result.isFailure].
|
||||
*
|
||||
* Note, that an exception thrown by [onSuccess] or by [onFailure] function is rethrown by this function.
|
||||
*/
|
||||
@InlineOnly
|
||||
@SinceKotlin("1.3")
|
||||
public inline fun <R, T> Result<T>.fold(
|
||||
onSuccess: (value: T) -> R,
|
||||
onFailure: (exception: Throwable) -> R
|
||||
): R {
|
||||
contract {
|
||||
callsInPlace(onSuccess, InvocationKind.AT_MOST_ONCE)
|
||||
callsInPlace(onFailure, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
return when (val exception = exceptionOrNull()) {
|
||||
null -> onSuccess(value as T)
|
||||
else -> onFailure(exception)
|
||||
}
|
||||
}
|
||||
|
||||
// transformation
|
||||
|
||||
/**
|
||||
* Returns the encapsulated result of the given [transform] function applied to encapsulated value
|
||||
* if this instance represents [success][Result.isSuccess] or the
|
||||
* original encapsulated exception if it is [failure][Result.isFailure].
|
||||
*
|
||||
* Note, that an exception thrown by [transform] function is rethrown by this function.
|
||||
* See [mapCatching] for an alternative that encapsulates exceptions.
|
||||
*/
|
||||
@InlineOnly
|
||||
@SinceKotlin("1.3")
|
||||
public inline fun <R, T> Result<T>.map(transform: (value: T) -> R): Result<R> {
|
||||
contract {
|
||||
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
return when {
|
||||
isSuccess -> Result.success(transform(value as T))
|
||||
else -> Result(value)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the encapsulated result of the given [transform] function applied to encapsulated value
|
||||
* if this instance represents [success][Result.isSuccess] or the
|
||||
* original encapsulated exception if it is [failure][Result.isFailure].
|
||||
*
|
||||
* Any exception thrown by [transform] function is caught, encapsulated as a failure and returned by this function.
|
||||
* See [map] for an alternative that rethrows exceptions.
|
||||
*/
|
||||
@InlineOnly
|
||||
@SinceKotlin("1.3")
|
||||
public inline fun <R, T> Result<T>.mapCatching(transform: (value: T) -> R): Result<R> {
|
||||
return when {
|
||||
isSuccess -> runCatching { transform(value as T) }
|
||||
else -> Result(value)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the encapsulated result of the given [transform] function applied to encapsulated exception
|
||||
* if this instance represents [failure][Result.isFailure] or the
|
||||
* original encapsulated value if it is [success][Result.isSuccess].
|
||||
*
|
||||
* Note, that an exception thrown by [transform] function is rethrown by this function.
|
||||
* See [recoverCatching] for an alternative that encapsulates exceptions.
|
||||
*/
|
||||
@InlineOnly
|
||||
@SinceKotlin("1.3")
|
||||
public inline fun <R, T : R> Result<T>.recover(transform: (exception: Throwable) -> R): Result<R> {
|
||||
contract {
|
||||
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
return when (val exception = exceptionOrNull()) {
|
||||
null -> this
|
||||
else -> Result.success(transform(exception))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the encapsulated result of the given [transform] function applied to encapsulated exception
|
||||
* if this instance represents [failure][Result.isFailure] or the
|
||||
* original encapsulated value if it is [success][Result.isSuccess].
|
||||
*
|
||||
* Any exception thrown by [transform] function is caught, encapsulated as a failure and returned by this function.
|
||||
* See [recover] for an alternative that rethrows exceptions.
|
||||
*/
|
||||
@InlineOnly
|
||||
@SinceKotlin("1.3")
|
||||
public inline fun <R, T : R> Result<T>.recoverCatching(transform: (exception: Throwable) -> R): Result<R> {
|
||||
val value = value // workaround for inline classes BE bug
|
||||
return when (val exception = exceptionOrNull()) {
|
||||
null -> this
|
||||
else -> runCatching { transform(exception) }
|
||||
}
|
||||
}
|
||||
|
||||
// "peek" onto value/exception and pipe
|
||||
|
||||
/**
|
||||
* Performs the given [action] on encapsulated value if this instance represents [success][Result.isSuccess].
|
||||
* Returns the original `Result` unchanged.
|
||||
*/
|
||||
@InlineOnly
|
||||
@SinceKotlin("1.3")
|
||||
public inline fun <T> Result<T>.onFailure(action: (exception: Throwable) -> Unit): Result<T> {
|
||||
contract {
|
||||
callsInPlace(action, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
exceptionOrNull()?.let { action(it) }
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the given [action] on encapsulated exception if this instance represents [failure][Result.isFailure].
|
||||
* Returns the original `Result` unchanged.
|
||||
*/
|
||||
@InlineOnly
|
||||
@SinceKotlin("1.3")
|
||||
public inline fun <T> Result<T>.onSuccess(action: (value: T) -> Unit): Result<T> {
|
||||
contract {
|
||||
callsInPlace(action, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
if (isSuccess) action(value as T)
|
||||
return this
|
||||
}
|
||||
|
||||
// -------------------
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package kotlin
|
||||
|
||||
/**
|
||||
* A discriminated union that encapsulates successful outcome with a value of type [T]
|
||||
* or a failure with an arbitrary [Throwable] exception.
|
||||
* @suppress **Deprecated**: Renamed to [Result].
|
||||
*/
|
||||
@Deprecated(
|
||||
message = "Renamed to Result",
|
||||
level = DeprecationLevel.ERROR,
|
||||
replaceWith = ReplaceWith("Result")
|
||||
)
|
||||
@SinceKotlin("1.3")
|
||||
public typealias SuccessOrFailure<T> = Result<T>
|
||||
Reference in New Issue
Block a user