Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ plugins {
}
object Conf {
const val GROUP = "net.kigawa"
const val VERSION = "2.1.0"
const val VERSION = "3.1.0"
}

group = Conf.GROUP
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package net.kigawa.hakate.api.multi

import net.kigawa.hakate.api.state.State

fun <T, U> mergeState(state1: State<T>, state2: State<U>): State<MultiValue2<T, U>> {
return state1.merge(state2) { a, b -> MultiValue2(a, b) }
}

data class MultiValue2<T, U>(val first: T, val second: U)
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package net.kigawa.hakate.api.multi

import net.kigawa.hakate.api.state.State

@Suppress("unused")
fun <T, U, V> mergeState(state1: State<T>, state2: State<U>, state3: State<V>): State<MultiValue3<T, U, V>> {
return mergeState(state1, state2).merge(state3)
}

fun <T, U, V> State<MultiValue2<T, U>>.merge(state3: State<V>): State<MultiValue3<T, U, V>> {
return merge(state3) { a, b -> MultiValue3(a.first, a.second, b) }
}

data class MultiValue3<T, U, V>(val first: T, val second: U, val third: V)
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package net.kigawa.hakate.api.state

import kotlinx.coroutines.Job

@Suppress("unused")
interface State<T> {
val stateContext: StateContext
fun collect(context: StateContext, block: suspend StateContext.(value: T) -> Unit): Job
fun <R> collect(
context: StateContext, defaultValue: R, block: suspend StateContext.(value: T, prev: R) -> R,
Expand All @@ -20,4 +22,5 @@ interface State<T> {

fun <R> child(block: (T) -> R): State<R>
fun currentValue(): T
fun <U, R> merge(state: State<U>, block: (first: T, second: U) -> R): State<R>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ package net.kigawa.hakate.api.state

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import net.kigawa.hakate.impl.state.MergedStateContextImpl

interface StateContext {
val coroutineScope: CoroutineScope
fun launch(block: suspend CoroutineScope.() -> Unit): Job
fun dispatcher(): StateDispatcher
fun dispatch(block: suspend StateContext.() -> Unit): Job
fun <T, R> State<T>.collect(defaultValue: R, block: suspend StateContext.(value: T, prev: R) -> R) =
Expand All @@ -14,4 +15,7 @@ interface StateContext {
this.collect(this@StateContext, block)

fun cancel()
fun merge(other: StateContext): StateContext {
return MergedStateContextImpl(this, other)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package net.kigawa.hakate.impl.state

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import net.kigawa.hakate.api.state.StateContext
import net.kigawa.hakate.api.state.StateDispatcher
import net.kigawa.hakate.impl.Utl.suspendApply

class MergedStateContextImpl(
private val first: StateContext,
private val second: StateContext,
) : StateContext {
override fun launch(block: suspend CoroutineScope.() -> Unit): Job {
return first.launch {
val f = this
second.launch {
val s = this
f.launch { withContext(s.coroutineContext) { block() } }
}
}
}

override fun dispatcher(): StateDispatcher = first.dispatcher()
override fun dispatch(
block: suspend StateContext.() -> Unit,
): Job {
return launch {
StateContextImpl(dispatcher(), this@launch).suspendApply {
block()
}
}
}

override fun cancel() {
first.cancel()
second.cancel()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@ import net.kigawa.hakate.impl.Utl.suspendApply

class StateContextImpl(
private val dispatcher: StateDispatcher,
override val coroutineScope: CoroutineScope,
val coroutineScope: CoroutineScope,
) : StateContext {
override fun launch(block: suspend CoroutineScope.() -> Unit): Job {
return coroutineScope.launch(block = block)
}

override fun dispatcher(): StateDispatcher = dispatcher
override fun dispatch(
block: suspend StateContext.() -> Unit,
): Job {
return coroutineScope.launch {
return launch {
StateContextImpl(dispatcher, this@launch).suspendApply {
block()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import net.kigawa.hakate.api.state.StateContext

class StateImpl<T>(
defaultValue: T,
private val stateContext: StateContext,
override val stateContext: StateContext,
) : MutableState<T> {
private val flow = MutableStateFlow<T>(defaultValue)
override fun collect(
Expand Down Expand Up @@ -45,5 +45,17 @@ class StateImpl<T>(
}

override fun currentValue(): T = flow.value
override fun <U, R> merge(
state: State<U>, block: (T, U) -> R,
): State<R> {
val mergedContext = stateContext.merge(state.stateContext)
val newState = StateImpl(block(currentValue(), state.currentValue()), mergedContext)
collect(mergedContext) { v1 ->
state.collect(mergedContext) { v2 ->
newState.set(block(v1, v2))
}
}
return newState
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ class StateTest : StateTestBase() {
isSet = false
state.set(next)

// waitStateSet { isSet }
// assertEquals("$next-child", value)
waitStateSet { isSet }
assertEquals("$next-child", value)
}

}
Expand Down