Skip to content

Commit 8d49f2c

Browse files
committed
Fix Tagging and Simplify
1 parent ebd87c9 commit 8d49f2c

File tree

14 files changed

+1060
-405
lines changed

14 files changed

+1060
-405
lines changed

formats/cbor/commonMain/src/kotlinx/serialization/cbor/CborElement.kt

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -89,30 +89,32 @@ public sealed class CborPrimitive<T : Any>(
8989
}
9090
}
9191

92+
@Serializable(with = CborIntSerializer::class)
9293
public sealed class CborInt<T : Any>(
9394
tags: ULongArray = ulongArrayOf(),
9495
value: T,
9596
) : CborPrimitive<T>(value, tags) {
9697
public companion object {
9798
public operator fun invoke(
9899
value: Long,
99-
tags: ULongArray = ulongArrayOf()
100-
): CborInt<*> = if (value >= 0) CborPositiveInt(value.toULong(), tags) else CborNegativeInt(value, tags)
100+
vararg tags: ULong
101+
): CborInt<*> =
102+
if (value >= 0) CborPositiveInt(value.toULong(), tags = tags) else CborNegativeInt(value, tags = tags)
101103

102104
public operator fun invoke(
103105
value: ULong,
104-
tags: ULongArray = ulongArrayOf()
105-
): CborInt<ULong> = CborPositiveInt(value, tags)
106+
vararg tags: ULong
107+
): CborInt<ULong> = CborPositiveInt(value, tags = tags)
106108
}
107109
}
108110

109111
/**
110112
* Class representing signed CBOR integer (major type 1).
111113
*/
112-
@Serializable(with = CborIntSerializer::class)
114+
@Serializable(with = CborNegativeIntSerializer::class)
113115
public class CborNegativeInt(
114116
value: Long,
115-
tags: ULongArray = ulongArrayOf()
117+
vararg tags: ULong
116118
) : CborInt<Long>(tags, value) {
117119
init {
118120
require(value < 0) { "Number must be negative: $value" }
@@ -122,10 +124,10 @@ public class CborNegativeInt(
122124
/**
123125
* Class representing unsigned CBOR integer (major type 0).
124126
*/
125-
@Serializable(with = CborUIntSerializer::class)
127+
@Serializable(with = CborPositiveIntSerializer::class)
126128
public class CborPositiveInt(
127129
value: ULong,
128-
tags: ULongArray = ulongArrayOf()
130+
vararg tags: ULong
129131
) : CborInt<ULong>(tags, value)
130132

131133
/**
@@ -134,7 +136,7 @@ public class CborPositiveInt(
134136
@Serializable(with = CborDoubleSerializer::class)
135137
public class CborDouble(
136138
value: Double,
137-
tags: ULongArray = ulongArrayOf()
139+
vararg tags: ULong
138140
) : CborPrimitive<Double>(value, tags)
139141

140142
/**
@@ -143,7 +145,7 @@ public class CborDouble(
143145
@Serializable(with = CborStringSerializer::class)
144146
public class CborString(
145147
value: String,
146-
tags: ULongArray = ulongArrayOf()
148+
vararg tags: ULong
147149
) : CborPrimitive<String>(value, tags)
148150

149151
/**
@@ -152,7 +154,7 @@ public class CborString(
152154
@Serializable(with = CborBooleanSerializer::class)
153155
public class CborBoolean(
154156
value: Boolean,
155-
tags: ULongArray = ulongArrayOf()
157+
vararg tags: ULong
156158
) : CborPrimitive<Boolean>(value, tags)
157159

158160
/**
@@ -161,7 +163,7 @@ public class CborBoolean(
161163
@Serializable(with = CborByteStringSerializer::class)
162164
public class CborByteString(
163165
value: ByteArray,
164-
tags: ULongArray = ulongArrayOf()
166+
vararg tags: ULong
165167
) : CborPrimitive<ByteArray>(value, tags) {
166168
override fun equals(other: Any?): Boolean {
167169
if (this === other) return true
@@ -189,7 +191,7 @@ public class CborByteString(
189191
* Class representing CBOR `null` value
190192
*/
191193
@Serializable(with = CborNullSerializer::class)
192-
public class CborNull(tags: ULongArray = ulongArrayOf()) : CborPrimitive<Unit>(Unit, tags)
194+
public class CborNull(vararg tags: ULong) : CborPrimitive<Unit>(Unit, tags)
193195

194196
/**
195197
* Class representing CBOR map, consisting of key-value pairs, where both key and value are arbitrary [CborElement]
@@ -200,7 +202,7 @@ public class CborNull(tags: ULongArray = ulongArrayOf()) : CborPrimitive<Unit>(U
200202
@Serializable(with = CborMapSerializer::class)
201203
public class CborMap(
202204
private val content: Map<CborElement, CborElement>,
203-
tags: ULongArray = ulongArrayOf()
205+
vararg tags: ULong
204206
) : CborElement(tags), Map<CborElement, CborElement> by content {
205207

206208
public override fun equals(other: Any?): Boolean =
@@ -226,7 +228,7 @@ public class CborMap(
226228
@Serializable(with = CborListSerializer::class)
227229
public class CborList(
228230
private val content: List<CborElement>,
229-
tags: ULongArray = ulongArrayOf()
231+
vararg tags: ULong
230232
) : CborElement(tags), List<CborElement> by content {
231233

232234
public override fun equals(other: Any?): Boolean =

formats/cbor/commonMain/src/kotlinx/serialization/cbor/internal/CborElementSerializers.kt

Lines changed: 59 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ import kotlinx.serialization.cbor.*
1111
import kotlinx.serialization.descriptors.*
1212
import kotlinx.serialization.encoding.*
1313

14+
internal interface CborSerializer
15+
1416
/**
1517
* Serializer object providing [SerializationStrategy] and [DeserializationStrategy] for [CborElement].
1618
* It can only be used by with [Cbor] format and its input ([CborDecoder] and [CborEncoder]).
1719
*/
18-
internal object CborElementSerializer : KSerializer<CborElement> {
20+
internal object CborElementSerializer : KSerializer<CborElement>, CborSerializer {
1921
override val descriptor: SerialDescriptor =
2022
buildSerialDescriptor("kotlinx.serialization.cbor.CborElement", PolymorphicKind.SEALED) {
2123
// Resolve cyclic dependency in descriptors by late binding
@@ -27,8 +29,8 @@ internal object CborElementSerializer : KSerializer<CborElement> {
2729
element("CborMap", defer { CborMapSerializer.descriptor })
2830
element("CborList", defer { CborListSerializer.descriptor })
2931
element("CborDouble", defer { CborDoubleSerializer.descriptor })
30-
element("CborInt", defer { CborIntSerializer.descriptor })
31-
element("CborUInt", defer { CborUIntSerializer.descriptor })
32+
element("CborInt", defer { CborNegativeIntSerializer.descriptor })
33+
element("CborUInt", defer { CborPositiveIntSerializer.descriptor })
3234
}
3335

3436
override fun serialize(encoder: Encoder, value: CborElement) {
@@ -52,23 +54,19 @@ internal object CborElementSerializer : KSerializer<CborElement> {
5254
* Serializer object providing [SerializationStrategy] and [DeserializationStrategy] for [CborPrimitive].
5355
* It can only be used by with [Cbor] format an its input ([CborDecoder] and [CborEncoder]).
5456
*/
55-
internal object CborPrimitiveSerializer : KSerializer<CborPrimitive<*>> {
57+
internal object CborPrimitiveSerializer : KSerializer<CborPrimitive<*>>, CborSerializer {
5658
override val descriptor: SerialDescriptor =
57-
buildSerialDescriptor("kotlinx.serialization.cbor.CborPrimitive", PrimitiveKind.STRING)
59+
buildSerialDescriptor("kotlinx.serialization.cbor.CborPrimitive", PolymorphicKind.SEALED)
5860

5961
override fun serialize(encoder: Encoder, value: CborPrimitive<*>) {
60-
val cborEncoder = encoder.asCborEncoder()
61-
62-
cborEncoder.encodeTags(value)
63-
6462
when (value) {
6563
is CborNull -> encoder.encodeSerializableValue(CborNullSerializer, value)
6664
is CborString -> encoder.encodeSerializableValue(CborStringSerializer, value)
6765
is CborBoolean -> encoder.encodeSerializableValue(CborBooleanSerializer, value)
6866
is CborByteString -> encoder.encodeSerializableValue(CborByteStringSerializer, value)
6967
is CborDouble -> encoder.encodeSerializableValue(CborDoubleSerializer, value)
70-
is CborNegativeInt -> encoder.encodeSerializableValue(CborIntSerializer, value)
71-
is CborPositiveInt -> encoder.encodeSerializableValue(CborUIntSerializer, value)
68+
is CborNegativeInt -> encoder.encodeSerializableValue(CborNegativeIntSerializer, value)
69+
is CborPositiveInt -> encoder.encodeSerializableValue(CborPositiveIntSerializer, value)
7270
}
7371
}
7472

@@ -83,13 +81,14 @@ internal object CborPrimitiveSerializer : KSerializer<CborPrimitive<*>> {
8381
* Serializer object providing [SerializationStrategy] and [DeserializationStrategy] for [CborNull].
8482
* It can only be used by with [Cbor] format an its input ([CborDecoder] and [CborEncoder]).
8583
*/
86-
internal object CborNullSerializer : KSerializer<CborNull> {
84+
internal object CborNullSerializer : KSerializer<CborNull>, CborSerializer {
8785

8886
override val descriptor: SerialDescriptor =
8987
buildSerialDescriptor("kotlinx.serialization.cbor.CborNull", SerialKind.ENUM)
9088

9189
override fun serialize(encoder: Encoder, value: CborNull) {
92-
encoder.asCborEncoder().encodeTags(value)
90+
val cborEncoder = encoder.asCborEncoder()
91+
cborEncoder.encodeTags(value)
9392
encoder.encodeNull()
9493
}
9594

@@ -98,16 +97,38 @@ internal object CborNullSerializer : KSerializer<CborNull> {
9897
if (decoder.decodeNotNullMark()) {
9998
throw CborDecodingException("Expected 'null' literal")
10099
}
100+
101101
decoder.decodeNull()
102102
return CborNull()
103103
}
104104
}
105105

106-
internal object CborIntSerializer : KSerializer<CborNegativeInt> {
107-
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("kotlinx.serialization.cbor.CborInt", PrimitiveKind.LONG)
106+
107+
internal object CborIntSerializer : KSerializer<CborInt<*>>, CborSerializer {
108+
override val descriptor: SerialDescriptor =
109+
PrimitiveSerialDescriptor("kotlinx.serialization.cbor.CborInt", PrimitiveKind.LONG)
110+
111+
override fun serialize(encoder: Encoder, value: CborInt<*>) {
112+
when (value) {
113+
is CborNegativeInt -> encoder.encodeSerializableValue(CborNegativeIntSerializer, value)
114+
is CborPositiveInt -> encoder.encodeSerializableValue(CborPositiveIntSerializer, value)
115+
}
116+
}
117+
118+
override fun deserialize(decoder: Decoder): CborInt<*> {
119+
val result = decoder.asCborDecoder().decodeCborElement()
120+
if (result !is CborInt<*>) throw CborDecodingException("Unexpected CBOR element, expected CborInt, had ${result::class}")
121+
return result
122+
}
123+
}
124+
125+
internal object CborNegativeIntSerializer : KSerializer<CborNegativeInt>, CborSerializer {
126+
override val descriptor: SerialDescriptor =
127+
PrimitiveSerialDescriptor("kotlinx.serialization.cbor.CborNegativeInt", PrimitiveKind.LONG)
108128

109129
override fun serialize(encoder: Encoder, value: CborNegativeInt) {
110-
encoder.asCborEncoder().encodeTags(value)
130+
val cborEncoder = encoder.asCborEncoder()
131+
cborEncoder.encodeTags(value)
111132
encoder.encodeLong(value.value)
112133
}
113134

@@ -117,12 +138,14 @@ internal object CborIntSerializer : KSerializer<CborNegativeInt> {
117138
}
118139
}
119140

120-
internal object CborUIntSerializer : KSerializer<CborPositiveInt> {
121-
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("CborUInt", PrimitiveKind.LONG)
141+
internal object CborPositiveIntSerializer : KSerializer<CborPositiveInt>, CborSerializer {
142+
override val descriptor: SerialDescriptor =
143+
PrimitiveSerialDescriptor("kotlinx.serialization.cbor.CborPositiveInt", PrimitiveKind.LONG)
122144

123145
override fun serialize(encoder: Encoder, value: CborPositiveInt) {
124-
encoder.asCborEncoder().encodeTags(value)
125-
encoder.encodeInline(descriptor).encodeSerializableValue(ULong.serializer(), value.value)
146+
val cborEncoder = encoder.asCborEncoder()
147+
cborEncoder.encodeTags(value)
148+
encoder.encodeInline(descriptor).encodeSerializableValue(ULong.serializer(), value.value as ULong)
126149
}
127150

128151
override fun deserialize(decoder: Decoder): CborPositiveInt {
@@ -131,11 +154,13 @@ internal object CborUIntSerializer : KSerializer<CborPositiveInt> {
131154
}
132155
}
133156

134-
internal object CborDoubleSerializer : KSerializer<CborDouble> {
135-
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("kotlinx.serialization.cbor.CborDouble", PrimitiveKind.DOUBLE)
157+
internal object CborDoubleSerializer : KSerializer<CborDouble>, CborSerializer {
158+
override val descriptor: SerialDescriptor =
159+
PrimitiveSerialDescriptor("kotlinx.serialization.cbor.CborDouble", PrimitiveKind.DOUBLE)
136160

137161
override fun serialize(encoder: Encoder, value: CborDouble) {
138-
encoder.asCborEncoder().encodeTags(value)
162+
val cborEncoder = encoder.asCborEncoder()
163+
cborEncoder.encodeTags(value)
139164
encoder.encodeDouble(value.value)
140165
}
141166

@@ -149,12 +174,13 @@ internal object CborDoubleSerializer : KSerializer<CborDouble> {
149174
* Serializer object providing [SerializationStrategy] and [DeserializationStrategy] for [CborString].
150175
* It can only be used by with [Cbor] format an its input ([CborDecoder] and [CborEncoder]).
151176
*/
152-
internal object CborStringSerializer : KSerializer<CborString> {
177+
internal object CborStringSerializer : KSerializer<CborString>, CborSerializer {
153178
override val descriptor: SerialDescriptor =
154179
PrimitiveSerialDescriptor("kotlinx.serialization.cbor.CborString", PrimitiveKind.STRING)
155180

156181
override fun serialize(encoder: Encoder, value: CborString) {
157-
encoder.asCborEncoder().encodeTags(value)
182+
val cborEncoder = encoder.asCborEncoder()
183+
cborEncoder.encodeTags(value)
158184
encoder.encodeString(value.value)
159185
}
160186

@@ -170,12 +196,13 @@ internal object CborStringSerializer : KSerializer<CborString> {
170196
* Serializer object providing [SerializationStrategy] and [DeserializationStrategy] for [CborBoolean].
171197
* It can only be used by with [Cbor] format an its input ([CborDecoder] and [CborEncoder]).
172198
*/
173-
internal object CborBooleanSerializer : KSerializer<CborBoolean> {
199+
internal object CborBooleanSerializer : KSerializer<CborBoolean>, CborSerializer {
174200
override val descriptor: SerialDescriptor =
175201
PrimitiveSerialDescriptor("kotlinx.serialization.cbor.CborBoolean", PrimitiveKind.BOOLEAN)
176202

177203
override fun serialize(encoder: Encoder, value: CborBoolean) {
178-
encoder.asCborEncoder().encodeTags(value)
204+
val cborEncoder = encoder.asCborEncoder()
205+
cborEncoder.encodeTags(value)
179206
encoder.encodeBoolean(value.value)
180207
}
181208

@@ -191,13 +218,13 @@ internal object CborBooleanSerializer : KSerializer<CborBoolean> {
191218
* Serializer object providing [SerializationStrategy] and [DeserializationStrategy] for [CborByteString].
192219
* It can only be used by with [Cbor] format and its input ([CborDecoder] and [CborEncoder]).
193220
*/
194-
internal object CborByteStringSerializer : KSerializer<CborByteString> {
221+
internal object CborByteStringSerializer : KSerializer<CborByteString>, CborSerializer {
195222
override val descriptor: SerialDescriptor =
196223
PrimitiveSerialDescriptor("kotlinx.serialization.cbor.CborByteString", PrimitiveKind.STRING)
197224

198225
override fun serialize(encoder: Encoder, value: CborByteString) {
199226
val cborEncoder = encoder.asCborEncoder()
200-
cborEncoder.encodeTags(value)
227+
cborEncoder.encodeTags(value)
201228
cborEncoder.encodeByteString(value.value)
202229
}
203230

@@ -213,7 +240,7 @@ internal object CborByteStringSerializer : KSerializer<CborByteString> {
213240
* Serializer object providing [SerializationStrategy] and [DeserializationStrategy] for [CborMap].
214241
* It can only be used by with [Cbor] format and its input ([CborDecoder] and [CborEncoder]).
215242
*/
216-
internal object CborMapSerializer : KSerializer<CborMap> {
243+
internal object CborMapSerializer : KSerializer<CborMap>, CborSerializer {
217244
private object CborMapDescriptor :
218245
SerialDescriptor by MapSerializer(CborElementSerializer, CborElementSerializer).descriptor {
219246
@ExperimentalSerializationApi
@@ -238,7 +265,7 @@ internal object CborMapSerializer : KSerializer<CborMap> {
238265
* Serializer object providing [SerializationStrategy] and [DeserializationStrategy] for [CborList].
239266
* It can only be used by with [Cbor] format an its input ([CborDecoder] and [CborEncoder]).
240267
*/
241-
internal object CborListSerializer : KSerializer<CborList> {
268+
internal object CborListSerializer : KSerializer<CborList>, CborSerializer {
242269
private object CborListDescriptor : SerialDescriptor by ListSerializer(CborElementSerializer).descriptor {
243270
@ExperimentalSerializationApi
244271
override val serialName: String = "kotlinx.serialization.cbor.CborList"
@@ -296,9 +323,7 @@ private fun defer(deferred: () -> SerialDescriptor): SerialDescriptor = object :
296323

297324
private fun CborWriter.encodeTags(value: CborElement) { // Encode tags if present
298325
if (value.tags.isNotEmpty()) {
299-
for (tag in value.tags) {
300-
encodeTag(tag)
301-
}
326+
encodeTags(value.tags)
302327
}
303328

304329
}

formats/cbor/commonMain/src/kotlinx/serialization/cbor/internal/CborParserInterface.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package kotlinx.serialization.cbor.internal
77

88
import kotlinx.serialization.*
9+
import kotlinx.serialization.cbor.CborList
910

1011
/**
1112
* Common interface for CBOR parsers that can read CBOR data from different sources.
@@ -38,4 +39,6 @@ internal sealed interface CborParserInterface {
3839

3940
// Tag verification
4041
fun verifyTagsAndThrow(expected: ULongArray, actual: ULongArray?)
42+
43+
fun processTags(tags: ULongArray?): ULongArray?
4144
}

0 commit comments

Comments
 (0)