Skip to content

Commit

Permalink
Json-rpc error state testing, serialization refactoring and cleanup.
Browse files Browse the repository at this point in the history
  • Loading branch information
Karel Hovorka committed Jul 20, 2021
1 parent 152f9c2 commit bf9c321
Show file tree
Hide file tree
Showing 17 changed files with 254 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package spaceEngineers.controller
import kotlinx.serialization.*
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import spaceEngineers.transport.JsonRpcRequest
import spaceEngineers.transport.JsonRpcResponse
import spaceEngineers.transport.jsonrpc.JsonRpcResponse
import spaceEngineers.transport.jsonrpc.KotlinJsonRpcRequest
import spaceEngineers.transport.jsonrpc.KotlinJsonRpcResponse
import spaceEngineers.transport.StringLineReaderWriter
import kotlin.random.Random
import kotlin.reflect.KClass
Expand Down Expand Up @@ -35,7 +36,7 @@ abstract class RpcSerializer(
val stringLineReaderWriter: StringLineReaderWriter,
) {

protected inline fun <reified I : Any, reified O : Any> processSingleParameterMethod(
inline fun <reified I : Any, reified O : Any> processSingleParameterMethod(
method: KFunction<O>,
parameter: I,
parameterName: String,
Expand All @@ -56,40 +57,56 @@ abstract class RpcSerializer(
}

@OptIn(ExperimentalStdlibApi::class)
protected inline fun <reified O : Any> processParameters(
inline fun <reified O : Any> processParameters(
method: KFunction<O?>,
parameters: List<TypedParameter<*>>,
methodName: String = method.name,
): O {
val request = JsonRpcRequest(
id = Random.nextLong(),
method = methodName,
params = parameters.associate { it.toJsonElementPair() }
return callRpc<O>(
stringLineReaderWriter,
encodeRequest(method, parameters, methodName),
typeOf<KotlinJsonRpcResponse<O>>()
)
return callRpc<O>(stringLineReaderWriter, request, parameters, typeOf<JsonRpcResponse<O>>())
}

@OptIn(ExperimentalStdlibApi::class)
open fun <O : Any> callRpc(
rw: StringLineReaderWriter,
request: JsonRpcRequest,
parameters: List<TypedParameter<*>>,
ktype: KType
): O {
return callRpc_<O>(rw, request, ktype).result ?: Unit as O
open fun nextRequestId(): Long {
return Random.nextLong()
}

open fun <O : Any> encodeRequest(
method: KFunction<O?>,
parameters: List<TypedParameter<*>>,
methodName: String = method.name
): String {
return json.encodeToString(KotlinJsonRpcRequest(
id = nextRequestId(),
method = methodName,
params = parameters.associate { it.toJsonElementPair() }
))
}

fun <O : Any> callRpc_(rw: StringLineReaderWriter, request: JsonRpcRequest, ktype: KType): JsonRpcResponse<O> {
val responseJson = rw.sendAndReceiveLine(json.encodeToString(request))
val response = json.decodeFromString<JsonRpcResponse<O>>(
serializer(ktype) as KSerializer<JsonRpcResponse<O>>,
open fun <O : Any> decodeResponse(responseJson: String, ktype: KType): JsonRpcResponse<O> {
return json.decodeFromString<KotlinJsonRpcResponse<O>>(
serializer(ktype) as KSerializer<KotlinJsonRpcResponse<O>>,
responseJson
)
}

open fun <O : Any> decodeAndUnwrap(responseJson: String, ktype: KType): O {
val response = decodeResponse<O>(responseJson, ktype)
return unwrap(response)
}

private fun <O : Any> unwrap(response: JsonRpcResponse<O>): O {
response.error?.let {
throw it
throw it as Exception
}
return response
return response.result ?: Unit as O
}

fun <O : Any> callRpc(rw: StringLineReaderWriter, encodedRequest: String, ktype: KType): O {
val responseJson = rw.sendAndReceiveLine(encodedRequest)
return decodeAndUnwrap<O>(responseJson, ktype)
}


Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package spaceEngineers.transport.jsonrpc

interface JsonRpcError<T> {
val code: Int
val message: String
val data: T?
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package spaceEngineers.transport.jsonrpc

interface JsonRpcResponse<T : Any> {
val id: Long?
val jsonrpc: String
val result: T?
val error: JsonRpcError<*>?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package spaceEngineers.transport.jsonrpc

import kotlinx.serialization.Contextual
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement

@Serializable
data class KotlinJsonRpcError(
@SerialName("code")
override val code: Int,
@SerialName("message")
override val message: String,
@SerialName("data")
@Contextual
override val data: JsonElement? = null
) : Exception(message), JsonRpcError<JsonElement>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package spaceEngineers.transport.jsonrpc

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement

@Serializable
data class KotlinJsonRpcRequest(
@SerialName("id")
val id: Long,
@SerialName("jsonrpc")
val jsonrpc: String = "2.0",
@SerialName("method")
val method: String,
@SerialName("params")
val params: Map<String, JsonElement?>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package spaceEngineers.transport.jsonrpc

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class KotlinJsonRpcResponse<T : Any>(
@SerialName("id")
override val id: Long? = null,
@SerialName("jsonrpc")
override val jsonrpc: String = "2.0",
@SerialName("result")
override val result: T? = null,
@SerialName("error")
override val error: KotlinJsonRpcError? = null
): JsonRpcResponse<T>
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ package spaceEngineers.controller
import com.google.gson.Gson
import com.google.gson.annotations.SerializedName
import com.google.gson.reflect.TypeToken
import spaceEngineers.transport.JsonRpcRequest
import spaceEngineers.transport.SocketReaderWriter
import spaceEngineers.transport.StringLineReaderWriter
import spaceEngineers.transport.*
import spaceEngineers.transport.jsonrpc.JsonRpcResponse
import spaceEngineers.transport.jsonrpc.JsonRpcError
import java.lang.reflect.Type
import kotlin.reflect.KFunction
import kotlin.reflect.KType
import kotlin.reflect.KTypeProjection

Expand All @@ -24,23 +25,23 @@ data class GsonRpcRequest(

data class GsonRpcError(
@SerializedName("code")
val code: Int,
override val code: Int,
@SerializedName("message")
override val message: String,
@SerializedName("data")
val data: Any? = null
) : Exception(message)
override val data: Any? = null
) : Exception(message), JsonRpcError<Any>

data class GsonRpcResponse<T>(
data class GsonRpcResponse<T : Any>(
@SerializedName("id")
val id: Long,
override val id: Long? = null,
@SerializedName("jsonrpc")
val jsonrpc: String = "2.0",
override val jsonrpc: String = "2.0",
@SerializedName("result")
val result: T?,
override val result: T?,
@SerializedName("error")
val error: GsonRpcError? = null
)
override val error: GsonRpcError? = null
) : JsonRpcResponse<T>

class GsonRpcSpaceEngineers(
agentId: String,
Expand All @@ -64,18 +65,20 @@ class GsonRpcSpaceEngineers(
blocksPrefix = blocksPrefix,
adminPrefix = adminPrefix,
) {
override fun <O : Any> callRpc(
rw: StringLineReaderWriter,
request: JsonRpcRequest,

override fun <O : Any> encodeRequest(
method: KFunction<O?>,
parameters: List<TypedParameter<*>>,
ktype: KType
): O {
val gsonRequest = GsonRpcRequest(
id = request.id,
method = request.method,
methodName: String
): String {
return gson.toJson(GsonRpcRequest(
id = nextRequestId(),
method = methodName,
params = parameters.associate { it.name to it.value }
)
val responseJson = stringLineReaderWriter.sendAndReceiveLine(gson.toJson(gsonRequest))
))
}

override fun <O : Any> decodeAndUnwrap(responseJson: String, ktype: KType): O {
val response = gson.fromJson(responseJson, GsonRpcResponse::class.java)
response.error?.let {
throw it
Expand All @@ -101,4 +104,5 @@ class GsonRpcSpaceEngineers(
}
return Unit as O
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package spaceEngineers.controller
import spaceEngineers.transport.AlwaysReturnSameLineReaderWriter
import spaceEngineers.transport.PresetLinesReaderWriter
import spaceEngineers.transport.SocketReaderWriter
import spaceEngineers.transport.StringLineReaderWriter
import java.io.File

class GsonRpcSpaceEngineersBuilder: JsonRpcSpaceEngineersBuilder {
Expand Down Expand Up @@ -37,4 +38,11 @@ class GsonRpcSpaceEngineersBuilder: JsonRpcSpaceEngineersBuilder {
stringLineReaderWriter = PresetLinesReaderWriter(lines)
)
}

override fun fromStringLineReaderWriter(
agentId: String,
stringLineReaderWriter: StringLineReaderWriter
): JsonRpcSpaceEngineers {
return GsonRpcSpaceEngineers(agentId, stringLineReaderWriter)
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package spaceEngineers.controller

import spaceEngineers.transport.StringLineReaderWriter
import java.io.File

interface JsonRpcSpaceEngineersBuilder {
Expand All @@ -12,10 +13,11 @@ interface JsonRpcSpaceEngineersBuilder {

fun mock(agentId: String, lines: List<String>): JsonRpcSpaceEngineers

fun fromStringLineReaderWriter(agentId: String, stringLineReaderWriter: StringLineReaderWriter): JsonRpcSpaceEngineers

companion object : JsonRpcSpaceEngineersBuilder {

var builder: JsonRpcSpaceEngineersBuilder = KotlinJsonRpcSpaceEngineersBuilder()
var builder: JsonRpcSpaceEngineersBuilder = GsonRpcSpaceEngineersBuilder()

override fun localhost(agentId: String): JsonRpcSpaceEngineers {
return builder.localhost(agentId)
Expand All @@ -33,5 +35,9 @@ interface JsonRpcSpaceEngineersBuilder {
return builder.mock(agentId, lines)
}

override fun fromStringLineReaderWriter(agentId: String, stringLineReaderWriter: StringLineReaderWriter): JsonRpcSpaceEngineers {
return builder.fromStringLineReaderWriter(agentId, stringLineReaderWriter)
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package spaceEngineers.controller
import spaceEngineers.transport.AlwaysReturnSameLineReaderWriter
import spaceEngineers.transport.PresetLinesReaderWriter
import spaceEngineers.transport.SocketReaderWriter
import spaceEngineers.transport.StringLineReaderWriter
import java.io.File

class KotlinJsonRpcSpaceEngineersBuilder: JsonRpcSpaceEngineersBuilder {
Expand Down Expand Up @@ -37,4 +38,11 @@ class KotlinJsonRpcSpaceEngineersBuilder: JsonRpcSpaceEngineersBuilder {
stringLineReaderWriter = PresetLinesReaderWriter(lines)
)
}

override fun fromStringLineReaderWriter(
agentId: String,
stringLineReaderWriter: StringLineReaderWriter
): JsonRpcSpaceEngineers {
return JsonRpcSpaceEngineers(agentId, stringLineReaderWriter)
}
}
Loading

0 comments on commit bf9c321

Please sign in to comment.