refactor(gateway): extract serialisation utils into one spot

This commit is contained in:
Cilly Leang 2026-01-27 16:35:50 +11:00
parent 3ff9b7d676
commit f0c0be0dd2
Signed by: cilly
GPG key ID: 6500251E087653C9
4 changed files with 47 additions and 43 deletions

View file

@ -1,27 +0,0 @@
package moe.lava.neon.core.api.gateway
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.json.JsonContentPolymorphicSerializer
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.int
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
object EventPolySerializer : JsonContentPolymorphicSerializer<Event.WithSequence>(Event.WithSequence::class) {
override fun selectDeserializer(element: JsonElement): DeserializationStrategy<Event.WithSequence> {
val op = element.jsonObject["op"]!!.jsonPrimitive.int
if (op == 0) {
val name = element.jsonObject["t"]?.jsonPrimitive?.content
return when (name) {
"READY" -> Event.Incoming.serializer(Payload.Ready.serializer())
else -> Event.Unknown.serializer()
}
}
return when (op) {
1 -> Event.Incoming.serializer(Payload.Heartbeat.serializer())
10 -> Event.Incoming.serializer(Payload.Hello.serializer())
11 -> Event.Incoming.serializer(Payload.HeartbeatAck.serializer())
else -> Event.Unknown.serializer()
}
}
}

View file

@ -73,16 +73,16 @@ class Gateway(
logger.d { "Received event ${frame.readText()}" }
val msg = json.decodeFromString(EventPolySerializer, frame.readText())
val raw = json.decodeFromString<Event.Unknown>(frame.readText())
val seq = this.seq ?: 0
if (seq + 1 == msg.s) {
this.seq = msg.s
} else if (msg.s != null) {
resume(ResumeReason.SkippedSequence(msg.s!!))
if (seq + 1 == raw.s) {
this.seq = raw.s
} else if (raw.s != null) {
resume(ResumeReason.SkippedSequence(raw.s))
return@onEach
}
when (msg) {
when (val msg = raw.asIncoming()) {
is Event.Incoming<*> -> scope.launch { handleEvent(msg) }
is Event.Unknown -> scope.launch { handleUnknownEvent(msg) }
}

View file

@ -99,13 +99,3 @@ sealed interface Payload {
// val application: Application,
) : Dispatch()
}
fun <T : Payload.Outgoing> T.pack(): Event.Outgoing<T> {
val opcode: Int = when (this) {
is Payload.Heartbeat -> 1
is Payload.QoSHeartbeat -> 40
is Payload.HeartbeatAck -> 11
is Payload.Identify -> 2
}
return Event.Outgoing(op = opcode, d = this)
}

View file

@ -0,0 +1,41 @@
package moe.lava.neon.core.api.gateway
import kotlinx.serialization.KSerializer
import kotlinx.serialization.json.decodeFromJsonElement
import moe.lava.neon.core.api.ApiConstants
private val json = ApiConstants.json
fun <T : Payload.Outgoing> T.pack(): Event.Outgoing<T> {
val opcode: Int = when (this) {
is Payload.Heartbeat -> 1
is Payload.Identify -> 2
is Payload.HeartbeatAck -> 11
is Payload.QoSHeartbeat -> 40
}
return Event.Outgoing(op = opcode, d = this)
}
fun Event.Unknown.asIncoming() : Event.WithSequence {
return when (op) {
0 -> when (t) {
"READY" -> decode<Payload.Ready>()
else -> this
}
1 -> decode<Payload.Heartbeat>()
10 -> decode<Payload.Hello>()
11 -> decode<Payload.HeartbeatAck>()
else -> this
}
}
private inline fun <reified T : Payload.Incoming> Event.Unknown.decode(): Event.Incoming<T> =
Event.Incoming(
op = op,
d = json.decodeFromJsonElement<T>(d!!),
s = s,
t = t,
)
private inline fun <reified T : Payload.Incoming> KSerializer<T>.wrap(): KSerializer<Event.Incoming<T>> =
Event.Incoming.serializer(this)