Skip to content

Commit 835acdf

Browse files
committed
Change: Make normalized path segments value classes
1 parent e165e50 commit 835acdf

1 file changed

Lines changed: 48 additions & 3 deletions

File tree

jsonpath4k/src/commonMain/kotlin/at/asitplus/jsonpath/core/NormalizedJsonPathSegment.kt

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,32 @@ package at.asitplus.jsonpath.core
22

33
import at.asitplus.jsonpath.generated.JsonPathLexer
44
import at.asitplus.jsonpath.generated.JsonPathParser
5+
import kotlinx.serialization.KSerializer
56
import kotlinx.serialization.Serializable
7+
import kotlinx.serialization.descriptors.SerialDescriptor
8+
import kotlinx.serialization.encoding.Decoder
9+
import kotlinx.serialization.encoding.Encoder
10+
import kotlinx.serialization.json.JsonDecoder
11+
import kotlinx.serialization.json.JsonElement
12+
import kotlinx.serialization.json.jsonPrimitive
13+
import kotlinx.serialization.json.long
614
import org.antlr.v4.kotlinruntime.CharStreams
715
import org.antlr.v4.kotlinruntime.CommonTokenStream
816
import org.antlr.v4.kotlinruntime.ListTokenSource
17+
import kotlin.jvm.JvmInline
918

1019
/**
1120
* specification: https://datatracker.ietf.org/doc/rfc9535/
1221
* date: 2024-02
1322
* section: 2.7. Normalized Paths
1423
*/
15-
@Serializable
24+
@Serializable(with = NormalizedJsonPathSegment.JsonDistinguishableSerializer::class)
1625
sealed interface NormalizedJsonPathSegment {
1726
fun toNormalizedJsonPathSegmentString(): String
1827

1928
@Serializable
20-
data class NameSegment(val memberName: String) : NormalizedJsonPathSegment {
29+
@JvmInline
30+
value class NameSegment(val memberName: String) : NormalizedJsonPathSegment {
2131
override fun toNormalizedJsonPathSegmentString() = toString()
2232

2333
override fun toString(): String {
@@ -48,7 +58,8 @@ sealed interface NormalizedJsonPathSegment {
4858
}
4959

5060
@Serializable
51-
data class IndexSegment(val index: UInt) : NormalizedJsonPathSegment {
61+
@JvmInline
62+
value class IndexSegment(val index: UInt) : NormalizedJsonPathSegment {
5263
companion object {
5364
operator fun invoke(int: Int) = IndexSegment(int.also {
5465
require(int >= 0)
@@ -61,4 +72,38 @@ sealed interface NormalizedJsonPathSegment {
6172
return "[$index]"
6273
}
6374
}
75+
76+
class JsonDistinguishableSerializer : KSerializer<NormalizedJsonPathSegment> {
77+
override val descriptor: SerialDescriptor
78+
get() = SerialDescriptor(
79+
original = JsonElement.serializer().descriptor,
80+
serialName = JsonDistinguishableSerializer::class.qualifiedName!!,
81+
)
82+
83+
override fun serialize(
84+
encoder: Encoder,
85+
value: NormalizedJsonPathSegment
86+
) {
87+
when (value) {
88+
is IndexSegment -> encoder.encodeLong(value.index.toLong())
89+
is NameSegment -> encoder.encodeString(value.memberName)
90+
}
91+
}
92+
93+
override fun deserialize(decoder: Decoder): NormalizedJsonPathSegment {
94+
require(decoder is JsonDecoder) {
95+
"Expected decoder to be ${JsonDecoder::class.qualifiedName!!}, but was `$decoder`."
96+
}
97+
val jsonElement = decoder.decodeJsonElement().jsonPrimitive
98+
return if (jsonElement.isString) {
99+
NameSegment(jsonElement.content)
100+
} else {
101+
IndexSegment(jsonElement.long.also {
102+
require(it >= 0) {
103+
"Expected index segment to be non-negative, but got `$it`."
104+
}
105+
}.toUInt())
106+
}
107+
}
108+
}
64109
}

0 commit comments

Comments
 (0)