mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2025-09-21 16:29:25 +00:00
Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
00acb9fddd | |||
de3d14dc41 | |||
67ff9cc9b3 | |||
af132103a0 | |||
3b1124a804 | |||
f226c2dfd6 |
11
CHANGELOG.md
11
CHANGELOG.md
@@ -1,5 +1,16 @@
|
||||
# Changelog
|
||||
|
||||
## 0.7.5
|
||||
|
||||
* `Versions`:
|
||||
* `Klock`: `2.4.6` -> `2.4.7`
|
||||
* `Ktor`: `1.6.4` -> `1.6.5`
|
||||
* `Common`:
|
||||
* Type `Either` got its own serializer
|
||||
* `FSM`:
|
||||
* `Common`:
|
||||
* Add opportunity for comfortable adding default state handler
|
||||
|
||||
## 0.7.4
|
||||
|
||||
* `Common`:
|
||||
|
@@ -1,5 +1,10 @@
|
||||
package dev.inmo.micro_utils.common
|
||||
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import kotlinx.serialization.descriptors.*
|
||||
import kotlinx.serialization.encoding.*
|
||||
|
||||
/**
|
||||
* Realization of this interface will contains at least one not null - [t1] or [t2]
|
||||
*
|
||||
@@ -10,16 +15,90 @@ package dev.inmo.micro_utils.common
|
||||
* @see Either.onFirst
|
||||
* @see Either.onSecond
|
||||
*/
|
||||
@Serializable(EitherSerializer::class)
|
||||
sealed interface Either<T1, T2> {
|
||||
val t1: T1?
|
||||
val t2: T2?
|
||||
|
||||
companion object
|
||||
companion object {
|
||||
fun <T1, T2> serializer(
|
||||
t1Serializer: KSerializer<T1>,
|
||||
t2Serializer: KSerializer<T2>,
|
||||
): KSerializer<Either<T1, T2>> = EitherSerializer(t1Serializer, t2Serializer)
|
||||
}
|
||||
}
|
||||
|
||||
class EitherSerializer<T1, T2>(
|
||||
t1Serializer: KSerializer<T1>,
|
||||
t2Serializer: KSerializer<T2>,
|
||||
) : KSerializer<Either<T1, T2>> {
|
||||
@ExperimentalSerializationApi
|
||||
@InternalSerializationApi
|
||||
override val descriptor: SerialDescriptor = buildSerialDescriptor(
|
||||
"TypedSerializer",
|
||||
SerialKind.CONTEXTUAL
|
||||
) {
|
||||
element("type", String.serializer().descriptor)
|
||||
element("value", ContextualSerializer(Either::class).descriptor)
|
||||
}
|
||||
private val t1EitherSerializer = EitherFirst.serializer(t1Serializer, t2Serializer)
|
||||
private val t2EitherSerializer = EitherSecond.serializer(t1Serializer, t2Serializer)
|
||||
|
||||
@ExperimentalSerializationApi
|
||||
@InternalSerializationApi
|
||||
override fun deserialize(decoder: Decoder): Either<T1, T2> {
|
||||
return decoder.decodeStructure(descriptor) {
|
||||
var type: String? = null
|
||||
lateinit var result: Either<T1, T2>
|
||||
while (true) {
|
||||
when (val index = decodeElementIndex(descriptor)) {
|
||||
0 -> type = decodeStringElement(descriptor, 0)
|
||||
1 -> {
|
||||
result = when (type) {
|
||||
"t1" -> decodeSerializableElement(
|
||||
descriptor,
|
||||
1,
|
||||
t1EitherSerializer
|
||||
)
|
||||
"t2" -> decodeSerializableElement(
|
||||
descriptor,
|
||||
1,
|
||||
t2EitherSerializer
|
||||
)
|
||||
else -> error("Unknown type of either: $type")
|
||||
}
|
||||
}
|
||||
CompositeDecoder.DECODE_DONE -> break
|
||||
else -> error("Unexpected index: $index")
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ExperimentalSerializationApi
|
||||
@InternalSerializationApi
|
||||
override fun serialize(encoder: Encoder, value: Either<T1, T2>) {
|
||||
encoder.encodeStructure(descriptor) {
|
||||
when (value) {
|
||||
is EitherFirst -> {
|
||||
encodeStringElement(descriptor, 0, "t1")
|
||||
encodeSerializableElement(descriptor, 1, t1EitherSerializer, value)
|
||||
}
|
||||
is EitherSecond -> {
|
||||
encodeStringElement(descriptor, 0, "t2")
|
||||
encodeSerializableElement(descriptor, 1, t2EitherSerializer, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This type [Either] will always have not nullable [t1]
|
||||
*/
|
||||
@Serializable
|
||||
data class EitherFirst<T1, T2>(
|
||||
override val t1: T1
|
||||
) : Either<T1, T2> {
|
||||
@@ -30,6 +109,7 @@ data class EitherFirst<T1, T2>(
|
||||
/**
|
||||
* This type [Either] will always have not nullable [t2]
|
||||
*/
|
||||
@Serializable
|
||||
data class EitherSecond<T1, T2>(
|
||||
override val t2: T2
|
||||
) : Either<T1, T2> {
|
||||
@@ -44,7 +124,7 @@ inline fun <T1, T2> Either.Companion.first(t1: T1): Either<T1, T2> = EitherFirst
|
||||
/**
|
||||
* @return New instance of [EitherSecond]
|
||||
*/
|
||||
inline fun <T1, T2> Either.Companion.second(t1: T1): Either<T1, T2> = EitherFirst(t1)
|
||||
inline fun <T1, T2> Either.Companion.second(t2: T2): Either<T1, T2> = EitherSecond(t2)
|
||||
|
||||
/**
|
||||
* Will call [block] in case when [Either.t1] of [this] is not null
|
||||
@@ -63,3 +143,9 @@ inline fun <T1, T2, E : Either<T1, T2>> E.onSecond(crossinline block: (T2) -> Un
|
||||
t2 ?.let(block)
|
||||
return this
|
||||
}
|
||||
|
||||
inline fun <reified T1, reified T2> Any.either() = when (this) {
|
||||
is T1 -> Either.first<T1, T2>(this)
|
||||
is T2 -> Either.second<T1, T2>(this)
|
||||
else -> error("Incorrect type of either argument $this")
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ import kotlin.reflect.KClass
|
||||
* Default realization of [StatesHandler]. It will incapsulate checking of [State] type in [checkHandleable] and class
|
||||
* casting in [handleState]
|
||||
*/
|
||||
class StateHandlerHolder<I : State>(
|
||||
class StatesHandlerHolder<I : State>(
|
||||
private val inputKlass: KClass<I>,
|
||||
private val strict: Boolean = false,
|
||||
private val delegateTo: StatesHandler<I>
|
||||
@@ -19,9 +19,20 @@ class StateHandlerHolder<I : State>(
|
||||
|
||||
/**
|
||||
* Calls [delegateTo] method [StatesHandler.handleState] with [state] casted to [I]. Use [checkHandleable]
|
||||
* to be sure that this [StateHandlerHolder] will be able to handle [state]
|
||||
* to be sure that this [StatesHandlerHolder] will be able to handle [state]
|
||||
*/
|
||||
override suspend fun StatesMachine.handleState(state: State): State? {
|
||||
return delegateTo.run { handleState(state as I) }
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Renamed", ReplaceWith("StatesHandlerHolder"))
|
||||
typealias StateHandlerHolder<T> = StatesHandlerHolder<T>
|
||||
|
||||
inline fun <reified T : State> StatesHandler<T>.holder(
|
||||
strict: Boolean = true
|
||||
) = StatesHandlerHolder(
|
||||
T::class,
|
||||
strict,
|
||||
this
|
||||
)
|
@@ -2,11 +2,10 @@ package dev.inmo.micro_utils.fsm.common
|
||||
|
||||
import dev.inmo.micro_utils.coroutines.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.asFlow
|
||||
|
||||
private suspend fun <I : State> StatesMachine.launchStateHandling(
|
||||
state: State,
|
||||
handlers: List<StateHandlerHolder<out I>>
|
||||
handlers: List<StatesHandlerHolder<out I>>
|
||||
): State? {
|
||||
return handlers.firstOrNull { it.checkHandleable(state) } ?.run {
|
||||
handleState(state)
|
||||
@@ -35,7 +34,7 @@ interface StatesMachine : StatesHandler<State> {
|
||||
*/
|
||||
operator fun invoke(
|
||||
statesManager: StatesManager,
|
||||
handlers: List<StateHandlerHolder<*>>
|
||||
handlers: List<StatesHandlerHolder<*>>
|
||||
) = DefaultStatesMachine(statesManager, handlers)
|
||||
}
|
||||
}
|
||||
@@ -46,7 +45,7 @@ interface StatesMachine : StatesHandler<State> {
|
||||
*/
|
||||
class DefaultStatesMachine (
|
||||
private val statesManager: StatesManager,
|
||||
private val handlers: List<StateHandlerHolder<*>>
|
||||
private val handlers: List<StatesHandlerHolder<*>>
|
||||
) : StatesMachine {
|
||||
/**
|
||||
* Will call [launchStateHandling] for state handling
|
||||
|
@@ -2,25 +2,27 @@ package dev.inmo.micro_utils.fsm.common.dsl
|
||||
|
||||
import dev.inmo.micro_utils.fsm.common.*
|
||||
import dev.inmo.micro_utils.fsm.common.managers.*
|
||||
import dev.inmo.micro_utils.fsm.common.managers.InMemoryStatesManager
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
class FSMBuilder(
|
||||
var statesManager: StatesManager = DefaultStatesManager(InMemoryDefaultStatesManagerRepo())
|
||||
var statesManager: StatesManager = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
|
||||
var defaultStateHandler: StatesHandler<State>? = StatesHandler { null }
|
||||
) {
|
||||
private var states = mutableListOf<StateHandlerHolder<*>>()
|
||||
private var states = mutableListOf<StatesHandlerHolder<*>>()
|
||||
|
||||
fun <I : State> add(kClass: KClass<I>, handler: StatesHandler<I>) {
|
||||
states.add(StateHandlerHolder(kClass, false, handler))
|
||||
states.add(StatesHandlerHolder(kClass, false, handler))
|
||||
}
|
||||
|
||||
fun <I : State> addStrict(kClass: KClass<I>, handler: StatesHandler<I>) {
|
||||
states.add(StateHandlerHolder(kClass, true, handler))
|
||||
states.add(StatesHandlerHolder(kClass, true, handler))
|
||||
}
|
||||
|
||||
fun build() = StatesMachine(
|
||||
statesManager,
|
||||
states.toList()
|
||||
states.toList().let { list ->
|
||||
defaultStateHandler ?.let { list + it.holder(false) } ?: list
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
@@ -12,9 +12,9 @@ kotlin_coroutines_version=1.5.2
|
||||
kotlin_serialisation_core_version=1.3.0
|
||||
kotlin_exposed_version=0.35.3
|
||||
|
||||
ktor_version=1.6.4
|
||||
ktor_version=1.6.5
|
||||
|
||||
klockVersion=2.4.6
|
||||
klockVersion=2.4.7
|
||||
|
||||
github_release_plugin_version=2.2.12
|
||||
|
||||
@@ -45,5 +45,5 @@ dokka_version=1.5.31
|
||||
# Project data
|
||||
|
||||
group=dev.inmo
|
||||
version=0.7.4
|
||||
android_code_version=78
|
||||
version=0.7.5
|
||||
android_code_version=79
|
||||
|
@@ -1,3 +1,5 @@
|
||||
@file:Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
|
||||
|
||||
package dev.inmo.micro_utils.language_codes
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
@@ -1,3 +1,5 @@
|
||||
@file:Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
|
||||
|
||||
package dev.inmo.micro_utils.mime_types
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
Reference in New Issue
Block a user