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

elements.events.kt Maven / Gradle / Ivy

package elements

import com.google.gson.JsonElement
import com.google.gson.JsonPrimitive
import com.pusher.platform.network.parseAs
import com.pusher.platform.network.DataParser
import com.pusher.util.Result
import com.pusher.util.Result.Companion.failuresOf
import com.pusher.util.asFailure
import com.pusher.util.asSuccess
import com.pusher.util.orElse

internal fun  String.toSubscriptionMessage(
    bodyParser: DataParser
): Result, Error> =
    parseAs>().flatMap {
        when (it.messageType) {
            0 -> it.createControlEvent()
            1 -> it.createSubscriptionEvent(bodyParser)
            255 -> it.createEosEvent()
            else -> Errors.other("Unknown message type: $this").asFailure()
        }
    }

@Suppress("unused")
sealed class SubscriptionMessage

data class SubscriptionEvent(val eventId: String, val headers: Headers, val body: A) : SubscriptionMessage()
data class EOSEvent(val statusCode: Int, val headers: Headers, val error: EosError) : SubscriptionMessage()
data class ControlEvent(val body: String) : SubscriptionMessage()

private fun  Array.createControlEvent(): Result, Error> =
    getOrElse(1) { JsonPrimitive("") }.asString.let { ControlEvent(body = it) }.asSuccess()

private fun  Array.createEosEvent(): Result, Error> =
    validate(statusCode) { statusCode ->
        EOSEvent(
            statusCode = statusCode,
            headers = headers,
            error = eosError
        )
    }

private fun  Array.createSubscriptionEvent(
    bodyParser: DataParser
): Result, Error> =
    validate(eventId, messageBody(bodyParser)) { eventId, body: A ->
        SubscriptionEvent(eventId, headers, body)
    }

private val Array.statusCode: Result
    get() = valueAt(1, "statusCode") { asInt }

private val Array.eosError: EosError
    get() = valueAt(3, "error") {
        asJsonObject.apply {
            if (!has("type")) addProperty("type", "unknown")
            if (!has("reason")) addProperty("reason", "unknown")
        }
    }
        .flatMap { it.parseAs() }
        .recover { EosError("unknown", "unknown") }

private val Array.headers: Headers
    get() = valueAt(2, "headers").recover { emptyHeaders() }

private val Array.eventId: Result
    get() = valueAt(1, "eventId")

private val Array.messageType
    get() = valueAt(0, "messageType") { asJsonPrimitive.takeIf { it.isNumber }?.asInt }.recover { -1 }

private fun  Array.messageBody(
    bodyParser: DataParser
): Result = jsonBody.flatMap { bodyParser(it.toString()) }

private val Array.jsonBody
    get() = valueAt(3, "body")

private fun  validate(a: Result, b: Result, block: (A, B) -> C): Result = when {
    a is Result.Success && b is Result.Success -> block(a.value, b.value).asSuccess()
    else -> Errors.compose(failuresOf(a, b)).asFailure()
}

private fun  validate(a: Result, block: (A) -> C): Result = when (a) {
    is Result.Success -> block(a.value).asSuccess()
    else -> Errors.compose(failuresOf(a)).asFailure()
}

private fun  Array?.valueAt(index: Int, name: String, block: JsonElement.() -> A?): Result =
    this?.getOrNull(index)?.block().orElse { fieldNotFoundError(name) }

private inline fun  Array.valueAt(index: Int, name: String): Result =
    getOrNull(index)?.parseAs()
        ?:fieldNotFoundError(name).asFailure()

private fun fieldNotFoundError(name: String) =
    Errors.other("Field '$name' not found in subscription message")





© 2015 - 2024 Weber Informatics LLC | Privacy Policy