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

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

package com.caesarealabs.rpc4k.runtime.api

import com.caesarealabs.rpc4k.runtime.implementation.fastConcat
import com.caesarealabs.rpc4k.runtime.implementation.serializers.TupleSerializer
import kotlinx.serialization.KSerializer


/**
 * Data representing a Remote Procedure Call.
 */
public data class Rpc(val method: String, val arguments: List<*>) {
    internal companion object {

        fun fromByteArray(bytes: ByteArray, format: SerializationFormat, argDeserializers: List>): Rpc {
            val (method, readBytes) = readMethodName(bytes)
            //SLOW: Copying of entire request create Rpc`s
            val arguments = format.decode(TupleSerializer(argDeserializers), bytes.copyOfRange(readBytes, bytes.size))
            return Rpc(method, arguments)
        }

         const val ColonCode: Byte = 58 // :

        fun peekMethodName(rpcBytes: ByteArray): String {
            return readMethodName(rpcBytes).first
        }

        /**
         * Returns the method name and how many bytes it spans at the start of the [bytes].
         */
        private fun readMethodName(bytes: ByteArray): Pair {
            var pos = 0
            // Reads up until COLON_CODE,
            do {
                if (pos == bytes.size) {
                    throw InvalidRpcRequestException("Missing colon (:) separator in RPC: '${bytes.decodeToString()}'")
                }
                val currentByte = bytes[pos]
                // Happens after array[pos] so we will already skip by the color itself
                pos++
            } while (currentByte != ColonCode)

            // Exclude colon itself
            return bytes.copyOfRange(0, pos - 1).decodeToString() to pos
        }
    }

    init {
        check(!method.contains(':')) { "Method name must not contain ':', but it did: \"$method\"" }
    }

    override fun toString(): String {
        return "$method(${arguments.joinToString()})"
    }


    /**
     * See docs/rpc_format.png
     */
    public fun toByteArray(format: SerializationFormat, serializers: List>): ByteArray {
        return method.encodeToByteArray().fastConcat(ColonCode, format.encode(TupleSerializer(serializers), arguments))
    }

}






© 2015 - 2024 Weber Informatics LLC | Privacy Policy