@@ -227,10 +227,29 @@ internal open class CborReader(private val cbor: Cbor, protected val decoder: Cb
227227 }
228228
229229 override fun decodeElementIndex (descriptor : SerialDescriptor ): Int {
230- if (! finiteMode && decoder.isEnd() || (finiteMode && readProperties >= size)) return CompositeDecoder .DECODE_DONE
231- val elemName = decoder.nextString()
232- readProperties++
233- val index = descriptor.getElementIndexOrThrow(elemName)
230+ val index = if (cbor.ignoreUnknownKeys) {
231+ val knownIndex: Int
232+ while (true ) {
233+ if (isDone()) return CompositeDecoder .DECODE_DONE
234+ val elemName = decoder.nextString()
235+ readProperties++
236+
237+ val index = descriptor.getElementIndex(elemName)
238+ if (index == CompositeDecoder .UNKNOWN_NAME ) {
239+ decoder.skipElement()
240+ } else {
241+ knownIndex = index
242+ break
243+ }
244+ }
245+ knownIndex
246+ } else {
247+ if (isDone()) return CompositeDecoder .DECODE_DONE
248+ val elemName = decoder.nextString()
249+ readProperties++
250+ descriptor.getElementIndexOrThrow(elemName)
251+ }
252+
234253 decodeByteArrayAsByteString = descriptor.isByteString(index)
235254 return index
236255 }
@@ -263,6 +282,7 @@ internal open class CborReader(private val cbor: Cbor, protected val decoder: Cb
263282 override fun decodeEnum (enumDescriptor : SerialDescriptor ): Int =
264283 enumDescriptor.getElementIndexOrThrow(decoder.nextString())
265284
285+ private fun isDone (): Boolean = ! finiteMode && decoder.isEnd() || (finiteMode && readProperties >= size)
266286}
267287
268288internal class CborDecoder (private val input : ByteArrayInput ) {
@@ -420,6 +440,65 @@ internal class CborDecoder(private val input: ByteArrayInput) {
420440 return result
421441 }
422442
443+ fun skipElement () {
444+ check(! isEnd()) { " Unexpected end marker" }
445+ val lengthStack = mutableListOf<Int >()
446+
447+ do {
448+ var prune = false
449+
450+ if (isEnd()) {
451+ check(lengthStack.lastOrNull() == - 1 ) { " Unexpected end marker" }
452+ lengthStack.removeAt(lengthStack.lastIndex)
453+ prune = true
454+ } else {
455+ val header = curByte and 0b111_00000
456+ val isIndefinite = curByte and 0b000_11111 == 0b000_11111 &&
457+ (header == HEADER_ARRAY || header == HEADER_MAP ||
458+ header == HEADER_BYTE_STRING .toInt() || header == HEADER_STRING .toInt())
459+
460+ if (isIndefinite) {
461+ lengthStack.add(- 1 )
462+ } else {
463+ val length = when (header) {
464+ HEADER_BYTE_STRING .toInt(), HEADER_STRING .toInt(), HEADER_ARRAY -> readNumber().toInt()
465+ HEADER_MAP -> readNumber().toInt() * 2
466+ else -> when (curByte and 0b000_11111 ) {
467+ 24 -> 1
468+ 25 -> 2
469+ 26 -> 4
470+ 27 -> 8
471+ else -> 0
472+ }
473+ }
474+
475+ if (header == HEADER_ARRAY || header == HEADER_MAP ) {
476+ check(length > 0 ) { " Length must be > 0" }
477+ lengthStack.add(length)
478+ } else {
479+ input.skip(length)
480+ prune = true
481+ }
482+ }
483+ }
484+
485+ if (prune) {
486+ for (i in lengthStack.lastIndex downTo 0 ) {
487+ when (lengthStack[i]) {
488+ - 1 -> break
489+ 1 -> lengthStack.removeAt(i)
490+ else -> {
491+ lengthStack[i] = lengthStack[i] - 1
492+ break
493+ }
494+ }
495+ }
496+ }
497+
498+ if (readByte() == - 1 && lengthStack.isNotEmpty()) error(" Unexpected end of bytes" )
499+ } while (lengthStack.isNotEmpty())
500+ }
501+
423502 /* *
424503 * Indefinite-length byte sequences contain an unknown number of fixed-length byte sequences (chunks).
425504 *
@@ -438,7 +517,8 @@ internal class CborDecoder(private val input: ByteArrayInput) {
438517private fun SerialDescriptor.getElementIndexOrThrow (name : String ): Int {
439518 val index = getElementIndex(name)
440519 if (index == CompositeDecoder .UNKNOWN_NAME )
441- throw SerializationException (" $serialName does not contain element with name '$name '" )
520+ throw SerializationException (" $serialName does not contain element with name '$name ." +
521+ " You can enable 'CborBuilder.ignoreUnknownKeys' property to ignore unknown keys" )
442522 return index
443523}
444524
0 commit comments