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

commonMain.com.caesarealabs.rpc4k.runtime.api.S2CEventMessage.kt Maven / Gradle / Ivy

package com.caesarealabs.rpc4k.runtime.api

import com.caesarealabs.rpc4k.runtime.implementation.fastConcat

public sealed interface S2CEventMessage {
    public data class Emitted(val listenerId: String, val payload: ByteArray) : S2CEventMessage {
        override fun equals(other: Any?): Boolean {
            if (this === other) return true
            if (other !is Emitted) return false

            if (listenerId != other.listenerId) return false
            if (!payload.contentEquals(other.payload)) return false

            return true
        }

        override fun hashCode(): Int {
            var result = listenerId.hashCode()
            result = 31 * result + payload.contentHashCode()
            return result
        }

    }

    public data class SubscriptionError(val error: String) : S2CEventMessage

    public fun toByteArray(): ByteArray = when (this) {
        is Emitted -> EventType.encodeToByteArray().fastConcat(Rpc.ColonCode, listenerId.encodeToByteArray(), payload)
        is SubscriptionError -> ErrorType.encodeToByteArray().fastConcat(Rpc.ColonCode, error.encodeToByteArray())
    }

    public companion object {
        private const val EventType = "event"
        private const val ErrorType = "error"

        public fun fromByteArray(byteArray: ByteArray): S2CEventMessage {
            val reader = RpcMessageReader(byteArray)
            when (val type = reader.readPart("type").decodeToString()) {
                EventType -> {
                    val listenerId = reader.readPart("listenerId").decodeToString()
                    val payload = reader.readPart("payload", finalPart = true)
                    return Emitted(listenerId, payload)
                }

                ErrorType -> {
                    return SubscriptionError(reader.readPart("error", finalPart = true).decodeToString())
                }

                else -> {
                    throw InvalidRpcRequestException("Malformed RPC message, Invalid type specified: $type")
                }
            }
        }

        public fun fromString(string: String): S2CEventMessage {
            val split = string.split(":")
            val type = split[0]
            when (type) {
                EventType -> {
                    if (split.size < 3) error("Malformed RPC event: $string")
                    val listenerId = split[1]
                    // SLOW: optimize splitting and joining
                    val payload = split.drop(2).joinToString(":")
                    return Emitted(listenerId, payload.encodeToByteArray())
                }

                ErrorType -> {
                    return SubscriptionError(split.drop(1).joinToString(":"))
                }

                else -> {
                    throw InvalidRpcRequestException("Malformed RPC message, no type specified: $string")
                }
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy