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

commonMain.io.lamart.lux.Behavior.kt Maven / Gradle / Ivy

There is a newer version: 0.5.2
Show newest version
package io.lamart.lux

import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.*
import kotlin.jvm.JvmName

interface Behavior : (Flow) -> Flow> {

    @OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class)
    companion object {

        fun  create(flow: suspend (I) -> Flow, transform: Flow.(suspend (I) -> Flow>) -> Flow>): Behavior =
            object : Behavior {
                override fun invoke(inputFlow: Flow): Flow> =
                    transform(inputFlow) { input ->
                        flow(input)
                            .map> { Signal.Next(it) }
                            .catch { emit(Signal.End(it)) }
                            .prepend(Signal.Start(input))
                            .append(Signal.End(null))
                            .distinctUntilChanged { old, new -> old is Signal.End && new is Signal.End } // make sure only 1 end is sent.
                    }
            }

        fun  from(suspension: suspend (I) -> O): suspend (I) -> Flow =
            { flowOf(it).map(suspension) }

        @JvmName("exhaustingSuspension")
        fun  exhausting(suspension: suspend (I) -> O): Behavior =
            exhausting(flow = from(suspension))

        @JvmName("exhaustingFlow")
        fun  exhausting(flow: suspend (I) -> Flow): Behavior =
            create(flow, { flatMapMerge(concurrency = 1, it) })

        @JvmName("mergingSuspension")
        fun  merging(suspension: suspend (I) -> O): Behavior =
            merging(flow = from(suspension))

        @JvmName("mergingFlow")
        fun  merging(flow: suspend (I) -> Flow): Behavior =
            create(flow, { flatMapMerge(concurrency = DEFAULT_CONCURRENCY, it) })

        @JvmName("concattingSuspension")
        fun  concatting(suspension: suspend (I) -> O): Behavior =
            concatting(flow = from(suspension))

        @JvmName("concattingFlow")
        fun  concatting(flow: suspend (I) -> Flow): Behavior =
            create(flow, { flatMapConcat(it) })

        @JvmName("switchingSuspension")
        fun  switching(suspension: suspend (I) -> O): Behavior =
            switching(flow = from(suspension))

        @JvmName("switchingFlow")
        fun  switching(flow: suspend (I) -> Flow): Behavior =
            create(flow, { flatMapLatest(it) })

    }
}

@OptIn(ExperimentalCoroutinesApi::class)
private fun  Flow.prepend(vararg values: T): Flow =
    listOf(flowOf(*values), this).asFlow().flattenConcat()

@OptIn(ExperimentalCoroutinesApi::class)
private fun  Flow.append(vararg values: T): Flow =
    listOf(this, flowOf(*values)).asFlow().flattenConcat()