Skip to content

Commit 7cdbe4d

Browse files
committed
fix tagging
1 parent 775b929 commit 7cdbe4d

File tree

7 files changed

+246
-98
lines changed

7 files changed

+246
-98
lines changed

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

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ public sealed class CborPrimitive<T : Any>(
8888
")"
8989
}
9090
}
91+
9192
@Serializable(with = CborIntSerializer::class)
9293
public sealed class CborInt<T : Any>(
9394
tags: ULongArray = ulongArrayOf(),
@@ -96,13 +97,14 @@ public sealed class CborInt<T : Any>(
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

@@ -112,7 +114,7 @@ public sealed class CborInt<T : Any>(
112114
@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" }
@@ -125,7 +127,7 @@ public class CborNegativeInt(
125127
@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
/**
@@ -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: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -323,9 +323,7 @@ private fun defer(deferred: () -> SerialDescriptor): SerialDescriptor = object :
323323

324324
private fun CborWriter.encodeTags(value: CborElement) { // Encode tags if present
325325
if (value.tags.isNotEmpty()) {
326-
for (tag in value.tags) {
327-
encodeTag(tag)
328-
}
326+
encodeTags(value.tags)
329327
}
330328

331329
}

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,20 @@ internal class CborTreeReader(
2828
val result = when (parser.curByte shr 5) { // Get major type from the first 3 bits
2929
0 -> { // Major type 0: unsigned integer
3030
val value = parser.nextNumber()
31-
CborPositiveInt(value.toULong(), tags)
31+
CborPositiveInt(value.toULong(), tags = tags)
3232
}
3333

3434
1 -> { // Major type 1: negative integer
3535
val value = parser.nextNumber()
36-
CborNegativeInt(value, tags)
36+
CborNegativeInt(value, tags = tags)
3737
}
3838

3939
2 -> { // Major type 2: byte string
40-
CborByteString(parser.nextByteString(), tags)
40+
CborByteString(parser.nextByteString(), tags = tags)
4141
}
4242

4343
3 -> { // Major type 3: text string
44-
CborString(parser.nextString(), tags)
44+
CborString(parser.nextString(), tags = tags)
4545
}
4646

4747
4 -> { // Major type 4: array
@@ -66,10 +66,10 @@ internal class CborTreeReader(
6666

6767
0xF6, 0xF7 -> {
6868
parser.nextNull()
69-
CborNull(tags)
69+
CborNull(tags = tags)
7070
}
7171
// Half/Float32/Float64
72-
NEXT_HALF, NEXT_FLOAT, NEXT_DOUBLE -> CborDouble(parser.nextDouble(), tags)
72+
NEXT_HALF, NEXT_FLOAT, NEXT_DOUBLE -> CborDouble(parser.nextDouble(), tags = tags)
7373
else -> throw CborDecodingException(
7474
"Invalid simple value or float type: ${parser.curByte.toString(16).uppercase()}"
7575
)
@@ -120,7 +120,7 @@ internal class CborTreeReader(
120120
parser.end()
121121
}
122122

123-
return CborList(elements, tags)
123+
return CborList(elements, tags = tags)
124124
}
125125

126126
private fun readMap(tags: ULongArray): CborMap {
@@ -144,6 +144,6 @@ internal class CborTreeReader(
144144
parser.end()
145145
}
146146

147-
return CborMap(elements, tags)
147+
return CborMap(elements, tags = tags)
148148
}
149149
}

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,9 @@ internal open class CborReader(override val cbor: Cbor, protected val parser: Cb
118118
override fun <T> decodeSerializableValue(deserializer: DeserializationStrategy<T>): T {
119119
@Suppress("UNCHECKED_CAST")
120120
return if (deserializer is CborSerializer) {
121-
parser.processTags(tags)
122-
decodeCborElement() as T
123-
}
124-
else if ((decodeByteArrayAsByteString || cbor.configuration.alwaysUseByteString)
121+
val tags = parser.processTags(tags)
122+
decodeCborElement().also { /*this is a NOOP for structured parser but not from bytes */it.tags = tags ?: ulongArrayOf() } as T
123+
} else if ((decodeByteArrayAsByteString || cbor.configuration.alwaysUseByteString)
125124
&& deserializer.descriptor == ByteArraySerializer().descriptor
126125
) {
127126
@Suppress("UNCHECKED_CAST")
@@ -602,7 +601,7 @@ internal class StructuredCborParser(internal val element: CborElement, private v
602601
CborParserInterface {
603602

604603
internal var layer: CborLayer = false to PeekingIterator(element)
605-
private set
604+
private set
606605

607606

608607
private val layerStack = ArrayDeque<CborLayer>()

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

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ internal sealed class CborWriter(
3838

3939
class Data(val bytes: ByteArrayOutput, var elementCount: Int)
4040

41-
internal abstract fun getDestination(): ByteArrayOutput
41+
protected abstract fun getDestination(): ByteArrayOutput
4242

4343
override val serializersModule: SerializersModule
4444
get() = cbor.serializersModule
@@ -148,7 +148,7 @@ internal sealed class CborWriter(
148148
return true
149149
}
150150

151-
internal fun encodeTag(tag: ULong) = getDestination().encodeTag(tag)
151+
internal abstract fun encodeTags(tags: ULongArray)
152152
}
153153

154154

@@ -183,6 +183,8 @@ internal class IndefiniteLengthCborWriter(cbor: Cbor, private val output: ByteAr
183183
override fun incrementChildren() {/*NOOP*/
184184
}
185185

186+
override fun encodeTags(tags: ULongArray) = tags.forEach { getDestination().encodeTag(it) }
187+
186188
}
187189

188190
// optimized indefinite length encoder
@@ -234,12 +236,13 @@ internal class StructuredCborWriter(cbor: Cbor) : CborWriter(cbor) {
234236

235237
private val stack = ArrayDeque<CborContainer>()
236238
private var currentElement: CborContainer? = null
239+
237240
// value tags are collects inside beginStructure, so we need to cache them here and write them in beginStructure or encodeXXX
238241
// and then null them out, so there are no leftovers
239-
private var nextValueTags : ULongArray = ulongArrayOf()
242+
private var nextValueTags: ULongArray = ulongArrayOf()
240243
get() {
241-
val ret=field
242-
field=ulongArrayOf()
244+
val ret = field
245+
field = ulongArrayOf()
243246
return ret
244247
}
245248

@@ -270,7 +273,7 @@ internal class StructuredCborWriter(cbor: Cbor) : CborWriter(cbor) {
270273
}
271274
}
272275

273-
override fun getDestination() = throw IllegalStateException("There is not byteArrayOutput")
276+
override fun getDestination() = throw IllegalStateException("There is no byteArrayInput")
274277

275278
override fun incrementChildren() {
276279
/*NOOP*/
@@ -295,67 +298,76 @@ internal class StructuredCborWriter(cbor: Cbor) : CborWriter(cbor) {
295298
if (cbor.configuration.preferCborLabelsOverNames && cborLabel != null) {
296299
currentElement += CborInt(value = cborLabel, tags = keyTags ?: ulongArrayOf())
297300
} else {
298-
currentElement += CborString(name, keyTags ?: ulongArrayOf())
301+
currentElement += CborString(name, tags = keyTags ?: ulongArrayOf())
299302
}
300303
}
301304
}
302305

303306
if (cbor.configuration.encodeValueTags) {
304-
descriptor.getValueTags(index)?.let { valueTags ->
307+
descriptor.getValueTags(index).let { valueTags ->
305308
//collect them for late encoding in beginStructure or encodeXXX
306-
nextValueTags = valueTags?:ulongArrayOf()
309+
nextValueTags = valueTags ?: ulongArrayOf()
307310
}
308311
}
309312
return true
310313
}
311314

315+
316+
override fun encodeTags(tags: ULongArray) {
317+
nextValueTags = tags
318+
}
319+
312320
override fun encodeBoolean(value: Boolean) {
313321
currentElement += CborBoolean(value, nextValueTags)
314322
}
315323

316324
override fun encodeByte(value: Byte) {
317-
currentElement += CborInt(value.toLong(), nextValueTags)
325+
currentElement += CborInt(value.toLong(), tags = nextValueTags)
318326
}
319327

320328
override fun encodeChar(value: Char) {
321-
currentElement += CborInt(value.code.toLong(), nextValueTags)
329+
currentElement += CborInt(value.code.toLong(), tags = nextValueTags)
322330
}
323331

324332
override fun encodeDouble(value: Double) {
325-
currentElement += CborDouble(value, nextValueTags)
333+
currentElement += CborDouble(value, tags = nextValueTags)
326334
}
327335

328336
override fun encodeFloat(value: Float) {
329-
currentElement += CborDouble(value.toDouble(), nextValueTags)
337+
currentElement += CborDouble(value.toDouble(), tags = nextValueTags)
330338
}
331339

332340
override fun encodeInt(value: Int) {
333-
currentElement += CborInt(value.toLong(), nextValueTags)
341+
currentElement += CborInt(value.toLong(), tags = nextValueTags)
334342
}
335343

336344
override fun encodeLong(value: Long) {
337-
currentElement += CborInt(value, nextValueTags)
345+
currentElement += CborInt(value, tags = nextValueTags)
338346
}
339347

340348
override fun encodeShort(value: Short) {
341-
currentElement += CborInt(value.toLong(), nextValueTags)
349+
currentElement += CborInt(value.toLong(), tags = nextValueTags)
342350
}
343351

344352
override fun encodeString(value: String) {
345-
currentElement += CborString(value, nextValueTags)
353+
currentElement += CborString(value, tags = nextValueTags)
346354
}
347355

348356
override fun encodeByteString(byteArray: ByteArray) {
349-
currentElement += CborByteString(byteArray, nextValueTags)
357+
currentElement += CborByteString(byteArray, tags = nextValueTags)
350358
}
351359

352360
override fun encodeNull() {
353-
currentElement += if (isClass) CborMap(mapOf(), nextValueTags) /*NOT CBOR-COMPLIANT, KxS-proprietary behaviour*/
354-
else CborNull(nextValueTags)
361+
/*NOT CBOR-COMPLIANT, KxS-proprietary behaviour*/
362+
currentElement += if (isClass) CborMap(
363+
mapOf(),
364+
tags = nextValueTags
365+
)
366+
else CborNull(tags = nextValueTags)
355367
}
356368

357369
override fun encodeEnum(enumDescriptor: SerialDescriptor, index: Int) {
358-
currentElement += CborString(enumDescriptor.getElementName(index), nextValueTags)
370+
currentElement += CborString(enumDescriptor.getElementName(index), tags = nextValueTags)
359371
}
360372

361373
}
@@ -372,6 +384,8 @@ internal class DefiniteLengthCborWriter(cbor: Cbor, output: ByteArrayOutput) : C
372384
structureStack.peek().elementCount++
373385
}
374386

387+
override fun encodeTags(tags: ULongArray) = tags.forEach { getDestination().encodeTag(it) }
388+
375389
override fun beginStructure(descriptor: SerialDescriptor): CompositeEncoder {
376390
val current = Data(ByteArrayOutput(), 0)
377391
structureStack.push(current)

0 commit comments

Comments
 (0)