From 51192553d06bf9f17348590be9efba0e392a8183 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petrus=20Nguy=E1=BB=85n=20Th=C3=A1i=20H=E1=BB=8Dc?= Date: Mon, 9 Dec 2024 01:11:29 +0700 Subject: [PATCH 1/7] add `StateFlow.mapState`, `combineStates` --- .idea/misc.xml | 3 +- .idea/vcs.xml | 2 +- .../com/hoc081098/flowext/StateFlows.kt | 478 ++++++++++++++++++ 3 files changed, 481 insertions(+), 2 deletions(-) create mode 100644 src/commonMain/kotlin/com/hoc081098/flowext/StateFlows.kt diff --git a/.idea/misc.xml b/.idea/misc.xml index ac801d80..d15a4819 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,7 @@ + - + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 4c6280eb..aae8b7c8 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -9,4 +9,4 @@ - \ No newline at end of file + diff --git a/src/commonMain/kotlin/com/hoc081098/flowext/StateFlows.kt b/src/commonMain/kotlin/com/hoc081098/flowext/StateFlows.kt new file mode 100644 index 00000000..56112450 --- /dev/null +++ b/src/commonMain/kotlin/com/hoc081098/flowext/StateFlows.kt @@ -0,0 +1,478 @@ +/* + * MIT License + * + * Copyright (c) 2021-2024 Petrus Nguyễn Thái Học + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.hoc081098.flowext + +import kotlinx.coroutines.ExperimentalForInheritanceCoroutinesApi +import kotlinx.coroutines.InternalCoroutinesApi +import kotlinx.coroutines.awaitCancellation +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.FlowCollector +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn + +/** + * Map a [StateFlow] to another [StateFlow] with the given [transform] function. + * + * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] + * with the latest value of the source [StateFlow]. + * This is useful when you want to map a [StateFlow] to another [StateFlow] instead of a [Flow]. + * + * @see map + * @see combineStates + */ +public fun StateFlow.mapState(transform: (value: T) -> R): StateFlow = + MappedAsStateFlow(this, transform) + +/** + * Combine two [StateFlow]s into a new [StateFlow] with the given [transform] function. + * + * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] + * with the latest values of the source [StateFlow]s. + * This is useful when you want to combine two or more [StateFlow]s into a single [StateFlow] instead of a [Flow]. + * + * @see combine + * @see mapState + */ +public fun combineStates( + flow1: StateFlow, + flow2: StateFlow, + transform: (T1, T2) -> R, +): StateFlow = + DerivedStateFlow( + source = combine(flow1, flow2, transform), + valueSupplier = { transform(flow1.value, flow2.value) }, + ) + +/** + * Combine three [StateFlow]s into a new [StateFlow] with the given [transform] function. + * + * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] + * with the latest values of the source [StateFlow]s. + * This is useful when you want to combine three or more [StateFlow]s into a single [StateFlow] instead of a [Flow]. + * + * @see combine + * @see mapState + */ +public fun combineStates( + flow1: StateFlow, + flow2: StateFlow, + flow3: StateFlow, + transform: (T1, T2, T3) -> R, +): StateFlow = + DerivedStateFlow( + source = combine(flow1, flow2, flow3, transform), + valueSupplier = { transform(flow1.value, flow2.value, flow3.value) }, + ) + +/** + * Combine four [StateFlow]s into a new [StateFlow] with the given [transform] function. + * + * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] + * with the latest values of the source [StateFlow]s. + * This is useful when you want to combine four or more [StateFlow]s into a single [StateFlow] instead of a [Flow]. + * + * @see combine + * @see mapState + */ +public fun combineStates( + flow1: StateFlow, + flow2: StateFlow, + flow3: StateFlow, + flow4: StateFlow, + transform: (T1, T2, T3, T4) -> R, +): StateFlow = + DerivedStateFlow( + source = combine(flow1, flow2, flow3, flow4, transform), + valueSupplier = { transform(flow1.value, flow2.value, flow3.value, flow4.value) }, + ) + +/** + * Combine five [StateFlow]s into a new [StateFlow] with the given [transform] function. + * + * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] + * with the latest values of the source [StateFlow]s. + * This is useful when you want to combine five or more [StateFlow]s into a single [StateFlow] instead of a [Flow]. + * + * @see combine + * @see mapState + */ +public fun combineStates( + flow1: StateFlow, + flow2: StateFlow, + flow3: StateFlow, + flow4: StateFlow, + flow5: StateFlow, + transform: (T1, T2, T3, T4, T5) -> R, +): StateFlow = + DerivedStateFlow( + source = combine(flow1, flow2, flow3, flow4, flow5, transform), + valueSupplier = { transform(flow1.value, flow2.value, flow3.value, flow4.value, flow5.value) }, + ) + +/** + * Combine six [StateFlow]s into a new [StateFlow] with the given [transform] function. + * + * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] + * with the latest values of the source [StateFlow]s. + * This is useful when you want to combine six or more [StateFlow]s into a single [StateFlow] instead of a [Flow]. + * + * @see combine + * @see mapState + */ +public fun combineStates( + flow1: StateFlow, + flow2: StateFlow, + flow3: StateFlow, + flow4: StateFlow, + flow5: StateFlow, + flow6: StateFlow, + transform: (T1, T2, T3, T4, T5, T6) -> R, +): StateFlow = + DerivedStateFlow( + source = combine(flow1, flow2, flow3, flow4, flow5, flow6, transform), + valueSupplier = { + transform( + flow1.value, + flow2.value, + flow3.value, + flow4.value, + flow5.value, + flow6.value, + ) + }, + ) + +/** + * Combine seven [StateFlow]s into a new [StateFlow] with the given [transform] function. + * + * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] + * with the latest values of the source [StateFlow]s. + * This is useful when you want to combine seven or more [StateFlow]s into a single [StateFlow] instead of a [Flow]. + * + * @see combine + * @see mapState + */ +public fun combineStates( + flow1: StateFlow, + flow2: StateFlow, + flow3: StateFlow, + flow4: StateFlow, + flow5: StateFlow, + flow6: StateFlow, + flow7: StateFlow, + transform: (T1, T2, T3, T4, T5, T6, T7) -> R, +): StateFlow = + DerivedStateFlow( + source = combine(flow1, flow2, flow3, flow4, flow5, flow6, flow7, transform), + valueSupplier = { + transform( + flow1.value, + flow2.value, + flow3.value, + flow4.value, + flow5.value, + flow6.value, + flow7.value, + ) + }, + ) + +/** + * Combine eight [StateFlow]s into a new [StateFlow] with the given [transform] function. + * + * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] + * with the latest values of the source [StateFlow]s. + * This is useful when you want to combine eight or more [StateFlow]s into a single [StateFlow] instead of a [Flow]. + * + * @see combine + * @see mapState + */ +public fun combineStates( + flow1: StateFlow, + flow2: StateFlow, + flow3: StateFlow, + flow4: StateFlow, + flow5: StateFlow, + flow6: StateFlow, + flow7: StateFlow, + flow8: StateFlow, + transform: (T1, T2, T3, T4, T5, T6, T7, T8) -> R, +): StateFlow = + DerivedStateFlow( + source = combine(flow1, flow2, flow3, flow4, flow5, flow6, flow7, flow8, transform), + valueSupplier = { + transform( + flow1.value, + flow2.value, + flow3.value, + flow4.value, + flow5.value, + flow6.value, + flow7.value, + flow8.value, + ) + }, + ) + +/** + * Combine nine [StateFlow]s into a new [StateFlow] with the given [transform] function. + * + * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] + * with the latest values of the source [StateFlow]s. + * This is useful when you want to combine nine or more [StateFlow]s into a single [StateFlow] instead of a [Flow]. + * + * @see combine + * @see mapState + */ +public fun combineStates( + flow1: StateFlow, + flow2: StateFlow, + flow3: StateFlow, + flow4: StateFlow, + flow5: StateFlow, + flow6: StateFlow, + flow7: StateFlow, + flow8: StateFlow, + flow9: StateFlow, + transform: (T1, T2, T3, T4, T5, T6, T7, T8, T9) -> R, +): StateFlow = + DerivedStateFlow( + source = combine(flow1, flow2, flow3, flow4, flow5, flow6, flow7, flow8, flow9, transform), + valueSupplier = { + transform( + flow1.value, + flow2.value, + flow3.value, + flow4.value, + flow5.value, + flow6.value, + flow7.value, + flow8.value, + flow9.value, + ) + }, + ) + +/** + * Combine ten [StateFlow]s into a new [StateFlow] with the given [transform] function. + * + * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] + * with the latest values of the source [StateFlow]s. + * This is useful when you want to combine ten or more [StateFlow]s into a single [StateFlow] instead of a [Flow]. + * + * @see combine + * @see mapState + */ +public fun combineStates( + flow1: StateFlow, + flow2: StateFlow, + flow3: StateFlow, + flow4: StateFlow, + flow5: StateFlow, + flow6: StateFlow, + flow7: StateFlow, + flow8: StateFlow, + flow9: StateFlow, + flow10: StateFlow, + transform: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) -> R, +): StateFlow = + DerivedStateFlow( + source = combine( + flow1, flow2, flow3, flow4, flow5, flow6, flow7, flow8, flow9, flow10, transform, + ), + valueSupplier = { + transform( + flow1.value, + flow2.value, + flow3.value, + flow4.value, + flow5.value, + flow6.value, + flow7.value, + flow8.value, + flow9.value, + flow10.value, + ) + }, + ) + +/** + * Combine eleven [StateFlow]s into a new [StateFlow] with the given [transform] function. + * + * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] + * with the latest values of the source [StateFlow]s. + * This is useful when you want to combine eleven or more [StateFlow]s into a single [StateFlow] instead of a [Flow]. + * + * @see combine + * @see mapState + */ +public fun combineStates( + flow1: StateFlow, + flow2: StateFlow, + flow3: StateFlow, + flow4: StateFlow, + flow5: StateFlow, + flow6: StateFlow, + flow7: StateFlow, + flow8: StateFlow, + flow9: StateFlow, + flow10: StateFlow, + flow11: StateFlow, + transform: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) -> R, +): StateFlow = + DerivedStateFlow( + source = combine( + flow1, flow2, flow3, flow4, flow5, flow6, flow7, flow8, flow9, flow10, flow11, transform, + ), + valueSupplier = { + transform( + flow1.value, + flow2.value, + flow3.value, + flow4.value, + flow5.value, + flow6.value, + flow7.value, + flow8.value, + flow9.value, + flow10.value, + flow11.value, + ) + }, + ) + +/** + * Combine twelve [StateFlow]s into a new [StateFlow] with the given [transform] function. + * + * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] + * with the latest values of the source [StateFlow]s. + * This is useful when you want to combine twelve or more [StateFlow]s into a single [StateFlow] instead of a [Flow]. + * + * @see combine + * @see mapState + */ +public fun combineStates( + flow1: StateFlow, + flow2: StateFlow, + flow3: StateFlow, + flow4: StateFlow, + flow5: StateFlow, + flow6: StateFlow, + flow7: StateFlow, + flow8: StateFlow, + flow9: StateFlow, + flow10: StateFlow, + flow11: StateFlow, + flow12: StateFlow, + transform: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) -> R, +): StateFlow = + DerivedStateFlow( + source = combine( + flow1, + flow2, + flow3, + flow4, + flow5, + flow6, + flow7, + flow8, + flow9, + flow10, + flow11, + flow12, + transform, + ), + valueSupplier = { + transform( + flow1.value, + flow2.value, + flow3.value, + flow4.value, + flow5.value, + flow6.value, + flow7.value, + flow8.value, + flow9.value, + flow10.value, + flow11.value, + flow12.value, + ) + }, + ) + +// ---------------------------------------- INTERNAL IMPLEMENTATION ---------------------------------------- + +/** + * Map a [Flow] to a [StateFlow] with the given [transform] function. + * + * Ref: [kotlinx.coroutines/issues/2631](https://github.com/Kotlin/kotlinx.coroutines/issues/2631#issuecomment-870565860) + */ +@Suppress("UnnecessaryOptInAnnotation") +@OptIn(ExperimentalForInheritanceCoroutinesApi::class) +private class MappedAsStateFlow( + private val source: StateFlow, + private val transform: (T) -> R, +) : StateFlow { + override val value: R get() = transform(source.value) + override val replayCache: List get() = listOf(value) + + override suspend fun collect(collector: FlowCollector): Nothing { + source + .map(transform) + .distinctUntilChanged() + .collect(collector) + + awaitCancellation() + } +} + +/** + * Special state flow which value is supplied by [valueSupplier] and collection is delegated to [source] + * [valueSupplier] should NEVER THROW to avoid contract violation + * + * Ref: [kotlinx.coroutines/issues/2631](https://github.com/Kotlin/kotlinx.coroutines/issues/2631#issuecomment-870565860) + */ +@Suppress("UnnecessaryOptInAnnotation") +@OptIn(ExperimentalForInheritanceCoroutinesApi::class) +private class DerivedStateFlow( + private val source: Flow, + private val valueSupplier: () -> T, +) : StateFlow { + override val value: T get() = valueSupplier() + override val replayCache: List get() = listOf(value) + + @InternalCoroutinesApi + override suspend fun collect(collector: FlowCollector): Nothing { + coroutineScope { + source + .stateIn(this) + .collect(collector) + } + } +} From c5d3a08729ffd4821b464e28d183b2b946c122a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petrus=20Nguy=E1=BB=85n=20Th=C3=A1i=20H=E1=BB=8Dc?= Date: Mon, 9 Dec 2024 01:15:12 +0700 Subject: [PATCH 2/7] gradle kotlinUpgradeYarnLock --- .idea/vcs.xml | 4 +++- kotlin-js-store/yarn.lock | 15 +++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/.idea/vcs.xml b/.idea/vcs.xml index aae8b7c8..90816381 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -3,10 +3,12 @@ + + - + \ No newline at end of file diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index bef08ef4..8c8f8034 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -274,6 +274,13 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" +kotlin-web-helpers@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/kotlin-web-helpers/-/kotlin-web-helpers-2.0.0.tgz#b112096b273c1e733e0b86560998235c09a19286" + integrity sha512-xkVGl60Ygn/zuLkDPx+oHj7jeLR7hCvoNF99nhwXMn8a3ApB4lLiC9pk4ol4NHPjyoCbvQctBqvzUcp8pkqyWw== + dependencies: + format-util "^1.0.5" + locate-path@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" @@ -296,10 +303,10 @@ minimatch@^5.0.1, minimatch@^5.1.6: dependencies: brace-expansion "^2.0.1" -mocha@10.7.0: - version "10.7.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.7.0.tgz#9e5cbed8fa9b37537a25bd1f7fb4f6fc45458b9a" - integrity sha512-v8/rBWr2VO5YkspYINnvu81inSz2y3ODJrhO175/Exzor1RcEZZkizgE2A+w/CAXXoESS8Kys5E62dOHGHzULA== +mocha@10.7.3: + version "10.7.3" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.7.3.tgz#ae32003cabbd52b59aece17846056a68eb4b0752" + integrity sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A== dependencies: ansi-colors "^4.1.3" browser-stdout "^1.3.1" From ea4d4a1b671a974515f5b1ede0dc8a16012ffecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petrus=20Nguy=E1=BB=85n=20Th=C3=A1i=20H=E1=BB=8Dc?= Date: Mon, 9 Dec 2024 01:18:00 +0700 Subject: [PATCH 3/7] apiDump --- api/FlowExt.klib.api | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/api/FlowExt.klib.api b/api/FlowExt.klib.api index 366ab74d..70986f1c 100644 --- a/api/FlowExt.klib.api +++ b/api/FlowExt.klib.api @@ -103,18 +103,29 @@ final val com.hoc081098.flowext.utils/NULL_VALUE // com.hoc081098.flowext.utils/ final fun (): com.hoc081098.flowext.utils/Symbol // com.hoc081098.flowext.utils/NULL_VALUE.|(){}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?, #I: kotlin/Any?, #J: kotlin/Any?, #K: kotlin/Any?, #L: kotlin/Any?, #M: kotlin/Any?> com.hoc081098.flowext/combine(kotlinx.coroutines.flow/Flow<#A>, kotlinx.coroutines.flow/Flow<#B>, kotlinx.coroutines.flow/Flow<#C>, kotlinx.coroutines.flow/Flow<#D>, kotlinx.coroutines.flow/Flow<#E>, kotlinx.coroutines.flow/Flow<#F>, kotlinx.coroutines.flow/Flow<#G>, kotlinx.coroutines.flow/Flow<#H>, kotlinx.coroutines.flow/Flow<#I>, kotlinx.coroutines.flow/Flow<#J>, kotlinx.coroutines.flow/Flow<#K>, kotlinx.coroutines.flow/Flow<#L>, kotlin.coroutines/SuspendFunction12<#A, #B, #C, #D, #E, #F, #G, #H, #I, #J, #K, #L, #M>): kotlinx.coroutines.flow/Flow<#M> // com.hoc081098.flowext/combine|combine(kotlinx.coroutines.flow.Flow<0:0>;kotlinx.coroutines.flow.Flow<0:1>;kotlinx.coroutines.flow.Flow<0:2>;kotlinx.coroutines.flow.Flow<0:3>;kotlinx.coroutines.flow.Flow<0:4>;kotlinx.coroutines.flow.Flow<0:5>;kotlinx.coroutines.flow.Flow<0:6>;kotlinx.coroutines.flow.Flow<0:7>;kotlinx.coroutines.flow.Flow<0:8>;kotlinx.coroutines.flow.Flow<0:9>;kotlinx.coroutines.flow.Flow<0:10>;kotlinx.coroutines.flow.Flow<0:11>;kotlin.coroutines.SuspendFunction12<0:0,0:1,0:2,0:3,0:4,0:5,0:6,0:7,0:8,0:9,0:10,0:11,0:12>){0§;1§;2§;3§;4§;5§;6§;7§;8§;9§;10§;11§;12§}[0] +final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?, #I: kotlin/Any?, #J: kotlin/Any?, #K: kotlin/Any?, #L: kotlin/Any?, #M: kotlin/Any?> com.hoc081098.flowext/combineStates(kotlinx.coroutines.flow/StateFlow<#A>, kotlinx.coroutines.flow/StateFlow<#B>, kotlinx.coroutines.flow/StateFlow<#C>, kotlinx.coroutines.flow/StateFlow<#D>, kotlinx.coroutines.flow/StateFlow<#E>, kotlinx.coroutines.flow/StateFlow<#F>, kotlinx.coroutines.flow/StateFlow<#G>, kotlinx.coroutines.flow/StateFlow<#H>, kotlinx.coroutines.flow/StateFlow<#I>, kotlinx.coroutines.flow/StateFlow<#J>, kotlinx.coroutines.flow/StateFlow<#K>, kotlinx.coroutines.flow/StateFlow<#L>, kotlin/Function12<#A, #B, #C, #D, #E, #F, #G, #H, #I, #J, #K, #L, #M>): kotlinx.coroutines.flow/StateFlow<#M> // com.hoc081098.flowext/combineStates|combineStates(kotlinx.coroutines.flow.StateFlow<0:0>;kotlinx.coroutines.flow.StateFlow<0:1>;kotlinx.coroutines.flow.StateFlow<0:2>;kotlinx.coroutines.flow.StateFlow<0:3>;kotlinx.coroutines.flow.StateFlow<0:4>;kotlinx.coroutines.flow.StateFlow<0:5>;kotlinx.coroutines.flow.StateFlow<0:6>;kotlinx.coroutines.flow.StateFlow<0:7>;kotlinx.coroutines.flow.StateFlow<0:8>;kotlinx.coroutines.flow.StateFlow<0:9>;kotlinx.coroutines.flow.StateFlow<0:10>;kotlinx.coroutines.flow.StateFlow<0:11>;kotlin.Function12<0:0,0:1,0:2,0:3,0:4,0:5,0:6,0:7,0:8,0:9,0:10,0:11,0:12>){0§;1§;2§;3§;4§;5§;6§;7§;8§;9§;10§;11§;12§}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?, #I: kotlin/Any?, #J: kotlin/Any?, #K: kotlin/Any?, #L: kotlin/Any?> com.hoc081098.flowext/combine(kotlinx.coroutines.flow/Flow<#A>, kotlinx.coroutines.flow/Flow<#B>, kotlinx.coroutines.flow/Flow<#C>, kotlinx.coroutines.flow/Flow<#D>, kotlinx.coroutines.flow/Flow<#E>, kotlinx.coroutines.flow/Flow<#F>, kotlinx.coroutines.flow/Flow<#G>, kotlinx.coroutines.flow/Flow<#H>, kotlinx.coroutines.flow/Flow<#I>, kotlinx.coroutines.flow/Flow<#J>, kotlinx.coroutines.flow/Flow<#K>, kotlin.coroutines/SuspendFunction11<#A, #B, #C, #D, #E, #F, #G, #H, #I, #J, #K, #L>): kotlinx.coroutines.flow/Flow<#L> // com.hoc081098.flowext/combine|combine(kotlinx.coroutines.flow.Flow<0:0>;kotlinx.coroutines.flow.Flow<0:1>;kotlinx.coroutines.flow.Flow<0:2>;kotlinx.coroutines.flow.Flow<0:3>;kotlinx.coroutines.flow.Flow<0:4>;kotlinx.coroutines.flow.Flow<0:5>;kotlinx.coroutines.flow.Flow<0:6>;kotlinx.coroutines.flow.Flow<0:7>;kotlinx.coroutines.flow.Flow<0:8>;kotlinx.coroutines.flow.Flow<0:9>;kotlinx.coroutines.flow.Flow<0:10>;kotlin.coroutines.SuspendFunction11<0:0,0:1,0:2,0:3,0:4,0:5,0:6,0:7,0:8,0:9,0:10,0:11>){0§;1§;2§;3§;4§;5§;6§;7§;8§;9§;10§;11§}[0] +final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?, #I: kotlin/Any?, #J: kotlin/Any?, #K: kotlin/Any?, #L: kotlin/Any?> com.hoc081098.flowext/combineStates(kotlinx.coroutines.flow/StateFlow<#A>, kotlinx.coroutines.flow/StateFlow<#B>, kotlinx.coroutines.flow/StateFlow<#C>, kotlinx.coroutines.flow/StateFlow<#D>, kotlinx.coroutines.flow/StateFlow<#E>, kotlinx.coroutines.flow/StateFlow<#F>, kotlinx.coroutines.flow/StateFlow<#G>, kotlinx.coroutines.flow/StateFlow<#H>, kotlinx.coroutines.flow/StateFlow<#I>, kotlinx.coroutines.flow/StateFlow<#J>, kotlinx.coroutines.flow/StateFlow<#K>, kotlin/Function11<#A, #B, #C, #D, #E, #F, #G, #H, #I, #J, #K, #L>): kotlinx.coroutines.flow/StateFlow<#L> // com.hoc081098.flowext/combineStates|combineStates(kotlinx.coroutines.flow.StateFlow<0:0>;kotlinx.coroutines.flow.StateFlow<0:1>;kotlinx.coroutines.flow.StateFlow<0:2>;kotlinx.coroutines.flow.StateFlow<0:3>;kotlinx.coroutines.flow.StateFlow<0:4>;kotlinx.coroutines.flow.StateFlow<0:5>;kotlinx.coroutines.flow.StateFlow<0:6>;kotlinx.coroutines.flow.StateFlow<0:7>;kotlinx.coroutines.flow.StateFlow<0:8>;kotlinx.coroutines.flow.StateFlow<0:9>;kotlinx.coroutines.flow.StateFlow<0:10>;kotlin.Function11<0:0,0:1,0:2,0:3,0:4,0:5,0:6,0:7,0:8,0:9,0:10,0:11>){0§;1§;2§;3§;4§;5§;6§;7§;8§;9§;10§;11§}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?, #I: kotlin/Any?, #J: kotlin/Any?, #K: kotlin/Any?> com.hoc081098.flowext/combine(kotlinx.coroutines.flow/Flow<#A>, kotlinx.coroutines.flow/Flow<#B>, kotlinx.coroutines.flow/Flow<#C>, kotlinx.coroutines.flow/Flow<#D>, kotlinx.coroutines.flow/Flow<#E>, kotlinx.coroutines.flow/Flow<#F>, kotlinx.coroutines.flow/Flow<#G>, kotlinx.coroutines.flow/Flow<#H>, kotlinx.coroutines.flow/Flow<#I>, kotlinx.coroutines.flow/Flow<#J>, kotlin.coroutines/SuspendFunction10<#A, #B, #C, #D, #E, #F, #G, #H, #I, #J, #K>): kotlinx.coroutines.flow/Flow<#K> // com.hoc081098.flowext/combine|combine(kotlinx.coroutines.flow.Flow<0:0>;kotlinx.coroutines.flow.Flow<0:1>;kotlinx.coroutines.flow.Flow<0:2>;kotlinx.coroutines.flow.Flow<0:3>;kotlinx.coroutines.flow.Flow<0:4>;kotlinx.coroutines.flow.Flow<0:5>;kotlinx.coroutines.flow.Flow<0:6>;kotlinx.coroutines.flow.Flow<0:7>;kotlinx.coroutines.flow.Flow<0:8>;kotlinx.coroutines.flow.Flow<0:9>;kotlin.coroutines.SuspendFunction10<0:0,0:1,0:2,0:3,0:4,0:5,0:6,0:7,0:8,0:9,0:10>){0§;1§;2§;3§;4§;5§;6§;7§;8§;9§;10§}[0] +final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?, #I: kotlin/Any?, #J: kotlin/Any?, #K: kotlin/Any?> com.hoc081098.flowext/combineStates(kotlinx.coroutines.flow/StateFlow<#A>, kotlinx.coroutines.flow/StateFlow<#B>, kotlinx.coroutines.flow/StateFlow<#C>, kotlinx.coroutines.flow/StateFlow<#D>, kotlinx.coroutines.flow/StateFlow<#E>, kotlinx.coroutines.flow/StateFlow<#F>, kotlinx.coroutines.flow/StateFlow<#G>, kotlinx.coroutines.flow/StateFlow<#H>, kotlinx.coroutines.flow/StateFlow<#I>, kotlinx.coroutines.flow/StateFlow<#J>, kotlin/Function10<#A, #B, #C, #D, #E, #F, #G, #H, #I, #J, #K>): kotlinx.coroutines.flow/StateFlow<#K> // com.hoc081098.flowext/combineStates|combineStates(kotlinx.coroutines.flow.StateFlow<0:0>;kotlinx.coroutines.flow.StateFlow<0:1>;kotlinx.coroutines.flow.StateFlow<0:2>;kotlinx.coroutines.flow.StateFlow<0:3>;kotlinx.coroutines.flow.StateFlow<0:4>;kotlinx.coroutines.flow.StateFlow<0:5>;kotlinx.coroutines.flow.StateFlow<0:6>;kotlinx.coroutines.flow.StateFlow<0:7>;kotlinx.coroutines.flow.StateFlow<0:8>;kotlinx.coroutines.flow.StateFlow<0:9>;kotlin.Function10<0:0,0:1,0:2,0:3,0:4,0:5,0:6,0:7,0:8,0:9,0:10>){0§;1§;2§;3§;4§;5§;6§;7§;8§;9§;10§}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?, #I: kotlin/Any?, #J: kotlin/Any?> com.hoc081098.flowext/combine(kotlinx.coroutines.flow/Flow<#A>, kotlinx.coroutines.flow/Flow<#B>, kotlinx.coroutines.flow/Flow<#C>, kotlinx.coroutines.flow/Flow<#D>, kotlinx.coroutines.flow/Flow<#E>, kotlinx.coroutines.flow/Flow<#F>, kotlinx.coroutines.flow/Flow<#G>, kotlinx.coroutines.flow/Flow<#H>, kotlinx.coroutines.flow/Flow<#I>, kotlin.coroutines/SuspendFunction9<#A, #B, #C, #D, #E, #F, #G, #H, #I, #J>): kotlinx.coroutines.flow/Flow<#J> // com.hoc081098.flowext/combine|combine(kotlinx.coroutines.flow.Flow<0:0>;kotlinx.coroutines.flow.Flow<0:1>;kotlinx.coroutines.flow.Flow<0:2>;kotlinx.coroutines.flow.Flow<0:3>;kotlinx.coroutines.flow.Flow<0:4>;kotlinx.coroutines.flow.Flow<0:5>;kotlinx.coroutines.flow.Flow<0:6>;kotlinx.coroutines.flow.Flow<0:7>;kotlinx.coroutines.flow.Flow<0:8>;kotlin.coroutines.SuspendFunction9<0:0,0:1,0:2,0:3,0:4,0:5,0:6,0:7,0:8,0:9>){0§;1§;2§;3§;4§;5§;6§;7§;8§;9§}[0] +final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?, #I: kotlin/Any?, #J: kotlin/Any?> com.hoc081098.flowext/combineStates(kotlinx.coroutines.flow/StateFlow<#A>, kotlinx.coroutines.flow/StateFlow<#B>, kotlinx.coroutines.flow/StateFlow<#C>, kotlinx.coroutines.flow/StateFlow<#D>, kotlinx.coroutines.flow/StateFlow<#E>, kotlinx.coroutines.flow/StateFlow<#F>, kotlinx.coroutines.flow/StateFlow<#G>, kotlinx.coroutines.flow/StateFlow<#H>, kotlinx.coroutines.flow/StateFlow<#I>, kotlin/Function9<#A, #B, #C, #D, #E, #F, #G, #H, #I, #J>): kotlinx.coroutines.flow/StateFlow<#J> // com.hoc081098.flowext/combineStates|combineStates(kotlinx.coroutines.flow.StateFlow<0:0>;kotlinx.coroutines.flow.StateFlow<0:1>;kotlinx.coroutines.flow.StateFlow<0:2>;kotlinx.coroutines.flow.StateFlow<0:3>;kotlinx.coroutines.flow.StateFlow<0:4>;kotlinx.coroutines.flow.StateFlow<0:5>;kotlinx.coroutines.flow.StateFlow<0:6>;kotlinx.coroutines.flow.StateFlow<0:7>;kotlinx.coroutines.flow.StateFlow<0:8>;kotlin.Function9<0:0,0:1,0:2,0:3,0:4,0:5,0:6,0:7,0:8,0:9>){0§;1§;2§;3§;4§;5§;6§;7§;8§;9§}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?, #I: kotlin/Any?> com.hoc081098.flowext/combine(kotlinx.coroutines.flow/Flow<#A>, kotlinx.coroutines.flow/Flow<#B>, kotlinx.coroutines.flow/Flow<#C>, kotlinx.coroutines.flow/Flow<#D>, kotlinx.coroutines.flow/Flow<#E>, kotlinx.coroutines.flow/Flow<#F>, kotlinx.coroutines.flow/Flow<#G>, kotlinx.coroutines.flow/Flow<#H>, kotlin.coroutines/SuspendFunction8<#A, #B, #C, #D, #E, #F, #G, #H, #I>): kotlinx.coroutines.flow/Flow<#I> // com.hoc081098.flowext/combine|combine(kotlinx.coroutines.flow.Flow<0:0>;kotlinx.coroutines.flow.Flow<0:1>;kotlinx.coroutines.flow.Flow<0:2>;kotlinx.coroutines.flow.Flow<0:3>;kotlinx.coroutines.flow.Flow<0:4>;kotlinx.coroutines.flow.Flow<0:5>;kotlinx.coroutines.flow.Flow<0:6>;kotlinx.coroutines.flow.Flow<0:7>;kotlin.coroutines.SuspendFunction8<0:0,0:1,0:2,0:3,0:4,0:5,0:6,0:7,0:8>){0§;1§;2§;3§;4§;5§;6§;7§;8§}[0] +final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?, #I: kotlin/Any?> com.hoc081098.flowext/combineStates(kotlinx.coroutines.flow/StateFlow<#A>, kotlinx.coroutines.flow/StateFlow<#B>, kotlinx.coroutines.flow/StateFlow<#C>, kotlinx.coroutines.flow/StateFlow<#D>, kotlinx.coroutines.flow/StateFlow<#E>, kotlinx.coroutines.flow/StateFlow<#F>, kotlinx.coroutines.flow/StateFlow<#G>, kotlinx.coroutines.flow/StateFlow<#H>, kotlin/Function8<#A, #B, #C, #D, #E, #F, #G, #H, #I>): kotlinx.coroutines.flow/StateFlow<#I> // com.hoc081098.flowext/combineStates|combineStates(kotlinx.coroutines.flow.StateFlow<0:0>;kotlinx.coroutines.flow.StateFlow<0:1>;kotlinx.coroutines.flow.StateFlow<0:2>;kotlinx.coroutines.flow.StateFlow<0:3>;kotlinx.coroutines.flow.StateFlow<0:4>;kotlinx.coroutines.flow.StateFlow<0:5>;kotlinx.coroutines.flow.StateFlow<0:6>;kotlinx.coroutines.flow.StateFlow<0:7>;kotlin.Function8<0:0,0:1,0:2,0:3,0:4,0:5,0:6,0:7,0:8>){0§;1§;2§;3§;4§;5§;6§;7§;8§}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?> com.hoc081098.flowext/combine(kotlinx.coroutines.flow/Flow<#A>, kotlinx.coroutines.flow/Flow<#B>, kotlinx.coroutines.flow/Flow<#C>, kotlinx.coroutines.flow/Flow<#D>, kotlinx.coroutines.flow/Flow<#E>, kotlinx.coroutines.flow/Flow<#F>, kotlinx.coroutines.flow/Flow<#G>, kotlin.coroutines/SuspendFunction7<#A, #B, #C, #D, #E, #F, #G, #H>): kotlinx.coroutines.flow/Flow<#H> // com.hoc081098.flowext/combine|combine(kotlinx.coroutines.flow.Flow<0:0>;kotlinx.coroutines.flow.Flow<0:1>;kotlinx.coroutines.flow.Flow<0:2>;kotlinx.coroutines.flow.Flow<0:3>;kotlinx.coroutines.flow.Flow<0:4>;kotlinx.coroutines.flow.Flow<0:5>;kotlinx.coroutines.flow.Flow<0:6>;kotlin.coroutines.SuspendFunction7<0:0,0:1,0:2,0:3,0:4,0:5,0:6,0:7>){0§;1§;2§;3§;4§;5§;6§;7§}[0] +final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?> com.hoc081098.flowext/combineStates(kotlinx.coroutines.flow/StateFlow<#A>, kotlinx.coroutines.flow/StateFlow<#B>, kotlinx.coroutines.flow/StateFlow<#C>, kotlinx.coroutines.flow/StateFlow<#D>, kotlinx.coroutines.flow/StateFlow<#E>, kotlinx.coroutines.flow/StateFlow<#F>, kotlinx.coroutines.flow/StateFlow<#G>, kotlin/Function7<#A, #B, #C, #D, #E, #F, #G, #H>): kotlinx.coroutines.flow/StateFlow<#H> // com.hoc081098.flowext/combineStates|combineStates(kotlinx.coroutines.flow.StateFlow<0:0>;kotlinx.coroutines.flow.StateFlow<0:1>;kotlinx.coroutines.flow.StateFlow<0:2>;kotlinx.coroutines.flow.StateFlow<0:3>;kotlinx.coroutines.flow.StateFlow<0:4>;kotlinx.coroutines.flow.StateFlow<0:5>;kotlinx.coroutines.flow.StateFlow<0:6>;kotlin.Function7<0:0,0:1,0:2,0:3,0:4,0:5,0:6,0:7>){0§;1§;2§;3§;4§;5§;6§;7§}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?> (kotlinx.coroutines.flow/Flow<#A>).com.hoc081098.flowext/select(kotlin.coroutines/SuspendFunction1<#A, #B>, kotlin.coroutines/SuspendFunction1<#A, #C>, kotlin.coroutines/SuspendFunction1<#A, #D>, kotlin.coroutines/SuspendFunction1<#A, #E>, kotlin.coroutines/SuspendFunction1<#A, #F>, kotlin.coroutines/SuspendFunction5<#B, #C, #D, #E, #F, #G>): kotlinx.coroutines.flow/Flow<#G> // com.hoc081098.flowext/select|select@kotlinx.coroutines.flow.Flow<0:0>(kotlin.coroutines.SuspendFunction1<0:0,0:1>;kotlin.coroutines.SuspendFunction1<0:0,0:2>;kotlin.coroutines.SuspendFunction1<0:0,0:3>;kotlin.coroutines.SuspendFunction1<0:0,0:4>;kotlin.coroutines.SuspendFunction1<0:0,0:5>;kotlin.coroutines.SuspendFunction5<0:1,0:2,0:3,0:4,0:5,0:6>){0§;1§;2§;3§;4§;5§;6§}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?> com.hoc081098.flowext/combine(kotlinx.coroutines.flow/Flow<#A>, kotlinx.coroutines.flow/Flow<#B>, kotlinx.coroutines.flow/Flow<#C>, kotlinx.coroutines.flow/Flow<#D>, kotlinx.coroutines.flow/Flow<#E>, kotlinx.coroutines.flow/Flow<#F>, kotlin.coroutines/SuspendFunction6<#A, #B, #C, #D, #E, #F, #G>): kotlinx.coroutines.flow/Flow<#G> // com.hoc081098.flowext/combine|combine(kotlinx.coroutines.flow.Flow<0:0>;kotlinx.coroutines.flow.Flow<0:1>;kotlinx.coroutines.flow.Flow<0:2>;kotlinx.coroutines.flow.Flow<0:3>;kotlinx.coroutines.flow.Flow<0:4>;kotlinx.coroutines.flow.Flow<0:5>;kotlin.coroutines.SuspendFunction6<0:0,0:1,0:2,0:3,0:4,0:5,0:6>){0§;1§;2§;3§;4§;5§;6§}[0] +final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?> com.hoc081098.flowext/combineStates(kotlinx.coroutines.flow/StateFlow<#A>, kotlinx.coroutines.flow/StateFlow<#B>, kotlinx.coroutines.flow/StateFlow<#C>, kotlinx.coroutines.flow/StateFlow<#D>, kotlinx.coroutines.flow/StateFlow<#E>, kotlinx.coroutines.flow/StateFlow<#F>, kotlin/Function6<#A, #B, #C, #D, #E, #F, #G>): kotlinx.coroutines.flow/StateFlow<#G> // com.hoc081098.flowext/combineStates|combineStates(kotlinx.coroutines.flow.StateFlow<0:0>;kotlinx.coroutines.flow.StateFlow<0:1>;kotlinx.coroutines.flow.StateFlow<0:2>;kotlinx.coroutines.flow.StateFlow<0:3>;kotlinx.coroutines.flow.StateFlow<0:4>;kotlinx.coroutines.flow.StateFlow<0:5>;kotlin.Function6<0:0,0:1,0:2,0:3,0:4,0:5,0:6>){0§;1§;2§;3§;4§;5§;6§}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?> (kotlinx.coroutines.flow/Flow<#A>).com.hoc081098.flowext/select(kotlin.coroutines/SuspendFunction1<#A, #B>, kotlin.coroutines/SuspendFunction1<#A, #C>, kotlin.coroutines/SuspendFunction1<#A, #D>, kotlin.coroutines/SuspendFunction1<#A, #E>, kotlin.coroutines/SuspendFunction4<#B, #C, #D, #E, #F>): kotlinx.coroutines.flow/Flow<#F> // com.hoc081098.flowext/select|select@kotlinx.coroutines.flow.Flow<0:0>(kotlin.coroutines.SuspendFunction1<0:0,0:1>;kotlin.coroutines.SuspendFunction1<0:0,0:2>;kotlin.coroutines.SuspendFunction1<0:0,0:3>;kotlin.coroutines.SuspendFunction1<0:0,0:4>;kotlin.coroutines.SuspendFunction4<0:1,0:2,0:3,0:4,0:5>){0§;1§;2§;3§;4§;5§}[0] +final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?> com.hoc081098.flowext/combineStates(kotlinx.coroutines.flow/StateFlow<#A>, kotlinx.coroutines.flow/StateFlow<#B>, kotlinx.coroutines.flow/StateFlow<#C>, kotlinx.coroutines.flow/StateFlow<#D>, kotlinx.coroutines.flow/StateFlow<#E>, kotlin/Function5<#A, #B, #C, #D, #E, #F>): kotlinx.coroutines.flow/StateFlow<#F> // com.hoc081098.flowext/combineStates|combineStates(kotlinx.coroutines.flow.StateFlow<0:0>;kotlinx.coroutines.flow.StateFlow<0:1>;kotlinx.coroutines.flow.StateFlow<0:2>;kotlinx.coroutines.flow.StateFlow<0:3>;kotlinx.coroutines.flow.StateFlow<0:4>;kotlin.Function5<0:0,0:1,0:2,0:3,0:4,0:5>){0§;1§;2§;3§;4§;5§}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?> (kotlinx.coroutines.flow/Flow<#A>).com.hoc081098.flowext/select(kotlin.coroutines/SuspendFunction1<#A, #B>, kotlin.coroutines/SuspendFunction1<#A, #C>, kotlin.coroutines/SuspendFunction1<#A, #D>, kotlin.coroutines/SuspendFunction3<#B, #C, #D, #E>): kotlinx.coroutines.flow/Flow<#E> // com.hoc081098.flowext/select|select@kotlinx.coroutines.flow.Flow<0:0>(kotlin.coroutines.SuspendFunction1<0:0,0:1>;kotlin.coroutines.SuspendFunction1<0:0,0:2>;kotlin.coroutines.SuspendFunction1<0:0,0:3>;kotlin.coroutines.SuspendFunction3<0:1,0:2,0:3,0:4>){0§;1§;2§;3§;4§}[0] +final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?> com.hoc081098.flowext/combineStates(kotlinx.coroutines.flow/StateFlow<#A>, kotlinx.coroutines.flow/StateFlow<#B>, kotlinx.coroutines.flow/StateFlow<#C>, kotlinx.coroutines.flow/StateFlow<#D>, kotlin/Function4<#A, #B, #C, #D, #E>): kotlinx.coroutines.flow/StateFlow<#E> // com.hoc081098.flowext/combineStates|combineStates(kotlinx.coroutines.flow.StateFlow<0:0>;kotlinx.coroutines.flow.StateFlow<0:1>;kotlinx.coroutines.flow.StateFlow<0:2>;kotlinx.coroutines.flow.StateFlow<0:3>;kotlin.Function4<0:0,0:1,0:2,0:3,0:4>){0§;1§;2§;3§;4§}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?> (kotlinx.coroutines.flow/Flow<#A>).com.hoc081098.flowext/select(kotlin.coroutines/SuspendFunction1<#A, #B>, kotlin.coroutines/SuspendFunction1<#A, #C>, kotlin.coroutines/SuspendFunction2<#B, #C, #D>): kotlinx.coroutines.flow/Flow<#D> // com.hoc081098.flowext/select|select@kotlinx.coroutines.flow.Flow<0:0>(kotlin.coroutines.SuspendFunction1<0:0,0:1>;kotlin.coroutines.SuspendFunction1<0:0,0:2>;kotlin.coroutines.SuspendFunction2<0:1,0:2,0:3>){0§;1§;2§;3§}[0] +final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?> com.hoc081098.flowext/combineStates(kotlinx.coroutines.flow/StateFlow<#A>, kotlinx.coroutines.flow/StateFlow<#B>, kotlinx.coroutines.flow/StateFlow<#C>, kotlin/Function3<#A, #B, #C, #D>): kotlinx.coroutines.flow/StateFlow<#D> // com.hoc081098.flowext/combineStates|combineStates(kotlinx.coroutines.flow.StateFlow<0:0>;kotlinx.coroutines.flow.StateFlow<0:1>;kotlinx.coroutines.flow.StateFlow<0:2>;kotlin.Function3<0:0,0:1,0:2,0:3>){0§;1§;2§;3§}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?> (kotlinx.coroutines.flow/Flow<#A>).com.hoc081098.flowext/groupBy(kotlin/Int = ..., kotlin.coroutines/SuspendFunction1<#A, #B>, kotlin.coroutines/SuspendFunction1<#A, #C>): kotlinx.coroutines.flow/Flow> // com.hoc081098.flowext/groupBy|groupBy@kotlinx.coroutines.flow.Flow<0:0>(kotlin.Int;kotlin.coroutines.SuspendFunction1<0:0,0:1>;kotlin.coroutines.SuspendFunction1<0:0,0:2>){0§;1§;2§}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?> (kotlinx.coroutines.flow/Flow<#A>).com.hoc081098.flowext/withLatestFrom(kotlinx.coroutines.flow/Flow<#B>, kotlin.coroutines/SuspendFunction2<#A, #B, #C>): kotlinx.coroutines.flow/Flow<#C> // com.hoc081098.flowext/withLatestFrom|withLatestFrom@kotlinx.coroutines.flow.Flow<0:0>(kotlinx.coroutines.flow.Flow<0:1>;kotlin.coroutines.SuspendFunction2<0:0,0:1,0:2>){0§;1§;2§}[0] +final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?> com.hoc081098.flowext/combineStates(kotlinx.coroutines.flow/StateFlow<#A>, kotlinx.coroutines.flow/StateFlow<#B>, kotlin/Function2<#A, #B, #C>): kotlinx.coroutines.flow/StateFlow<#C> // com.hoc081098.flowext/combineStates|combineStates(kotlinx.coroutines.flow.StateFlow<0:0>;kotlinx.coroutines.flow.StateFlow<0:1>;kotlin.Function2<0:0,0:1,0:2>){0§;1§;2§}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?> (kotlinx.coroutines.flow/Flow<#A>).com.hoc081098.flowext/exhaustMap(kotlin.coroutines/SuspendFunction1<#A, kotlinx.coroutines.flow/Flow<#B>>): kotlinx.coroutines.flow/Flow<#B> // com.hoc081098.flowext/exhaustMap|exhaustMap@kotlinx.coroutines.flow.Flow<0:0>(kotlin.coroutines.SuspendFunction1<0:0,kotlinx.coroutines.flow.Flow<0:1>>){0§;1§}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?> (kotlinx.coroutines.flow/Flow<#A>).com.hoc081098.flowext/flatMapConcatEager(kotlin/Int = ..., kotlin/Int = ..., kotlin.coroutines/SuspendFunction1<#A, kotlinx.coroutines.flow/Flow<#B>>): kotlinx.coroutines.flow/Flow<#B> // com.hoc081098.flowext/flatMapConcatEager|flatMapConcatEager@kotlinx.coroutines.flow.Flow<0:0>(kotlin.Int;kotlin.Int;kotlin.coroutines.SuspendFunction1<0:0,kotlinx.coroutines.flow.Flow<0:1>>){0§;1§}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?> (kotlinx.coroutines.flow/Flow<#A>).com.hoc081098.flowext/flatMapFirst(kotlin.coroutines/SuspendFunction1<#A, kotlinx.coroutines.flow/Flow<#B>>): kotlinx.coroutines.flow/Flow<#B> // com.hoc081098.flowext/flatMapFirst|flatMapFirst@kotlinx.coroutines.flow.Flow<0:0>(kotlin.coroutines.SuspendFunction1<0:0,kotlinx.coroutines.flow.Flow<0:1>>){0§;1§}[0] @@ -126,6 +137,7 @@ final fun <#A: kotlin/Any?, #B: kotlin/Any?> (kotlinx.coroutines.flow/Flow<#A>). final fun <#A: kotlin/Any?, #B: kotlin/Any?> (kotlinx.coroutines.flow/Flow<#A>).com.hoc081098.flowext/select(kotlin.coroutines/SuspendFunction1<#A, #B>): kotlinx.coroutines.flow/Flow<#B> // com.hoc081098.flowext/select|select@kotlinx.coroutines.flow.Flow<0:0>(kotlin.coroutines.SuspendFunction1<0:0,0:1>){0§;1§}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?> (kotlinx.coroutines.flow/Flow<#A>).com.hoc081098.flowext/zipWithNext(kotlin.coroutines/SuspendFunction2<#A, #A, #B>): kotlinx.coroutines.flow/Flow<#B> // com.hoc081098.flowext/zipWithNext|zipWithNext@kotlinx.coroutines.flow.Flow<0:0>(kotlin.coroutines.SuspendFunction2<0:0,0:0,0:1>){0§;1§}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?> (kotlinx.coroutines.flow/Flow>).com.hoc081098.flowext/mapResultCatching(kotlin.coroutines/SuspendFunction1<#A, #B>): kotlinx.coroutines.flow/Flow> // com.hoc081098.flowext/mapResultCatching|mapResultCatching@kotlinx.coroutines.flow.Flow>(kotlin.coroutines.SuspendFunction1<0:0,0:1>){0§;1§}[0] +final fun <#A: kotlin/Any?, #B: kotlin/Any?> (kotlinx.coroutines.flow/StateFlow<#A>).com.hoc081098.flowext/mapState(kotlin/Function1<#A, #B>): kotlinx.coroutines.flow/StateFlow<#B> // com.hoc081098.flowext/mapState|mapState@kotlinx.coroutines.flow.StateFlow<0:0>(kotlin.Function1<0:0,0:1>){0§;1§}[0] final fun <#A: kotlin/Any?> (kotlinx.coroutines.flow/Flow<#A>).com.hoc081098.flowext/ambWith(kotlinx.coroutines.flow/Flow<#A>, kotlin/Array>...): kotlinx.coroutines.flow/Flow<#A> // com.hoc081098.flowext/ambWith|ambWith@kotlinx.coroutines.flow.Flow<0:0>(kotlinx.coroutines.flow.Flow<0:0>;kotlin.Array>...){0§}[0] final fun <#A: kotlin/Any?> (kotlinx.coroutines.flow/Flow<#A>).com.hoc081098.flowext/bufferCount(kotlin/Int): kotlinx.coroutines.flow/Flow> // com.hoc081098.flowext/bufferCount|bufferCount@kotlinx.coroutines.flow.Flow<0:0>(kotlin.Int){0§}[0] final fun <#A: kotlin/Any?> (kotlinx.coroutines.flow/Flow<#A>).com.hoc081098.flowext/bufferCount(kotlin/Int, kotlin/Int): kotlinx.coroutines.flow/Flow> // com.hoc081098.flowext/bufferCount|bufferCount@kotlinx.coroutines.flow.Flow<0:0>(kotlin.Int;kotlin.Int){0§}[0] From ef2586b2f518a24ae7e39329c4c5e4c4afdcb1f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petrus=20Nguy=E1=BB=85n=20Th=C3=A1i=20H=E1=BB=8Dc?= Date: Mon, 9 Dec 2024 01:19:19 +0700 Subject: [PATCH 4/7] apiDump --- api/FlowExt.api | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/api/FlowExt.api b/api/FlowExt.api index 20e0ec5e..b1eaf703 100644 --- a/api/FlowExt.api +++ b/api/FlowExt.api @@ -250,6 +250,21 @@ public final class com/hoc081098/flowext/SkipUntilKt { public static final fun skipUntil (Lkotlinx/coroutines/flow/Flow;Lkotlinx/coroutines/flow/Flow;)Lkotlinx/coroutines/flow/Flow; } +public final class com/hoc081098/flowext/StateFlowsKt { + public static final fun combineStates (Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/flow/StateFlow; + public static final fun combineStates (Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlin/jvm/functions/Function3;)Lkotlinx/coroutines/flow/StateFlow; + public static final fun combineStates (Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlin/jvm/functions/Function4;)Lkotlinx/coroutines/flow/StateFlow; + public static final fun combineStates (Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlin/jvm/functions/Function5;)Lkotlinx/coroutines/flow/StateFlow; + public static final fun combineStates (Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlin/jvm/functions/Function6;)Lkotlinx/coroutines/flow/StateFlow; + public static final fun combineStates (Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlin/jvm/functions/Function7;)Lkotlinx/coroutines/flow/StateFlow; + public static final fun combineStates (Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlin/jvm/functions/Function8;)Lkotlinx/coroutines/flow/StateFlow; + public static final fun combineStates (Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlin/jvm/functions/Function9;)Lkotlinx/coroutines/flow/StateFlow; + public static final fun combineStates (Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlin/jvm/functions/Function10;)Lkotlinx/coroutines/flow/StateFlow; + public static final fun combineStates (Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlin/jvm/functions/Function11;)Lkotlinx/coroutines/flow/StateFlow; + public static final fun combineStates (Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlinx/coroutines/flow/StateFlow;Lkotlin/jvm/functions/Function12;)Lkotlinx/coroutines/flow/StateFlow; + public static final fun mapState (Lkotlinx/coroutines/flow/StateFlow;Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/flow/StateFlow; +} + public final class com/hoc081098/flowext/TakeUntilKt { public static final fun takeUntil (Lkotlinx/coroutines/flow/Flow;Lkotlinx/coroutines/flow/Flow;)Lkotlinx/coroutines/flow/Flow; } From c635ac60458db7d907be62e4ec8dfe363a7e6776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petrus=20Nguy=E1=BB=85n=20Th=C3=A1i=20H=E1=BB=8Dc?= Date: Mon, 9 Dec 2024 01:21:49 +0700 Subject: [PATCH 5/7] `@FlowExtPreview` --- .../kotlin/com/hoc081098/flowext/StateFlows.kt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/commonMain/kotlin/com/hoc081098/flowext/StateFlows.kt b/src/commonMain/kotlin/com/hoc081098/flowext/StateFlows.kt index 56112450..bd516ac1 100644 --- a/src/commonMain/kotlin/com/hoc081098/flowext/StateFlows.kt +++ b/src/commonMain/kotlin/com/hoc081098/flowext/StateFlows.kt @@ -46,6 +46,7 @@ import kotlinx.coroutines.flow.stateIn * @see map * @see combineStates */ +@FlowExtPreview public fun StateFlow.mapState(transform: (value: T) -> R): StateFlow = MappedAsStateFlow(this, transform) @@ -59,6 +60,7 @@ public fun StateFlow.mapState(transform: (value: T) -> R): StateFlow combineStates( flow1: StateFlow, flow2: StateFlow, @@ -79,6 +81,7 @@ public fun combineStates( * @see combine * @see mapState */ +@FlowExtPreview public fun combineStates( flow1: StateFlow, flow2: StateFlow, @@ -100,6 +103,7 @@ public fun combineStates( * @see combine * @see mapState */ +@FlowExtPreview public fun combineStates( flow1: StateFlow, flow2: StateFlow, @@ -122,6 +126,7 @@ public fun combineStates( * @see combine * @see mapState */ +@FlowExtPreview public fun combineStates( flow1: StateFlow, flow2: StateFlow, @@ -145,6 +150,7 @@ public fun combineStates( * @see combine * @see mapState */ +@FlowExtPreview public fun combineStates( flow1: StateFlow, flow2: StateFlow, @@ -178,6 +184,7 @@ public fun combineStates( * @see combine * @see mapState */ +@FlowExtPreview public fun combineStates( flow1: StateFlow, flow2: StateFlow, @@ -213,6 +220,7 @@ public fun combineStates( * @see combine * @see mapState */ +@FlowExtPreview public fun combineStates( flow1: StateFlow, flow2: StateFlow, @@ -250,6 +258,7 @@ public fun combineStates( * @see combine * @see mapState */ +@FlowExtPreview public fun combineStates( flow1: StateFlow, flow2: StateFlow, @@ -289,6 +298,7 @@ public fun combineStates( * @see combine * @see mapState */ +@FlowExtPreview public fun combineStates( flow1: StateFlow, flow2: StateFlow, @@ -332,6 +342,7 @@ public fun combineStates( * @see combine * @see mapState */ +@FlowExtPreview public fun combineStates( flow1: StateFlow, flow2: StateFlow, @@ -377,6 +388,7 @@ public fun combineStates( * @see combine * @see mapState */ +@FlowExtPreview public fun combineStates( flow1: StateFlow, flow2: StateFlow, @@ -435,6 +447,7 @@ public fun combineStates( */ @Suppress("UnnecessaryOptInAnnotation") @OptIn(ExperimentalForInheritanceCoroutinesApi::class) +@FlowExtPreview private class MappedAsStateFlow( private val source: StateFlow, private val transform: (T) -> R, @@ -460,6 +473,7 @@ private class MappedAsStateFlow( */ @Suppress("UnnecessaryOptInAnnotation") @OptIn(ExperimentalForInheritanceCoroutinesApi::class) +@FlowExtPreview private class DerivedStateFlow( private val source: Flow, private val valueSupplier: () -> T, From e771c480903464ec0dc65841c039c5f2c1fee512 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petrus=20Nguy=E1=BB=85n=20Th=C3=A1i=20H=E1=BB=8Dc?= Date: Mon, 9 Dec 2024 01:38:13 +0700 Subject: [PATCH 6/7] mapState tests --- .../com/hoc081098/flowext/StateFlows.kt | 24 +++--- .../com/hoc081098/flowext/MapStateTest.kt | 76 +++++++++++++++++++ .../com/hoc081098/flowext/utils/BaseTest.kt | 9 +++ 3 files changed, 97 insertions(+), 12 deletions(-) create mode 100644 src/commonTest/kotlin/com/hoc081098/flowext/MapStateTest.kt diff --git a/src/commonMain/kotlin/com/hoc081098/flowext/StateFlows.kt b/src/commonMain/kotlin/com/hoc081098/flowext/StateFlows.kt index bd516ac1..725e8c6e 100644 --- a/src/commonMain/kotlin/com/hoc081098/flowext/StateFlows.kt +++ b/src/commonMain/kotlin/com/hoc081098/flowext/StateFlows.kt @@ -37,7 +37,7 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn /** - * Map a [StateFlow] to another [StateFlow] with the given [transform] function. + * Map a [StateFlow] to another read-only [StateFlow] with the given [transform] function. * * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] * with the latest value of the source [StateFlow]. @@ -51,7 +51,7 @@ public fun StateFlow.mapState(transform: (value: T) -> R): StateFlow combineStates( ) /** - * Combine three [StateFlow]s into a new [StateFlow] with the given [transform] function. + * Combine three [StateFlow]s into a new read-only [StateFlow] with the given [transform] function.. * * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] * with the latest values of the source [StateFlow]s. @@ -94,7 +94,7 @@ public fun combineStates( ) /** - * Combine four [StateFlow]s into a new [StateFlow] with the given [transform] function. + * Combine four [StateFlow]s into a new read-only [StateFlow] with the given [transform] function.. * * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] * with the latest values of the source [StateFlow]s. @@ -117,7 +117,7 @@ public fun combineStates( ) /** - * Combine five [StateFlow]s into a new [StateFlow] with the given [transform] function. + * Combine five [StateFlow]s into a new read-only [StateFlow] with the given [transform] function.. * * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] * with the latest values of the source [StateFlow]s. @@ -141,7 +141,7 @@ public fun combineStates( ) /** - * Combine six [StateFlow]s into a new [StateFlow] with the given [transform] function. + * Combine six [StateFlow]s into a new read-only [StateFlow] with the given [transform] function.. * * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] * with the latest values of the source [StateFlow]s. @@ -175,7 +175,7 @@ public fun combineStates( ) /** - * Combine seven [StateFlow]s into a new [StateFlow] with the given [transform] function. + * Combine seven [StateFlow]s into a new read-only [StateFlow] with the given [transform] function.. * * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] * with the latest values of the source [StateFlow]s. @@ -211,7 +211,7 @@ public fun combineStates( ) /** - * Combine eight [StateFlow]s into a new [StateFlow] with the given [transform] function. + * Combine eight [StateFlow]s into a new read-only [StateFlow] with the given [transform] function.. * * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] * with the latest values of the source [StateFlow]s. @@ -249,7 +249,7 @@ public fun combineStates( ) /** - * Combine nine [StateFlow]s into a new [StateFlow] with the given [transform] function. + * Combine nine [StateFlow]s into a new read-only [StateFlow] with the given [transform] function.. * * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] * with the latest values of the source [StateFlow]s. @@ -289,7 +289,7 @@ public fun combineStates( ) /** - * Combine ten [StateFlow]s into a new [StateFlow] with the given [transform] function. + * Combine ten [StateFlow]s into a new read-only [StateFlow] with the given [transform] function.. * * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] * with the latest values of the source [StateFlow]s. @@ -333,7 +333,7 @@ public fun combineStates( ) /** - * Combine eleven [StateFlow]s into a new [StateFlow] with the given [transform] function. + * Combine eleven [StateFlow]s into a new read-only [StateFlow] with the given [transform] function.. * * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] * with the latest values of the source [StateFlow]s. @@ -379,7 +379,7 @@ public fun combineStates( ) /** - * Combine twelve [StateFlow]s into a new [StateFlow] with the given [transform] function. + * Combine twelve [StateFlow]s into a new read-only [StateFlow] with the given [transform] function.. * * Accessing [StateFlow.value] of the returned [StateFlow] always calls [transform] * with the latest values of the source [StateFlow]s. diff --git a/src/commonTest/kotlin/com/hoc081098/flowext/MapStateTest.kt b/src/commonTest/kotlin/com/hoc081098/flowext/MapStateTest.kt new file mode 100644 index 00000000..9af00ba3 --- /dev/null +++ b/src/commonTest/kotlin/com/hoc081098/flowext/MapStateTest.kt @@ -0,0 +1,76 @@ +/* + * MIT License + * + * Copyright (c) 2021-2024 Petrus Nguyễn Thái Học + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.hoc081098.flowext + +import com.hoc081098.flowext.utils.BaseTest +import com.hoc081098.flowext.utils.asserReadonlyStateFlow +import com.hoc081098.flowext.utils.test +import kotlin.math.abs +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.take +import kotlinx.coroutines.launch + +@ExperimentalCoroutinesApi +@FlowExtPreview +class MapStateTest : BaseTest() { + @Test + fun testMapState() = runTest { + val source = MutableStateFlow(1) + val mapped: StateFlow = source.mapState { abs(it) + 1 } + + asserReadonlyStateFlow(mapped, 42) + + launch { + mapped + .take(3) + .test( + expected = listOf( + Event.Value(2), + Event.Value(11), + Event.Value(1), + Event.Complete, + ), + ) + } + + assertEquals(2, mapped.value) + + source.value = -1 + assertEquals(2, mapped.value) + + source.value = 10 + assertEquals(11, mapped.value) + + source.value = -10 + assertEquals(11, mapped.value) + + source.value = 0 + assertEquals(1, mapped.value) + } +} diff --git a/src/commonTest/kotlin/com/hoc081098/flowext/utils/BaseTest.kt b/src/commonTest/kotlin/com/hoc081098/flowext/utils/BaseTest.kt index d4f727b3..06d227ed 100644 --- a/src/commonTest/kotlin/com/hoc081098/flowext/utils/BaseTest.kt +++ b/src/commonTest/kotlin/com/hoc081098/flowext/utils/BaseTest.kt @@ -24,12 +24,16 @@ package com.hoc081098.flowext.utils +import kotlin.test.assertFails +import kotlin.test.assertFalse import kotlin.test.assertTrue import kotlin.test.fail import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.fold import kotlinx.coroutines.suspendCancellableCoroutine @@ -89,3 +93,8 @@ suspend inline fun assertFailsWith( } suspend fun Flow.sum() = fold(0) { acc, value -> acc + value } + +inline fun asserReadonlyStateFlow(stateFlow: StateFlow, value: T) { + assertFalse { stateFlow is MutableStateFlow } + assertFails { (stateFlow as MutableStateFlow).value = value } +} From 3ebb41ece9ec7b39359c5d6e93231335355c7eea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petrus=20Nguy=E1=BB=85n=20Th=C3=A1i=20H=E1=BB=8Dc?= Date: Mon, 9 Dec 2024 01:38:43 +0700 Subject: [PATCH 7/7] mapState tests --- src/commonTest/kotlin/com/hoc081098/flowext/MapStateTest.kt | 4 ++-- src/commonTest/kotlin/com/hoc081098/flowext/utils/BaseTest.kt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/commonTest/kotlin/com/hoc081098/flowext/MapStateTest.kt b/src/commonTest/kotlin/com/hoc081098/flowext/MapStateTest.kt index 9af00ba3..e72778a3 100644 --- a/src/commonTest/kotlin/com/hoc081098/flowext/MapStateTest.kt +++ b/src/commonTest/kotlin/com/hoc081098/flowext/MapStateTest.kt @@ -25,7 +25,7 @@ package com.hoc081098.flowext import com.hoc081098.flowext.utils.BaseTest -import com.hoc081098.flowext.utils.asserReadonlyStateFlow +import com.hoc081098.flowext.utils.assertReadonlyStateFlow import com.hoc081098.flowext.utils.test import kotlin.math.abs import kotlin.test.Test @@ -44,7 +44,7 @@ class MapStateTest : BaseTest() { val source = MutableStateFlow(1) val mapped: StateFlow = source.mapState { abs(it) + 1 } - asserReadonlyStateFlow(mapped, 42) + assertReadonlyStateFlow(mapped, 42) launch { mapped diff --git a/src/commonTest/kotlin/com/hoc081098/flowext/utils/BaseTest.kt b/src/commonTest/kotlin/com/hoc081098/flowext/utils/BaseTest.kt index 06d227ed..9ea522c9 100644 --- a/src/commonTest/kotlin/com/hoc081098/flowext/utils/BaseTest.kt +++ b/src/commonTest/kotlin/com/hoc081098/flowext/utils/BaseTest.kt @@ -94,7 +94,7 @@ suspend inline fun assertFailsWith( suspend fun Flow.sum() = fold(0) { acc, value -> acc + value } -inline fun asserReadonlyStateFlow(stateFlow: StateFlow, value: T) { +inline fun assertReadonlyStateFlow(stateFlow: StateFlow, value: T) { assertFalse { stateFlow is MutableStateFlow } assertFails { (stateFlow as MutableStateFlow).value = value } }