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

commonMain.dev.inmo.micro_utils.fsm.common.CheckableHandlerHolder.kt Maven / Gradle / Ivy

package dev.inmo.micro_utils.fsm.common

import kotlin.reflect.KClass

/**
 * Define checkable holder which can be used to precheck that this handler may handle incoming [State]
 */
interface CheckableHandlerHolder : StatesHandler {
    suspend fun checkHandleable(state: O): Boolean
}

/**
 * Default realization of [StatesHandler]. It will incapsulate checking of [State] type in [checkHandleable] and class
 * casting in [handleState]
 */
class CustomizableHandlerHolder(
    private val delegateTo: StatesHandler,
    private val filter: suspend (state: O) -> Boolean
) : CheckableHandlerHolder {
    /**
     * Checks that [state] can be handled by [delegateTo]. Under the hood it will check exact equality of [state]
     * [KClass] and use [KClass.isInstance] of [inputKlass] if [strict] == false
     */
    override suspend fun checkHandleable(state: O) = filter(state)

    /**
     * Calls [delegateTo] method [StatesHandler.handleState] with [state] casted to [I]. Use [checkHandleable]
     * to be sure that this [StatesHandlerHolder] will be able to handle [state]
     */
    override suspend fun StatesMachine.handleState(state: I): O? {
        return delegateTo.run { handleState(state) }
    }
}

fun  CheckableHandlerHolder(
    inputKlass: KClass,
    strict: Boolean = false,
    delegateTo: StatesHandler
) = CustomizableHandlerHolder(
    StatesHandler {
        delegateTo.run { handleState(it as I) }
    },
    if (strict) {
        { it::class == inputKlass }
    } else {
        { inputKlass.isInstance(it) }
    }
)

inline fun  CheckableHandlerHolder(
    strict: Boolean = false,
    delegateTo: StatesHandler
) = CheckableHandlerHolder(I::class, strict, delegateTo)

inline fun  StatesHandler.holder(
    strict: Boolean = true
) = CheckableHandlerHolder(
    I::class,
    strict,
    this
)

inline fun  StatesHandler.holder(
    noinline filter: suspend (state: State) -> Boolean
) = CustomizableHandlerHolder(
    { [email protected] { handleState(it as I) } },
    filter
)