Skip to content
This repository was archived by the owner on Nov 28, 2025. It is now read-only.

Commit 6e5d778

Browse files
committed
Add UnionCodec and UnionStreamCodec
1 parent 9d75b7c commit 6e5d778

6 files changed

Lines changed: 208 additions & 3 deletions

File tree

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
kotlin.code.style=official
2-
tide.version=3.5
2+
tide.version=3.6

src/main/kotlin/io/github/dockyardmc/tide/codec/Codec.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,18 @@ interface Codec<T> {
2929
return DefaultCodec<T>(this, default)
3030
}
3131

32+
fun <R> union(serializers: (T) -> StructCodec<out R>, keyFunc: (R) -> T): StructCodec<R> {
33+
return union("type", this, serializers, keyFunc)
34+
}
35+
36+
fun <R> union(keyCodec: Codec<T>, serializers: (T) -> StructCodec<out R>, keyFunc: (R) -> T): StructCodec<R> {
37+
return union("type", keyCodec, serializers, keyFunc)
38+
}
39+
40+
fun <R> union(keyFiled: String, keyCodec: Codec<T>, serializers: (T) -> StructCodec<out R>, keyFunc: (R) -> T): StructCodec<R> {
41+
return UnionCodec<T, R>(keyFiled, keyCodec, serializers, keyFunc)
42+
}
43+
3244
class EncodingException(override val message: String) : Exception()
3345
class DecodingException(override val message: String) : Exception()
3446

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.github.dockyardmc.tide.codec
2+
3+
import io.github.dockyardmc.tide.transcoder.Transcoder
4+
5+
data class UnionCodec<T, R>(val keyFiled: String, val keyCodec: Codec<T>, val serializers: (T) -> StructCodec<out R>, val keyFunc: (R) -> T) : StructCodec<R> {
6+
7+
override fun <T> decodeFromMap(transcoder: Transcoder<T>, map: Transcoder.VirtualMap<T>): R {
8+
val key = keyCodec.decode(transcoder, map.getValue(keyFiled))
9+
val serializer = serializers.invoke(key)
10+
return serializer.decodeFromMap(transcoder, map)
11+
}
12+
13+
@Suppress("UNCHECKED_CAST")
14+
override fun <T> encodeToMap(transcoder: Transcoder<T>, value: R, map: Transcoder.VirtualMapBuilder<T>): T {
15+
val key = keyFunc.invoke(value)
16+
val serializer = serializers.invoke(key) as StructCodec<R>
17+
map.put(keyFiled, keyCodec.encode(transcoder, key))
18+
return serializer.encodeToMap(transcoder, value, map)
19+
}
20+
}

src/main/kotlin/io/github/dockyardmc/tide/stream/StreamCodec.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package io.github.dockyardmc.tide.stream
22

3-
import io.github.dockyardmc.tide.codec.Codec
43
import io.github.dockyardmc.tide.codec.CodecUtils
5-
import io.github.dockyardmc.tide.codec.RecursiveCodec
64
import io.netty.buffer.ByteBuf
75
import java.util.*
86

@@ -30,6 +28,10 @@ interface StreamCodec<T> {
3028
return ListStreamCodec<T>(this)
3129
}
3230

31+
fun <R, TR : R> union(serializers: (T) -> StreamCodec<out TR>, keyFunc: (R) -> T): UnionStreamCodec<TR, T, TR> {
32+
return UnionStreamCodec(this, keyFunc, serializers)
33+
}
34+
3335

3436
companion object {
3537
val UNIT = object : StreamCodec<Unit> {
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package io.github.dockyardmc.tide.stream
2+
3+
import io.netty.buffer.ByteBuf
4+
5+
data class UnionStreamCodec<T, K, out TR : T>(
6+
val keyCodec: StreamCodec<K>,
7+
val keyFunc: (T) -> K,
8+
val serializers: (K) -> StreamCodec<out TR>
9+
) : StreamCodec<T> {
10+
11+
@Suppress("UNCHECKED_CAST")
12+
override fun write(buffer: ByteBuf, value: T) {
13+
val key = keyFunc.invoke(value)
14+
keyCodec.write(buffer, key)
15+
val serializer = serializers.invoke(key)
16+
(serializer as StreamCodec<TR>).write(buffer, value as TR)
17+
}
18+
19+
override fun read(buffer: ByteBuf): T {
20+
val key = keyCodec.read(buffer)
21+
val serializer = serializers.invoke(key)
22+
return serializer.read(buffer)
23+
}
24+
25+
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
package io.github.dockyardmc.tide
2+
3+
import io.github.dockyardmc.tide.codec.Codec
4+
import io.github.dockyardmc.tide.codec.StructCodec
5+
import io.github.dockyardmc.tide.stream.StreamCodec
6+
import io.github.dockyardmc.tide.transcoder.JsonTranscoder
7+
import io.netty.buffer.Unpooled
8+
import org.junit.jupiter.api.Test
9+
import kotlin.test.assertEquals
10+
11+
class UnionCodecTest {
12+
13+
sealed interface ConsumeEffect {
14+
companion object {
15+
val STREAM_CODEC = StreamCodec.enum<Type>().union(
16+
{ type ->
17+
when (type) {
18+
Type.APPLY_EFFECTS -> ApplyEffects.STREAM_CODEC
19+
Type.REMOVE_EFFECTS -> RemoveEffects.STREAM_CODEC
20+
Type.PLAY_SOUND -> PlaySound.STREAM_CODEC
21+
Type.TELEPORT -> Teleport.STREAM_CODEC
22+
}
23+
},
24+
{ consumeEffect ->
25+
when (consumeEffect) {
26+
is ApplyEffects -> Type.APPLY_EFFECTS
27+
is RemoveEffects -> Type.REMOVE_EFFECTS
28+
is PlaySound -> Type.PLAY_SOUND
29+
is Teleport -> Type.TELEPORT
30+
}
31+
})
32+
33+
val CODEC = Codec.enum<Type>().union<ConsumeEffect>(
34+
{ type ->
35+
when (type) {
36+
Type.APPLY_EFFECTS -> ApplyEffects.CODEC
37+
Type.REMOVE_EFFECTS -> RemoveEffects.CODEC
38+
Type.PLAY_SOUND -> PlaySound.CODEC
39+
Type.TELEPORT -> Teleport.CODEC
40+
}
41+
},
42+
{ consumeEffect ->
43+
when (consumeEffect) {
44+
is ApplyEffects -> Type.APPLY_EFFECTS
45+
is RemoveEffects -> Type.REMOVE_EFFECTS
46+
is PlaySound -> Type.PLAY_SOUND
47+
is Teleport -> Type.TELEPORT
48+
}
49+
})
50+
51+
}
52+
53+
fun consumeEffectToType(consumeEffect: ConsumeEffect): Type {
54+
return when (consumeEffect) {
55+
is ApplyEffects -> Type.APPLY_EFFECTS
56+
is RemoveEffects -> Type.REMOVE_EFFECTS
57+
is PlaySound -> Type.PLAY_SOUND
58+
is Teleport -> Type.TELEPORT
59+
}
60+
}
61+
62+
enum class Type {
63+
APPLY_EFFECTS,
64+
REMOVE_EFFECTS,
65+
PLAY_SOUND,
66+
TELEPORT
67+
}
68+
69+
data class ApplyEffects(val effects: List<String>) : ConsumeEffect {
70+
companion object {
71+
val CODEC = StructCodec.of(
72+
"effects", Codec.STRING.list(), ApplyEffects::effects,
73+
::ApplyEffects
74+
)
75+
76+
val STREAM_CODEC = StreamCodec.of(
77+
StreamCodec.STRING.list(), ApplyEffects::effects,
78+
::ApplyEffects
79+
)
80+
}
81+
}
82+
83+
data class RemoveEffects(val effects: List<String>) : ConsumeEffect {
84+
companion object {
85+
val CODEC = StructCodec.of(
86+
"effects", Codec.STRING.list(), RemoveEffects::effects,
87+
::RemoveEffects
88+
)
89+
90+
val STREAM_CODEC = StreamCodec.of(
91+
StreamCodec.STRING.list(), RemoveEffects::effects,
92+
::RemoveEffects
93+
)
94+
}
95+
}
96+
97+
data class PlaySound(val sound: String, val range: Float? = null) : ConsumeEffect {
98+
companion object {
99+
val CODEC = StructCodec.of(
100+
"sound", Codec.STRING, PlaySound::sound,
101+
"range", Codec.FLOAT.optional(), PlaySound::range,
102+
::PlaySound
103+
)
104+
105+
val STREAM_CODEC = StreamCodec.of(
106+
StreamCodec.STRING, PlaySound::sound,
107+
StreamCodec.FLOAT.optional(), PlaySound::range,
108+
::PlaySound
109+
)
110+
}
111+
}
112+
113+
data class Teleport(val radius: Float? = 1.6f) : ConsumeEffect {
114+
companion object {
115+
val CODEC = StructCodec.of(
116+
"radius", Codec.FLOAT.optional(), Teleport::radius,
117+
::Teleport
118+
)
119+
120+
val STREAM_CODEC = StreamCodec.of(
121+
StreamCodec.FLOAT.optional(), Teleport::radius,
122+
::Teleport
123+
)
124+
}
125+
}
126+
127+
}
128+
129+
@Test
130+
fun testUnionCodec() {
131+
val tp = ConsumeEffect.ApplyEffects(listOf("minecraft:speed", "minecraft:gayness"))
132+
val encoded = ConsumeEffect.CODEC.encode(JsonTranscoder, tp)
133+
val decoded = ConsumeEffect.CODEC.decode(JsonTranscoder, encoded)
134+
assertEquals(tp, decoded)
135+
}
136+
137+
@Test
138+
fun testUnionStreamCodec() {
139+
val tp = ConsumeEffect.ApplyEffects(listOf("minecraft:speed", "minecraft:gayness"))
140+
val buffer = Unpooled.buffer()
141+
ConsumeEffect.STREAM_CODEC.write(buffer, tp)
142+
val decoded = ConsumeEffect.STREAM_CODEC.read(buffer)
143+
assertEquals(tp, decoded)
144+
}
145+
146+
}

0 commit comments

Comments
 (0)