Использование Kotlin сопрограмм для реализации процедуры рукопожатия с участием конечного автомата - PullRequest
1 голос
/ 28 мая 2020

Я новичок в Kotlin, и мне нужно реализовать код, который выполняет процедуру установления связи. Это означает, что есть входные и выходные данные и конечный автомат. Пример:

class Handshake {
    fun readData(data: List<Byte>): Outcome {
        if (currentState == State.STATE_1) {
            if (inspectState1Data(data) == Result.INVALID) {
                return Outcome.NEED_MORE_DATA // 
            } else {
                currentState = State.STATE_2
                return Outcome.CALL_AGAIN
            }
        } else if (currentState == State.STATE_2) {
            when (inspectState2Data(data)) {
                Result.REQUIRES_EXTRA_INFO -> return Outcome.PROVIDE_EXTRA_INFO
                Result.INVALID -> return Outcome.FAILURE
            }
        }
    }
}

Эту функцию readData() придется вызывать повторно. Если возвращается Outcome.CALL_AGAIN, он просто вызывается снова. Если возвращается Outcome.PROVIDE_EXTRA_INFO, дополнительная информация должна быть передана классу рукопожатия сначала каким-то образом et c.

В этом примере функция короткая и легко читается, однако, как только задействованы другие состояния, и состояния становятся более сложными, этот код может быстро стать беспорядочным.

Я бы хотел изменить это на что-то вроде:

suspend fun processHandshake(): Boolean {
    // State 1

    while (true) {
        // Loop until we get valid data
        val data: List<Byte> = suspendUntilResumedWithData() // How would this look like in Kotlin?
        if (inspectState1Data(data) != Result.INVALID)
            break
    }

    // State 2

    while (true) {
        // Loop until we are done. If during the process we
        // require extra info, request one. In this state,
        // however, receiving invalid data is not recoverable,
        // we need to exit with failure instead.
        val data: List<Byte> = suspendUntilResumedWithData()
        when (inspectState2Data(data)) {
            Result.REQUIRES_EXTRA_INFO -> {
                val extraInfo: ExtraInfo = suspendUntilResumedWithExtraInfo()
                processExtraInfo(extraInfo)
            }
            Result.INVALID -> return false // Return false to indicate failure
        }
    }

    return true // Success - return true
}

Для меня вторая форма более читабельна , и, конечно же, хорошо работает с инфраструктурой сопрограмм Kotlin, особенно с такими деталями, как отмена заданий и т. д. c. Этот код также имеет гораздо более последовательный вид по сравнению с другим.

Однако у меня нет четкого представления о том, как будут выглядеть suspendUntilResumedWithData() и suspendUntilResumedWithExtraInfo(). Я знаю об объектах Continuation, но не знаю, как их здесь правильно использовать. Есть предложения?

...